|
@ -3,6 +3,7 @@
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
@inject IModuleDefinitionService ModuleDefinitionService
|
@inject IModuleDefinitionService ModuleDefinitionService
|
||||||
@inject IModuleService ModuleService
|
@inject IModuleService ModuleService
|
||||||
|
@inject ISystemService SystemService
|
||||||
|
|
||||||
<table class="table table-borderless">
|
<table class="table table-borderless">
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -34,13 +35,24 @@
|
||||||
<Label For="template" HelpText="Select a module template. Internal modules are created inside of the Oqtane solution. External modules are created outside of the Oqtane solution.">Template: </Label>
|
<Label For="template" HelpText="Select a module template. Internal modules are created inside of the Oqtane solution. External modules are created outside of the Oqtane solution.">Template: </Label>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<select id="template" class="form-control" @bind="@_template">
|
<select id="template" class="form-control" @onchange="(e => TemplateChanged(e))">
|
||||||
<option value=""><Select Template></option>
|
<option value="-"><Select Template></option>
|
||||||
<option value="internal">Internal</option>
|
<option value="internal">Internal</option>
|
||||||
<option value="external">External</option>
|
<option value="external">External</option>
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (!string.IsNullOrEmpty(_location))
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<Label For="location" HelpText="Location where the module will be created">Location: </Label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<input id="module" class="form-control" @bind="@_location" readonly />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<button type="button" class="btn btn-success" @onclick="CreateModule">Create Module</button>
|
<button type="button" class="btn btn-success" @onclick="CreateModule">Create Module</button>
|
||||||
|
@ -49,7 +61,8 @@
|
||||||
private string _owner = string.Empty;
|
private string _owner = string.Empty;
|
||||||
private string _module = string.Empty;
|
private string _module = string.Empty;
|
||||||
private string _description = string.Empty;
|
private string _description = string.Empty;
|
||||||
private string _template = string.Empty;
|
private string _template = "-";
|
||||||
|
private string _location = string.Empty;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Host;
|
||||||
|
|
||||||
|
@ -62,7 +75,7 @@
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && !string.IsNullOrEmpty(_template))
|
if (!string.IsNullOrEmpty(_owner) && !string.IsNullOrEmpty(_module) && _template != "-")
|
||||||
{
|
{
|
||||||
var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ", ""), Name = _module.Replace(" ", ""), Description = _description, Template = _template };
|
var moduleDefinition = new ModuleDefinition { Owner = _owner.Replace(" ", ""), Name = _module.Replace(" ", ""), Description = _description, Template = _template };
|
||||||
await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition, ModuleState.ModuleId);
|
await ModuleDefinitionService.CreateModuleDefinitionAsync(moduleDefinition, ModuleState.ModuleId);
|
||||||
|
@ -77,4 +90,35 @@
|
||||||
await logger.LogError(ex, "Error Creating Module");
|
await logger.LogError(ex, "Error Creating Module");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async void TemplateChanged(ChangeEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_location = string.Empty;
|
||||||
|
_template = (string)e.Value;
|
||||||
|
if (_template != "-")
|
||||||
|
{
|
||||||
|
Dictionary<string, string> systeminfo = await SystemService.GetSystemInfoAsync();
|
||||||
|
if (systeminfo != null)
|
||||||
|
{
|
||||||
|
string[] path = systeminfo["serverpath"].Split('\\');
|
||||||
|
if (_template == "internal")
|
||||||
|
{
|
||||||
|
_location = string.Join("\\", path, 0, path.Length - 1) + "\\Oqtane.Client\\Modules\\" + _owner + "." + _module;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_location = string.Join("\\", path, 0, path.Length - 2) + "\\" + _owner + "." + _module;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await logger.LogError(ex, "Error Getting System Info {Error}", ex.Message);
|
||||||
|
AddModuleMessage("Error Getting System Info", MessageType.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Scripts\[Owner].[Module].1.0.0.sql" />
|
<EmbeddedResource Include="Scripts\[Owner].[Module]s.1.0.0.sql" />
|
||||||
<EmbeddedResource Include="Scripts\[Owner].[Module].Uninstall.sql" />
|
<EmbeddedResource Include="Scripts\[Owner].[Module]s.Uninstall.sql" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -98,9 +98,6 @@
|
||||||
private string _message = string.Empty;
|
private string _message = string.Empty;
|
||||||
private string _image = string.Empty;
|
private string _image = string.Empty;
|
||||||
private string _guid;
|
private string _guid;
|
||||||
private int _folderId = -1;
|
|
||||||
private bool _uploadMultiple;
|
|
||||||
private int _fileId;
|
|
||||||
|
|
||||||
[Parameter]
|
[Parameter]
|
||||||
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
public string Id { get; set; } // optional - for setting the id of the FileManager component for accessibility
|
||||||
|
|
|
@ -20,6 +20,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
||||||
|
|
||||||
|
public override string Title => "Edit Html/Text";
|
||||||
|
|
||||||
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
|
||||||
|
// the following resources should be declared in the RichTextEditor component however the framework currently only supports resource management for modules and themes
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.6.bubble.css" },
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "css/quill/quill1.3.6.snow.css" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Url = "js/quill1.3.6.min.js" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Url = "js/quill-blot-formatter.min.js" },
|
||||||
|
new Resource { ResourceType = ResourceType.Script, Url = "js/quill-interop.js" }
|
||||||
|
};
|
||||||
|
|
||||||
private RichTextEditor RichTextEditorHtml;
|
private RichTextEditor RichTextEditorHtml;
|
||||||
private string _content = null;
|
private string _content = null;
|
||||||
private string _createdby;
|
private string _createdby;
|
||||||
|
@ -27,10 +42,6 @@
|
||||||
private string _modifiedby;
|
private string _modifiedby;
|
||||||
private DateTime _modifiedon;
|
private DateTime _modifiedon;
|
||||||
|
|
||||||
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
|
|
||||||
|
|
||||||
public override string Title => "Edit Html/Text";
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
|
||||||
|
};
|
||||||
|
|
||||||
private string content = "";
|
private string content = "";
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Oqtane.Services;
|
||||||
using System;
|
using System;
|
||||||
using Oqtane.Enums;
|
using Oqtane.Enums;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Oqtane.Modules
|
namespace Oqtane.Modules
|
||||||
{
|
{
|
||||||
|
@ -37,6 +38,9 @@ namespace Oqtane.Modules
|
||||||
|
|
||||||
public virtual bool UseAdminContainer { get { return true; } }
|
public virtual bool UseAdminContainer { get { return true; } }
|
||||||
|
|
||||||
|
public virtual List<Resource> Resources { get; set; }
|
||||||
|
|
||||||
|
|
||||||
// path method
|
// path method
|
||||||
|
|
||||||
public string ModulePath()
|
public string ModulePath()
|
||||||
|
|
|
@ -28,9 +28,8 @@
|
||||||
@code {
|
@code {
|
||||||
public override string Panes => "Content";
|
public override string Panes => "Content";
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
await IncludeCSS("Theme.css");
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
|
||||||
}
|
};
|
||||||
|
|
||||||
}
|
}
|
|
@ -17,7 +17,6 @@ namespace Oqtane.Themes
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected Module ModuleState { get; set; }
|
protected Module ModuleState { get; set; }
|
||||||
|
|
||||||
public virtual string Name { get; set; }
|
|
||||||
|
|
||||||
public string ThemePath()
|
public string ThemePath()
|
||||||
{
|
{
|
||||||
|
|
|
@ -149,7 +149,7 @@
|
||||||
<label for="Pane" class="control-label">Pane: </label>
|
<label for="Pane" class="control-label">Pane: </label>
|
||||||
<select class="form-control" @bind="@_pane">
|
<select class="form-control" @bind="@_pane">
|
||||||
<option value=""><Select Pane></option>
|
<option value=""><Select Pane></option>
|
||||||
@foreach (string pane in PageState.Page.Panes.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries))
|
@foreach (string pane in PageState.Page.Panes)
|
||||||
{
|
{
|
||||||
<option value="@pane">@pane Pane</option>
|
<option value="@pane">@pane Pane</option>
|
||||||
}
|
}
|
||||||
|
@ -275,7 +275,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var panes = PageState.Page.Panes.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries);
|
var panes = PageState.Page.Panes;
|
||||||
_pane = panes.Count() == 1 ? panes.SingleOrDefault() : "";
|
_pane = panes.Count() == 1 ? panes.SingleOrDefault() : "";
|
||||||
var themes = await ThemeService.GetThemesAsync();
|
var themes = await ThemeService.GetThemesAsync();
|
||||||
_containers = ThemeService.GetContainerTypes(themes);
|
_containers = ThemeService.GetContainerTypes(themes);
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace Oqtane.Themes.Controls
|
||||||
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
actionList.Add(new ActionViewModel {Name = "Move To Bottom", Action = async (s, m) => await MoveBottom(s, m)});
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string pane in PageState.Page.Panes.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries))
|
foreach (string pane in PageState.Page.Panes)
|
||||||
{
|
{
|
||||||
if (pane != ModuleState.Pane)
|
if (pane != ModuleState.Pane)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,5 @@
|
||||||
{
|
{
|
||||||
public interface IContainerControl
|
public interface IContainerControl
|
||||||
{
|
{
|
||||||
string Name { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,11 +19,10 @@
|
||||||
@code {
|
@code {
|
||||||
public override string Panes => string.Empty;
|
public override string Panes => string.Empty;
|
||||||
|
|
||||||
protected override async Task OnParametersSetAsync()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
// go to https://www.bootstrapcdn.com/bootswatch/ and take your favorite theme
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css", Integrity = "sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM", CrossOrigin = "anonymous" },
|
||||||
//<link href="https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css" rel="stylesheet" integrity="sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM" crossorigin="anonymous">
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
|
||||||
await LoadBootstrapTheme("https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css","sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM");
|
};
|
||||||
await IncludeCSS("Theme.css");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
9
Oqtane.Client/Themes/OqtaneTheme/NoTitle.razor
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
@namespace Oqtane.Themes.OqtaneTheme
|
||||||
|
@inherits ContainerBase
|
||||||
|
<div class="container">
|
||||||
|
@if (PageState.EditMode)
|
||||||
|
{
|
||||||
|
<ModuleActions />
|
||||||
|
}
|
||||||
|
<ModuleInstance />
|
||||||
|
</div>
|
|
@ -1,7 +1,9 @@
|
||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Microsoft.JSInterop;
|
using Microsoft.JSInterop;
|
||||||
|
using Oqtane.Models;
|
||||||
using Oqtane.Shared;
|
using Oqtane.Shared;
|
||||||
using Oqtane.UI;
|
using Oqtane.UI;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
namespace Oqtane.Themes
|
||||||
|
@ -11,31 +13,21 @@ namespace Oqtane.Themes
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
|
||||||
|
// optional interface properties
|
||||||
|
|
||||||
[CascadingParameter]
|
[CascadingParameter]
|
||||||
protected PageState PageState { get; set; }
|
protected PageState PageState { get; set; }
|
||||||
public virtual string Panes { get; set; }
|
public virtual string Panes { get; set; }
|
||||||
|
public virtual List<Resource> Resources { get; set; }
|
||||||
|
|
||||||
|
// path method
|
||||||
|
|
||||||
public string ThemePath()
|
public string ThemePath()
|
||||||
{
|
{
|
||||||
return "Themes/" + GetType().Namespace + "/";
|
return "Themes/" + GetType().Namespace + "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task IncludeCSS(string Url)
|
// url methods
|
||||||
{
|
|
||||||
if (!Url.StartsWith("http"))
|
|
||||||
{
|
|
||||||
Url = ThemePath() + Url;
|
|
||||||
}
|
|
||||||
var interop = new Interop(JSRuntime);
|
|
||||||
await interop.IncludeCSS("Theme", Url);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task LoadBootstrapTheme(string url, string integrity = null)
|
|
||||||
{
|
|
||||||
var interop = new Interop(JSRuntime);
|
|
||||||
string crossorigin = string.IsNullOrEmpty(integrity) ? string.Empty : "anonymous";
|
|
||||||
await interop.IncludeLink("bootstrap", "stylesheet", url, "text/css", integrity, crossorigin);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string NavigateUrl()
|
public string NavigateUrl()
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="mx-auto text-center">
|
<div class="mx-auto text-center">
|
||||||
<img src="oqtane.png" />
|
<img src="oqtane-black.png" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr class="app-rule" />
|
<hr class="app-rule" />
|
||||||
|
|
|
@ -118,6 +118,22 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task RemoveElementsById(string prefix, string first, string last)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_jsRuntime.InvokeAsync<string>(
|
||||||
|
"interop.removeElementsById",
|
||||||
|
prefix, first, last);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public ValueTask<string> GetElementByName(string name)
|
public ValueTask<string> GetElementByName(string name)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -238,21 +238,7 @@
|
||||||
{
|
{
|
||||||
page = await ProcessPage(page, site, user);
|
page = await ProcessPage(page, site, user);
|
||||||
|
|
||||||
_pagestate = new PageState
|
if (PageState != null && (PageState.ModuleId != moduleid || PageState.Action != action))
|
||||||
{
|
|
||||||
Alias = alias,
|
|
||||||
Site = site,
|
|
||||||
Pages = pages,
|
|
||||||
Page = page,
|
|
||||||
User = user,
|
|
||||||
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
|
||||||
QueryString = querystring,
|
|
||||||
ModuleId = moduleid,
|
|
||||||
Action = action,
|
|
||||||
Runtime = runtime
|
|
||||||
};
|
|
||||||
|
|
||||||
if (PageState != null && (PageState.ModuleId != _pagestate.ModuleId || PageState.Action != _pagestate.Action))
|
|
||||||
{
|
{
|
||||||
reload = Reload.Page;
|
reload = Reload.Page;
|
||||||
}
|
}
|
||||||
|
@ -260,15 +246,29 @@
|
||||||
if (PageState == null || reload >= Reload.Page)
|
if (PageState == null || reload >= Reload.Page)
|
||||||
{
|
{
|
||||||
modules = await ModuleService.GetModulesAsync(site.SiteId);
|
modules = await ModuleService.GetModulesAsync(site.SiteId);
|
||||||
modules = ProcessModules(modules, page.PageId, _pagestate.ModuleId, _pagestate.Action, page.Panes, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
|
(page, modules) = ProcessModules(page, modules, moduleid, action, (!string.IsNullOrEmpty(page.DefaultContainerType)) ? page.DefaultContainerType : site.DefaultContainerType);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
modules = PageState.Modules;
|
modules = PageState.Modules;
|
||||||
}
|
}
|
||||||
_pagestate.Modules = modules;
|
|
||||||
_pagestate.EditMode = editmode;
|
_pagestate = new PageState
|
||||||
_pagestate.LastSyncDate = lastsyncdate;
|
{
|
||||||
|
Alias = alias,
|
||||||
|
Site = site,
|
||||||
|
Pages = pages,
|
||||||
|
Page = page,
|
||||||
|
User = user,
|
||||||
|
Modules = modules,
|
||||||
|
Uri = new Uri(_absoluteUri, UriKind.Absolute),
|
||||||
|
QueryString = querystring,
|
||||||
|
ModuleId = moduleid,
|
||||||
|
Action = action,
|
||||||
|
EditMode = editmode,
|
||||||
|
LastSyncDate = lastsyncdate,
|
||||||
|
Runtime = runtime
|
||||||
|
};
|
||||||
|
|
||||||
OnStateChange?.Invoke(_pagestate);
|
OnStateChange?.Invoke(_pagestate);
|
||||||
}
|
}
|
||||||
|
@ -355,19 +355,31 @@
|
||||||
page.ThemeType = site.DefaultThemeType;
|
page.ThemeType = site.DefaultThemeType;
|
||||||
page.LayoutType = site.DefaultLayoutType;
|
page.LayoutType = site.DefaultLayoutType;
|
||||||
}
|
}
|
||||||
Type type;
|
|
||||||
|
page.Panes = new List<string>();
|
||||||
|
page.Resources = new List<Resource>();
|
||||||
|
|
||||||
|
string panes = "";
|
||||||
|
Type themetype = Type.GetType(page.ThemeType);
|
||||||
|
var themeobject = Activator.CreateInstance(themetype);
|
||||||
|
if (themeobject != null)
|
||||||
|
{
|
||||||
|
panes = (string)themetype.GetProperty("Panes").GetValue(themeobject, null);
|
||||||
|
var resources = (List<Resource>)themetype.GetProperty("Resources").GetValue(themeobject, null);
|
||||||
|
page.Resources = ManagePageResources(page.Resources, resources);
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(page.LayoutType))
|
if (!string.IsNullOrEmpty(page.LayoutType))
|
||||||
{
|
{
|
||||||
type = Type.GetType(page.LayoutType);
|
themetype = Type.GetType(page.LayoutType);
|
||||||
}
|
themeobject = Activator.CreateInstance(themetype);
|
||||||
else
|
if (themeobject != null)
|
||||||
{
|
{
|
||||||
type = Type.GetType(page.ThemeType);
|
panes = (string)themetype.GetProperty("Panes").GetValue(themeobject, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var property = type.GetProperty("Panes");
|
page.Panes = panes.Replace(";", ",").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||||
page.Panes = (string)property.GetValue(Activator.CreateInstance(type), null);
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
@ -377,12 +389,12 @@
|
||||||
return page;
|
return page;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Module> ProcessModules(List<Module> modules, int pageid, int moduleid, string control, string panes, string defaultcontainertype)
|
private (Page Page, List<Module> Modules) ProcessModules(Page page, List<Module> modules, int moduleid, string control, string defaultcontainertype)
|
||||||
{
|
{
|
||||||
var paneindex = new Dictionary<string, int>();
|
var paneindex = new Dictionary<string, int>();
|
||||||
foreach (Module module in modules)
|
foreach (Module module in modules)
|
||||||
{
|
{
|
||||||
if (module.PageId == pageid || module.ModuleId == moduleid)
|
if (module.PageId == page.PageId || module.ModuleId == moduleid)
|
||||||
{
|
{
|
||||||
var typename = string.Empty;
|
var typename = string.Empty;
|
||||||
if (module.ModuleDefinition != null)
|
if (module.ModuleDefinition != null)
|
||||||
|
@ -408,49 +420,53 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
module.ModuleType = typename.Replace(Constants.ActionToken, control);
|
module.ModuleType = typename.Replace(Constants.ActionToken, control);
|
||||||
|
|
||||||
// admin controls need to load additional metadata from the IModuleControl interface
|
|
||||||
if (moduleid == module.ModuleId)
|
|
||||||
{
|
|
||||||
typename = module.ModuleType;
|
|
||||||
// check for core module actions component
|
|
||||||
if (Constants.DefaultModuleActions.Contains(control))
|
|
||||||
{
|
|
||||||
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, control);
|
|
||||||
}
|
|
||||||
Type moduletype = Type.GetType(typename);
|
|
||||||
if (moduletype != null)
|
|
||||||
{
|
|
||||||
var moduleobject = Activator.CreateInstance(moduletype);
|
|
||||||
module.SecurityAccessLevel = (SecurityAccessLevel)moduletype.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
|
||||||
module.ControlTitle = (string)moduletype.GetProperty("Title").GetValue(moduleobject);
|
|
||||||
module.Actions = (string)moduletype.GetProperty("Actions").GetValue(moduleobject);
|
|
||||||
module.UseAdminContainer = (bool)moduletype.GetProperty("UseAdminContainer").GetValue(moduleobject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
module.ModuleType = typename.Replace(Constants.ActionToken, Constants.DefaultAction);
|
module.ModuleType = typename.Replace(Constants.ActionToken, Constants.DefaultAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get additional metadata from IModuleControl interface
|
||||||
|
typename = module.ModuleType;
|
||||||
|
if (Constants.DefaultModuleActions.Contains(control))
|
||||||
|
{
|
||||||
|
// core framework module action components
|
||||||
|
typename = Constants.DefaultModuleActionsTemplate.Replace(Constants.ActionToken, control);
|
||||||
|
}
|
||||||
|
Type moduletype = Type.GetType(typename);
|
||||||
|
if (moduletype != null)
|
||||||
|
{
|
||||||
|
var moduleobject = Activator.CreateInstance(moduletype);
|
||||||
|
var resources = (List<Resource>)moduletype.GetProperty("Resources").GetValue(moduleobject, null);
|
||||||
|
page.Resources = ManagePageResources(page.Resources, resources);
|
||||||
|
|
||||||
|
// additional metadata needed for admin components
|
||||||
|
if (module.ModuleId == moduleid && control != "")
|
||||||
|
{
|
||||||
|
module.SecurityAccessLevel = (SecurityAccessLevel)moduletype.GetProperty("SecurityAccessLevel").GetValue(moduleobject, null);
|
||||||
|
module.ControlTitle = (string)moduletype.GetProperty("Title").GetValue(moduleobject);
|
||||||
|
module.Actions = (string)moduletype.GetProperty("Actions").GetValue(moduleobject);
|
||||||
|
module.UseAdminContainer = (bool)moduletype.GetProperty("UseAdminContainer").GetValue(moduleobject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
// ensure module's pane exists in current page and if not, assign it to the Admin pane
|
||||||
if (panes == null || !panes.ToLower().Contains(module.Pane.ToLower()))
|
if (page.Panes == null || page.Panes.FindIndex(item => item.Equals(module.Pane, StringComparison.OrdinalIgnoreCase)) == -1)
|
||||||
{
|
{
|
||||||
module.Pane = Constants.AdminPane;
|
module.Pane = Constants.AdminPane;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate module position within pane
|
// calculate module position within pane
|
||||||
if (paneindex.ContainsKey(module.Pane))
|
if (paneindex.ContainsKey(module.Pane.ToLower()))
|
||||||
{
|
{
|
||||||
paneindex[module.Pane] += 1;
|
paneindex[module.Pane.ToLower()] += 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paneindex.Add(module.Pane, 0);
|
paneindex.Add(module.Pane.ToLower(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.PaneModuleIndex = paneindex[module.Pane];
|
module.PaneModuleIndex = paneindex[module.Pane.ToLower()];
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(module.ContainerType))
|
if (string.IsNullOrEmpty(module.ContainerType))
|
||||||
{
|
{
|
||||||
|
@ -459,12 +475,28 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Module module in modules.Where(item => item.PageId == pageid))
|
foreach (Module module in modules.Where(item => item.PageId == page.PageId))
|
||||||
{
|
{
|
||||||
module.PaneModuleCount = paneindex[module.Pane] + 1;
|
module.PaneModuleCount = paneindex[module.Pane.ToLower()] + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return modules;
|
return (page, modules);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Resource> ManagePageResources(List<Resource> pageresources, List<Resource> resources)
|
||||||
|
{
|
||||||
|
if (resources != null)
|
||||||
|
{
|
||||||
|
foreach (var resource in resources)
|
||||||
|
{
|
||||||
|
// ensure resource does not exist already
|
||||||
|
if (pageresources.Find(item => item.Url == resource.Url) == null)
|
||||||
|
{
|
||||||
|
pageresources.Add(resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pageresources;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Runtime GetRuntime()
|
private Runtime GetRuntime()
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
protected override async Task OnParametersSetAsync()
|
protected override async Task OnParametersSetAsync()
|
||||||
{
|
{
|
||||||
var interop = new Interop(JsRuntime);
|
var interop = new Interop(JsRuntime);
|
||||||
|
|
||||||
|
// set page title
|
||||||
if (!string.IsNullOrEmpty(PageState.Page.Title))
|
if (!string.IsNullOrEmpty(PageState.Page.Title))
|
||||||
{
|
{
|
||||||
await interop.UpdateTitle(PageState.Page.Title);
|
await interop.UpdateTitle(PageState.Page.Title);
|
||||||
|
@ -20,10 +22,34 @@
|
||||||
{
|
{
|
||||||
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
await interop.UpdateTitle(PageState.Site.Name + " - " + PageState.Page.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update page resources
|
||||||
|
int stylesheet = 0;
|
||||||
|
int script = 0;
|
||||||
|
foreach (Resource resource in PageState.Page.Resources)
|
||||||
|
{
|
||||||
|
switch (resource.ResourceType)
|
||||||
|
{
|
||||||
|
case ResourceType.Stylesheet:
|
||||||
|
stylesheet += 1;
|
||||||
|
await interop.IncludeLink("app-stylesheet" + stylesheet.ToString("00"), "stylesheet", resource.Url, "text/css", resource.Integrity ?? "", resource.CrossOrigin ?? "");
|
||||||
|
break;
|
||||||
|
case ResourceType.Script:
|
||||||
|
script += 1;
|
||||||
|
await interop.IncludeScript("app-script" + script.ToString("00"), resource.Url, "", "body", resource.Integrity ?? "", resource.CrossOrigin ?? "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// remove any page resources references which are no longer required for this page
|
||||||
|
await interop.RemoveElementsById("app-stylesheet", "app-stylesheet" + (stylesheet + 1).ToString("00"), "");
|
||||||
|
await interop.RemoveElementsById("app-script", "app-script" + (script + 1).ToString("00"), "");
|
||||||
|
|
||||||
|
// add favicon
|
||||||
if (PageState.Site.FaviconFileId != null)
|
if (PageState.Site.FaviconFileId != null)
|
||||||
{
|
{
|
||||||
await interop.IncludeLink("fav-icon", "shortcut icon", Utilities.ContentUrl(PageState.Alias, PageState.Site.FaviconFileId.Value), "image/x-icon", "", "");
|
await interop.IncludeLink("fav-icon", "shortcut icon", Utilities.ContentUrl(PageState.Alias, PageState.Site.FaviconFileId.Value), "image/x-icon", "", "");
|
||||||
}
|
}
|
||||||
|
// add PWA support
|
||||||
if (PageState.Site.PwaIsEnabled)
|
if (PageState.Site.PwaIsEnabled)
|
||||||
{
|
{
|
||||||
await InitializePwa(interop);
|
await InitializePwa(interop);
|
||||||
|
|
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 7.8 KiB |
|
@ -231,8 +231,8 @@ namespace Oqtane.Controllers
|
||||||
{
|
{
|
||||||
// add embedded resources to project
|
// add embedded resources to project
|
||||||
List<string> resources = new List<string>();
|
List<string> resources = new List<string>();
|
||||||
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.1.0.0.sql"));
|
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.1.0.0.sql"));
|
||||||
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Uninstall.sql"));
|
resources.Add(Utilities.PathCombine("Modules", moduleDefinition.Owner + "." + moduleDefinition.Name, "Scripts", moduleDefinition.Owner + "." + moduleDefinition.Name + "s.Uninstall.sql"));
|
||||||
EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources);
|
EmbedResourceFiles(Utilities.PathCombine(rootPath, "Oqtane.Server", "Oqtane.Server.csproj"), resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ namespace Oqtane.SiteTemplates
|
||||||
new Permission(PermissionNames.Edit, Constants.AdminRole, true)
|
new Permission(PermissionNames.Edit, Constants.AdminRole, true)
|
||||||
}.EncodePermissions(),
|
}.EncodePermissions(),
|
||||||
Content = "<p><a href=\"https://www.oqtane.org\" target=\"_new\">Oqtane</a> is an open source <b>modular application framework</b> built from the ground up using modern .NET Core technology. It leverages the revolutionary new Blazor component model to create a <b>fully dynamic</b> web development experience which can be executed on a client or server. Whether you are looking for a platform to <b>accelerate your web development</b> efforts, or simply interested in exploring the anatomy of a large-scale Blazor application, Oqtane provides a solid foundation based on proven enterprise architectural principles.</p>" +
|
Content = "<p><a href=\"https://www.oqtane.org\" target=\"_new\">Oqtane</a> is an open source <b>modular application framework</b> built from the ground up using modern .NET Core technology. It leverages the revolutionary new Blazor component model to create a <b>fully dynamic</b> web development experience which can be executed on a client or server. Whether you are looking for a platform to <b>accelerate your web development</b> efforts, or simply interested in exploring the anatomy of a large-scale Blazor application, Oqtane provides a solid foundation based on proven enterprise architectural principles.</p>" +
|
||||||
"<p align=\"center\"><a href=\"https://www.oqtane.org\" target=\"_new\"><img class=\"img-fluid\" src=\"oqtane.png\"></a></p><p align=\"center\"><a class=\"btn btn-primary\" href=\"https://www.oqtane.org/Community\" target=\"_new\">Join Our Community</a> <a class=\"btn btn-primary\" href=\"https://github.com/oqtane/oqtane.framework\" target=\"_new\">Clone Our Repo</a></p>" +
|
"<p align=\"center\"><a href=\"https://www.oqtane.org\" target=\"_new\"><img class=\"img-fluid\" src=\"oqtane-white.png\"></a></p><p align=\"center\"><a class=\"btn btn-primary\" href=\"https://www.oqtane.org/Community\" target=\"_new\">Join Our Community</a> <a class=\"btn btn-primary\" href=\"https://github.com/oqtane/oqtane.framework\" target=\"_new\">Clone Our Repo</a></p>" +
|
||||||
"<p><a href=\"https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor\" target=\"_new\">Blazor</a> is a single-page app framework that lets you build interactive web applications using C# instead of JavaScript. Client-side Blazor relies on WebAssembly, an open web standard that does not require plugins or code transpilation in order to run natively in a web browser. Server-side Blazor uses SignalR to host your application on a web server and provide a responsive and robust debugging experience. Blazor applications works in all modern web browsers, including mobile browsers.</p>" +
|
"<p><a href=\"https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor\" target=\"_new\">Blazor</a> is a single-page app framework that lets you build interactive web applications using C# instead of JavaScript. Client-side Blazor relies on WebAssembly, an open web standard that does not require plugins or code transpilation in order to run natively in a web browser. Server-side Blazor uses SignalR to host your application on a web server and provide a responsive and robust debugging experience. Blazor applications works in all modern web browsers, including mobile browsers.</p>" +
|
||||||
"<p>Blazor is a feature of <a href=\"https://dotnet.microsoft.com/apps/aspnet\" target=\"_new\">ASP.NET Core 3</a>, the popular cross platform web development framework from Microsoft that extends the <a href=\"https://dotnet.microsoft.com/learn/dotnet/what-is-dotnet\" target=\"_new\" >.NET developer platform</a> with tools and libraries for building web apps.</p>"
|
"<p>Blazor is a feature of <a href=\"https://dotnet.microsoft.com/apps/aspnet\" target=\"_new\">ASP.NET Core 3</a>, the popular cross platform web development framework from Microsoft that extends the <a href=\"https://dotnet.microsoft.com/learn/dotnet/what-is-dotnet\" target=\"_new\" >.NET developer platform</a> with tools and libraries for building web apps.</p>"
|
||||||
},
|
},
|
||||||
|
@ -132,16 +132,16 @@ namespace Oqtane.SiteTemplates
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (System.IO.File.Exists(Path.Combine(_environment.WebRootPath, "images", "logo.png")))
|
if (System.IO.File.Exists(Path.Combine(_environment.WebRootPath, "images", "logo-white.png")))
|
||||||
{
|
{
|
||||||
string folderpath = Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", site.TenantId.ToString(), "Sites", site.SiteId.ToString(),"\\");
|
string folderpath = Utilities.PathCombine(_environment.ContentRootPath, "Content", "Tenants", site.TenantId.ToString(), "Sites", site.SiteId.ToString(),"\\");
|
||||||
System.IO.Directory.CreateDirectory(folderpath);
|
System.IO.Directory.CreateDirectory(folderpath);
|
||||||
if (!System.IO.File.Exists(Path.Combine(folderpath, "logo.png")))
|
if (!System.IO.File.Exists(Path.Combine(folderpath, "logo-white.png")))
|
||||||
{
|
{
|
||||||
System.IO.File.Copy(Path.Combine(_environment.WebRootPath, "images", "logo.png"), Path.Combine(folderpath, "logo.png"));
|
System.IO.File.Copy(Path.Combine(_environment.WebRootPath, "images", "logo-white.png"), Path.Combine(folderpath, "logo-white.png"));
|
||||||
}
|
}
|
||||||
Folder folder = _folderRepository.GetFolder(site.SiteId, "");
|
Folder folder = _folderRepository.GetFolder(site.SiteId, "");
|
||||||
Oqtane.Models.File file = _fileRepository.AddFile(new Oqtane.Models.File { FolderId = folder.FolderId, Name = "logo.png", Extension = "png", Size = 8192, ImageHeight = 80, ImageWidth = 250 });
|
Oqtane.Models.File file = _fileRepository.AddFile(new Oqtane.Models.File { FolderId = folder.FolderId, Name = "logo-white.png", Extension = "png", Size = 8192, ImageHeight = 80, ImageWidth = 250 });
|
||||||
site.LogoFileId = file.FileId;
|
site.LogoFileId = file.FileId;
|
||||||
_siteRepository.UpdateSite(site);
|
_siteRepository.UpdateSite(site);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,8 +14,6 @@
|
||||||
<link id="fav-icon" rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link id="fav-icon" rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
||||||
<!-- stub the PWA manifest but defer the assignment of href -->
|
<!-- stub the PWA manifest but defer the assignment of href -->
|
||||||
<link id="pwa-manifest" rel="manifest" />
|
<link id="pwa-manifest" rel="manifest" />
|
||||||
<link href="css/quill/quill1.3.6.bubble.css" rel="stylesheet" />
|
|
||||||
<link href="css/quill/quill1.3.6.snow.css" rel="stylesheet" />
|
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
|
||||||
<link href="css/app.css" rel="stylesheet" />
|
<link href="css/app.css" rel="stylesheet" />
|
||||||
</head>
|
</head>
|
||||||
|
@ -25,10 +23,7 @@
|
||||||
<component type="typeof(Oqtane.App)" render-mode="Server" />
|
<component type="typeof(Oqtane.App)" render-mode="Server" />
|
||||||
</app>
|
</app>
|
||||||
|
|
||||||
<script src="js/site.js"></script>
|
|
||||||
<script src="js/interop.js"></script>
|
<script src="js/interop.js"></script>
|
||||||
<script src="js/quill1.3.6.min.js"></script>
|
|
||||||
<script src="js/quill-blot-formatter.min.js"></script>
|
|
||||||
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
|
||||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
<body>
|
<body>
|
||||||
<div>
|
<div>
|
||||||
<br /><br /><h1 align="center">Please Wait... Upgrade In Progress....</h1>
|
<br /><br /><h1 align="center">Please Wait... Upgrade In Progress....</h1>
|
||||||
<img src="https://www.oqtane.org/Portals/0/oqtane.png" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);" />
|
<img src="https://www.oqtane.org/Portals/0/oqtane-black.png" style="position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);" />
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* HtmlText Module Custom Styles */
|
BIN
Oqtane.Server/wwwroot/images/logo-black.png
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
Oqtane.Server/wwwroot/images/logo-white.png
Normal file
After Width: | Height: | Size: 7.8 KiB |
|
@ -62,10 +62,10 @@ window.interop = {
|
||||||
link.id = id;
|
link.id = id;
|
||||||
}
|
}
|
||||||
link.rel = rel;
|
link.rel = rel;
|
||||||
link.href = url;
|
|
||||||
if (type !== "") {
|
if (type !== "") {
|
||||||
link.type = type;
|
link.type = type;
|
||||||
}
|
}
|
||||||
|
link.href = url;
|
||||||
if (integrity !== "") {
|
if (integrity !== "") {
|
||||||
link.integrity = integrity;
|
link.integrity = integrity;
|
||||||
}
|
}
|
||||||
|
@ -78,9 +78,6 @@ window.interop = {
|
||||||
if (link.rel !== rel) {
|
if (link.rel !== rel) {
|
||||||
link.setAttribute('rel', rel);
|
link.setAttribute('rel', rel);
|
||||||
}
|
}
|
||||||
if (link.href !== url) {
|
|
||||||
link.setAttribute('href', url);
|
|
||||||
}
|
|
||||||
if (type !== "") {
|
if (type !== "") {
|
||||||
if (link.type !== type) {
|
if (link.type !== type) {
|
||||||
link.setAttribute('type', type);
|
link.setAttribute('type', type);
|
||||||
|
@ -88,6 +85,11 @@ window.interop = {
|
||||||
} else {
|
} else {
|
||||||
link.removeAttribute('type');
|
link.removeAttribute('type');
|
||||||
}
|
}
|
||||||
|
if (link.href !== url) {
|
||||||
|
link.removeAttribute('integrity');
|
||||||
|
link.removeAttribute('crossorigin');
|
||||||
|
link.setAttribute('href', url);
|
||||||
|
}
|
||||||
if (integrity !== "") {
|
if (integrity !== "") {
|
||||||
if (link.integrity !== integrity) {
|
if (link.integrity !== integrity) {
|
||||||
link.setAttribute('integrity', integrity);
|
link.setAttribute('integrity', integrity);
|
||||||
|
@ -136,6 +138,8 @@ window.interop = {
|
||||||
else {
|
else {
|
||||||
if (src !== "") {
|
if (src !== "") {
|
||||||
if (script.src !== src) {
|
if (script.src !== src) {
|
||||||
|
script.removeAttribute('integrity');
|
||||||
|
script.removeAttribute('crossorigin');
|
||||||
script.src = src;
|
script.src = src;
|
||||||
}
|
}
|
||||||
if (integrity !== "") {
|
if (integrity !== "") {
|
||||||
|
@ -160,6 +164,15 @@ window.interop = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
removeElementsById: function (prefix, first, last) {
|
||||||
|
var elements = document.querySelectorAll('[id^=' + prefix + ']');
|
||||||
|
for (var i = elements.length - 1; i >= 0; i--) {
|
||||||
|
var element = elements[i];
|
||||||
|
if (element.id.startsWith(prefix) && (first === '' || element.id >= first) && (last === '' || element.id <= last)) {
|
||||||
|
element.parentNode.removeChild(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
getElementByName: function (name) {
|
getElementByName: function (name) {
|
||||||
var elements = document.getElementsByName(name);
|
var elements = document.getElementsByName(name);
|
||||||
if (elements.length) {
|
if (elements.length) {
|
||||||
|
@ -251,53 +264,5 @@ window.interop = {
|
||||||
request.send(data);
|
request.send(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
createQuill: function (
|
|
||||||
quillElement, toolBar, readOnly,
|
|
||||||
placeholder, theme, debugLevel) {
|
|
||||||
|
|
||||||
Quill.register('modules/blotFormatter', QuillBlotFormatter.default);
|
|
||||||
|
|
||||||
var options = {
|
|
||||||
debug: debugLevel,
|
|
||||||
modules: {
|
|
||||||
toolbar: toolBar,
|
|
||||||
blotFormatter: {}
|
|
||||||
},
|
|
||||||
placeholder: placeholder,
|
|
||||||
readOnly: readOnly,
|
|
||||||
theme: theme
|
|
||||||
};
|
|
||||||
|
|
||||||
new Quill(quillElement, options);
|
|
||||||
},
|
|
||||||
getQuillContent: function (editorElement) {
|
|
||||||
return JSON.stringify(editorElement.__quill.getContents());
|
|
||||||
},
|
|
||||||
getQuillText: function (editorElement) {
|
|
||||||
return editorElement.__quill.getText();
|
|
||||||
},
|
|
||||||
getQuillHTML: function (editorElement) {
|
|
||||||
return editorElement.__quill.root.innerHTML;
|
|
||||||
},
|
|
||||||
loadQuillContent: function (editorElement, editorContent) {
|
|
||||||
return editorElement.__quill.root.innerHTML = editorContent;
|
|
||||||
},
|
|
||||||
enableQuillEditor: function (editorElement, mode) {
|
|
||||||
editorElement.__quill.enable(mode);
|
|
||||||
},
|
|
||||||
insertQuillImage: function (quillElement, imageURL) {
|
|
||||||
var Delta = Quill.import('delta');
|
|
||||||
editorIndex = 0;
|
|
||||||
|
|
||||||
if (quillElement.__quill.getSelection() !== null) {
|
|
||||||
editorIndex = quillElement.__quill.getSelection().index;
|
|
||||||
}
|
|
||||||
|
|
||||||
return quillElement.__quill.updateContents(
|
|
||||||
new Delta()
|
|
||||||
.retain(editorIndex)
|
|
||||||
.insert({ image: imageURL },
|
|
||||||
{ alt: imageURL }));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
50
Oqtane.Server/wwwroot/js/quill-interop.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
window.interop = {
|
||||||
|
createQuill: function (
|
||||||
|
quillElement, toolBar, readOnly,
|
||||||
|
placeholder, theme, debugLevel) {
|
||||||
|
|
||||||
|
Quill.register('modules/blotFormatter', QuillBlotFormatter.default);
|
||||||
|
|
||||||
|
var options = {
|
||||||
|
debug: debugLevel,
|
||||||
|
modules: {
|
||||||
|
toolbar: toolBar,
|
||||||
|
blotFormatter: {}
|
||||||
|
},
|
||||||
|
placeholder: placeholder,
|
||||||
|
readOnly: readOnly,
|
||||||
|
theme: theme
|
||||||
|
};
|
||||||
|
|
||||||
|
new Quill(quillElement, options);
|
||||||
|
},
|
||||||
|
getQuillContent: function (editorElement) {
|
||||||
|
return JSON.stringify(editorElement.__quill.getContents());
|
||||||
|
},
|
||||||
|
getQuillText: function (editorElement) {
|
||||||
|
return editorElement.__quill.getText();
|
||||||
|
},
|
||||||
|
getQuillHTML: function (editorElement) {
|
||||||
|
return editorElement.__quill.root.innerHTML;
|
||||||
|
},
|
||||||
|
loadQuillContent: function (editorElement, editorContent) {
|
||||||
|
return editorElement.__quill.root.innerHTML = editorContent;
|
||||||
|
},
|
||||||
|
enableQuillEditor: function (editorElement, mode) {
|
||||||
|
editorElement.__quill.enable(mode);
|
||||||
|
},
|
||||||
|
insertQuillImage: function (quillElement, imageURL) {
|
||||||
|
var Delta = Quill.import('delta');
|
||||||
|
editorIndex = 0;
|
||||||
|
|
||||||
|
if (quillElement.__quill.getSelection() !== null) {
|
||||||
|
editorIndex = quillElement.__quill.getSelection().index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return quillElement.__quill.updateContents(
|
||||||
|
new Delta()
|
||||||
|
.retain(editorIndex)
|
||||||
|
.insert({ image: imageURL },
|
||||||
|
{ alt: imageURL }));
|
||||||
|
}
|
||||||
|
};
|
|
@ -1 +0,0 @@
|
||||||
|
|
BIN
Oqtane.Server/wwwroot/oqtane-black.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
Oqtane.Server/wwwroot/oqtane-white.png
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 14 KiB |
8
Oqtane.Shared/Enums/ResourceType.cs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
namespace Oqtane.Shared
|
||||||
|
{
|
||||||
|
public enum ResourceType
|
||||||
|
{
|
||||||
|
Stylesheet,
|
||||||
|
Script
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using Oqtane.Shared;
|
using Oqtane.Models;
|
||||||
|
using Oqtane.Shared;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace Oqtane.Modules
|
namespace Oqtane.Modules
|
||||||
{
|
{
|
||||||
|
@ -8,5 +10,6 @@ namespace Oqtane.Modules
|
||||||
string Title { get; } // title to display for this control - defaults to module title
|
string Title { get; } // title to display for this control - defaults to module title
|
||||||
string Actions { get; } // allows for routing by configuration rather than by convention ( comma delimited ) - defaults to using component file name
|
string Actions { get; } // allows for routing by configuration rather than by convention ( comma delimited ) - defaults to using component file name
|
||||||
bool UseAdminContainer { get; } // container for embedding module control - defaults to true. false will suppress the default modal UI popup behavior and render the component in the page.
|
bool UseAdminContainer { get; } // container for embedding module control - defaults to true. false will suppress the default modal UI popup behavior and render the component in the page.
|
||||||
|
List<Resource> Resources { get; } // identifies all resources in a module
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
namespace Oqtane.Themes
|
using Oqtane.Models;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Oqtane.Themes
|
||||||
{
|
{
|
||||||
public interface IThemeControl
|
public interface IThemeControl
|
||||||
{
|
{
|
||||||
string Panes { get; } // identifies all panes in a theme ( delimited by ";" ) - assumed to be a layout if no panes specified
|
string Panes { get; } // identifies all panes in a theme ( delimited by ";" ) - assumed to be a layout if no panes specified
|
||||||
|
List<Resource> Resources { get; } // identifies all resources in a theme
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
namespace Oqtane.Models
|
namespace Oqtane.Models
|
||||||
|
@ -31,7 +32,9 @@ namespace Oqtane.Models
|
||||||
public bool IsDeleted { get; set; }
|
public bool IsDeleted { get; set; }
|
||||||
|
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string Panes { get; set; }
|
public List<string> Panes { get; set; }
|
||||||
|
[NotMapped]
|
||||||
|
public List<Resource> Resources { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
public string Permissions { get; set; }
|
public string Permissions { get; set; }
|
||||||
[NotMapped]
|
[NotMapped]
|
||||||
|
|
12
Oqtane.Shared/Models/Resource.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Oqtane.Shared;
|
||||||
|
|
||||||
|
namespace Oqtane.Models
|
||||||
|
{
|
||||||
|
public class Resource
|
||||||
|
{
|
||||||
|
public ResourceType ResourceType { get; set; }
|
||||||
|
public string Url { get; set; }
|
||||||
|
public string Integrity { get; set; }
|
||||||
|
public string CrossOrigin { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
namespace Oqtane.Models
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Oqtane.Models
|
||||||
{
|
{
|
||||||
public class Theme
|
public class Theme
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,9 +11,9 @@ namespace Oqtane.Shared
|
||||||
public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client";
|
public const string PageComponent = "Oqtane.UI.ThemeBuilder, Oqtane.Client";
|
||||||
public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client";
|
public const string ContainerComponent = "Oqtane.UI.ContainerBuilder, Oqtane.Client";
|
||||||
|
|
||||||
public const string DefaultTheme = "Oqtane.Themes.BlazorTheme.Default, Oqtane.Client";
|
public const string DefaultTheme = "Oqtane.Themes.OqtaneTheme.Default, Oqtane.Client";
|
||||||
public const string DefaultLayout = "";
|
public const string DefaultLayout = "Oqtane.Themes.OqtaneTheme.SinglePane, Oqtane.Client";
|
||||||
public const string DefaultContainer = "Oqtane.Themes.BlazorTheme.Container, Oqtane.Client";
|
public const string DefaultContainer = "Oqtane.Themes.OqtaneTheme.Container, Oqtane.Client";
|
||||||
public const string DefaultAdminContainer = "Oqtane.Themes.AdminContainer, Oqtane.Client";
|
public const string DefaultAdminContainer = "Oqtane.Themes.AdminContainer, Oqtane.Client";
|
||||||
|
|
||||||
public const string ActionToken = "{Action}";
|
public const string ActionToken = "{Action}";
|
||||||
|
|