Merge pull request #2817 from sbwalker/dev

added HeadContent property to Site and replaced Meta property on Page with HeadContent property.
This commit is contained in:
Shaun Walker 2023-05-16 16:23:34 -04:00 committed by GitHub
commit e32ca089ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 346 additions and 281 deletions

View File

@ -85,6 +85,15 @@
<input id="url" class="form-control" @bind="@_url" /> <input id="url" class="form-control" @bind="@_url" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9">
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div> </div>
<Section Name="Appearance" ResourceKey="Appearance"> <Section Name="Appearance" ResourceKey="Appearance">
@ -96,9 +105,9 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="meta" HelpText="Optionally enter meta tags (in exactly the form you want them to be included in the page output)." ResourceKey="Meta">Meta: </Label> <Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<textarea id="meta" class="form-control" @bind="@_meta" rows="3"></textarea> <input id="icon" class="form-control" @bind="@_icon" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
@ -125,18 +134,9 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label> <Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta and link tags are valid, script tags are not)." ResourceKey="HeadContent">Head Content: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="icon" class="form-control" @bind="@_icon" /> <textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9">
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div> </div>
</div> </div>
</div> </div>
@ -170,7 +170,6 @@
private List<ThemeControl> _containers = new List<ThemeControl>(); private List<ThemeControl> _containers = new List<ThemeControl>();
private string _name; private string _name;
private string _title; private string _title;
private string _meta;
private string _path = string.Empty; private string _path = string.Empty;
private string _parentid = "-1"; private string _parentid = "-1";
private string _insert = ">>"; private string _insert = ">>";
@ -182,6 +181,7 @@
private string _ispersonalizable = "False"; private string _ispersonalizable = "False";
private string _themetype = string.Empty; private string _themetype = string.Empty;
private string _containertype = string.Empty; private string _containertype = string.Empty;
private string _headcontent;
private string _icon = string.Empty; private string _icon = string.Empty;
private string _permissions = null; private string _permissions = null;
private PermissionGrid _permissionGrid; private PermissionGrid _permissionGrid;
@ -376,11 +376,11 @@
{ {
page.DefaultContainerType = string.Empty; page.DefaultContainerType = string.Empty;
} }
page.HeadContent = _headcontent;
page.Icon = (_icon == null ? string.Empty : _icon); page.Icon = (_icon == null ? string.Empty : _icon);
page.PermissionList = _permissionGrid.GetPermissionList(); page.PermissionList = _permissionGrid.GetPermissionList();
page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable)); page.IsPersonalizable = (_ispersonalizable == null ? false : Boolean.Parse(_ispersonalizable));
page.UserId = null; page.UserId = null;
page.Meta = _meta;
page = await PageService.AddPageAsync(page); page = await PageService.AddPageAsync(page);
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId); await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);

View File

@ -93,6 +93,15 @@
<input id="url" class="form-control" @bind="@_url" maxlength="500"/> <input id="url" class="form-control" @bind="@_url" maxlength="500"/>
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9">
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
</div> </div>
<Section Name="Appearance" ResourceKey="Appearance"> <Section Name="Appearance" ResourceKey="Appearance">
<div class="container"> <div class="container">
@ -103,9 +112,9 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="meta" HelpText="Optionally enter meta tags (in exactly the form you want them to be included in the page output)." ResourceKey="Meta">Meta: </Label> <Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<textarea id="meta" class="form-control" @bind="@_meta" rows="3"></textarea> <input id="icon" class="form-control" @bind="@_icon" maxlength="50" />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
@ -132,18 +141,9 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="icon" HelpText="Optionally provide an icon class name for this page which will be displayed in the site navigation" ResourceKey="Icon">Icon: </Label> <Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta and link tags are valid, script tags are not)." ResourceKey="HeadContent">Head Content: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<input id="icon" class="form-control" @bind="@_icon" maxlength="50"/> <textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="personalizable" HelpText="Select whether you would like users to be able to personalize this page with their own content" ResourceKey="Personalizable">Personalizable? </Label>
<div class="col-sm-9">
<select id="personalizable" class="form-select" @bind="@_ispersonalizable" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div> </div>
</div> </div>
</div> </div>
@ -207,7 +207,6 @@
private int _pageId; private int _pageId;
private string _name; private string _name;
private string _title; private string _title;
private string _meta;
private string _path; private string _path;
private string _currentparentid; private string _currentparentid;
private string _parentid = "-1"; private string _parentid = "-1";
@ -220,6 +219,7 @@
private string _ispersonalizable; private string _ispersonalizable;
private string _themetype; private string _themetype;
private string _containertype = "-"; private string _containertype = "-";
private string _headcontent;
private string _icon; private string _icon;
private List<Permission> _permissions = null; private List<Permission> _permissions = null;
private string _createdby; private string _createdby;
@ -250,7 +250,6 @@
{ {
_name = page.Name; _name = page.Name;
_title = page.Title; _title = page.Title;
_meta = page.Meta;
_path = page.Path; _path = page.Path;
_pageModules = PageState.Modules.Where(m => m.PageId == page.PageId).ToList(); _pageModules = PageState.Modules.Where(m => m.PageId == page.PageId).ToList();
@ -291,6 +290,7 @@
{ {
_containertype = PageState.Site.DefaultContainerType; _containertype = PageState.Site.DefaultContainerType;
} }
_headcontent = page.HeadContent;
_icon = page.Icon; _icon = page.Icon;
_permissions = page.PermissionList; _permissions = page.PermissionList;
_createdby = page.CreatedBy; _createdby = page.CreatedBy;
@ -508,11 +508,11 @@
{ {
page.DefaultContainerType = string.Empty; page.DefaultContainerType = string.Empty;
} }
page.HeadContent = _headcontent;
page.Icon = _icon ?? string.Empty; page.Icon = _icon ?? string.Empty;
page.PermissionList = _permissionGrid.GetPermissionList(); page.PermissionList = _permissionGrid.GetPermissionList();
page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable)); page.IsPersonalizable = (_ispersonalizable != null && Boolean.Parse(_ispersonalizable));
page.UserId = null; page.UserId = null;
page.Meta = _meta;
page = await PageService.UpdatePageAsync(page); page = await PageService.UpdatePageAsync(page);
await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId); await PageService.UpdatePageOrderAsync(page.SiteId, page.PageId, page.ParentId);

View File

@ -22,6 +22,39 @@
<input id="name" class="form-control" @bind="@_name" maxlength="200" required /> <input id="name" class="form-control" @bind="@_name" maxlength="200" required />
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="homepage" HelpText="Select the home page for the site (to be used if there is no page with a path of '/')" ResourceKey="HomePage">Home Page: </Label>
<div class="col-sm-9">
<select id="homepage" class="form-select" @bind="@_homepageid" required>
<option value="-">&lt;@Localizer["Not Specified"]&gt;</option>
@foreach (Page page in PageState.Pages)
{
if (UserSecurity.ContainsRole(page.PermissionList, PermissionNames.View, RoleNames.Everyone))
{
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
}
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Deleted? </Label>
<div class="col-sm-9">
<select id="isDeleted" class="form-select" @bind="@_isdeleted" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="sitemap" HelpText="The site map url for this site which can be submitted to search engines for indexing" ResourceKey="SiteMap">Site Map: </Label>
<div class="col-sm-9">
<input id="sitemap" class="form-control" @bind="@_sitemap" required disabled />
</div>
</div>
</div>
<br />
<Section Name="Appearance" ResourceKey="Appearance">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label> <Label Class="col-sm-3" For="logo" HelpText="Specify a logo for the site" ResourceKey="Logo">Logo: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
@ -72,36 +105,12 @@
</div> </div>
</div> </div>
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="homepage" HelpText="Select the home page for the site (to be used if there is no page with a path of '/')" ResourceKey="HomePage">Home Page: </Label> <Label Class="col-sm-3" For="headcontent" HelpText="Optionally enter content to be included in the page head (ie. meta and link tags are valid, script tags are not)." ResourceKey="HeadContent">Head Content: </Label>
<div class="col-sm-9"> <div class="col-sm-9">
<select id="homepage" class="form-select" @bind="@_homepageid" required> <textarea id="headcontent" class="form-control" @bind="@_headcontent" rows="3"></textarea>
<option value="-">&lt;@Localizer["Not Specified"]&gt;</option>
@foreach (Page page in PageState.Pages)
{
if (UserSecurity.ContainsRole(page.PermissionList, PermissionNames.View, RoleNames.Everyone))
{
<option value="@(page.PageId)">@(new string('-', page.Level * 2))@(page.Name)</option>
}
}
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="isDeleted" HelpText="Is this site deleted?" ResourceKey="IsDeleted">Deleted? </Label>
<div class="col-sm-9">
<select id="isDeleted" class="form-select" @bind="@_isdeleted" required>
<option value="True">@SharedLocalizer["Yes"]</option>
<option value="False">@SharedLocalizer["No"]</option>
</select>
</div>
</div>
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="sitemap" HelpText="The site map url for this site which can be submitted to search engines for indexing" ResourceKey="SiteMap">Site Map: </Label>
<div class="col-sm-9">
<input id="sitemap" class="form-control" @bind="@_sitemap" required disabled />
</div>
</div> </div>
</div> </div>
</Section>
<Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings"> <Section Name="SMTP" Heading="SMTP Settings" ResourceKey="SMTPSettings">
<div class="container"> <div class="container">
<div class="row mb-1 align-items-center"> <div class="row mb-1 align-items-center">
@ -326,6 +335,7 @@
private string _themetype = "-"; private string _themetype = "-";
private string _containertype = "-"; private string _containertype = "-";
private string _admincontainertype = "-"; private string _admincontainertype = "-";
private string _headcontent = string.Empty;
private string _homepageid = "-"; private string _homepageid = "-";
private string _sitemap = ""; private string _sitemap = "";
private string _smtphost = string.Empty; private string _smtphost = string.Empty;
@ -387,6 +397,7 @@
_containers = ThemeService.GetContainerControls(_themeList, _themetype); _containers = ThemeService.GetContainerControls(_themeList, _themetype);
_containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer; _containertype = (!string.IsNullOrEmpty(site.DefaultContainerType)) ? site.DefaultContainerType : Constants.DefaultContainer;
_admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer; _admincontainertype = (!string.IsNullOrEmpty(site.AdminContainerType)) ? site.AdminContainerType : Constants.DefaultAdminContainer;
_headcontent = site.HeadContent;
if (site.HomePageId != null) if (site.HomePageId != null)
{ {
@ -520,6 +531,7 @@
refresh = true; // needs to be refreshed on client refresh = true; // needs to be refreshed on client
} }
site.AdminContainerType = _admincontainertype; site.AdminContainerType = _admincontainertype;
site.HeadContent = _headcontent;
site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null); site.HomePageId = (_homepageid != "-" ? int.Parse(_homepageid) : null);
if (site.PwaIsEnabled.ToString() != _pwaisenabled) if (site.PwaIsEnabled.ToString() != _pwaisenabled)

View File

@ -228,11 +228,11 @@
<data name="Appearance.Name" xml:space="preserve"> <data name="Appearance.Name" xml:space="preserve">
<value>Appearance</value> <value>Appearance</value>
</data> </data>
<data name="Meta.HelpText" xml:space="preserve"> <data name="HeadContent.HelpText" xml:space="preserve">
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value> <value>Optionally enter content to be included in the page head (ie. meta and link tags are valid, script tags are not).</value>
</data> </data>
<data name="Meta.Text" xml:space="preserve"> <data name="HeadContent.Text" xml:space="preserve">
<value>Meta:</value> <value>Head Content:</value>
</data> </data>
<data name="Message.Page.Reserved" xml:space="preserve"> <data name="Message.Page.Reserved" xml:space="preserve">
<value>The page name {0} is reserved. Please enter a different name for your page.</value> <value>The page name {0} is reserved. Please enter a different name for your page.</value>

View File

@ -264,11 +264,11 @@
<data name="Clickable.Text" xml:space="preserve"> <data name="Clickable.Text" xml:space="preserve">
<value>Clickable?</value> <value>Clickable?</value>
</data> </data>
<data name="Meta.HelpText" xml:space="preserve"> <data name="HeadContent.HelpText" xml:space="preserve">
<value>Optionally enter meta tags (in exactly the form you want them to be included in the page output).</value> <value>Optionally enter content to be included in the page head (ie. meta and link tags are valid, script tags are not).</value>
</data> </data>
<data name="Meta.Text" xml:space="preserve"> <data name="HeadContent.Text" xml:space="preserve">
<value>Meta:</value> <value>Head Content:</value>
</data> </data>
<data name="Message.Page.Reserved" xml:space="preserve"> <data name="Message.Page.Reserved" xml:space="preserve">
<value>The page name {0} is reserved. Please enter a different name for your page.</value> <value>The page name {0} is reserved. Please enter a different name for your page.</value>

View File

@ -351,4 +351,13 @@
<data name="SiteMap.Text" xml:space="preserve"> <data name="SiteMap.Text" xml:space="preserve">
<value>Site Map:</value> <value>Site Map:</value>
</data> </data>
<data name="Appearance.Heading" xml:space="preserve">
<value>Appearance</value>
</data>
<data name="HeadContent.HelpText" xml:space="preserve">
<value>Optionally enter content to be included in the page head (ie. meta and link tags are valid, script tags are not).</value>
</data>
<data name="HeadContent.Text" xml:space="preserve">
<value>Head Content:</value>
</data>
</root> </root>

View File

@ -38,15 +38,14 @@
favicon = Utilities.FileUrl(PageState.Alias, PageState.Site.FaviconFileId.Value); favicon = Utilities.FileUrl(PageState.Alias, PageState.Site.FaviconFileId.Value);
} }
headcontent += $"<link id=\"app-favicon\" rel=\"shortcut icon\" type=\"image/x-icon\" href=\"{favicon}\" />\n"; headcontent += $"<link id=\"app-favicon\" rel=\"shortcut icon\" type=\"image/x-icon\" href=\"{favicon}\" />\n";
// PWA manifest // head content
if (PageState.Site.PwaIsEnabled && PageState.Site.PwaAppIconFileId != null && PageState.Site.PwaSplashIconFileId != null) if (!string.IsNullOrEmpty(PageState.Site.HeadContent))
{ {
headcontent += "<link id=\"app-manifest\" rel=\"manifest\" />\n"; headcontent += PageState.Site.HeadContent + "\n";
} }
// meta if (!string.IsNullOrEmpty(PageState.Page.HeadContent))
if (!string.IsNullOrEmpty(PageState.Page.Meta))
{ {
headcontent += PageState.Page.Meta + "\n"; headcontent += PageState.Page.HeadContent + "\n";
} }
// stylesheets // stylesheets
foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet)) foreach (Resource resource in PageState.Page.Resources.Where(item => item.ResourceType == ResourceType.Stylesheet))
@ -54,6 +53,11 @@
var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url; var url = (resource.Url.Contains("://")) ? resource.Url : PageState.Alias.BaseUrl + resource.Url;
headcontent += CreateLink(url, resource.Integrity, resource.CrossOrigin) + "\n"; headcontent += CreateLink(url, resource.Integrity, resource.CrossOrigin) + "\n";
} }
// PWA manifest
if (PageState.Site.PwaIsEnabled && PageState.Site.PwaAppIconFileId != null && PageState.Site.PwaSplashIconFileId != null)
{
headcontent += "<link id=\"app-manifest\" rel=\"manifest\" />\n";
}
SiteState.Properties.HeadContent = headcontent; SiteState.Properties.HeadContent = headcontent;
// set page body content // set page body content

View File

@ -0,0 +1,35 @@
using Microsoft.AspNetCore.Components.Web;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Oqtane.Databases.Interfaces;
using Oqtane.Migrations.EntityBuilders;
using Oqtane.Repository;
namespace Oqtane.Migrations.Tenant
{
[DbContext(typeof(TenantDBContext))]
[Migration("Tenant.04.00.00.01")]
public class AddHeaderContent : MultiDatabaseMigration
{
public AddHeaderContent(IDatabase database) : base(database)
{
}
protected override void Up(MigrationBuilder migrationBuilder)
{
var siteEntityBuilder = new SiteEntityBuilder(migrationBuilder, ActiveDatabase);
siteEntityBuilder.AddStringColumn("HeadContent", 4000, true);
var pageEntityBuilder = new PageEntityBuilder(migrationBuilder, ActiveDatabase);
pageEntityBuilder.AddStringColumn("HeadContent", 4000, true);
pageEntityBuilder.UpdateColumn("HeadContent", "Meta");
pageEntityBuilder.DropColumn("Meta");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
// not implemented
}
}
}

View File

@ -65,9 +65,9 @@ namespace Oqtane.Models
public string DefaultContainerType { get; set; } public string DefaultContainerType { get; set; }
/// <summary> /// <summary>
/// Meta tags to be included in the head of the page /// Content to be included in the head of the page
/// </summary> /// </summary>
public string Meta { get; set; } public string HeadContent { get; set; }
/// <summary> /// <summary>
/// Icon file for this page. /// Icon file for this page.

View File

@ -79,7 +79,7 @@ namespace Oqtane.Models
public string RenderMode { get; set; } public string RenderMode { get; set; }
/// <summary> /// <summary>
/// Keeps track of site configuration changes and is used by the IUpgradeable interface /// Keeps track of site configuration changes and is used by the ISiteMigration interface
/// </summary> /// </summary>
public string Version { get; set; } public string Version { get; set; }
@ -88,6 +88,11 @@ namespace Oqtane.Models
/// </summary> /// </summary>
public int? HomePageId { get; set; } public int? HomePageId { get; set; }
/// <summary>
/// Content to be included in the head of the page
/// </summary>
public string HeadContent { get; set; }
[NotMapped] [NotMapped]
public Dictionary<string, string> Settings { get; set; } public Dictionary<string, string> Settings { get; set; }