Merge pull request #1959 from sbwalker/dev

added router support for url fragments, added language attribute to HTML document tag to improve validation, fixed Theme Settings so they can only be invoked via the Control Panel, added support for webp image files
This commit is contained in:
Shaun Walker 2022-01-22 19:24:51 -05:00 committed by GitHub
commit 7b9a83a273
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 336 additions and 267 deletions

View File

@ -384,6 +384,8 @@
private void ThemeSettings()
{
_themeSettingsType = null;
if (PageState.QueryString.ContainsKey("cp")) // can only be displayed if invoked from Control Panel
{
var theme = _themeList.FirstOrDefault(item => item.Themes.Any(themecontrol => themecontrol.TypeName.Equals(_themetype)));
if (theme != null && !string.IsNullOrEmpty(theme.ThemeSettingsType))
{
@ -400,6 +402,7 @@
_refresh = true;
}
}
}
private async Task SavePage()
{

View File

@ -3,7 +3,9 @@
@attribute [OqtaneIgnore]
<span class="app-moduletitle">
<a id="@ModuleState.PageModuleId.ToString()">
@((MarkupString)title)
</a>
</span>
@code {

View File

@ -279,5 +279,19 @@ namespace Oqtane.UI
}
}
public Task ScrollToId(string id)
{
try
{
_jsRuntime.InvokeVoidAsync(
"Oqtane.Interop.scrollToId",
id);
return Task.CompletedTask;
}
catch
{
return Task.CompletedTask;
}
}
}
}

View File

@ -11,6 +11,7 @@
@inject IModuleService ModuleService
@inject IUrlMappingService UrlMappingService
@inject ILogService LogService
@inject IJSRuntime JSRuntime
@implements IHandleAfterRender
@DynamicComponent
@ -234,6 +235,7 @@
};
OnStateChange?.Invoke(_pagestate);
await ScrollToFragment(_pagestate.Uri);
}
}
else // page not found
@ -496,4 +498,25 @@
}
return pageresources;
}
private async Task ScrollToFragment(Uri uri)
{
var fragment = uri.Fragment;
if (fragment.StartsWith('#'))
{
// handle text fragment (https://example.org/#test:~:text=foo)
var id = fragment.Substring(1);
var index = id.IndexOf(":~:", StringComparison.Ordinal);
if (index > 0)
{
id = id.Substring(0, index);
}
if (!string.IsNullOrEmpty(id))
{
var interop = new Interop(JSRuntime);
await interop.ScrollToId(id);
}
}
}
}

View File

@ -3,7 +3,7 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model Oqtane.Pages.HostModel
<!DOCTYPE html>
<html>
<html lang="@Model.Language">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width">

View File

@ -52,6 +52,7 @@ namespace Oqtane.Pages
_settings = settings;
}
public string Language = "en";
public string AntiForgeryToken = "";
public string Runtime = "Server";
public RenderMode RenderMode = RenderMode.Server;
@ -174,19 +175,29 @@ namespace Oqtane.Pages
}
// set culture if not specified
if (HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName] == null)
string culture = HttpContext.Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
if (culture == null)
{
// set default language for site if the culture is not supported
// get default language for site
var languages = _languages.GetLanguages(alias.SiteId);
if (languages.Any() && languages.All(l => l.Code != CultureInfo.CurrentUICulture.Name))
if (languages.Any())
{
var defaultLanguage = languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First();
SetLocalizationCookie(defaultLanguage.Code);
// use default language if specified otherwise use first language in collection
culture = (languages.Where(l => l.IsDefault).SingleOrDefault() ?? languages.First()).Code;
}
else
{
SetLocalizationCookie(_localizationManager.GetDefaultCulture());
culture = _localizationManager.GetDefaultCulture();
}
SetLocalizationCookie(culture);
}
// set language for page
if (!string.IsNullOrEmpty(culture))
{
// localization cookie value in form of c=en|uic=en
Language = culture.Split('|')[0];
Language = Language.Replace("c=", "");
}
}
}

View File

@ -125,6 +125,8 @@ namespace Oqtane.Repository
foreach (Type containertype in containertypes)
{
var containerobject = Activator.CreateInstance(containertype) as IThemeControl;
if (theme.Containers.FirstOrDefault(item => item.TypeName == containertype.FullName + ", " + themeControlType.Assembly.GetName().Name) == null)
{
theme.Containers.Add(
new ThemeControl
{
@ -135,6 +137,7 @@ namespace Oqtane.Repository
}
);
}
}
themes[index] = theme;
}

View File

@ -126,6 +126,10 @@ app {
margin-bottom: 15px;
}
.app-moduletitle a {
scroll-margin-top: 7rem;
}
/* Tooltips */
.app-tooltip {
cursor: help;

View File

@ -376,5 +376,14 @@ Oqtane.Interop = {
left: left,
behavior: behavior
});
},
scrollToId: function (id) {
var element = document.getElementById(id);
if (element instanceof HTMLElement) {
element.scrollIntoView({
behavior: "smooth",
block: "start",
inline: "nearest"
});
}
};
}};

View File

@ -62,7 +62,7 @@ namespace Oqtane.Shared {
[Obsolete(RoleObsoleteMessage)]
public const string RegisteredRole = RoleNames.Registered;
public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png,ico";
public const string ImageFiles = "jpg,jpeg,jpe,gif,bmp,png,ico,webp";
public const string UploadableFiles = ImageFiles + ",mov,wmv,avi,mp4,mp3,doc,docx,xls,xlsx,ppt,pptx,pdf,txt,zip,nupkg,csv";
public const string ReservedDevices = "CON,NUL,PRN,COM0,COM1,COM2,COM3,COM4,COM5,COM6,COM7,COM8,COM9,LPT0,LPT1,LPT2,LPT3,LPT4,LPT5,LPT6,LPT7,LPT8,LPT9,CONIN$,CONOUT$";