-
- |
-
- FunctionChanged(e))">
+
+ FunctionChanged(e))">
@@ -36,8 +36,8 @@ else
|
-
- RowsChanged(e))">
+
+ RowsChanged(e))">
diff --git a/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor b/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor
index d824e595..0354f1bd 100644
--- a/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor
+++ b/Oqtane.Client/Modules/Admin/ModuleCreator/Index.razor
@@ -9,7 +9,7 @@
@using System.Text.RegularExpressions
@using System.IO;
-@if (string.IsNullOrEmpty(_moduledefinitionname))
+@if (string.IsNullOrEmpty(_moduledefinitionname) && _systeminfo != null && _templates != null)
{
@@ -38,13 +38,15 @@
-
+
|
TemplateChanged(e))">
-
-
+ @foreach (string template in _templates)
+ {
+
+ }
|
@@ -90,9 +92,11 @@ else
private string _module = string.Empty;
private string _description = string.Empty;
private string _template = "-";
- public string _reference = Constants.Version;
+ private string _reference = Constants.Version;
private string _location = string.Empty;
+
private Dictionary _systeminfo;
+ private List _templates;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
@@ -102,12 +106,11 @@ else
{
_moduledefinitionname = SettingService.GetSetting(ModuleState.Settings, "ModuleDefinitionName", "");
_systeminfo = await SystemService.GetSystemInfoAsync();
+ _templates = await ModuleDefinitionService.GetModuleDefinitionTemplatesAsync();
if (string.IsNullOrEmpty(_moduledefinitionname))
{
- _owner = ModuleState.Title;
- _module = ModuleState.Title;
- _description = ModuleState.Title;
+ AddModuleMessage(Localizer["Please Note That The Module Creator Is Only Intended To Be Used In A Development Environment"], MessageType.Info);
}
else
{
@@ -185,18 +188,8 @@ else
if (_template != "-" && _systeminfo != null && _systeminfo.ContainsKey("serverpath"))
{
string[] path = _systeminfo["serverpath"].Split(Path.DirectorySeparatorChar);
- if (_template == "internal")
- {
- _location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 1) +
- Path.DirectorySeparatorChar + "Oqtane.Client" +
- Path.DirectorySeparatorChar + "Modules" +
- Path.DirectorySeparatorChar + _owner + "." + _module;
- }
- else
- {
- _location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 2) +
- Path.DirectorySeparatorChar + _owner + "." + _module;
- }
+ _location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 2) +
+ Path.DirectorySeparatorChar + _owner + "." + _module;
}
StateHasChanged();
}
diff --git a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor
index 538bf700..3ebfed0b 100644
--- a/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor
+++ b/Oqtane.Client/Modules/Admin/ModuleDefinitions/Index.razor
@@ -26,7 +26,7 @@ else
@if (context.AssemblyName != "Oqtane.Client")
{
-
+
}
|
@context.Name |
diff --git a/Oqtane.Client/Modules/Admin/Pages/Add.razor b/Oqtane.Client/Modules/Admin/Pages/Add.razor
index 171ab885..b0234619 100644
--- a/Oqtane.Client/Modules/Admin/Pages/Add.razor
+++ b/Oqtane.Client/Modules/Admin/Pages/Add.razor
@@ -101,18 +101,11 @@
- ThemeChanged(e))">
+ ThemeChanged(e))">
@foreach (var theme in _themes)
{
- if (theme.TypeName == _themetype)
- {
-
- }
- else
- {
-
- }
+
}
|
diff --git a/Oqtane.Client/Modules/Admin/Pages/Edit.razor b/Oqtane.Client/Modules/Admin/Pages/Edit.razor
index 5efdd992..3b0d71c4 100644
--- a/Oqtane.Client/Modules/Admin/Pages/Edit.razor
+++ b/Oqtane.Client/Modules/Admin/Pages/Edit.razor
@@ -23,15 +23,11 @@
- ParentChanged(e))">
+ ParentChanged(e))">
@foreach (Page page in _pageList)
{
- if (page.PageId.ToString() == _parentid)
- {
-
- }
- else
+ if (page.PageId != _pageId)
{
}
@@ -112,18 +108,11 @@
|
- ThemeChanged(e))">
-
+ ThemeChanged(e))">
+
@foreach (var theme in _themes)
{
- if (theme.TypeName == _themetype)
- {
-
- }
- else
- {
-
- }
+
}
|
diff --git a/Oqtane.Client/Modules/Admin/Pages/Index.razor b/Oqtane.Client/Modules/Admin/Pages/Index.razor
index 4ff925fc..fef67427 100644
--- a/Oqtane.Client/Modules/Admin/Pages/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Pages/Index.razor
@@ -16,7 +16,7 @@
|
- |
+ |
@(new string('-', context.Level * 2))@(context.Name) |
diff --git a/Oqtane.Client/Modules/Admin/Profiles/Index.razor b/Oqtane.Client/Modules/Admin/Profiles/Index.razor
index 0bdf8554..4705b290 100644
--- a/Oqtane.Client/Modules/Admin/Profiles/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Profiles/Index.razor
@@ -19,7 +19,7 @@ else
|
- |
+ |
@context.Name |
@@ -30,9 +30,9 @@ else
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Admin;
- protected override async Task OnInitializedAsync()
+ protected override async Task OnParametersSetAsync()
{
- _profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
+ await GetProfilesAsync();
}
private async Task DeleteProfile(int profileId)
@@ -41,7 +41,12 @@ else
{
await ProfileService.DeleteProfileAsync(profileId);
await logger.LogInformation("Profile Deleted {ProfileId}", profileId);
+
AddModuleMessage(Localizer["Profile Deleted"], MessageType.Success);
+
+ await GetProfilesAsync();
+
+ StateHasChanged();
}
catch (Exception ex)
{
@@ -49,4 +54,9 @@ else
AddModuleMessage(Localizer["Error Deleting Profile"], MessageType.Error);
}
}
+
+ private async Task GetProfilesAsync()
+ {
+ _profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
+ }
}
diff --git a/Oqtane.Client/Modules/Admin/RecycleBin/Index.razor b/Oqtane.Client/Modules/Admin/RecycleBin/Index.razor
index 7c30c7a1..47e2a47a 100644
--- a/Oqtane.Client/Modules/Admin/RecycleBin/Index.razor
+++ b/Oqtane.Client/Modules/Admin/RecycleBin/Index.razor
@@ -34,7 +34,7 @@
@if (_pages.Any())
{
}
}
@@ -68,7 +68,7 @@
@if (_modules.Any())
{
}
diff --git a/Oqtane.Client/Modules/Admin/Site/Index.razor b/Oqtane.Client/Modules/Admin/Site/Index.razor
index bbfd28f7..4fcb5dd3 100644
--- a/Oqtane.Client/Modules/Admin/Site/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Site/Index.razor
@@ -7,146 +7,143 @@
@inject IThemeService ThemeService
@inject ISettingService SettingService
@inject IStringLocalizer Localizer
+@inject INotificationService NotificationService
@if (_initialized)
{
-
+
- @Localizer["Please Note That SMTP Requires The Notification Job To Be Enabled In the Scheduled Jobs"]
+ @Localizer["Please Note That SMTP Requires The Notification Job To Be Enabled In Scheduled Jobs"]
|
@@ -201,6 +198,8 @@
+
+
@@ -482,7 +481,6 @@
await SettingService.UpdateSiteSettingsAsync(settings, site.SiteId);
await logger.LogInformation("Site Settings Saved {Site}", site);
-
AddModuleMessage(Localizer["Site Settings Saved"], MessageType.Success);
}
}
@@ -502,4 +500,36 @@
AddModuleMessage(Localizer["Error Saving Site"], MessageType.Error);
}
}
+
+ private async Task SendEmail()
+ {
+ if (_smtphost != "" && _smtpport != "" && _smtpsender != "")
+ {
+ try
+ {
+ var settings = await SettingService.GetSiteSettingsAsync(PageState.Site.SiteId);
+ SettingService.SetSetting(settings, "SMTPHost", _smtphost);
+ SettingService.SetSetting(settings, "SMTPPort", _smtpport);
+ SettingService.SetSetting(settings, "SMTPSSL", _smtpssl);
+ SettingService.SetSetting(settings, "SMTPUsername", _smtpusername);
+ SettingService.SetSetting(settings, "SMTPPassword", _smtppassword);
+ SettingService.SetSetting(settings, "SMTPSender", _smtpsender);
+ await SettingService.UpdateSiteSettingsAsync(settings, PageState.Site.SiteId);
+ await logger.LogInformation("Site SMTP Settings Saved");
+
+ await NotificationService.AddNotificationAsync(new Notification(PageState.Site.SiteId, PageState.User.DisplayName, PageState.User.Email, PageState.User.DisplayName, PageState.User.Email, PageState.Site.Name + " SMTP Configuration Test", "SMTP Server Is Configured Correctly."));
+ AddModuleMessage(Localizer["SMTP Settings Saved And A Message Has Been Sent To The Email Address Associated To Your User Account... Please Wait A Few Minutes For Delivery. If You Do Not Receive The Email Please Review The Notification Job In Scheduled Jobs For Any Log Details."], MessageType.Info);
+ }
+ catch (Exception ex)
+ {
+ await logger.LogError(ex, "Error Testing SMTP Configuration");
+ AddModuleMessage(Localizer["Error Testing SMTP Configuration"], MessageType.Error);
+ }
+ }
+ else
+ {
+ AddModuleMessage(Localizer["You Must Specify The SMTP Host, Port, And Sender"], MessageType.Warning);
+ }
+
+ }
}
diff --git a/Oqtane.Client/Modules/Admin/Sites/Edit.razor b/Oqtane.Client/Modules/Admin/Sites/Edit.razor
index b1afc85c..6d28aee6 100644
--- a/Oqtane.Client/Modules/Admin/Sites/Edit.razor
+++ b/Oqtane.Client/Modules/Admin/Sites/Edit.razor
@@ -31,18 +31,11 @@
- ThemeChanged(e))">
+ ThemeChanged(e))">
@foreach (var theme in _themes)
{
- if (theme.TypeName == _themetype)
- {
-
- }
- else
- {
-
- }
+
}
|
diff --git a/Oqtane.Client/Modules/Admin/Sites/Index.razor b/Oqtane.Client/Modules/Admin/Sites/Index.razor
index 3a571cd3..9d028e1d 100644
--- a/Oqtane.Client/Modules/Admin/Sites/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Sites/Index.razor
@@ -22,7 +22,7 @@ else
|
|
- @context.Name |
+ @context.Name |
}
diff --git a/Oqtane.Client/Modules/Admin/ThemeCreator/Index.razor b/Oqtane.Client/Modules/Admin/ThemeCreator/Index.razor
new file mode 100644
index 00000000..cc15b1da
--- /dev/null
+++ b/Oqtane.Client/Modules/Admin/ThemeCreator/Index.razor
@@ -0,0 +1,186 @@
+@namespace Oqtane.Modules.Admin.ThemeCreator
+@inherits ModuleBase
+@inject NavigationManager NavigationManager
+@inject IThemeService ThemeService
+@inject IModuleService ModuleService
+@inject IPageModuleService PageModuleService
+@inject ISystemService SystemService
+@inject ISettingService SettingService
+@inject IStringLocalizer Localizer
+@using System.Text.RegularExpressions
+@using System.IO;
+
+@if (string.IsNullOrEmpty(_themename) && _systeminfo != null && _templates != null)
+{
+
+
+}
+else
+{
+
+}
+
+@code {
+ private string _themename = string.Empty;
+ private string _owner = string.Empty;
+ private string _theme = string.Empty;
+ private string _template = "-";
+ private string _reference = Constants.Version;
+ private string _location = string.Empty;
+
+ private Dictionary _systeminfo;
+ private List _templates;
+
+ public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
+
+ protected override async Task OnInitializedAsync()
+ {
+ try
+ {
+ _themename = SettingService.GetSetting(ModuleState.Settings, "ThemeName", "");
+ _systeminfo = await SystemService.GetSystemInfoAsync();
+ _templates = await ThemeService.GetThemeTemplatesAsync();
+
+ if (string.IsNullOrEmpty(_themename))
+ {
+ AddModuleMessage(Localizer["Please Note That The Theme Creator Is Only Intended To Be Used In A Development Environment"], MessageType.Info);
+ }
+ else
+ {
+ AddModuleMessage(Localizer["Once You Have Compiled The Theme And Restarted The Application You Can Activate The Theme Below"], MessageType.Info);
+ }
+ }
+ catch (Exception ex)
+ {
+ await logger.LogError(ex, "Error Loading Theme Creator");
+ }
+ }
+
+ private async Task CreateTheme()
+ {
+ try
+ {
+ if (IsValid(_owner) && IsValid(_theme) && _owner != _theme && _template != "-")
+ {
+ var theme = new Theme { Owner = _owner, Name = _theme, Template = _template, Version = _reference };
+ theme = await ThemeService.CreateThemeAsync(theme);
+
+ var settings = ModuleState.Settings;
+ SettingService.SetSetting(settings, "ThemeName", theme.ThemeName);
+ await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
+
+ GetLocation();
+
+ AddModuleMessage(Localizer["The Source Code For Your Theme Has Been Created At The Location Specified Below And Must Be Compiled In Order To Make It Functional. Once It Has Been Compiled You Must Restart Your Application To Apply These Changes.", NavigateUrl("admin/system")], MessageType.Success);
+ }
+ else
+ {
+ AddModuleMessage(Localizer["You Must Provide A Valid Owner Name And Theme Name ( ie. No Punctuation Or Spaces And The Values Cannot Be The Same ) And Choose A Template"], MessageType.Warning);
+ }
+ }
+ catch (Exception ex)
+ {
+ await logger.LogError(ex, "Error Creating Theme");
+ }
+ }
+
+ private async Task ActivateTheme()
+ {
+ try
+ {
+ if (!string.IsNullOrEmpty(_themename))
+ {
+ await PageModuleService.DeletePageModuleAsync(ModuleState.PageModuleId);
+ await ModuleService.DeleteModuleAsync(ModuleState.ModuleId);
+ NavigationManager.NavigateTo(NavigateUrl());
+ }
+ }
+ catch (Exception ex)
+ {
+ await logger.LogError(ex, "Error Activating Theme");
+ }
+ }
+
+ private bool IsValid(string name)
+ {
+ // must contain letters, underscores and digits and first character must be letter or underscore
+ return !string.IsNullOrEmpty(name) && Regex.IsMatch(name, "^[A-Za-z_][A-Za-z0-9_]*$");
+ }
+
+ private void TemplateChanged(ChangeEventArgs e)
+ {
+ _template = (string)e.Value;
+ GetLocation();
+ }
+
+ private void GetLocation()
+ {
+ _location = string.Empty;
+ if (_template != "-" && _systeminfo != null && _systeminfo.ContainsKey("serverpath"))
+ {
+ string[] path = _systeminfo["serverpath"].Split(Path.DirectorySeparatorChar);
+ _location = string.Join(Path.DirectorySeparatorChar, path, 0, path.Length - 2) +
+ Path.DirectorySeparatorChar + _owner + "." + _theme;
+ }
+ StateHasChanged();
+ }
+}
diff --git a/Oqtane.Client/Modules/Admin/ThemeCreator/ModuleInfo.cs b/Oqtane.Client/Modules/Admin/ThemeCreator/ModuleInfo.cs
new file mode 100644
index 00000000..621b0953
--- /dev/null
+++ b/Oqtane.Client/Modules/Admin/ThemeCreator/ModuleInfo.cs
@@ -0,0 +1,15 @@
+using Oqtane.Models;
+
+namespace Oqtane.Modules.Admin.ThemeCreator
+{
+ public class ModuleInfo : IModule
+ {
+ public ModuleDefinition ModuleDefinition => new ModuleDefinition
+ {
+ Name = "Theme Creator",
+ Description = "Enables software developers to quickly create themes by automating many of the initial theme creation tasks",
+ Version = "1.0.0",
+ Categories = "Developer"
+ };
+ }
+}
diff --git a/Oqtane.Client/Modules/Admin/Themes/View.razor b/Oqtane.Client/Modules/Admin/Themes/View.razor
index 2510759d..d6d4b4de 100644
--- a/Oqtane.Client/Modules/Admin/Themes/View.razor
+++ b/Oqtane.Client/Modules/Admin/Themes/View.razor
@@ -24,7 +24,7 @@
-
+
|
diff --git a/Oqtane.Client/Modules/Admin/UserProfile/Add.razor b/Oqtane.Client/Modules/Admin/UserProfile/Add.razor
index dcc96ff4..48959e80 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/Add.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/Add.razor
@@ -55,7 +55,7 @@
{
var notification = new Notification(PageState.Site.SiteId, PageState.User, user, subject, body, null);
notification = await NotificationService.AddNotificationAsync(notification);
- await logger.LogInformation("Notification Created {Notification}", notification);
+ await logger.LogInformation("Notification Created {NotificationId}", notification.NotificationId);
NavigationManager.NavigateTo(NavigateUrl());
}
else
diff --git a/Oqtane.Client/Modules/Admin/UserProfile/View.razor b/Oqtane.Client/Modules/Admin/UserProfile/View.razor
index ff9f3937..263a0345 100644
--- a/Oqtane.Client/Modules/Admin/UserProfile/View.razor
+++ b/Oqtane.Client/Modules/Admin/UserProfile/View.razor
@@ -183,7 +183,7 @@
{
var notification = new Notification(PageState.Site.SiteId, PageState.User, user, subject, body, notificationid);
notification = await NotificationService.AddNotificationAsync(notification);
- await logger.LogInformation("Notification Created {Notification}", notification);
+ await logger.LogInformation("Notification Created {NotificationId}", notification.NotificationId);
NavigationManager.NavigateTo(NavigateUrl());
}
else
diff --git a/Oqtane.Client/Modules/Admin/Users/Index.razor b/Oqtane.Client/Modules/Admin/Users/Index.razor
index 8ac788ee..e648083f 100644
--- a/Oqtane.Client/Modules/Admin/Users/Index.razor
+++ b/Oqtane.Client/Modules/Admin/Users/Index.razor
@@ -85,7 +85,7 @@ else
var user = await UserService.GetUserAsync(UserRole.UserId, PageState.Site.SiteId);
if (user != null)
{
- await UserService.DeleteUserAsync(user.UserId);
+ await UserService.DeleteUserAsync(user.UserId, PageState.Site.SiteId);
await logger.LogInformation("User Deleted {User}", UserRole.User);
StateHasChanged();
}
diff --git a/Oqtane.Client/Modules/Controls/FileManager.razor b/Oqtane.Client/Modules/Controls/FileManager.razor
index f4650202..90bc48c5 100644
--- a/Oqtane.Client/Modules/Controls/FileManager.razor
+++ b/Oqtane.Client/Modules/Controls/FileManager.razor
@@ -12,21 +12,14 @@
@if (ShowFolders || FolderId <= 0)
{
- FolderChanged(e))">
+ FolderChanged(e))">
@if (string.IsNullOrEmpty(Folder))
{
}
@foreach (Folder folder in _folders)
{
- if (folder.FolderId == FolderId)
- {
-
- }
- else
- {
-
- }
+
}
@@ -34,18 +27,11 @@
@if (ShowFiles)
{
- FileChanged(e))">
+ FileChanged(e))">
@foreach (File file in _files)
{
- if (file.FileId == FileId)
- {
-
- }
- else
- {
-
- }
+
}
diff --git a/Oqtane.Client/Modules/Controls/Pager.razor b/Oqtane.Client/Modules/Controls/Pager.razor
index 64f32728..c89b1301 100644
--- a/Oqtane.Client/Modules/Controls/Pager.razor
+++ b/Oqtane.Client/Modules/Controls/Pager.razor
@@ -1,4 +1,4 @@
-@namespace Oqtane.Modules.Controls
+@namespace Oqtane.Modules.Controls
@inherits ModuleControlBase
@typeparam TableItem
@@ -114,10 +114,10 @@
@code {
private int _pages = 0;
private int _page = 1;
- private int _maxItems;
- private int _maxPages;
- private int _startPage;
- private int _endPage;
+ private int _maxItems = 10;
+ private int _maxPages = 5;
+ private int _startPage = 0;
+ private int _endPage = 0;
[Parameter]
public string Format { get; set; }
@@ -172,24 +172,20 @@
}
}
- if (string.IsNullOrEmpty(PageSize))
- {
- _maxItems = 10;
- }
- else
+ if (!string.IsNullOrEmpty(PageSize))
{
_maxItems = int.Parse(PageSize);
}
- if (string.IsNullOrEmpty(DisplayPages))
- {
- _maxPages = 5;
- }
- else
+ if (!string.IsNullOrEmpty(DisplayPages))
{
_maxPages = int.Parse(DisplayPages);
}
+ _page = 1;
+ _startPage = 0;
+ _endPage = 0;
+
if (Items != null)
{
ItemList = Items.Skip((_page - 1) * _maxItems).Take(_maxItems);
diff --git a/Oqtane.Client/Resources/.gitkeep b/Oqtane.Client/Resources/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/Oqtane.Client/Services/FolderService.cs b/Oqtane.Client/Services/FolderService.cs
index 691f87ab..19f07946 100644
--- a/Oqtane.Client/Services/FolderService.cs
+++ b/Oqtane.Client/Services/FolderService.cs
@@ -35,13 +35,7 @@ namespace Oqtane.Services
public async Task GetFolderAsync(int siteId, [NotNull] string folderPath)
{
- if (!(folderPath.EndsWith(System.IO.Path.DirectorySeparatorChar) || folderPath.EndsWith(System.IO.Path.AltDirectorySeparatorChar)))
- {
- folderPath = Utilities.PathCombine(folderPath, System.IO.Path.DirectorySeparatorChar.ToString());
- }
-
var path = WebUtility.UrlEncode(folderPath);
-
return await GetJsonAsync($"{ApiUrl}/{siteId}/{path}");
}
diff --git a/Oqtane.Client/Services/Interfaces/IModuleDefinitionService.cs b/Oqtane.Client/Services/Interfaces/IModuleDefinitionService.cs
index e4b8ce64..55f8ad91 100644
--- a/Oqtane.Client/Services/Interfaces/IModuleDefinitionService.cs
+++ b/Oqtane.Client/Services/Interfaces/IModuleDefinitionService.cs
@@ -13,5 +13,6 @@ namespace Oqtane.Services
Task InstallModuleDefinitionsAsync();
Task DeleteModuleDefinitionAsync(int moduleDefinitionId, int siteId);
Task CreateModuleDefinitionAsync(ModuleDefinition moduleDefinition);
+ Task> GetModuleDefinitionTemplatesAsync();
}
}
diff --git a/Oqtane.Client/Services/Interfaces/IThemeService.cs b/Oqtane.Client/Services/Interfaces/IThemeService.cs
index b75a2988..609dd00c 100644
--- a/Oqtane.Client/Services/Interfaces/IThemeService.cs
+++ b/Oqtane.Client/Services/Interfaces/IThemeService.cs
@@ -1,4 +1,4 @@
-using Oqtane.Models;
+using Oqtane.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
@@ -12,5 +12,7 @@ namespace Oqtane.Services
List GetContainerControls(List themes, string themeName);
Task InstallThemesAsync();
Task DeleteThemeAsync(string themeName);
+ Task CreateThemeAsync(Theme theme);
+ Task> GetThemeTemplatesAsync();
}
}
diff --git a/Oqtane.Client/Services/Interfaces/IUserService.cs b/Oqtane.Client/Services/Interfaces/IUserService.cs
index eca072c5..b47b3481 100644
--- a/Oqtane.Client/Services/Interfaces/IUserService.cs
+++ b/Oqtane.Client/Services/Interfaces/IUserService.cs
@@ -1,4 +1,4 @@
-using Oqtane.Models;
+using Oqtane.Models;
using System.Threading.Tasks;
namespace Oqtane.Services
@@ -13,7 +13,7 @@ namespace Oqtane.Services
Task UpdateUserAsync(User user);
- Task DeleteUserAsync(int userId);
+ Task DeleteUserAsync(int userId, int siteId);
Task LoginUserAsync(User user, bool setCookie, bool isPersistent);
diff --git a/Oqtane.Client/Services/ModuleDefinitionService.cs b/Oqtane.Client/Services/ModuleDefinitionService.cs
index 87ae7e09..9f8984c0 100644
--- a/Oqtane.Client/Services/ModuleDefinitionService.cs
+++ b/Oqtane.Client/Services/ModuleDefinitionService.cs
@@ -53,5 +53,11 @@ namespace Oqtane.Services
{
return await PostJsonAsync($"{Apiurl}", moduleDefinition);
}
+
+ public async Task> GetModuleDefinitionTemplatesAsync()
+ {
+ List templates = await GetJsonAsync>($"{Apiurl}/templates");
+ return templates;
+ }
}
}
diff --git a/Oqtane.Client/Services/ThemeService.cs b/Oqtane.Client/Services/ThemeService.cs
index bd349b93..c58c7178 100644
--- a/Oqtane.Client/Services/ThemeService.cs
+++ b/Oqtane.Client/Services/ThemeService.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
@@ -50,5 +50,16 @@ namespace Oqtane.Services
{
await DeleteAsync($"{ApiUrl}/{themeName}");
}
+
+ public async Task CreateThemeAsync(Theme theme)
+ {
+ return await PostJsonAsync($"{ApiUrl}", theme);
+ }
+
+ public async Task> GetThemeTemplatesAsync()
+ {
+ List templates = await GetJsonAsync>($"{ApiUrl}/templates");
+ return templates;
+ }
}
}
diff --git a/Oqtane.Client/Services/UserService.cs b/Oqtane.Client/Services/UserService.cs
index 34aaaebb..3538ecb7 100644
--- a/Oqtane.Client/Services/UserService.cs
+++ b/Oqtane.Client/Services/UserService.cs
@@ -1,4 +1,4 @@
-using Oqtane.Shared;
+using Oqtane.Shared;
using Oqtane.Models;
using System.Net.Http;
using System.Threading.Tasks;
@@ -36,9 +36,9 @@ namespace Oqtane.Services
return await PutJsonAsync($"{Apiurl}/{user.UserId}", user);
}
- public async Task DeleteUserAsync(int userId)
+ public async Task DeleteUserAsync(int userId, int siteId)
{
- await DeleteAsync($"{Apiurl}/{userId}");
+ await DeleteAsync($"{Apiurl}/{userId}?siteid={siteId}");
}
public async Task LoginUserAsync(User user, bool setCookie, bool isPersistent)
diff --git a/Oqtane.Client/Themes/BlazorTheme/Container.razor b/Oqtane.Client/Themes/BlazorTheme/Containers/Container.razor
similarity index 100%
rename from Oqtane.Client/Themes/BlazorTheme/Container.razor
rename to Oqtane.Client/Themes/BlazorTheme/Containers/Container.razor
diff --git a/Oqtane.Client/Themes/BlazorTheme/Default.razor b/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor
similarity index 93%
rename from Oqtane.Client/Themes/BlazorTheme/Default.razor
rename to Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor
index bf62b5c5..dc723002 100644
--- a/Oqtane.Client/Themes/BlazorTheme/Default.razor
+++ b/Oqtane.Client/Themes/BlazorTheme/Themes/Default.razor
@@ -1,4 +1,4 @@
-@namespace Oqtane.Themes.BlazorTheme
+@namespace Oqtane.Themes.BlazorTheme
@inherits ThemeBase
diff --git a/Oqtane.Client/Themes/Controls/MenuItemsHorizontal.razor b/Oqtane.Client/Themes/Controls/MenuItemsHorizontal.razor
index 840fbf4e..5e75738b 100644
--- a/Oqtane.Client/Themes/Controls/MenuItemsHorizontal.razor
+++ b/Oqtane.Client/Themes/Controls/MenuItemsHorizontal.razor
@@ -8,15 +8,15 @@
{
if (childPage.PageId == PageState.Page.PageId)
{
-
-
- @childPage.Name (current)
+
+
+ @childPage.Name (current)
}
else
{
-
-
+
+
@childPage.Name
}
@@ -34,7 +34,7 @@ else
{
-
+
@childPage.Name (current)
@@ -43,7 +43,7 @@ else
{
-
+
@childPage.Name
@@ -55,7 +55,7 @@ else
{
-
+
@childPage.Name (current)
@@ -65,7 +65,7 @@ else
{
-
+
@childPage.Name
diff --git a/Oqtane.Client/Themes/Controls/MenuItemsVertical.razor b/Oqtane.Client/Themes/Controls/MenuItemsVertical.razor
index a27f9a7a..2f314ca0 100644
--- a/Oqtane.Client/Themes/Controls/MenuItemsVertical.razor
+++ b/Oqtane.Client/Themes/Controls/MenuItemsVertical.razor
@@ -9,7 +9,7 @@
{
-
+
@childPage.Name (current)
@@ -18,7 +18,7 @@
{
-
+
@childPage.Name
@@ -38,7 +38,7 @@ else
{
-
+
@childPage.Name (current)
@@ -47,7 +47,7 @@ else
{
-
+
@childPage.Name
diff --git a/Oqtane.Client/Themes/Controls/ModuleActions.razor b/Oqtane.Client/Themes/Controls/ModuleActions.razor
index dbc8c15b..2468bf89 100644
--- a/Oqtane.Client/Themes/Controls/ModuleActions.razor
+++ b/Oqtane.Client/Themes/Controls/ModuleActions.razor
@@ -2,33 +2,41 @@
@inherits ModuleActionsBase
@attribute [OqtaneIgnore]
-@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions))
+@if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User,PermissionNames.Edit, ModuleState.Permissions) && PageState.Action == Constants.DefaultAction)
{
}
diff --git a/Oqtane.Client/Themes/Controls/ModuleActionsBase.cs b/Oqtane.Client/Themes/Controls/ModuleActionsBase.cs
index b0e95901..3551b897 100644
--- a/Oqtane.Client/Themes/Controls/ModuleActionsBase.cs
+++ b/Oqtane.Client/Themes/Controls/ModuleActionsBase.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@@ -76,7 +76,7 @@ namespace Oqtane.Themes.Controls
{
if (pane != ModuleState.Pane)
{
- actionList.Add(new ActionViewModel {Icon = Icons.AccountLogin, Name = "Move To " + pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
+ actionList.Add(new ActionViewModel {Icon = Icons.AccountLogin, Name = pane + " Pane", Action = async (s, m) => await MoveToPane(s, pane, m)});
}
}
}
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Containers/DefaultNoTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/Containers/DefaultNoTitle.razor
new file mode 100644
index 00000000..b236edda
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Containers/DefaultNoTitle.razor
@@ -0,0 +1,10 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits ContainerBase
+
+
+
+
+
+@code {
+ public override string Name => "No Background Color - No Title";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Containers/DefaultTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/Containers/DefaultTitle.razor
new file mode 100644
index 00000000..0ba6af46
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Containers/DefaultTitle.razor
@@ -0,0 +1,20 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits ContainerBase
+
+
+
+@code {
+ public override string Name => "No Background Color - With Title";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Containers/PrimaryNoTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/Containers/PrimaryNoTitle.razor
new file mode 100644
index 00000000..7c7463f6
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Containers/PrimaryNoTitle.razor
@@ -0,0 +1,10 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits ContainerBase
+
+
+
+
+
+@code {
+ public override string Name => "Primary Background Color - No Title";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Containers/PrimaryTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/Containers/PrimaryTitle.razor
new file mode 100644
index 00000000..99cd8ff0
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Containers/PrimaryTitle.razor
@@ -0,0 +1,20 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits ContainerBase
+
+
+
+@code {
+ public override string Name => "Primary Background Color - With Title";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Containers/SecondaryNoTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/Containers/SecondaryNoTitle.razor
new file mode 100644
index 00000000..2a8a40cc
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Containers/SecondaryNoTitle.razor
@@ -0,0 +1,10 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits ContainerBase
+
+
+
+
+
+@code {
+ public override string Name => "Secondary Background Color - No Title";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Containers/SecondaryTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/Containers/SecondaryTitle.razor
new file mode 100644
index 00000000..5d033cec
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Containers/SecondaryTitle.razor
@@ -0,0 +1,20 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits ContainerBase
+
+
+
+@code {
+ public override string Name => "Secondary Background Color - With Title";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Layouts/MultiPane.razor b/Oqtane.Client/Themes/OqtaneTheme/Layouts/MultiPane.razor
new file mode 100644
index 00000000..128720ce
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Layouts/MultiPane.razor
@@ -0,0 +1,90 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits LayoutBase
+
+
+
+
+
+
+@code {
+ public override string Name => "Multiple Panes";
+
+ public override string Panes => "Content, Top Full Width,Top 100%,Left 50%,Right 50%,Left 33%,Center 33%,Right 33%,Left Outer 25%,Left Inner 25%,Right Inner 25%,Right Outer 25%,Left 25%,Center 50%,Right 25%,Left Sidebar 66%,Right Sidebar 33%,Left Sidebar 33%,Right Sidebar 66%,Bottom 100%,Bottom Full Width";
+}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Layouts/SinglePane.razor b/Oqtane.Client/Themes/OqtaneTheme/Layouts/SinglePane.razor
new file mode 100644
index 00000000..6f808141
--- /dev/null
+++ b/Oqtane.Client/Themes/OqtaneTheme/Layouts/SinglePane.razor
@@ -0,0 +1,16 @@
+@namespace Oqtane.Themes.OqtaneTheme
+@inherits LayoutBase
+
+
+
+@code {
+ public override string Name => "Single Pane";
+
+ public override string Panes => "Content";
+}
diff --git a/Oqtane.Client/Themes/OqtaneTheme/MultiPane.razor b/Oqtane.Client/Themes/OqtaneTheme/MultiPane.razor
deleted file mode 100644
index b40d1989..00000000
--- a/Oqtane.Client/Themes/OqtaneTheme/MultiPane.razor
+++ /dev/null
@@ -1,20 +0,0 @@
-@namespace Oqtane.Themes.OqtaneTheme
-@inherits LayoutBase
-
-
-
-
-
-@code {
- public override string Name => "Multiple Panes";
-
- public override string Panes => "Top,Left,Content,Right,Bottom";
-}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/NoTitle.razor b/Oqtane.Client/Themes/OqtaneTheme/NoTitle.razor
deleted file mode 100644
index 082bbe5a..00000000
--- a/Oqtane.Client/Themes/OqtaneTheme/NoTitle.razor
+++ /dev/null
@@ -1,13 +0,0 @@
-@namespace Oqtane.Themes.OqtaneTheme
-@inherits ContainerBase
-
- @if (PageState.EditMode)
- {
-
- }
-
-
-
-@code {
- public override string Name => "No Header";
-}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/SinglePane.razor b/Oqtane.Client/Themes/OqtaneTheme/SinglePane.razor
deleted file mode 100644
index 864209e1..00000000
--- a/Oqtane.Client/Themes/OqtaneTheme/SinglePane.razor
+++ /dev/null
@@ -1,12 +0,0 @@
-@namespace Oqtane.Themes.OqtaneTheme
-@inherits LayoutBase
-
-
-
-@code {
- public override string Name => "Single Pane";
-
- public override string Panes => "Content";
-}
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Default.razor b/Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor
similarity index 87%
rename from Oqtane.Client/Themes/OqtaneTheme/Default.razor
rename to Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor
index 1878ed09..8b566485 100644
--- a/Oqtane.Client/Themes/OqtaneTheme/Default.razor
+++ b/Oqtane.Client/Themes/OqtaneTheme/Themes/Default.razor
@@ -1,4 +1,4 @@
-@namespace Oqtane.Themes.OqtaneTheme
+@namespace Oqtane.Themes.OqtaneTheme
@inherits ThemeBase
@@ -8,16 +8,11 @@
-
+
@code {
- public override string Name => "Default";
+ public override string Name => "Default Theme";
public override string Panes => string.Empty;
diff --git a/Oqtane.Client/UI/ContainerBuilder.razor b/Oqtane.Client/UI/ContainerBuilder.razor
index 6992c34a..174f251f 100644
--- a/Oqtane.Client/UI/ContainerBuilder.razor
+++ b/Oqtane.Client/UI/ContainerBuilder.razor
@@ -1,11 +1,21 @@
@namespace Oqtane.UI
- @DynamicComponent
+ @if (_useadminborder)
+ {
+
+ @DynamicComponent
+
+ }
+ else
+ {
+ @DynamicComponent
+ }
@code {
private Module _moduleState;
+ private bool _useadminborder = false;
[CascadingParameter]
protected PageState PageState { get; set; }
@@ -24,6 +34,15 @@
container = (!string.IsNullOrEmpty(PageState.Site.AdminContainerType)) ? PageState.Site.AdminContainerType : Constants.DefaultAdminContainer;
}
+ if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
+ {
+ _useadminborder = true;
+ }
+ else
+ {
+ _useadminborder = false;
+ }
+
DynamicComponent = builder =>
{
Type containerType = Type.GetType(container);
diff --git a/Oqtane.Client/UI/Interop.cs b/Oqtane.Client/UI/Interop.cs
index 3964b070..b54fde6f 100644
--- a/Oqtane.Client/UI/Interop.cs
+++ b/Oqtane.Client/UI/Interop.cs
@@ -1,3 +1,4 @@
+using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System.Threading.Tasks;
@@ -232,5 +233,19 @@ namespace Oqtane.UI
return Task.CompletedTask;
}
}
+
+ public ValueTask FormValid(ElementReference form)
+ {
+ try
+ {
+ return _jsRuntime.InvokeAsync(
+ "Oqtane.Interop.formValid",
+ form);
+ }
+ catch
+ {
+ return new ValueTask(Task.FromResult(false));
+ }
+ }
}
}
diff --git a/Oqtane.Client/UI/Pane.razor b/Oqtane.Client/UI/Pane.razor
index 0c04ff94..fe71f45e 100644
--- a/Oqtane.Client/UI/Pane.razor
+++ b/Oqtane.Client/UI/Pane.razor
@@ -6,7 +6,7 @@
@if (_useadminborder)
{
-
+
@((MarkupString)_panetitle)
@DynamicComponent
@@ -18,7 +18,6 @@ else
@code {
private bool _useadminborder = false;
- private string _paneadminborder = "container";
private string _panetitle = "";
[CascadingParameter]
@@ -31,15 +30,14 @@ else
protected override void OnParametersSet()
{
- if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && Name != PaneNames.Admin)
+ if (PageState.EditMode && UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, PageState.Page.Permissions) && PageState.Action == Constants.DefaultAction)
{
_useadminborder = true;
- _paneadminborder = "app-pane-admin-border";
_panetitle = " " + Name + " Pane ";
}
else
{
- _paneadminborder = "container";
+ _useadminborder = false;
_panetitle = "";
}
@@ -130,4 +128,4 @@ else
builder.SetKey(module.PageModuleId);
builder.CloseComponent();
}
-}
\ No newline at end of file
+}
diff --git a/Oqtane.Client/UI/SiteRouter.razor b/Oqtane.Client/UI/SiteRouter.razor
index 6b42f15b..70bda7df 100644
--- a/Oqtane.Client/UI/SiteRouter.razor
+++ b/Oqtane.Client/UI/SiteRouter.razor
@@ -80,7 +80,7 @@
var urlparameters = string.Empty;
var editmode = false;
var reload = Reload.None;
- var lastsyncdate = DateTime.UtcNow;
+ var lastsyncdate = DateTime.UtcNow.AddHours(-1);
var runtime = GetRuntime();
Uri uri = new Uri(_absoluteUri);
@@ -107,9 +107,14 @@
SiteState.Alias = alias; // set state for services
lastsyncdate = alias.SyncDate;
- // process any sync events for site
+ // process any sync events
if (reload != Reload.Site && alias.SyncEvents.Any())
{
+ // if running on WebAssembly reload the client application if the server application was restarted
+ if (runtime == Shared.Runtime.WebAssembly && PageState != null && alias.SyncEvents.Exists(item => item.TenantId == -1))
+ {
+ NavigationManager.NavigateTo(_absoluteUri + (!_absoluteUri.Contains("?") ? "?" : "&") + "reload", true);
+ }
if (alias.SyncEvents.Exists(item => item.EntityName == EntityNames.Site && item.EntityId == alias.SiteId))
{
reload = Reload.Site;
diff --git a/Oqtane.Client/wwwroot/Themes/Siliqon.TestTheme/Theme.css b/Oqtane.Client/wwwroot/Themes/Siliqon.TestTheme/Theme.css
new file mode 100644
index 00000000..93d1b672
--- /dev/null
+++ b/Oqtane.Client/wwwroot/Themes/Siliqon.TestTheme/Theme.css
@@ -0,0 +1,83 @@
+/* Oqtane Styles */
+
+body {
+ padding-top: 7rem;
+}
+
+.controls {
+ z-index: 2000;
+ padding-top: 15px;
+ padding-bottom: 15px;
+ margin-right: 10px;
+}
+
+.app-menu .nav-item {
+ font-size: 0.9rem;
+ padding-bottom: 0.5rem;
+}
+
+.app-menu .nav-item a {
+ border-radius: 4px;
+ height: 3rem;
+ display: flex;
+ align-items: center;
+ line-height: 3rem;
+}
+
+.app-menu .nav-item a.active {
+ background-color: rgba(255,255,255,0.25);
+ color: white;
+}
+
+.app-menu .nav-item a:hover {
+ background-color: rgba(255,255,255,0.1);
+ color: white;
+}
+
+.app-menu .nav-link .oi {
+ width: 1.5rem;
+ font-size: 1.1rem;
+ vertical-align: text-top;
+ top: -2px;
+}
+
+.navbar-toggler {
+ background-color: rgba(255, 255, 255, 0.1);
+ margin-left: auto;
+}
+
+div.app-moduleactions a.dropdown-toggle, div.app-moduleactions div.dropdown-menu {
+ color:#ffffff;
+}
+
+@media (max-width: 767px) {
+
+ .app-menu {
+ width: 100%
+ }
+
+ .navbar {
+ position: fixed;
+ top: 60px;
+ width: 100%;
+ }
+
+ .controls {
+ height: 60px;
+ top: 15px;
+ position: fixed;
+ top: 0px;
+ width: 100%;
+ background-color: rgb(0, 0, 0);
+ }
+
+ .controls-group {
+ float: right;
+ margin-right: 25px;
+ }
+
+ .content {
+ position: relative;
+ top: 60px;
+ }
+}
diff --git a/Oqtane.Server/Controllers/FolderController.cs b/Oqtane.Server/Controllers/FolderController.cs
index aad20a77..a3fcb03a 100644
--- a/Oqtane.Server/Controllers/FolderController.cs
+++ b/Oqtane.Server/Controllers/FolderController.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.IO;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
@@ -69,6 +69,10 @@ namespace Oqtane.Controllers
public Folder GetByPath(int siteId, string path)
{
var folderPath = WebUtility.UrlDecode(path);
+ if (!(folderPath.EndsWith(System.IO.Path.DirectorySeparatorChar) || folderPath.EndsWith(System.IO.Path.AltDirectorySeparatorChar)))
+ {
+ folderPath = Utilities.PathCombine(folderPath, System.IO.Path.DirectorySeparatorChar.ToString());
+ }
Folder folder = _folders.GetFolder(siteId, folderPath);
if (folder != null)
if (_userPermissions.IsAuthorized(User, PermissionNames.Browse, folder.Permissions))
diff --git a/Oqtane.Server/Controllers/InstallationController.cs b/Oqtane.Server/Controllers/InstallationController.cs
index cac15728..2d8491d6 100644
--- a/Oqtane.Server/Controllers/InstallationController.cs
+++ b/Oqtane.Server/Controllers/InstallationController.cs
@@ -55,8 +55,7 @@ namespace Oqtane.Controllers
[HttpGet("installed")]
public Installation IsInstalled()
{
- bool isInstalled = _databaseManager.IsInstalled();
- return new Installation {Success = isInstalled, Message = string.Empty};
+ return _databaseManager.IsInstalled();
}
[HttpGet("upgrade")]
@@ -130,7 +129,14 @@ namespace Oqtane.Controllers
var instance = Activator.CreateInstance(type) as IModule;
foreach (string name in instance.ModuleDefinition.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
- if (!list.Contains(name)) list.Insert(0, name);
+ if (System.IO.File.Exists(Path.Combine(binFolder, name + ".dll")))
+ {
+ if (!list.Contains(name)) list.Insert(0, name);
+ }
+ else
+ {
+ Console.WriteLine("Module " + instance.ModuleDefinition.ModuleDefinitionName + " dependency " + name + ".dll does not exist");
+ }
}
}
foreach (var type in assembly.GetTypes().Where(item => item.GetInterfaces().Contains(typeof(ITheme))))
@@ -138,7 +144,14 @@ namespace Oqtane.Controllers
var instance = Activator.CreateInstance(type) as ITheme;
foreach (string name in instance.Theme.Dependencies.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
- if (!list.Contains(name)) list.Insert(0, name);
+ if (System.IO.File.Exists(Path.Combine(binFolder, name + ".dll")))
+ {
+ if (!list.Contains(name)) list.Insert(0, name);
+ }
+ else
+ {
+ Console.WriteLine("Theme " + instance.Theme.ThemeName + " dependency " + name + ".dll does not exist" );
+ }
}
}
}
diff --git a/Oqtane.Server/Controllers/ModuleDefinitionController.cs b/Oqtane.Server/Controllers/ModuleDefinitionController.cs
index f417ce33..b9d7d47f 100644
--- a/Oqtane.Server/Controllers/ModuleDefinitionController.cs
+++ b/Oqtane.Server/Controllers/ModuleDefinitionController.cs
@@ -13,8 +13,6 @@ using Oqtane.Repository;
using Oqtane.Security;
using System;
using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Configuration;
-using System.Xml.Linq;
using System.Text.Json;
namespace Oqtane.Controllers
@@ -174,7 +172,21 @@ namespace Oqtane.Controllers
}
}
- // POST api/ ?moduleid=x
+ // GET: api//templates
+ [HttpGet("templates")]
+ [Authorize(Roles = RoleNames.Host)]
+ public List GetTemplates()
+ {
+ var templates = new List();
+ string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", Path.DirectorySeparatorChar.ToString());
+ foreach (string directory in Directory.GetDirectories(templatePath))
+ {
+ templates.Add(directory.Replace(templatePath, ""));
+ }
+ return templates;
+ }
+
+ // POST api/
[HttpPost]
[Authorize(Roles = RoleNames.Host)]
public ModuleDefinition Post([FromBody] ModuleDefinition moduleDefinition)
@@ -185,30 +197,12 @@ namespace Oqtane.Controllers
DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", moduleDefinition.Template,Path.DirectorySeparatorChar.ToString());
- if (moduleDefinition.Template == "internal")
- {
- rootPath = Utilities.PathCombine(rootFolder.FullName,Path.DirectorySeparatorChar.ToString());
- moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + ", Oqtane.Client";
- moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, Oqtane.Server";
- }
- else
- {
- rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name,Path.DirectorySeparatorChar.ToString());
- moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + ", " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Client.Oqtane";
- moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Server.Oqtane";
- }
+ rootPath = Utilities.PathCombine(rootFolder.Parent.FullName , moduleDefinition.Owner + "." + moduleDefinition.Name,Path.DirectorySeparatorChar.ToString());
+ moduleDefinition.ModuleDefinitionName = moduleDefinition.Owner + "." + moduleDefinition.Name + ", " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Client.Oqtane";
+ moduleDefinition.ServerManagerType = moduleDefinition.Owner + "." + moduleDefinition.Name + ".Manager." + moduleDefinition.Name + "Manager, " + moduleDefinition.Owner + "." + moduleDefinition.Name + ".Server.Oqtane";
ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, moduleDefinition);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Module Definition Created {ModuleDefinition}", moduleDefinition);
-
- if (moduleDefinition.Template == "internal")
- {
- // add embedded resources to project file
- List resources = new List();
- resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + ".1.0.0.sql"));
- resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + ".Uninstall.sql"));
- EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources);
- }
}
return moduleDefinition;
@@ -269,19 +263,5 @@ namespace Oqtane.Controllers
}
}
}
-
- private void EmbedResourceFiles(string projectfile, List 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);
- }
}
}
diff --git a/Oqtane.Server/Controllers/NotificationController.cs b/Oqtane.Server/Controllers/NotificationController.cs
index 5c73eb78..8fbb4872 100644
--- a/Oqtane.Server/Controllers/NotificationController.cs
+++ b/Oqtane.Server/Controllers/NotificationController.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Oqtane.Enums;
@@ -65,7 +65,7 @@ namespace Oqtane.Controllers
if (IsAuthorized(notification.FromUserId))
{
notification = _notifications.AddNotification(notification);
- _logger.Log(LogLevel.Information, this, LogFunction.Create, "Notification Added {Notification}", notification);
+ _logger.Log(LogLevel.Information, this, LogFunction.Create, "Notification Added {NotificationId}", notification.NotificationId);
}
return notification;
}
@@ -78,7 +78,7 @@ namespace Oqtane.Controllers
if (IsAuthorized(notification.FromUserId))
{
notification = _notifications.UpdateNotification(notification);
- _logger.Log(LogLevel.Information, this, LogFunction.Update, "Notification Updated {Folder}", notification);
+ _logger.Log(LogLevel.Information, this, LogFunction.Update, "Notification Updated {NotificationId}", notification.NotificationId);
}
return notification;
}
diff --git a/Oqtane.Server/Controllers/ThemeController.cs b/Oqtane.Server/Controllers/ThemeController.cs
index 851aeb68..6b2f7892 100644
--- a/Oqtane.Server/Controllers/ThemeController.cs
+++ b/Oqtane.Server/Controllers/ThemeController.cs
@@ -103,5 +103,91 @@ namespace Oqtane.Controllers
}
}
+ // GET: api//templates
+ [HttpGet("templates")]
+ [Authorize(Roles = RoleNames.Host)]
+ public List GetTemplates()
+ {
+ var templates = new List();
+ string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Themes", "Templates", Path.DirectorySeparatorChar.ToString());
+ foreach (string directory in Directory.GetDirectories(templatePath))
+ {
+ templates.Add(directory.Replace(templatePath, ""));
+ }
+ return templates;
+ }
+
+ // POST api/
+ [HttpPost]
+ [Authorize(Roles = RoleNames.Host)]
+ public Theme Post([FromBody] Theme theme)
+ {
+ if (ModelState.IsValid)
+ {
+ string rootPath;
+ DirectoryInfo rootFolder = Directory.GetParent(_environment.ContentRootPath);
+ string templatePath = Utilities.PathCombine(_environment.WebRootPath, "Themes", "Templates", theme.Template, Path.DirectorySeparatorChar.ToString());
+
+ rootPath = Utilities.PathCombine(rootFolder.Parent.FullName, theme.Owner + "." + theme.Name, Path.DirectorySeparatorChar.ToString());
+ theme.ThemeName = theme.Owner + "." + theme.Name + ", " + theme.Owner + "." + theme.Name + ".Client.Oqtane";
+
+ ProcessTemplatesRecursively(new DirectoryInfo(templatePath), rootPath, rootFolder.Name, templatePath, theme);
+ _logger.Log(LogLevel.Information, this, LogFunction.Create, "Theme Created {Theme}", theme);
+ }
+
+ return theme;
+ }
+
+ private void ProcessTemplatesRecursively(DirectoryInfo current, string rootPath, string rootFolder, string templatePath, Theme theme)
+ {
+ // process folder
+ string folderPath = Utilities.PathCombine(rootPath, current.FullName.Replace(templatePath, ""));
+ folderPath = folderPath.Replace("[Owner]", theme.Owner);
+ folderPath = folderPath.Replace("[Theme]", theme.Name);
+ if (!Directory.Exists(folderPath))
+ {
+ Directory.CreateDirectory(folderPath);
+ }
+
+ FileInfo[] files = current.GetFiles("*.*");
+ if (files != null)
+ {
+ foreach (FileInfo file in files)
+ {
+ // process file
+ string filePath = Path.Combine(folderPath, file.Name);
+ filePath = filePath.Replace("[Owner]", theme.Owner);
+ filePath = filePath.Replace("[Theme]", theme.Name);
+
+ string text = System.IO.File.ReadAllText(file.FullName);
+ text = text.Replace("[Owner]", theme.Owner);
+ text = text.Replace("[Theme]", theme.Name);
+ text = text.Replace("[RootPath]", rootPath);
+ text = text.Replace("[RootFolder]", rootFolder);
+ text = text.Replace("[Folder]", folderPath);
+ text = text.Replace("[File]", Path.GetFileName(filePath));
+ if (theme.Version == "local")
+ {
+ text = text.Replace("[FrameworkVersion]", Constants.Version);
+ text = text.Replace("[ClientReference]", "..\\..\\oqtane.framework\\Oqtane.Server\\bin\\Debug\\net5.0\\Oqtane.Client.dll");
+ text = text.Replace("[SharedReference]", "..\\..\\oqtane.framework\\Oqtane.Server\\bin\\Debug\\net5.0\\Oqtane.Shared.dll");
+ }
+ else
+ {
+ text = text.Replace("[FrameworkVersion]", theme.Version);
+ text = text.Replace("[ClientReference]", "");
+ text = text.Replace("[SharedReference]", "");
+ }
+ System.IO.File.WriteAllText(filePath, text);
+ }
+
+ DirectoryInfo[] folders = current.GetDirectories();
+
+ foreach (DirectoryInfo folder in folders.Reverse())
+ {
+ ProcessTemplatesRecursively(folder, rootPath, rootFolder, templatePath, theme);
+ }
+ }
+ }
}
}
diff --git a/Oqtane.Server/Controllers/UserController.cs b/Oqtane.Server/Controllers/UserController.cs
index 9819994b..4d3f1abc 100644
--- a/Oqtane.Server/Controllers/UserController.cs
+++ b/Oqtane.Server/Controllers/UserController.cs
@@ -111,7 +111,6 @@ namespace Oqtane.Controllers
return null;
}
- //TODO shoud be moved to another layer
private async Task CreateUser(User user)
{
User newUser = null;
@@ -261,18 +260,50 @@ namespace Oqtane.Controllers
// DELETE api//5?siteid=x
[HttpDelete("{id}")]
[Authorize(Roles = RoleNames.Admin)]
- public async Task Delete(int id)
+ public async Task Delete(int id, string siteid)
{
- IdentityUser identityuser = await _identityUserManager.FindByNameAsync(_users.GetUser(id).Username);
-
- if (identityuser != null)
+ User user = _users.GetUser(id);
+ if (user != null)
{
- var result = await _identityUserManager.DeleteAsync(identityuser);
-
- if (result != null)
+ // remove user roles for site
+ foreach (UserRole userrole in _userRoles.GetUserRoles(user.UserId, Int32.Parse(siteid)).ToList())
{
- _users.DeleteUser(id);
- _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Deleted {UserId}", id);
+ _userRoles.DeleteUserRole(userrole.UserRoleId);
+ _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Role Deleted {UserRole}", userrole);
+ }
+
+ // remove user folder for site
+ var folder = _folders.GetFolder(Int32.Parse(siteid), Utilities.PathCombine("Users", user.UserId.ToString(), Path.DirectorySeparatorChar.ToString()));
+ if (folder != null)
+ {
+ if (Directory.Exists(_folders.GetFolderPath(folder)))
+ {
+ Directory.Delete(_folders.GetFolderPath(folder), true);
+ }
+ _folders.DeleteFolder(folder.FolderId);
+ _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Folder Deleted {Folder}", folder);
+ }
+
+ // delete user if they are not a member of any other sites
+ if (!_userRoles.GetUserRoles(user.UserId, -1).Any())
+ {
+ // get identity user
+ IdentityUser identityuser = await _identityUserManager.FindByNameAsync(user.Username);
+ if (identityuser != null)
+ {
+ // delete identity user
+ var result = await _identityUserManager.DeleteAsync(identityuser);
+ if (result != null)
+ {
+ // delete user
+ _users.DeleteUser(user.UserId);
+ _logger.Log(LogLevel.Information, this, LogFunction.Delete, "User Deleted {UserId}", user.UserId);
+ }
+ else
+ {
+ _logger.Log(LogLevel.Error, this, LogFunction.Delete, "Error Deleting User {UserId}", user.UserId, result.ToString());
+ }
+ }
}
}
}
diff --git a/Oqtane.Server/Infrastructure/DatabaseManager.cs b/Oqtane.Server/Infrastructure/DatabaseManager.cs
index 18dc820f..99e67e57 100644
--- a/Oqtane.Server/Infrastructure/DatabaseManager.cs
+++ b/Oqtane.Server/Infrastructure/DatabaseManager.cs
@@ -37,27 +37,30 @@ namespace Oqtane.Infrastructure
_cache = cache;
}
- public bool IsInstalled()
+ public Installation IsInstalled()
{
- var defaultConnectionString = NormalizeConnectionString(_config.GetConnectionString(SettingKeys.ConnectionStringKey));
- var result = !string.IsNullOrEmpty(defaultConnectionString);
- if (result)
+ var result = new Installation { Success = false, Message = string.Empty };
+ if (!string.IsNullOrEmpty(_config.GetConnectionString(SettingKeys.ConnectionStringKey)))
{
+ result.Success = true;
using (var scope = _serviceScopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService();
- result = db.Database.CanConnect();
- if (result)
+ if (db.Database.CanConnect())
{
try
{
- result = db.Tenant.Any();
+ var provisioned = db.Tenant.Any();
}
catch
{
- result = false;
+ result.Message = "Master Database Not Installed Correctly";
}
}
+ else
+ {
+ result.Message = "Cannot Connect To Master Database";
+ }
}
}
return result;
@@ -84,7 +87,8 @@ namespace Oqtane.Infrastructure
IsNewTenant = false
};
- if (!IsInstalled())
+ var installation = IsInstalled();
+ if (!installation.Success)
{
install.Aliases = GetInstallationConfig(SettingKeys.DefaultAliasKey, string.Empty);
install.HostPassword = GetInstallationConfig(SettingKeys.HostPasswordKey, string.Empty);
@@ -107,6 +111,14 @@ namespace Oqtane.Infrastructure
install.ConnectionString = "";
}
}
+ else
+ {
+ if (!string.IsNullOrEmpty(installation.Message))
+ {
+ // problem with prior installation
+ install.ConnectionString = "";
+ }
+ }
}
else
{
diff --git a/Oqtane.Server/Infrastructure/Interfaces/IDatabaseManager.cs b/Oqtane.Server/Infrastructure/Interfaces/IDatabaseManager.cs
index ffb0ff9c..6257db16 100644
--- a/Oqtane.Server/Infrastructure/Interfaces/IDatabaseManager.cs
+++ b/Oqtane.Server/Infrastructure/Interfaces/IDatabaseManager.cs
@@ -1,11 +1,11 @@
-using Oqtane.Models;
+using Oqtane.Models;
using Oqtane.Shared;
namespace Oqtane.Infrastructure
{
public interface IDatabaseManager
{
- bool IsInstalled();
+ Installation IsInstalled();
Installation Install();
Installation Install(InstallConfig install);
}
diff --git a/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs b/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs
index e21629d8..2c7f6603 100644
--- a/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs
+++ b/Oqtane.Server/Infrastructure/SiteTemplates/DefaultSiteTemplate.cs
@@ -48,7 +48,7 @@ namespace Oqtane.SiteTemplates
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
}.EncodePermissions() ,
PageTemplateModules = new List {
- new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "Welcome To Oqtane...", Pane = "Content",
+ new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "Welcome To Oqtane...", Pane = PaneNames.Admin,
ModulePermissions = new List {
new Permission(PermissionNames.View, RoleNames.Everyone, true),
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -70,7 +70,7 @@ namespace Oqtane.SiteTemplates
"The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. " +
"THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. "
},
- new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "Secure Content", Pane = "Content",
+ new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "Secure Content", Pane = PaneNames.Admin,
ModulePermissions = new List {
new Permission(PermissionNames.View, RoleNames.Registered, true),
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -94,7 +94,7 @@ namespace Oqtane.SiteTemplates
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
}.EncodePermissions(),
PageTemplateModules = new List {
- new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "Secure Content", Pane = "Content",
+ new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "Secure Content", Pane = PaneNames.Admin,
ModulePermissions = new List {
new Permission(PermissionNames.View, RoleNames.Registered, true),
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -118,7 +118,7 @@ namespace Oqtane.SiteTemplates
new Permission(PermissionNames.Edit, RoleNames.Admin, true)
}.EncodePermissions(),
PageTemplateModules = new List {
- new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "My Page", Pane = "Content",
+ new PageTemplateModule { ModuleDefinitionName = "Oqtane.Modules.HtmlText, Oqtane.Client", Title = "My Page", Pane = PaneNames.Admin,
ModulePermissions = new List {
new Permission(PermissionNames.View, RoleNames.Everyone, true),
new Permission(PermissionNames.View, RoleNames.Admin, true),
diff --git a/Oqtane.Server/Infrastructure/SyncManager.cs b/Oqtane.Server/Infrastructure/SyncManager.cs
index f41c01b0..d70cc456 100644
--- a/Oqtane.Server/Infrastructure/SyncManager.cs
+++ b/Oqtane.Server/Infrastructure/SyncManager.cs
@@ -1,4 +1,4 @@
-using Oqtane.Models;
+using Oqtane.Models;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -17,7 +17,7 @@ namespace Oqtane.Infrastructure
public List GetSyncEvents(int tenantId, DateTime lastSyncDate)
{
- return SyncEvents.Where(item => item.TenantId == tenantId && item.ModifiedOn >= lastSyncDate).ToList();
+ return SyncEvents.Where(item => (item.TenantId == tenantId || item.TenantId == -1) && item.ModifiedOn >= lastSyncDate).ToList();
}
public void AddSyncEvent(int tenantId, string entityName, int entityId)
diff --git a/Oqtane.Server/Infrastructure/UpgradeManager.cs b/Oqtane.Server/Infrastructure/UpgradeManager.cs
index 0344de6e..fc435f10 100644
--- a/Oqtane.Server/Infrastructure/UpgradeManager.cs
+++ b/Oqtane.Server/Infrastructure/UpgradeManager.cs
@@ -1,9 +1,10 @@
-using Microsoft.Extensions.DependencyInjection;
-using Oqtane.Extensions;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Extensions.DependencyInjection;
using Oqtane.Models;
using Oqtane.Repository;
using Oqtane.Shared;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
namespace Oqtane.Infrastructure
@@ -12,80 +13,105 @@ namespace Oqtane.Infrastructure
{
private readonly IAliasRepository _aliases;
private readonly IServiceScopeFactory _serviceScopeFactory;
+ private readonly IWebHostEnvironment _environment;
- public UpgradeManager(IAliasRepository aliases, IServiceScopeFactory serviceScopeFactory)
+ public UpgradeManager(IAliasRepository aliases, IServiceScopeFactory serviceScopeFactory, IWebHostEnvironment environment)
{
_aliases = aliases;
_serviceScopeFactory = serviceScopeFactory;
+ _environment = environment;
}
public void Upgrade(Tenant tenant, string version)
{
- // core framework upgrade logic - note that you can check if current tenant is Master if you only want to execute logic once
- var pageTemplates = new List();
-
- switch (version)
+ // core framework upgrade logic - executed for every tenant
+ using (var scope = _serviceScopeFactory.CreateScope())
{
- case "0.9.0":
- // add a page to all existing sites on upgrade
+ // set SiteState based on tenant
+ var siteState = scope.ServiceProvider.GetRequiredService();
+ siteState.Alias = new Alias { TenantId = tenant.TenantId };
- //pageTemplates.Add(new PageTemplate
- //{
- // Name = "Test",
- // Parent = "",
- // Path = "test",
- // Icon = Icons.Badge,
- // IsNavigation = true,
- // IsPersonalizable = false,
- // EditMode = false,
- // PagePermissions = new List
- // {
- // new Permission(PermissionNames.View, RoleNames.Admin, true),
- // new Permission(PermissionNames.View, RoleNames.Everyone, true),
- // new Permission(PermissionNames.Edit, RoleNames.Admin, true)
- // }.EncodePermissions(),
- // PageTemplateModules = new List
- // {
- // new PageTemplateModule
- // {
- // ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Login.Index).ToModuleDefinitionName(), Title = "Test", Pane = "Content",
- // ModulePermissions = new List
- // {
- // new Permission(PermissionNames.View, RoleNames.Admin, true),
- // new Permission(PermissionNames.View, RoleNames.Everyone, true),
- // new Permission(PermissionNames.Edit, RoleNames.Admin, true)
- // }.EncodePermissions(),
- // Content = ""
- // }
- // }
- //});
- CreateSitePages(tenant, pageTemplates);
- break;
+ switch (version)
+ {
+ case "1.0.0":
+ Upgrade_1_0_0(tenant, scope);
+ break;
+ case "2.0.2":
+ Upgrade_2_0_2(tenant, scope);
+ break;
+ }
}
}
- private void CreateSitePages(Tenant tenant, List pageTemplates)
+ private void Upgrade_1_0_0(Tenant tenant, IServiceScope scope)
+ {
+ var pageTemplates = new List();
+
+ // **Note: this code is commented out on purpose - it provides an example of how to programmatically add a page to all existing sites on upgrade
+
+ //pageTemplates.Add(new PageTemplate
+ //{
+ // Name = "Test",
+ // Parent = "",
+ // Path = "test",
+ // Icon = Icons.Badge,
+ // IsNavigation = true,
+ // IsPersonalizable = false,
+ // EditMode = false,
+ // PagePermissions = new List
+ // {
+ // new Permission(PermissionNames.View, RoleNames.Admin, true),
+ // new Permission(PermissionNames.View, RoleNames.Everyone, true),
+ // new Permission(PermissionNames.Edit, RoleNames.Admin, true)
+ // }.EncodePermissions(),
+ // PageTemplateModules = new List
+ // {
+ // new PageTemplateModule
+ // {
+ // ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Login.Index).ToModuleDefinitionName(), Title = "Test", Pane = "Content",
+ // ModulePermissions = new List
+ // {
+ // new Permission(PermissionNames.View, RoleNames.Admin, true),
+ // new Permission(PermissionNames.View, RoleNames.Everyone, true),
+ // new Permission(PermissionNames.Edit, RoleNames.Admin, true)
+ // }.EncodePermissions(),
+ // Content = ""
+ // }
+ // }
+ //});
+
+ CreateSitePages(scope, pageTemplates);
+ }
+
+ private void Upgrade_2_0_2(Tenant tenant, IServiceScope scope)
+ {
+ if (tenant.Name == TenantNames.Master)
+ {
+ // remove Internal module template files as they are no longer supported
+ var internalTemplatePath = Utilities.PathCombine(_environment.WebRootPath, "Modules", "Templates", "Internal", Path.DirectorySeparatorChar.ToString());
+ if (Directory.Exists(internalTemplatePath))
+ {
+ Directory.Delete(internalTemplatePath, true);
+ }
+ }
+
+ // initialize SiteGuid
+ var sites = scope.ServiceProvider.GetRequiredService();
+ foreach (Site site in sites.GetSites().ToList())
+ {
+ site.SiteGuid = System.Guid.NewGuid().ToString();
+ sites.UpdateSite(site);
+ }
+ }
+
+ private void CreateSitePages(IServiceScope scope, List pageTemplates)
{
if (pageTemplates.Count != 0)
{
- var processed = new List();
- foreach (Alias alias in _aliases.GetAliases().Where(item => item.TenantId == tenant.TenantId))
+ var sites = scope.ServiceProvider.GetRequiredService();
+ foreach (Site site in sites.GetSites().ToList())
{
- if (!processed.Exists(item => item.SiteId == alias.SiteId))
- {
- using (var scope = _serviceScopeFactory.CreateScope())
- {
- var siteState = scope.ServiceProvider.GetRequiredService();
- siteState.Alias = alias;
- var sites = scope.ServiceProvider.GetRequiredService();
- var site = sites.GetSite(alias.SiteId);
- if (site != null)
- {
- sites.CreatePages(site, pageTemplates);
- }
- processed.Add(site);
- }
- }
+ sites.CreatePages(site, pageTemplates);
}
}
}
diff --git a/Oqtane.Server/Pages/_Host.cshtml b/Oqtane.Server/Pages/_Host.cshtml
index cf2d69f0..74b13c99 100644
--- a/Oqtane.Server/Pages/_Host.cshtml
+++ b/Oqtane.Server/Pages/_Host.cshtml
@@ -1,4 +1,4 @@
-@page "/"
+@page "/"
@namespace Oqtane.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@using Microsoft.Extensions.Configuration
@@ -15,6 +15,7 @@
+
@Html.Raw(@Model.HeadResources)
@@ -35,6 +36,13 @@
🗙
+ @if (Model.Message != "")
+ {
+
+ @Model.Message
+
+ }
+
@if (Configuration.GetSection("Runtime").Value == "WebAssembly")
diff --git a/Oqtane.Server/Pages/_Host.cshtml.cs b/Oqtane.Server/Pages/_Host.cshtml.cs
index 4dc9cb7e..156b5fac 100644
--- a/Oqtane.Server/Pages/_Host.cshtml.cs
+++ b/Oqtane.Server/Pages/_Host.cshtml.cs
@@ -39,6 +39,7 @@ namespace Oqtane.Pages
public string HeadResources = "";
public string BodyResources = "";
+ public string Message = "";
public void OnGet()
{
@@ -54,20 +55,28 @@ namespace Oqtane.Pages
if (HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName] == null && !string.IsNullOrEmpty(_configuration.GetConnectionString("DefaultConnection")))
{
var uri = new Uri(Request.GetDisplayUrl());
- var alias = _aliases.GetAlias(uri.Authority + "/" + uri.LocalPath.Substring(1));
- _state.Alias = alias;
-
- // set default language for site if the culture is not supported
- var languages = _languages.GetLanguages(alias.SiteId);
- if (languages.Any() && languages.All(l => l.Code != CultureInfo.CurrentUICulture.Name))
+ var hostname = uri.Authority + "/" + uri.LocalPath.Substring(1);
+ var alias = _aliases.GetAlias(hostname);
+ if (alias != null)
{
- var defaultLanguage = languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First();
+ _state.Alias = alias;
- SetLocalizationCookie(defaultLanguage.Code);
+ // set default language for site if the culture is not supported
+ var languages = _languages.GetLanguages(alias.SiteId);
+ if (languages.Any() && languages.All(l => l.Code != CultureInfo.CurrentUICulture.Name))
+ {
+ var defaultLanguage = languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First();
+
+ SetLocalizationCookie(defaultLanguage.Code);
+ }
+ else
+ {
+ SetLocalizationCookie(_localizationManager.GetDefaultCulture());
+ }
}
else
{
- SetLocalizationCookie(_localizationManager.GetDefaultCulture());
+ Message = $"No Matching Alias For Host Name {hostname}";
}
}
}
diff --git a/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs b/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs
index 5ce7467f..dba914a7 100644
--- a/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs
+++ b/Oqtane.Server/Repository/Interfaces/IFolderRepository.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using Oqtane.Models;
namespace Oqtane.Repository
diff --git a/Oqtane.Server/Repository/SiteRepository.cs b/Oqtane.Server/Repository/SiteRepository.cs
index ba23d218..af4f2b06 100644
--- a/Oqtane.Server/Repository/SiteRepository.cs
+++ b/Oqtane.Server/Repository/SiteRepository.cs
@@ -68,7 +68,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Login.Index).ToModuleDefinitionName(), Title = "User Login", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Login.Index).ToModuleDefinitionName(), Title = "User Login", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -97,7 +97,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Register.Index).ToModuleDefinitionName(), Title = "User Registration", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Register.Index).ToModuleDefinitionName(), Title = "User Registration", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -127,7 +127,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Reset.Index).ToModuleDefinitionName(), Title = "Password Reset", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Reset.Index).ToModuleDefinitionName(), Title = "Password Reset", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -156,7 +156,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.UserProfile.Index).ToModuleDefinitionName(), Title = "User Profile", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.UserProfile.Index).ToModuleDefinitionName(), Title = "User Profile", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -181,7 +181,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Dashboard.Index).ToModuleDefinitionName(), Title = "Admin Dashboard", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Dashboard.Index).ToModuleDefinitionName(), Title = "Admin Dashboard", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -208,7 +208,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Site.Index).ToModuleDefinitionName(), Title = "Site Settings", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Site.Index).ToModuleDefinitionName(), Title = "Site Settings", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -235,7 +235,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Pages.Index).ToModuleDefinitionName(), Title = "Page Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Pages.Index).ToModuleDefinitionName(), Title = "Page Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -262,7 +262,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Users.Index).ToModuleDefinitionName(), Title = "User Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Users.Index).ToModuleDefinitionName(), Title = "User Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -289,7 +289,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Profiles.Index).ToModuleDefinitionName(), Title = "Profile Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Profiles.Index).ToModuleDefinitionName(), Title = "Profile Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -316,7 +316,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Roles.Index).ToModuleDefinitionName(), Title = "Role Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Roles.Index).ToModuleDefinitionName(), Title = "Role Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -343,7 +343,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Files.Index).ToModuleDefinitionName(), Title = "File Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Files.Index).ToModuleDefinitionName(), Title = "File Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -370,7 +370,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.RecycleBin.Index).ToModuleDefinitionName(), Title = "Recycle Bin", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.RecycleBin.Index).ToModuleDefinitionName(), Title = "Recycle Bin", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Admin, true),
@@ -399,7 +399,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Logs.Index).ToModuleDefinitionName(), Title = "Event Log", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Logs.Index).ToModuleDefinitionName(), Title = "Event Log", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -421,7 +421,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Sites.Index).ToModuleDefinitionName(), Title = "Site Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Sites.Index).ToModuleDefinitionName(), Title = "Site Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -443,7 +443,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.ModuleDefinitions.Index).ToModuleDefinitionName(), Title = "Module Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.ModuleDefinitions.Index).ToModuleDefinitionName(), Title = "Module Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -465,7 +465,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Themes.Index).ToModuleDefinitionName(), Title = "Theme Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Themes.Index).ToModuleDefinitionName(), Title = "Theme Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -494,7 +494,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Languages.Index).ToModuleDefinitionName(), Title = "Language Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Languages.Index).ToModuleDefinitionName(), Title = "Language Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -518,7 +518,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Jobs.Index).ToModuleDefinitionName(), Title = "Scheduled Jobs", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Jobs.Index).ToModuleDefinitionName(), Title = "Scheduled Jobs", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -540,7 +540,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Sql.Index).ToModuleDefinitionName(), Title = "Sql Management", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Sql.Index).ToModuleDefinitionName(), Title = "Sql Management", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -562,7 +562,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.SystemInfo.Index).ToModuleDefinitionName(), Title = "System Info", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.SystemInfo.Index).ToModuleDefinitionName(), Title = "System Info", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -584,7 +584,7 @@ namespace Oqtane.Repository
{
new PageTemplateModule
{
- ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Upgrade.Index).ToModuleDefinitionName(), Title = "System Update", Pane = "Content",
+ ModuleDefinitionName = typeof(Oqtane.Modules.Admin.Upgrade.Index).ToModuleDefinitionName(), Title = "System Update", Pane = PaneNames.Admin,
ModulePermissions = new List
{
new Permission(PermissionNames.View, RoleNames.Host, true),
@@ -605,7 +605,7 @@ namespace Oqtane.Repository
public Site AddSite(Site site)
{
-
+ site.SiteGuid = System.Guid.NewGuid().ToString();
_db.Site.Add(site);
_db.SaveChanges();
CreateSite(site);
diff --git a/Oqtane.Server/Repository/UserRoleRepository.cs b/Oqtane.Server/Repository/UserRoleRepository.cs
index 79f8a629..b47bd6f7 100644
--- a/Oqtane.Server/Repository/UserRoleRepository.cs
+++ b/Oqtane.Server/Repository/UserRoleRepository.cs
@@ -1,4 +1,4 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Oqtane.Models;
@@ -27,7 +27,7 @@ namespace Oqtane.Repository
return _db.UserRole.Where(item => item.UserId == userId)
.Include(item => item.Role) // eager load roles
.Include(item => item.User) // eager load users
- .Where(item => item.Role.SiteId == siteId || item.Role.SiteId == null);
+ .Where(item => item.Role.SiteId == siteId || item.Role.SiteId == null || siteId == -1);
}
public UserRole AddUserRole(UserRole userRole)
diff --git a/Oqtane.Server/Scripts/Tenant.02.00.02.01.sql b/Oqtane.Server/Scripts/Tenant.02.00.02.01.sql
new file mode 100644
index 00000000..03e5c566
--- /dev/null
+++ b/Oqtane.Server/Scripts/Tenant.02.00.02.01.sql
@@ -0,0 +1,10 @@
+/*
+
+Version 2.0.2 Tenant migration script
+
+*/
+
+ALTER TABLE [dbo].[Site] ADD
+ [SiteGuid] [char](36) NULL
+GO
+
diff --git a/Oqtane.Server/Scripts/Tenant.02.00.02.02.sql b/Oqtane.Server/Scripts/Tenant.02.00.02.02.sql
new file mode 100644
index 00000000..64a08e76
--- /dev/null
+++ b/Oqtane.Server/Scripts/Tenant.02.00.02.02.sql
@@ -0,0 +1,20 @@
+/*
+
+Version 2.0.2 Tenant migration script
+
+*/
+
+UPDATE [dbo].[Site] SET DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client' WHERE DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client';
+GO
+UPDATE [dbo].[Site] SET DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client' WHERE DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client';
+GO
+
+UPDATE [dbo].[Page] SET DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client' WHERE DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client';
+GO
+UPDATE [dbo].[Page] SET DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client' WHERE DefaultContainerType = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client';
+GO
+
+UPDATE [dbo].[PageModule] SET ContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client' WHERE ContainerType = 'Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client';
+GO
+UPDATE [dbo].[PageModule] SET ContainerType = 'Oqtane.Themes.OqtaneTheme.DefaultNoTitle, Oqtane.Client' WHERE ContainerType = 'Oqtane.Themes.OqtaneTheme.NoTitle, Oqtane.Client';
+GO
diff --git a/Oqtane.Server/Startup.cs b/Oqtane.Server/Startup.cs
index 60ae50b8..f337238e 100644
--- a/Oqtane.Server/Startup.cs
+++ b/Oqtane.Server/Startup.cs
@@ -227,7 +227,7 @@ namespace Oqtane
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
- public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ISyncManager sync)
{
ServiceActivator.Configure(app.ApplicationServices);
@@ -265,6 +265,9 @@ namespace Oqtane
endpoints.MapControllers();
endpoints.MapFallbackToPage("/_Host");
});
+
+ // create a sync event to identify server application startup
+ sync.AddSyncEvent(-1, "Application", -1);
}
}
}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Edit.razor b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Edit.razor
similarity index 72%
rename from Oqtane.Server/wwwroot/Modules/Templates/External/Client/Edit.razor
rename to Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Edit.razor
index 339879f8..9858a044 100644
--- a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Edit.razor
+++ b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Edit.razor
@@ -74,22 +74,29 @@
{
try
{
- if (PageState.Action == "Add")
+ if (string.IsNullOrEmpty(_name))
{
- [Module] [Module] = new [Module]();
- [Module].ModuleId = ModuleState.ModuleId;
- [Module].Name = _name;
- [Module] = await [Module]Service.Add[Module]Async([Module]);
- await logger.LogInformation("[Module] Added {[Module]}", [Module]);
+ if (PageState.Action == "Add")
+ {
+ [Module] [Module] = new [Module]();
+ [Module].ModuleId = ModuleState.ModuleId;
+ [Module].Name = _name;
+ [Module] = await [Module]Service.Add[Module]Async([Module]);
+ await logger.LogInformation("[Module] Added {[Module]}", [Module]);
+ }
+ else
+ {
+ [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
+ [Module].Name = _name;
+ await [Module]Service.Update[Module]Async([Module]);
+ await logger.LogInformation("[Module] Updated {[Module]}", [Module]);
+ }
+ NavigationManager.NavigateTo(NavigateUrl());
}
else
{
- [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
- [Module].Name = _name;
- await [Module]Service.Update[Module]Async([Module]);
- await logger.LogInformation("[Module] Updated {[Module]}", [Module]);
+ AddModuleMessage("The Name Is Required", MessageType.Warning);
}
- NavigationManager.NavigateTo(NavigateUrl());
}
catch (Exception ex)
{
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Index.razor b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Index.razor
similarity index 100%
rename from Oqtane.Server/wwwroot/Modules/Templates/External/Client/Index.razor
rename to Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Index.razor
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/ModuleInfo.cs b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/ModuleInfo.cs
similarity index 100%
rename from Oqtane.Server/wwwroot/Modules/Templates/External/Client/ModuleInfo.cs
rename to Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/ModuleInfo.cs
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Settings.razor b/Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Settings.razor
similarity index 100%
rename from Oqtane.Server/wwwroot/Modules/Templates/External/Client/Settings.razor
rename to Oqtane.Server/wwwroot/Modules/Templates/External/Client/Modules/[Owner].[Module]/Settings.razor
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Edit.razor b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Edit.razor
deleted file mode 100644
index 339879f8..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Edit.razor
+++ /dev/null
@@ -1,100 +0,0 @@
-@using Oqtane.Modules.Controls
-@using [Owner].[Module].Services
-@using [Owner].[Module].Models
-
-@namespace [Owner].[Module]
-@inherits ModuleBase
-@inject I[Module]Service [Module]Service
-@inject NavigationManager NavigationManager
-
-
-
-Cancel
-
-
-@if (PageState.Action == "Edit")
-{
-
-}
-
-@code {
- public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
-
- public override string Actions => "Add,Edit";
-
- public override string Title => "Manage [Module]";
-
- public override List Resources => new List()
- {
- new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
- };
-
- int _id;
- string _name;
- string _createdby;
- DateTime _createdon;
- string _modifiedby;
- DateTime _modifiedon;
-
- protected override async Task OnInitializedAsync()
- {
- try
- {
- if (PageState.Action == "Edit")
- {
- _id = Int32.Parse(PageState.QueryString["id"]);
- [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
- if ([Module] != null)
- {
- _name = [Module].Name;
- _createdby = [Module].CreatedBy;
- _createdon = [Module].CreatedOn;
- _modifiedby = [Module].ModifiedBy;
- _modifiedon = [Module].ModifiedOn;
- }
- }
- }
- catch (Exception ex)
- {
- await logger.LogError(ex, "Error Loading [Module] {[Module]Id} {Error}", _id, ex.Message);
- AddModuleMessage("Error Loading [Module]", MessageType.Error);
- }
- }
-
- private async Task Save()
- {
- try
- {
- if (PageState.Action == "Add")
- {
- [Module] [Module] = new [Module]();
- [Module].ModuleId = ModuleState.ModuleId;
- [Module].Name = _name;
- [Module] = await [Module]Service.Add[Module]Async([Module]);
- await logger.LogInformation("[Module] Added {[Module]}", [Module]);
- }
- else
- {
- [Module] [Module] = await [Module]Service.Get[Module]Async(_id, ModuleState.ModuleId);
- [Module].Name = _name;
- await [Module]Service.Update[Module]Async([Module]);
- await logger.LogInformation("[Module] Updated {[Module]}", [Module]);
- }
- NavigationManager.NavigateTo(NavigateUrl());
- }
- catch (Exception ex)
- {
- await logger.LogError(ex, "Error Saving [Module] {Error}", ex.Message);
- AddModuleMessage("Error Saving [Module]", MessageType.Error);
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Index.razor b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Index.razor
deleted file mode 100644
index 37cfef2a..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Index.razor
+++ /dev/null
@@ -1,100 +0,0 @@
-@using [Owner].[Module].Services
-@using [Owner].[Module].Models
-
-@namespace [Owner].[Module]
-@inherits ModuleBase
-@inject I[Module]Service [Module]Service
-@inject NavigationManager NavigationManager
-
-@if (_[Module]s == null)
-{
- Loading...
-}
-else
-{
-
-
-
- @if (@_[Module]s.Count != 0)
- {
-
-
-
- |
- |
- @context.Name |
-
-
- }
- else
- {
- No [Module]s To Display
- }
-}
-
-
-
-
-[Module] Module Created Successfully. Use Edit Mode To Add A [Module]. You Can Access The Files At The Following Locations:
-[RootPath]Oqtane.Client\Modules\[Module]\
-- Edit.razor - component for adding or editing content
-- Index.razor - main component for your module **the content you are reading is in this file**
-- ModuleInfo.cs - implements IModule interface to provide configuration settings for your module
-- Settings.razor - component for managing module settings
-- Services\I[Module]Service.cs - interface for defining service API methods
-- Services\[Module]Service.cs - implements service API interface methods
-[RootPath]Oqtane.Server\Modules\[Module]\
-- Controllers\[Module]Controller.cs - API methods implemented using a REST pattern
-- Manager\[Module]Manager.cs - implements optional module interfaces for features such as import/export of content
-- Repository\I[Module]Repository.cs - interface for defining repository methods
-- Repository\[Module]Respository.cs - implements repository interface methods for data access using EF Core
-- Repository\[Module]Context.cs - provides a DB Context for data access
-- Scripts\[Owner].[Module]s.1.0.0.sql - database schema definition script
-- Scripts\[Owner].[Module]s.Uninstall.sql - database uninstall script
-[RootPath]Oqtane.Shared\Modules\[Module]\
-- Models\[Module].cs - model definition
-
-
-
-@code {
- public override List Resources => new List()
- {
- new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
- new Resource { ResourceType = ResourceType.Script, Url = ModulePath() + "Module.js" }
- };
-
- List<[Module]> _[Module]s;
-
- protected override async Task OnInitializedAsync()
- {
- try
- {
- _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
- }
- catch (Exception ex)
- {
- await logger.LogError(ex, "Error Loading [Module] {Error}", ex.Message);
- AddModuleMessage("Error Loading [Module]", MessageType.Error);
- }
- }
-
- private async Task Delete([Module] [Module])
- {
- try
- {
- await [Module]Service.Delete[Module]Async([Module].[Module]Id, ModuleState.ModuleId);
- await logger.LogInformation("[Module] Deleted {[Module]}", [Module]);
- _[Module]s = await [Module]Service.Get[Module]sAsync(ModuleState.ModuleId);
- StateHasChanged();
- }
- catch (Exception ex)
- {
- await logger.LogError(ex, "Error Deleting [Module] {[Module]} {Error}", [Module], ex.Message);
- AddModuleMessage("Error Deleting [Module]", MessageType.Error);
- }
- }
-}
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Interop.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Interop.cs
deleted file mode 100644
index 9d6f0a4e..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Interop.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using Microsoft.JSInterop;
-using System.Threading.Tasks;
-
-namespace [Owner].[Module]
-{
- public class Interop
- {
- private readonly IJSRuntime _jsRuntime;
-
- public Interop(IJSRuntime jsRuntime)
- {
- _jsRuntime = jsRuntime;
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/ModuleInfo.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/ModuleInfo.cs
deleted file mode 100644
index 6586d51d..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/ModuleInfo.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-using Oqtane.Models;
-using Oqtane.Modules;
-
-namespace [Owner].[Module]
-{
- public class ModuleInfo : IModule
- {
- public ModuleDefinition ModuleDefinition => new ModuleDefinition
- {
- Name = "[Module]",
- Description = "[Module]",
- Version = "1.0.0",
- ServerManagerType = "[ServerManagerType]",
- ReleaseVersions = "1.0.0"
- };
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Services/I[Module]Service.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Services/I[Module]Service.cs
deleted file mode 100644
index 601eba6a..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Services/I[Module]Service.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using [Owner].[Module].Models;
-
-namespace [Owner].[Module].Services
-{
- public interface I[Module]Service
- {
- Task> Get[Module]sAsync(int ModuleId);
-
- Task Get[Module]Async(int [Module]Id, int ModuleId);
-
- Task Add[Module]Async(Models.[Module] [Module]);
-
- Task Update[Module]Async(Models.[Module] [Module]);
-
- Task Delete[Module]Async(int [Module]Id, int ModuleId);
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Services/[Module]Service.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Services/[Module]Service.cs
deleted file mode 100644
index 05a85ac7..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Services/[Module]Service.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Net.Http;
-using System.Threading.Tasks;
-using Oqtane.Modules;
-using Oqtane.Services;
-using Oqtane.Shared;
-using [Owner].[Module].Models;
-
-namespace [Owner].[Module].Services
-{
- public class [Module]Service : ServiceBase, I[Module]Service, IService
- {
- private readonly SiteState _siteState;
-
- public [Module]Service(HttpClient http, SiteState siteState) : base(http)
- {
- _siteState = siteState;
- }
-
- private string Apiurl => CreateApiUrl(_siteState.Alias, "[Module]");
-
- public async Task> Get[Module]sAsync(int ModuleId)
- {
- List [Module]s = await GetJsonAsync>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", ModuleId));
- return [Module]s.OrderBy(item => item.Name).ToList();
- }
-
- public async Task Get[Module]Async(int [Module]Id, int ModuleId)
- {
- return await GetJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
- }
-
- public async Task Add[Module]Async(Models.[Module] [Module])
- {
- return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", [Module].ModuleId), [Module]);
- }
-
- public async Task Update[Module]Async(Models.[Module] [Module])
- {
- return await PutJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{[Module].[Module]Id}", [Module].ModuleId), [Module]);
- }
-
- public async Task Delete[Module]Async(int [Module]Id, int ModuleId)
- {
- await DeleteAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{[Module]Id}", ModuleId));
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Settings.razor b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Settings.razor
deleted file mode 100644
index 7989d7c9..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Client/Modules/[Owner].[Module]/Settings.razor
+++ /dev/null
@@ -1,47 +0,0 @@
-@namespace [Owner].[Module]
-@inherits ModuleBase
-@inject ISettingService SettingService
-
-
-
-@code {
- public override string Title => "[Module] Settings";
-
- string _value;
-
- protected override async Task OnInitializedAsync()
- {
- try
- {
- Dictionary settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
- _value = SettingService.GetSetting(settings, "SettingName", "");
- }
- catch (Exception ex)
- {
- ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
- }
- }
-
- public async Task UpdateSettings()
- {
- try
- {
- Dictionary settings = await SettingService.GetModuleSettingsAsync(ModuleState.ModuleId);
- SettingService.SetSetting(settings, "SettingName", _value);
- await SettingService.UpdateModuleSettingsAsync(settings, ModuleState.ModuleId);
- }
- catch (Exception ex)
- {
- ModuleInstance.AddModuleMessage(ex.Message, MessageType.Error);
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Controllers/[Module]Controller.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Controllers/[Module]Controller.cs
deleted file mode 100644
index 3e2fe7b8..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Controllers/[Module]Controller.cs
+++ /dev/null
@@ -1,91 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Authorization;
-using System.Collections.Generic;
-using Microsoft.AspNetCore.Http;
-using Oqtane.Shared;
-using Oqtane.Enums;
-using Oqtane.Infrastructure;
-using [Owner].[Module].Models;
-using [Owner].[Module].Repository;
-
-namespace [Owner].[Module].Controllers
-{
- [Route(ControllerRoutes.Default)]
- public class [Module]Controller : Controller
- {
- private readonly I[Module]Repository _[Module]Repository;
- private readonly ILogManager _logger;
- protected int _entityId = -1;
-
- public [Module]Controller(I[Module]Repository [Module]Repository, ILogManager logger, IHttpContextAccessor accessor)
- {
- _[Module]Repository = [Module]Repository;
- _logger = logger;
-
- if (accessor.HttpContext.Request.Query.ContainsKey("entityid"))
- {
- _entityId = int.Parse(accessor.HttpContext.Request.Query["entityid"]);
- }
- }
-
- // GET: api/?moduleid=x
- [HttpGet]
- [Authorize(Policy = PolicyNames.ViewModule)]
- public IEnumerable Get(string moduleid)
- {
- return _[Module]Repository.Get[Module]s(int.Parse(moduleid));
- }
-
- // GET api//5
- [HttpGet("{id}")]
- [Authorize(Policy = PolicyNames.ViewModule)]
- public Models.[Module] Get(int id)
- {
- Models.[Module] [Module] = _[Module]Repository.Get[Module](id);
- if ([Module] != null && [Module].ModuleId != _entityId)
- {
- [Module] = null;
- }
- return [Module];
- }
-
- // POST api/
- [HttpPost]
- [Authorize(Policy = PolicyNames.EditModule)]
- public Models.[Module] Post([FromBody] Models.[Module] [Module])
- {
- if (ModelState.IsValid && [Module].ModuleId == _entityId)
- {
- [Module] = _[Module]Repository.Add[Module]([Module]);
- _logger.Log(LogLevel.Information, this, LogFunction.Create, "[Module] Added {[Module]}", [Module]);
- }
- return [Module];
- }
-
- // PUT api//5
- [HttpPut("{id}")]
- [Authorize(Policy = PolicyNames.EditModule)]
- public Models.[Module] Put(int id, [FromBody] Models.[Module] [Module])
- {
- if (ModelState.IsValid && [Module].ModuleId == _entityId)
- {
- [Module] = _[Module]Repository.Update[Module]([Module]);
- _logger.Log(LogLevel.Information, this, LogFunction.Update, "[Module] Updated {[Module]}", [Module]);
- }
- return [Module];
- }
-
- // DELETE api//5
- [HttpDelete("{id}")]
- [Authorize(Policy = PolicyNames.EditModule)]
- public void Delete(int id)
- {
- Models.[Module] [Module] = _[Module]Repository.Get[Module](id);
- if ([Module] != null && [Module].ModuleId == _entityId)
- {
- _[Module]Repository.Delete[Module](id);
- _logger.Log(LogLevel.Information, this, LogFunction.Delete, "[Module] Deleted {[Module]Id}", id);
- }
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Manager/[Module]Manager.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Manager/[Module]Manager.cs
deleted file mode 100644
index 486c8ddf..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Manager/[Module]Manager.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Text.Json;
-using Oqtane.Modules;
-using Oqtane.Models;
-using Oqtane.Infrastructure;
-using Oqtane.Repository;
-using [Owner].[Module].Models;
-using [Owner].[Module].Repository;
-
-namespace [Owner].[Module].Manager
-{
- public class [Module]Manager : IInstallable, IPortable
- {
- private I[Module]Repository _[Module]Repository;
- private ISqlRepository _sql;
-
- public [Module]Manager(I[Module]Repository [Module]Repository, ISqlRepository sql)
- {
- _[Module]Repository = [Module]Repository;
- _sql = sql;
- }
-
- public bool Install(Tenant tenant, string version)
- {
- return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module]." + version + ".sql");
- }
-
- public bool Uninstall(Tenant tenant)
- {
- return _sql.ExecuteScript(tenant, GetType().Assembly, "[Owner].[Module].Uninstall.sql");
- }
-
- public string ExportModule(Module module)
- {
- string content = "";
- List [Module]s = _[Module]Repository.Get[Module]s(module.ModuleId).ToList();
- if ([Module]s != null)
- {
- content = JsonSerializer.Serialize([Module]s);
- }
- return content;
- }
-
- public void ImportModule(Module module, string content, string version)
- {
- List [Module]s = null;
- if (!string.IsNullOrEmpty(content))
- {
- [Module]s = JsonSerializer.Deserialize>(content);
- }
- if ([Module]s != null)
- {
- foreach(var [Module] in [Module]s)
- {
- _[Module]Repository.Add[Module](new Models.[Module] { ModuleId = module.ModuleId, Name = [Module].Name });
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/I[Module]Repository.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/I[Module]Repository.cs
deleted file mode 100644
index 52b7913a..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/I[Module]Repository.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-using System.Collections.Generic;
-using [Owner].[Module].Models;
-
-namespace [Owner].[Module].Repository
-{
- public interface I[Module]Repository
- {
- IEnumerable Get[Module]s(int ModuleId);
- Models.[Module] Get[Module](int [Module]Id);
- Models.[Module] Add[Module](Models.[Module] [Module]);
- Models.[Module] Update[Module](Models.[Module] [Module]);
- void Delete[Module](int [Module]Id);
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/[Module]Context.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/[Module]Context.cs
deleted file mode 100644
index a10d7219..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/[Module]Context.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using Microsoft.AspNetCore.Http;
-using Oqtane.Modules;
-using Oqtane.Repository;
-using [Owner].[Module].Models;
-
-namespace [Owner].[Module].Repository
-{
- public class [Module]Context : DBContextBase, IService
- {
- public virtual DbSet [Module] { get; set; }
-
- public [Module]Context(ITenantResolver tenantResolver, IHttpContextAccessor accessor) : base(tenantResolver, accessor)
- {
- // ContextBase handles multi-tenant database connections
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/[Module]Repository.cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/[Module]Repository.cs
deleted file mode 100644
index 9c8c3628..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Repository/[Module]Repository.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using Microsoft.EntityFrameworkCore;
-using System.Linq;
-using System.Collections.Generic;
-using Oqtane.Modules;
-using [Owner].[Module].Models;
-
-namespace [Owner].[Module].Repository
-{
- public class [Module]Repository : I[Module]Repository, IService
- {
- private readonly [Module]Context _db;
-
- public [Module]Repository([Module]Context context)
- {
- _db = context;
- }
-
- public IEnumerable Get[Module]s(int ModuleId)
- {
- return _db.[Module].Where(item => item.ModuleId == ModuleId);
- }
-
- public Models.[Module] Get[Module](int [Module]Id)
- {
- return _db.[Module].Find([Module]Id);
- }
-
- public Models.[Module] Add[Module](Models.[Module] [Module])
- {
- _db.[Module].Add([Module]);
- _db.SaveChanges();
- return [Module];
- }
-
- public Models.[Module] Update[Module](Models.[Module] [Module])
- {
- _db.Entry([Module]).State = EntityState.Modified;
- _db.SaveChanges();
- return [Module];
- }
-
- public void Delete[Module](int [Module]Id)
- {
- Models.[Module] [Module] = _db.[Module].Find([Module]Id);
- _db.[Module].Remove([Module]);
- _db.SaveChanges();
- }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Scripts/[Owner].[Module].1.0.0.sql b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Scripts/[Owner].[Module].1.0.0.sql
deleted file mode 100644
index 7a1b99ea..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Scripts/[Owner].[Module].1.0.0.sql
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
-Create [Owner][Module] table
-*/
-
-CREATE TABLE [dbo].[[Owner][Module]](
- [[Module]Id] [int] IDENTITY(1,1) NOT NULL,
- [ModuleId] [int] NOT NULL,
- [Name] [nvarchar](256) NOT NULL,
- [CreatedBy] [nvarchar](256) NOT NULL,
- [CreatedOn] [datetime] NOT NULL,
- [ModifiedBy] [nvarchar](256) NOT NULL,
- [ModifiedOn] [datetime] NOT NULL,
- CONSTRAINT [PK_[Owner][Module]] PRIMARY KEY CLUSTERED
- (
- [[Module]Id] ASC
- )
-)
-GO
-
-/*
-Create foreign key relationships
-*/
-ALTER TABLE [dbo].[[Owner][Module]] WITH CHECK ADD CONSTRAINT [FK_[Owner][Module]_Module] FOREIGN KEY([ModuleId])
-REFERENCES [dbo].Module ([ModuleId])
-ON DELETE CASCADE
-GO
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Scripts/[Owner].[Module].Uninstall.sql b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Scripts/[Owner].[Module].Uninstall.sql
deleted file mode 100644
index 47baecc9..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/Modules/[Owner].[Module]/Scripts/[Owner].[Module].Uninstall.sql
+++ /dev/null
@@ -1,6 +0,0 @@
-/*
-Remove [Owner][Module] table
-*/
-
-DROP TABLE [dbo].[[Owner][Module]]
-GO
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/wwwroot/Modules/[Owner].[Module]/Module.css b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/wwwroot/Modules/[Owner].[Module]/Module.css
deleted file mode 100644
index 0856a263..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/wwwroot/Modules/[Owner].[Module]/Module.css
+++ /dev/null
@@ -1 +0,0 @@
-/* Module Custom Styles */
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/wwwroot/Modules/[Owner].[Module]/Module.js b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/wwwroot/Modules/[Owner].[Module]/Module.js
deleted file mode 100644
index 8f072470..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Server/wwwroot/Modules/[Owner].[Module]/Module.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/* Module Script */
-var [Owner] = [Owner] || {};
-
-[Owner].[Module] = {
-};
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Shared/Modules/[Owner].[Module]/Models/[Module].cs b/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Shared/Modules/[Owner].[Module]/Models/[Module].cs
deleted file mode 100644
index 94f73ffa..00000000
--- a/Oqtane.Server/wwwroot/Modules/Templates/Internal/Oqtane.Shared/Modules/[Owner].[Module]/Models/[Module].cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using System;
-using System.ComponentModel.DataAnnotations.Schema;
-using Oqtane.Models;
-
-namespace [Owner].[Module].Models
-{
- [Table("[Owner][Module]")]
- public class [Module] : IAuditable
- {
- public int [Module]Id { get; set; }
- public int ModuleId { get; set; }
- public string Name { get; set; }
-
- public string CreatedBy { get; set; }
- public DateTime CreatedOn { get; set; }
- public string ModifiedBy { get; set; }
- public DateTime ModifiedOn { get; set; }
- }
-}
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/AssemblyInfo.cs b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/AssemblyInfo.cs
new file mode 100644
index 00000000..91d5ec4b
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/AssemblyInfo.cs
@@ -0,0 +1,4 @@
+using System.Resources;
+using Microsoft.Extensions.Localization;
+
+[assembly: RootNamespace("[Owner].[Theme].Client")]
\ No newline at end of file
diff --git a/Oqtane.Client/Themes/OqtaneTheme/Container.razor b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Containers/Container1.razor
similarity index 79%
rename from Oqtane.Client/Themes/OqtaneTheme/Container.razor
rename to Oqtane.Server/wwwroot/Themes/Templates/External/Client/Containers/Container1.razor
index 6d0148fa..2778aa22 100644
--- a/Oqtane.Client/Themes/OqtaneTheme/Container.razor
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Containers/Container1.razor
@@ -1,5 +1,6 @@
-@namespace Oqtane.Themes.OqtaneTheme
+@namespace [Owner].[Theme]
@inherits ContainerBase
+
@@ -15,5 +16,5 @@
@code {
- public override string Name => "Standard Header";
+ public override string Name => "Container1";
}
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/ThemeInfo.cs b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/ThemeInfo.cs
new file mode 100644
index 00000000..3f543b38
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/ThemeInfo.cs
@@ -0,0 +1,15 @@
+using Oqtane.Models;
+using Oqtane.Themes;
+
+namespace [Owner].[Theme]
+{
+ public class ThemeInfo : ITheme
+ {
+ public Theme Theme => new Theme
+ {
+ Name = "[Theme]",
+ Version = "1.0.0"
+ };
+
+ }
+}
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Themes/Theme1.razor b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Themes/Theme1.razor
new file mode 100644
index 00000000..7ffefe5f
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/Themes/Theme1.razor
@@ -0,0 +1,107 @@
+@namespace [Owner].[Theme]
+@inherits ThemeBase
+
+
+
+
+
+
+
+
+
+@code {
+ public override string Name => "Theme1";
+
+ public override string Panes => "Content,Top Full Width,Top 100%,Left 50%,Right 50%,Left 33%,Center 33%,Right 33%,Left Outer 25%,Left Inner 25%,Right Inner 25%,Right Outer 25%,Left 25%,Center 50%,Right 25%,Left Sidebar 66%,Right Sidebar 33%,Left Sidebar 33%,Right Sidebar 66%,Bottom 100%,Bottom Full Width";
+
+ public override List Resources => new List()
+ {
+ new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css", Integrity = "sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk", CrossOrigin = "anonymous" },
+ new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" },
+ new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://code.jquery.com/jquery-3.5.1.slim.min.js", Integrity = "sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj", CrossOrigin = "anonymous" },
+ new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js", Integrity = "sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo", CrossOrigin = "anonymous" },
+ new Resource { ResourceType = ResourceType.Script, Bundle = "Bootstrap", Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js", Integrity = "sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI", CrossOrigin = "anonymous" }
+ };
+}
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].[Theme].Client.csproj b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].[Theme].Client.csproj
new file mode 100644
index 00000000..746694b4
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/[Owner].[Theme].Client.csproj
@@ -0,0 +1,34 @@
+
+
+
+ net5.0
+ 3.0
+ 1.0.0
+ [Owner]
+ [Owner]
+ [Description]
+ [Owner].[Theme]
+ [Owner]
+ [Owner].[Theme].Client.Oqtane
+
+
+
+
+
+
+
+
+
+
+
+ [ClientReference]
+ [SharedReference]
+
+
+
+
+ false
+ false
+
+
+
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/_Imports.razor b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/_Imports.razor
new file mode 100644
index 00000000..d206b36e
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/_Imports.razor
@@ -0,0 +1,21 @@
+@using System
+@using System.Linq
+@using System.Collections.Generic
+@using System.Net.Http
+@using System.Net.Http.Json
+
+@using Microsoft.AspNetCore.Components.Routing
+@using Microsoft.AspNetCore.Components.Web
+@using Microsoft.JSInterop
+
+@using Oqtane.Models
+@using Oqtane.Modules
+@using Oqtane.Modules.Controls
+@using Oqtane.Providers
+@using Oqtane.Security
+@using Oqtane.Services
+@using Oqtane.Shared
+@using Oqtane.Themes
+@using Oqtane.Themes.Controls
+@using Oqtane.UI
+@using Oqtane.Enums
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Client/wwwroot/Themes/[Owner].[Theme]/Theme.css b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/wwwroot/Themes/[Owner].[Theme]/Theme.css
new file mode 100644
index 00000000..b8056c79
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Client/wwwroot/Themes/[Owner].[Theme]/Theme.css
@@ -0,0 +1,83 @@
+/* Oqtane Styles */
+
+body {
+ padding-top: 7rem;
+}
+
+.controls {
+ z-index: 2000;
+ padding-top: 15px;
+ padding-bottom: 15px;
+ margin-right: 10px;
+}
+
+.app-menu .nav-item {
+ font-size: 0.9rem;
+ padding-bottom: 0.5rem;
+}
+
+.app-menu .nav-item a {
+ border-radius: 4px;
+ height: 3rem;
+ display: flex;
+ align-items: center;
+ line-height: 3rem;
+}
+
+.app-menu .nav-item a.active {
+ background-color: rgba(255,255,255,0.25);
+ color: white;
+}
+
+.app-menu .nav-item a:hover {
+ background-color: rgba(255,255,255,0.1);
+ color: white;
+}
+
+.app-menu .nav-link .oi {
+ width: 1.5rem;
+ font-size: 1.1rem;
+ vertical-align: text-top;
+ top: -2px;
+}
+
+.navbar-toggler {
+ background-color: rgba(255, 255, 255, 0.1);
+ margin-left: auto;
+}
+
+div.app-moduleactions a.dropdown-toggle, div.app-moduleactions div.dropdown-menu {
+ color:#ffffff;
+}
+
+@media (max-width: 767px) {
+
+ .app-menu {
+ width: 100%
+ }
+
+ .navbar {
+ position: fixed;
+ top: 60px;
+ width: 100%;
+ }
+
+ .controls {
+ height: 60px;
+ top: 15px;
+ position: fixed;
+ top: 0px;
+ width: 100%;
+ background-color: rgb(0, 0, 0);
+ }
+
+ .controls-group {
+ float: right;
+ margin-right: 25px;
+ }
+
+ .content {
+ position: relative;
+ top: 60px;
+ }
+}
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Package/[Owner].[Theme].Package.csproj b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/[Owner].[Theme].Package.csproj
new file mode 100644
index 00000000..30043010
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/[Owner].[Theme].Package.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net5.0
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Package/[Owner].[Theme].nuspec b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/[Owner].[Theme].nuspec
new file mode 100644
index 00000000..e73d4618
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/[Owner].[Theme].nuspec
@@ -0,0 +1,27 @@
+
+
+
+ [Owner].[Theme]
+ 1.0.0
+ [Owner]
+ [Owner]
+ [Theme]
+ [Theme]
+ [Owner]
+ false
+ MIT
+ https://github.com/oqtane/oqtane.framework
+ https://www.oqtane.org/Portals/0/icon.jpg
+ oqtane module
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Package/debug.cmd b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/debug.cmd
new file mode 100644
index 00000000..7eea5a36
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/debug.cmd
@@ -0,0 +1,3 @@
+XCOPY "..\Client\bin\Debug\net5.0\[Owner].[Theme].Client.Oqtane.dll" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net5.0\" /Y
+XCOPY "..\Client\bin\Debug\net5.0\[Owner].[Theme].Client.Oqtane.pdb" "..\..\[RootFolder]\Oqtane.Server\bin\Debug\net5.0\" /Y
+XCOPY "..\Client\wwwroot\*" "..\..\[RootFolder]\Oqtane.Client\wwwroot\" /Y /S /I
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/Package/release.cmd b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/release.cmd
new file mode 100644
index 00000000..3d4edfe1
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/Package/release.cmd
@@ -0,0 +1,2 @@
+"..\..\[RootFolder]\oqtane.package\nuget.exe" pack [Owner].[Theme].nuspec
+XCOPY "*.nupkg" "..\..\[RootFolder]\Oqtane.Server\wwwroot\Themes\" /Y
diff --git a/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln b/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln
new file mode 100644
index 00000000..7c1739bd
--- /dev/null
+++ b/Oqtane.Server/wwwroot/Themes/Templates/External/[Owner].[Theme].sln
@@ -0,0 +1,36 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28621.142
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "[Owner].[Theme].Client", "Client\[Owner].[Theme].Client.csproj", "{AA8E58A1-CD09-4208-BF66-A8BB341FD669}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "[Owner].[Theme].Package", "Package\[Owner].[Theme].Package.csproj", "{C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ Wasm|Any CPU = Wasm|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.ActiveCfg = Release|Any CPU
+ {AA8E58A1-CD09-4208-BF66-A8BB341FD669}.Wasm|Any CPU.Build.0 = Release|Any CPU
+ {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.ActiveCfg = Debug|Any CPU
+ {C5CE512D-CBB7-4545-AF0F-9B6591A0C3A7}.Wasm|Any CPU.Build.0 = Debug|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {1D016F15-46FE-4726-8DFD-2E4FD4DC7668}
+ EndGlobalSection
+EndGlobal
diff --git a/Oqtane.Server/wwwroot/css/app.css b/Oqtane.Server/wwwroot/css/app.css
index ce87887d..35a44e3f 100644
--- a/Oqtane.Server/wwwroot/css/app.css
+++ b/Oqtane.Server/wwwroot/css/app.css
@@ -1,4 +1,4 @@
-@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
+@import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
@@ -90,6 +90,17 @@ app {
color: gray;
}
+.app-moduleactions .dropdown-submenu {
+ position: relative;
+}
+
+ .app-moduleactions .dropdown-submenu > .dropdown-menu {
+ top: 0;
+ left: 100%;
+ margin-top: 0px;
+ margin-left: 0px;
+ }
+
.app-progress-indicator {
background: rgba(0,0,0,0.2) url('../loading.gif') no-repeat 50% 50%;
width: 100%;
@@ -125,6 +136,13 @@ app {
vertical-align: inherit;
}
+.app-alert {
+ padding: 20px;
+ background-color: #f44336; /* red */
+ color: white;
+ margin-bottom: 15px;
+}
+
/* Tooltips */
.app-tooltip {
cursor: help;
@@ -207,4 +225,4 @@ app {
position: absolute;
right: 0.75rem;
top: 0.5rem;
-}
\ No newline at end of file
+}
diff --git a/Oqtane.Server/wwwroot/js/app.js b/Oqtane.Server/wwwroot/js/app.js
new file mode 100644
index 00000000..2c5d837e
--- /dev/null
+++ b/Oqtane.Server/wwwroot/js/app.js
@@ -0,0 +1,8 @@
+function subMenu(a) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ var li = a.parentElement, submenu = li.getElementsByTagName('ul')[0];
+ submenu.style.display = submenu.style.display == "block" ? "none" : "block";
+ return false;
+}
\ No newline at end of file
diff --git a/Oqtane.Server/wwwroot/js/interop.js b/Oqtane.Server/wwwroot/js/interop.js
index 2e4092e4..6d1b549d 100644
--- a/Oqtane.Server/wwwroot/js/interop.js
+++ b/Oqtane.Server/wwwroot/js/interop.js
@@ -362,5 +362,8 @@ Oqtane.Interop = {
setInterval(function () {
window.location.href = url;
}, wait * 1000);
+ },
+ formValid: function (formRef) {
+ return formRef.checkValidity();
}
};
diff --git a/Oqtane.Shared/Models/Site.cs b/Oqtane.Shared/Models/Site.cs
index 49f3524e..5adf1318 100644
--- a/Oqtane.Shared/Models/Site.cs
+++ b/Oqtane.Shared/Models/Site.cs
@@ -18,6 +18,7 @@ namespace Oqtane.Models
public int? PwaAppIconFileId { get; set; }
public int? PwaSplashIconFileId { get; set; }
public bool AllowRegistration { get; set; }
+ public string SiteGuid { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
diff --git a/Oqtane.Shared/Models/Theme.cs b/Oqtane.Shared/Models/Theme.cs
index ee420dd9..398cc537 100644
--- a/Oqtane.Shared/Models/Theme.cs
+++ b/Oqtane.Shared/Models/Theme.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
namespace Oqtane.Models
@@ -14,6 +14,7 @@ namespace Oqtane.Models
Contact = "";
License = "";
Dependencies = "";
+ Template = "";
}
public string ThemeName { get; set; }
@@ -28,6 +29,7 @@ namespace Oqtane.Models
public List Themes { get; set; }
public List Layouts { get; set; }
public List Containers { get; set; }
+ public string Template { get; set; }
//[Obsolete("This property is obsolete. Use Themes instead.", false)]
public string ThemeControls { get; set; }
diff --git a/Oqtane.Shared/Shared/Constants.cs b/Oqtane.Shared/Shared/Constants.cs
index 60106dd2..89d0e9a7 100644
--- a/Oqtane.Shared/Shared/Constants.cs
+++ b/Oqtane.Shared/Shared/Constants.cs
@@ -13,7 +13,7 @@ namespace Oqtane.Shared {
public const string DefaultTheme = "Oqtane.Themes.OqtaneTheme.Default, Oqtane.Client";
public const string DefaultLayout = "Oqtane.Themes.OqtaneTheme.SinglePane, Oqtane.Client";
- public const string DefaultContainer = "Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client";
+ public const string DefaultContainer = "Oqtane.Themes.OqtaneTheme.DefaultTitle, Oqtane.Client";
public const string DefaultAdminContainer = "Oqtane.Themes.AdminContainer, Oqtane.Client";
public const string ActionToken = "{Action}";
diff --git a/Oqtane.Shared/Shared/PaneNames.cs b/Oqtane.Shared/Shared/PaneNames.cs
index 063924f9..7806f821 100644
--- a/Oqtane.Shared/Shared/PaneNames.cs
+++ b/Oqtane.Shared/Shared/PaneNames.cs
@@ -1,9 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
namespace Oqtane.Shared {
public class PaneNames {
- public const string Admin = "Admin";
+ public const string Admin = "Content";
}
}
| |