Merge pull request #621 from sbwalker/master
resolve #566 by moving Bootstrap declaration into theme
This commit is contained in:
commit
d4d12b6f41
|
@ -4,12 +4,12 @@
|
||||||
|
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div>
|
<div>
|
||||||
<a data-toggle="collapse" class="app-link-unstyled" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name">
|
<a data-toggle="collapse" class="app-link-unstyled" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name" @onclick:preventDefault="true">
|
||||||
<h5>@_heading</h5>
|
<h5>@_heading</h5>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-auto">
|
<div class="ml-auto">
|
||||||
<a data-toggle="collapse" class="app-link-unstyled float-right" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name">
|
<a data-toggle="collapse" class="app-link-unstyled float-right" href="#@Name" aria-expanded="@_expanded" aria-controls="@Name" @onclick:preventDefault="true">
|
||||||
<i class="oi oi-chevron-bottom"></i>
|
<i class="oi oi-chevron-bottom"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,13 +11,13 @@
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
@if (tabPanel.Name == ActiveTab)
|
@if (tabPanel.Name == ActiveTab)
|
||||||
{
|
{
|
||||||
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab">
|
<a class="nav-link active" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
||||||
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab">
|
<a class="nav-link" data-toggle="tab" href="#@tabPanel.Name" role="tab" @onclick:preventDefault="true">
|
||||||
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
@DisplayHeading(tabPanel.Name, tabPanel.Heading)
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,7 +55,7 @@ namespace Oqtane.Modules
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
foreach (var resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
foreach (var resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
||||||
{
|
{
|
||||||
await interop.LoadScript(resource.Url);
|
await interop.LoadScript(resource.Url, resource.Integrity ?? "", resource.CrossOrigin ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
@namespace Oqtane.Themes.BlazorTheme
|
@namespace Oqtane.Themes.BlazorTheme
|
||||||
@inherits ThemeBase
|
@inherits ThemeBase
|
||||||
|
@implements IThemeControl
|
||||||
|
|
||||||
<div class="breadcrumbs">
|
<div class="breadcrumbs">
|
||||||
<Breadcrumbs />
|
<Breadcrumbs />
|
||||||
|
@ -30,6 +31,16 @@
|
||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css", Integrity = "sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T", CrossOrigin = "anonymous" },
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.LoadBootstrapJS();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
@namespace Oqtane.Themes.OqtaneTheme
|
@namespace Oqtane.Themes.OqtaneTheme
|
||||||
@inherits ThemeBase
|
@inherits ThemeBase
|
||||||
|
@implements IThemeControl
|
||||||
|
|
||||||
<main role="main">
|
<main role="main">
|
||||||
<nav class="navbar navbar-expand-md navbar-dark bg-primary fixed-top">
|
<nav class="navbar navbar-expand-md navbar-dark bg-primary fixed-top">
|
||||||
|
@ -23,10 +24,16 @@
|
||||||
|
|
||||||
public override List<Resource> Resources => new List<Resource>()
|
public override List<Resource> Resources => new List<Resource>()
|
||||||
{
|
{
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "BootswatchCyborg.css" },
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css", Integrity = "sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM", CrossOrigin = "anonymous" },
|
||||||
// remote stylesheets can be linked using the format below, however we want the default theme to display properly in local development scenarios where an Internet connection is not available
|
|
||||||
//new Resource { ResourceType = ResourceType.Stylesheet, Url = "https://stackpath.bootstrapcdn.com/bootswatch/4.4.1/cyborg/bootstrap.min.css", Integrity = "sha384-l7xaoY0cJM4h9xh1RfazbgJVUZvdtyLWPueWNtLAphf/UbBgOVzqbOTogxPwYLHM", CrossOrigin = "anonymous" },
|
|
||||||
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
|
new Resource { ResourceType = ResourceType.Stylesheet, Url = ThemePath() + "Theme.css" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
var interop = new Interop(JSRuntime);
|
||||||
|
await interop.LoadBootstrapJS();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Oqtane.Themes
|
namespace Oqtane.Themes
|
||||||
{
|
{
|
||||||
public abstract class ThemeBase : ComponentBase, IThemeControl
|
public abstract class ThemeBase : ComponentBase
|
||||||
{
|
{
|
||||||
[Inject]
|
[Inject]
|
||||||
protected IJSRuntime JSRuntime { get; set; }
|
protected IJSRuntime JSRuntime { get; set; }
|
||||||
|
@ -34,7 +34,7 @@ namespace Oqtane.Themes
|
||||||
var interop = new Interop(JSRuntime);
|
var interop = new Interop(JSRuntime);
|
||||||
foreach (var resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
foreach (var resource in Resources.Where(item => item.ResourceType == ResourceType.Script))
|
||||||
{
|
{
|
||||||
await interop.LoadScript(resource.Url);
|
await interop.LoadScript(resource.Url, resource.Integrity ?? "", resource.CrossOrigin ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,11 +117,23 @@ namespace Oqtane.UI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task LoadScript(string path)
|
public async Task LoadScript(string url, string integrity, string crossorigin)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _jsRuntime.InvokeVoidAsync("Oqtane.Interop.loadScript", path);
|
await _jsRuntime.InvokeVoidAsync("Oqtane.Interop.loadScript", url, integrity, crossorigin);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// ignore exception
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadBootstrapJS()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _jsRuntime.InvokeVoidAsync("Oqtane.Interop.loadBootstrapJS");
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
<link id="app-favicon" rel="shortcut icon" type="image/x-icon" href="favicon.ico" />
|
<link id="app-favicon" 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="app-manifest" rel="manifest" />
|
<link id="app-manifest" rel="manifest" />
|
||||||
<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="css/app.css" />
|
<link rel="stylesheet" href="css/app.css" />
|
||||||
<script src="js/loadjs.min.js"></script>
|
<script src="js/loadjs.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
@ -36,9 +35,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="js/interop.js"></script>
|
<script src="js/interop.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://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>
|
|
||||||
|
|
||||||
@if (Configuration.GetSection("Runtime").Value == "WebAssembly")
|
@if (Configuration.GetSection("Runtime").Value == "WebAssembly")
|
||||||
{
|
{
|
||||||
|
|
|
@ -198,12 +198,30 @@ Oqtane.Interop = {
|
||||||
script.onerror = rej();
|
script.onerror = rej();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
loadScript: async function (path) {
|
loadScript: async function (url, integrity, crossorigin) {
|
||||||
const promise = new Promise((resolve, reject) => {
|
const promise = new Promise((resolve, reject) => {
|
||||||
loadjs(path, { returnPromise: true })
|
|
||||||
|
if (loadjs.isDefined(url)) {
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadjs(url, url, {
|
||||||
|
async: false,
|
||||||
|
returnPromise: true,
|
||||||
|
before: function (path, element) {
|
||||||
|
if (path === url && integrity !== '') {
|
||||||
|
element.integrity = integrity;
|
||||||
|
}
|
||||||
|
if (path === url && crossorigin !== '') {
|
||||||
|
element.crossOrigin = crossorigin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
.then(function () { resolve(true) })
|
.then(function () { resolve(true) })
|
||||||
.catch(function (pathsNotFound) { reject(false) });
|
.catch(function (pathsNotFound) { reject(false) });
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await promise;
|
const result = await promise;
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
@ -325,5 +343,31 @@ Oqtane.Interop = {
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}, wait * 1000);
|
}, wait * 1000);
|
||||||
|
},
|
||||||
|
loadBootstrapJS: async function () {
|
||||||
|
if (!loadjs.isDefined('Bootstrap')) {
|
||||||
|
const bootstrap = loadjs(['https://code.jquery.com/jquery-3.3.1.slim.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js', 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js'], 'Bootstrap', {
|
||||||
|
async: false,
|
||||||
|
returnPromise: true,
|
||||||
|
before: function (path, element) {
|
||||||
|
if (path === 'https://code.jquery.com/jquery-3.3.1.slim.min.js') {
|
||||||
|
element.integrity = 'sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo';
|
||||||
|
element.crossOrigin = 'anonymous';
|
||||||
|
}
|
||||||
|
if (path === 'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js') {
|
||||||
|
element.integrity = 'sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1';
|
||||||
|
element.crossOrigin = 'anonymous';
|
||||||
|
}
|
||||||
|
if (path === 'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js') {
|
||||||
|
element.integrity = 'sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM';
|
||||||
|
element.crossOrigin = 'anonymous';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(function () { })
|
||||||
|
.catch(function (pathsNotFound) { });
|
||||||
|
|
||||||
|
await bootstrap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,10 +5,15 @@ Oqtane.RichTextEditor = {
|
||||||
quillElement, toolBar, readOnly,
|
quillElement, toolBar, readOnly,
|
||||||
placeholder, theme, debugLevel) {
|
placeholder, theme, debugLevel) {
|
||||||
|
|
||||||
|
if (!loadjs.isDefined('Quill')) {
|
||||||
const loadQuill = loadjs(['js/quill1.3.6.min.js', 'js/quill-blot-formatter.min.js'], 'Quill',
|
const loadQuill = loadjs(['js/quill1.3.6.min.js', 'js/quill-blot-formatter.min.js'], 'Quill',
|
||||||
{ async: true, returnPromise: true })
|
{ async: true, returnPromise: true })
|
||||||
.then(function () {
|
.then(function () {
|
||||||
Quill.register('modules/blotFormatter', QuillBlotFormatter.default);
|
Quill.register('modules/blotFormatter', QuillBlotFormatter.default);
|
||||||
|
})
|
||||||
|
.catch(function (pathsNotFound) { });
|
||||||
|
await loadQuill;
|
||||||
|
}
|
||||||
|
|
||||||
var options = {
|
var options = {
|
||||||
debug: debugLevel,
|
debug: debugLevel,
|
||||||
|
@ -22,10 +27,6 @@ Oqtane.RichTextEditor = {
|
||||||
};
|
};
|
||||||
|
|
||||||
new Quill(quillElement, options);
|
new Quill(quillElement, options);
|
||||||
})
|
|
||||||
.catch(function (pathsNotFound) { });
|
|
||||||
|
|
||||||
await loadQuill;
|
|
||||||
},
|
},
|
||||||
getQuillContent: function (editorElement) {
|
getQuillContent: function (editorElement) {
|
||||||
return JSON.stringify(editorElement.__quill.getContents());
|
return JSON.stringify(editorElement.__quill.getContents());
|
||||||
|
|
Loading…
Reference in New Issue
Block a user