Merge remote-tracking branch 'origin/v8/dev' into netcore/dev
Signed-off-by: Bjarke Berg <mail@bergmania.dk> # Conflicts: # src/Umbraco.Infrastructure/Services/Implement/IIconService.cs # src/Umbraco.Infrastructure/Services/Implement/IconService.cs # src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml # src/Umbraco.Web/Editors/BackOfficeController.cs # src/Umbraco.Web/Editors/BackOfficeModel.cs # src/Umbraco.Web/Editors/BackOfficePreviewModel.cs # src/Umbraco.Web/Editors/IconController.cs # src/Umbraco.Web/Editors/PreviewController.cs # src/Umbraco.Web/Runtime/WebInitialComposer.cs
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
namespace Umbraco.Web.Models
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public class IconModel
|
||||
{
|
||||
22
src/Umbraco.Core/Services/IIconService.cs
Normal file
22
src/Umbraco.Core/Services/IIconService.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Web.Models;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
{
|
||||
public interface IIconService
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path
|
||||
/// </summary>
|
||||
/// <param name="iconName"></param>
|
||||
/// <returns></returns>
|
||||
IconModel GetIcon(string iconName);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all svg icons found at at the global icons path.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
IList<IconModel> GetAllIcons();
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
{ oldIcon: ".sprToPublish", newIcon: "mail-forward" },
|
||||
{ oldIcon: ".sprTranslate", newIcon: "comments" },
|
||||
{ oldIcon: ".sprUpdate", newIcon: "save" },
|
||||
|
||||
|
||||
{ oldIcon: ".sprTreeSettingDomain", newIcon: "icon-home" },
|
||||
{ oldIcon: ".sprTreeDoc", newIcon: "icon-document" },
|
||||
{ oldIcon: ".sprTreeDoc2", newIcon: "icon-diploma-alt" },
|
||||
@@ -39,21 +39,21 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
{ oldIcon: ".sprTreeDoc4", newIcon: "icon-newspaper-alt" },
|
||||
{ oldIcon: ".sprTreeDoc5", newIcon: "icon-notepad-alt" },
|
||||
|
||||
{ oldIcon: ".sprTreeDocPic", newIcon: "icon-picture" },
|
||||
{ oldIcon: ".sprTreeDocPic", newIcon: "icon-picture" },
|
||||
{ oldIcon: ".sprTreeFolder", newIcon: "icon-folder" },
|
||||
{ oldIcon: ".sprTreeFolder_o", newIcon: "icon-folder" },
|
||||
{ oldIcon: ".sprTreeMediaFile", newIcon: "icon-music" },
|
||||
{ oldIcon: ".sprTreeMediaMovie", newIcon: "icon-movie" },
|
||||
{ oldIcon: ".sprTreeMediaPhoto", newIcon: "icon-picture" },
|
||||
|
||||
|
||||
{ oldIcon: ".sprTreeMember", newIcon: "icon-user" },
|
||||
{ oldIcon: ".sprTreeMemberGroup", newIcon: "icon-users" },
|
||||
{ oldIcon: ".sprTreeMemberType", newIcon: "icon-users" },
|
||||
|
||||
|
||||
{ oldIcon: ".sprTreeNewsletter", newIcon: "icon-file-text-alt" },
|
||||
{ oldIcon: ".sprTreePackage", newIcon: "icon-box" },
|
||||
{ oldIcon: ".sprTreeRepository", newIcon: "icon-server-alt" },
|
||||
|
||||
|
||||
{ oldIcon: ".sprTreeSettingDataType", newIcon: "icon-autofill" },
|
||||
|
||||
// TODO: Something needs to be done with the old tree icons that are commented out.
|
||||
@@ -61,7 +61,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
{ oldIcon: ".sprTreeSettingAgent", newIcon: "" },
|
||||
{ oldIcon: ".sprTreeSettingCss", newIcon: "" },
|
||||
{ oldIcon: ".sprTreeSettingCssItem", newIcon: "" },
|
||||
|
||||
|
||||
{ oldIcon: ".sprTreeSettingDataTypeChild", newIcon: "" },
|
||||
{ oldIcon: ".sprTreeSettingDomain", newIcon: "" },
|
||||
{ oldIcon: ".sprTreeSettingLanguage", newIcon: "" },
|
||||
@@ -94,9 +94,9 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
var iconCache = [];
|
||||
var liveRequests = [];
|
||||
var allIconsRequested = false;
|
||||
|
||||
|
||||
return {
|
||||
|
||||
|
||||
/** Used by the create dialogs for content/media types to format the data so that the thumbnails are styled properly */
|
||||
formatContentTypeThumbnails: function (contentTypes) {
|
||||
for (var i = 0; i < contentTypes.length; i++) {
|
||||
@@ -209,15 +209,11 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
,'Failed to retrieve icon: ' + iconName)
|
||||
.then(icon => {
|
||||
if(icon) {
|
||||
var trustedIcon = {
|
||||
name: icon.Name,
|
||||
svgString: $sce.trustAsHtml(icon.SvgString)
|
||||
};
|
||||
this._cacheIcon(trustedIcon);
|
||||
var trustedIcon = this.defineIcon(icon.Name, icon.SvgString);
|
||||
|
||||
liveRequests = _.filter(liveRequests, iconRequestPath);
|
||||
liveRequests = _.filter(liveRequests, iconRequestPath);
|
||||
|
||||
resolve(trustedIcon);
|
||||
resolve(trustedIcon);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
@@ -240,15 +236,10 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
,'Failed to retrieve icons')
|
||||
.then(icons => {
|
||||
icons.forEach(icon => {
|
||||
var trustedIcon = {
|
||||
name: icon.Name,
|
||||
svgString: $sce.trustAsHtml(icon.SvgString)
|
||||
};
|
||||
|
||||
this._cacheIcon(trustedIcon);
|
||||
this.defineIcon(icon.Name, icon.SvgString);
|
||||
});
|
||||
|
||||
resolve(iconCache);
|
||||
resolve(iconCache);
|
||||
})
|
||||
.catch(err => {
|
||||
console.warn(err);
|
||||
@@ -278,7 +269,7 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
console.warn("Can't read the css rules of: " + document.styleSheets[i].href, e);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (classes !== null) {
|
||||
for(var x=0;x<classes.length;x++) {
|
||||
var cur = classes[x];
|
||||
@@ -312,11 +303,17 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
|
||||
return deferred.promise;
|
||||
},
|
||||
|
||||
/** A simple cache to ensure that the icon is only requested from the server if is isn't already in memory */
|
||||
_cacheIcon: function(icon) {
|
||||
if(_.find(iconCache, {name: icon.name}) === undefined) {
|
||||
iconCache = _.union(iconCache, [icon]);
|
||||
}
|
||||
/** Creates a icon object, and caches it in a runtime cache */
|
||||
defineIcon: function(name, svg) {
|
||||
var icon = iconCache.find(x => x.name === name);
|
||||
if(icon === undefined) {
|
||||
icon = {
|
||||
name: name,
|
||||
svgString: $sce.trustAsHtml(svg)
|
||||
};
|
||||
iconCache.push(icon);
|
||||
}
|
||||
return icon;
|
||||
},
|
||||
|
||||
/** Returns the cached icon or undefined */
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
vm.submit = submit;
|
||||
vm.close = close;
|
||||
vm.cropSet = cropSet;
|
||||
|
||||
if (!$scope.model.target.coordinates && !$scope.model.target.focalPoint) {
|
||||
$scope.model.target.focalPoint = { left: .5, top: .5 };
|
||||
@@ -56,4 +57,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
function cropSet() {
|
||||
var model = $scope.model;
|
||||
return (model.cropSize || {}).width && model.target.thumbnail;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<div class="umb-control-group" ng-if="model.target">
|
||||
|
||||
<div ng-if="model.disableFocalPoint && model.target.thumbnail">
|
||||
<div ng-if="vm.cropSet() === false">
|
||||
<h5>
|
||||
<localize key="general_preview">Preview</localize>
|
||||
</h5>
|
||||
@@ -34,7 +34,7 @@
|
||||
<img ng-src="{{model.target.thumbnail}}" alt="{{model.target.name}}" />
|
||||
</div>
|
||||
|
||||
<div ng-if="!model.disableFocalPoint">
|
||||
<div ng-if="vm.cropSet()">
|
||||
<h5>
|
||||
<localize key="@general_cropSection">Crop section</localize>
|
||||
</h5>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<!-- Renders when it's only possible to create one specific document type for which a blueprint exits-->
|
||||
<div class="btn-group" ng-show="createAllowedButtonSingleWithBlueprints" deep-blur="leaveDropdown()">
|
||||
<button type="button" class="btn btn-white dropdown-toggle" aria-expanded="{{page.createDropdownOpen}}" ng-click="toggleDropdown()">
|
||||
<button type="button" class="btn btn-outline umb-outline dropdown-toggle" aria-expanded="{{page.createDropdownOpen}}" ng-click="toggleDropdown()">
|
||||
<span>
|
||||
<localize key="actions_create">Create</localize> {{listViewAllowedTypes[0].name}}
|
||||
</span>
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<!-- Renders when it's possible to create multiple document types and blueprints for one or more of the document types-->
|
||||
<div class="btn-group" ng-show="createAllowedButtonMultiWithBlueprints" deep-blur="leaveDropdown()">
|
||||
<button type="button" class="btn btn-white dropdown-toggle" aria-expanded="{{page.createDropdownOpen === undefined ? false : page.createDropdownOpen}}" ng-click="toggleDropdown()">
|
||||
<button type="button" class="btn btn-outline umb-outline dropdown-toggle" aria-expanded="{{page.createDropdownOpen === undefined ? false : page.createDropdownOpen}}" ng-click="toggleDropdown()">
|
||||
<localize key="actions_create">Create</localize>
|
||||
<span class="caret" aria-hidden="true"></span>
|
||||
</button>
|
||||
|
||||
@@ -68,14 +68,15 @@
|
||||
|
||||
</div>
|
||||
|
||||
<umb-tour ng-if="tour.show"
|
||||
model="tour">
|
||||
</umb-tour>
|
||||
|
||||
<umb-notifications></umb-notifications>
|
||||
|
||||
</div>
|
||||
|
||||
<umb-tour
|
||||
ng-if="tour.show"
|
||||
model="tour">
|
||||
</umb-tour>
|
||||
|
||||
<!-- help dialog controller by the help button - this also forces the backoffice UI to shift 400px -->
|
||||
<umb-drawer data-element="drawer" ng-if="drawer.show" model="drawer.model" view="drawer.view"></umb-drawer>
|
||||
|
||||
@@ -112,6 +113,12 @@
|
||||
@Html.AngularValueResetPasswordCodeInfoScript(ViewData["PasswordResetCode"])
|
||||
@Html.AngularValueTinyMceAssets(Current.RuntimeMinifier)
|
||||
|
||||
app.run(["iconHelper", function (iconHelper) {
|
||||
@* We inject icons to the icon helper(service), since icons can only be loaded if user is authorized. By injecting these to the service they will not be requested as they will become cached. *@
|
||||
iconHelper.defineIcon("icon-check", '@Html.Raw(Model.IconCheckData)');
|
||||
iconHelper.defineIcon("icon-delete", '@Html.Raw(Model.IconDeleteData)');
|
||||
}]);
|
||||
|
||||
//required for the noscript trick
|
||||
document.getElementById("mainwrapper").style.display = "inherit";
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
Defaults to "false".
|
||||
@keepAlivePingUrl
|
||||
The url of the KeepAlivePing action. By default, the url will use the umbracoApplicationUrl setting as the basis.
|
||||
Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/api/keepalive/ping
|
||||
Change this setting to specify an alternative url to reach the KeepAlivePing action. eg http://localhost/umbraco/api/keepalive/ping
|
||||
Defaults to "{umbracoApplicationUrl}/api/keepalive/ping".
|
||||
-->
|
||||
<keepAlive disableKeepAliveTask="false" keepAlivePingUrl="{umbracoApplicationUrl}/api/keepalive/ping" />
|
||||
|
||||
@@ -176,6 +176,9 @@ namespace Umbraco.Web.Composing
|
||||
public static ISectionService SectionService
|
||||
=> Factory.GetInstance<ISectionService>();
|
||||
|
||||
public static IIconService IconService
|
||||
=> Factory.GetInstance<IIconService>();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Web Constants
|
||||
|
||||
@@ -14,6 +14,7 @@ using Newtonsoft.Json;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Web.Models;
|
||||
@@ -56,6 +57,7 @@ namespace Umbraco.Web.Editors
|
||||
private readonly IRuntimeSettings _runtimeSettings;
|
||||
private readonly ISecuritySettings _securitySettings;
|
||||
private readonly IRuntimeMinifier _runtimeMinifier;
|
||||
private readonly IIconService _iconService;
|
||||
|
||||
public BackOfficeController(
|
||||
UmbracoFeatures features,
|
||||
@@ -73,7 +75,8 @@ namespace Umbraco.Web.Editors
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IRuntimeSettings settings,
|
||||
ISecuritySettings securitySettings,
|
||||
IRuntimeMinifier runtimeMinifier)
|
||||
IRuntimeMinifier runtimeMinifier,
|
||||
IIconService iconService)
|
||||
: base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger)
|
||||
|
||||
{
|
||||
@@ -88,6 +91,7 @@ namespace Umbraco.Web.Editors
|
||||
_runtimeSettings = settings;
|
||||
_securitySettings = securitySettings;
|
||||
_runtimeMinifier = runtimeMinifier;
|
||||
_iconService = iconService;
|
||||
}
|
||||
|
||||
protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.GetBackOfficeSignInManager());
|
||||
@@ -102,11 +106,12 @@ namespace Umbraco.Web.Editors
|
||||
/// <returns></returns>
|
||||
public async Task<ActionResult> Default()
|
||||
{
|
||||
var backofficeModel = new BackOfficeModel(_features, GlobalSettings, _umbracoVersion, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings, _iconService);
|
||||
return await RenderDefaultOrProcessExternalLoginAsync(
|
||||
() =>
|
||||
View(GlobalSettings.GetBackOfficePath(_hostingEnvironment).EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings, _umbracoVersion, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings)),
|
||||
View(GlobalSettings.GetBackOfficePath(_hostingEnvironment).EnsureEndsWith('/') + "Views/Default.cshtml", backofficeModel),
|
||||
() =>
|
||||
View(GlobalSettings.GetBackOfficePath(_hostingEnvironment).EnsureEndsWith('/') + "Views/Default.cshtml", new BackOfficeModel(_features, GlobalSettings, _umbracoVersion, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings))
|
||||
View(GlobalSettings.GetBackOfficePath(_hostingEnvironment).EnsureEndsWith('/') + "Views/Default.cshtml", backofficeModel)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -184,7 +189,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
return await RenderDefaultOrProcessExternalLoginAsync(
|
||||
//The default view to render when there is no external login info or errors
|
||||
() => View(GlobalSettings.GetBackOfficePath(_hostingEnvironment).EnsureEndsWith('/') + "Views/AuthorizeUpgrade.cshtml", new BackOfficeModel(_features, GlobalSettings, _umbracoVersion, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings)),
|
||||
() => View(GlobalSettings.GetBackOfficePath(_hostingEnvironment).EnsureEndsWith('/') + "Views/AuthorizeUpgrade.cshtml", new BackOfficeModel(_features, GlobalSettings, _umbracoVersion, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings, _iconService)),
|
||||
//The ActionResult to perform if external login is successful
|
||||
() => Redirect("/"));
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Features;
|
||||
using Umbraco.Web.Services;
|
||||
using Umbraco.Web.Trees;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -13,7 +14,7 @@ namespace Umbraco.Web.Editors
|
||||
public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion,
|
||||
IContentSettings contentSettings, TreeCollection treeCollection,
|
||||
IHttpContextAccessor httpContextAccessor, IHostingEnvironment hostingEnvironment,
|
||||
IRuntimeSettings runtimeSettings, ISecuritySettings securitySettings)
|
||||
IRuntimeSettings runtimeSettings, ISecuritySettings securitySettings, IIconService iconService)
|
||||
{
|
||||
Features = features;
|
||||
GlobalSettings = globalSettings;
|
||||
@@ -25,6 +26,8 @@ namespace Umbraco.Web.Editors
|
||||
RuntimeSettings = runtimeSettings;
|
||||
SecuritySettings = securitySettings;
|
||||
BackOfficePath = GlobalSettings.GetBackOfficePath(HostingEnvironment);
|
||||
IconCheckData = iconService.GetIcon("icon-check")?.SvgString;
|
||||
IconDeleteData = iconService.GetIcon("icon-delete")?.SvgString;
|
||||
}
|
||||
|
||||
public UmbracoFeatures Features { get; }
|
||||
@@ -37,6 +40,8 @@ namespace Umbraco.Web.Editors
|
||||
public IRuntimeSettings RuntimeSettings { get; set; }
|
||||
public ISecuritySettings SecuritySettings { get; set; }
|
||||
|
||||
public string BackOfficePath { get; }
|
||||
public string BackOfficePath { get; }
|
||||
public string IconCheckData { get; }
|
||||
public string IconDeleteData { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Features;
|
||||
using Umbraco.Web.Services;
|
||||
using Umbraco.Web.Trees;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
@@ -14,8 +15,29 @@ namespace Umbraco.Web.Editors
|
||||
private readonly UmbracoFeatures _features;
|
||||
public IEnumerable<ILanguage> Languages { get; }
|
||||
|
||||
public BackOfficePreviewModel(UmbracoFeatures features, IGlobalSettings globalSettings, IUmbracoVersion umbracoVersion, IEnumerable<ILanguage> languages, IContentSettings contentSettings, TreeCollection treeCollection, IHttpContextAccessor httpContextAccessor, IHostingEnvironment hostingEnvironment, IRuntimeSettings runtimeSettings, ISecuritySettings securitySettings)
|
||||
: base(features, globalSettings, umbracoVersion, contentSettings, treeCollection, httpContextAccessor, hostingEnvironment, runtimeSettings, securitySettings)
|
||||
public BackOfficePreviewModel(
|
||||
UmbracoFeatures features,
|
||||
IGlobalSettings globalSettings,
|
||||
IUmbracoVersion umbracoVersion,
|
||||
IEnumerable<ILanguage> languages,
|
||||
IContentSettings contentSettings,
|
||||
TreeCollection treeCollection,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IHostingEnvironment hostingEnvironment,
|
||||
IRuntimeSettings runtimeSettings,
|
||||
ISecuritySettings securitySettings,
|
||||
IIconService iconService)
|
||||
: base(
|
||||
features,
|
||||
globalSettings,
|
||||
umbracoVersion,
|
||||
contentSettings,
|
||||
treeCollection,
|
||||
httpContextAccessor,
|
||||
hostingEnvironment,
|
||||
runtimeSettings,
|
||||
securitySettings,
|
||||
iconService)
|
||||
{
|
||||
_features = features;
|
||||
Languages = languages;
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Models;
|
||||
using System.IO;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.IO;
|
||||
using Ganss.XSS;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Mapping;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.Routing;
|
||||
@@ -22,7 +16,7 @@ namespace Umbraco.Web.Editors
|
||||
[PluginController("UmbracoApi")]
|
||||
public class IconController : UmbracoAuthorizedApiController
|
||||
{
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
private readonly IIconService _iconService;
|
||||
|
||||
public IconController(
|
||||
IGlobalSettings globalSettings,
|
||||
@@ -34,9 +28,9 @@ namespace Umbraco.Web.Editors
|
||||
IRuntimeState runtimeState,
|
||||
UmbracoMapper umbracoMapper,
|
||||
IPublishedUrlProvider publishedUrlProvider,
|
||||
IHostingEnvironment hostingEnvironment) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider)
|
||||
IIconService iconService) : base(globalSettings, umbracoContextAccessor, sqlContext, services, appCaches, logger, runtimeState, umbracoMapper, publishedUrlProvider)
|
||||
{
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
_iconService = iconService;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -46,76 +40,16 @@ namespace Umbraco.Web.Editors
|
||||
/// <returns></returns>
|
||||
public IconModel GetIcon(string iconName)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(iconName)
|
||||
? null
|
||||
: CreateIconModel(iconName.StripFileExtension(), _hostingEnvironment.MapPath($"{GlobalSettings.IconsPath}/{iconName}.svg"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IconModel using values from a FileInfo model
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <returns></returns>
|
||||
public IconModel GetIcon(FileInfo fileInfo)
|
||||
{
|
||||
return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name)
|
||||
? null
|
||||
: CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName);
|
||||
return _iconService.GetIcon(iconName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of all svg icons found at at the global icons path.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public List<IconModel> GetAllIcons()
|
||||
public IList<IconModel> GetAllIcons()
|
||||
{
|
||||
var icons = new List<IconModel>();
|
||||
var directory = new DirectoryInfo(_hostingEnvironment.MapPath($"{GlobalSettings.IconsPath}/"));
|
||||
var iconNames = directory.GetFiles("*.svg");
|
||||
|
||||
iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo =>
|
||||
{
|
||||
var icon = GetIcon(iconInfo);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
icons.Add(icon);
|
||||
}
|
||||
});
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IconModel containing the icon name and SvgString
|
||||
/// </summary>
|
||||
/// <param name="iconName"></param>
|
||||
/// <param name="iconPath"></param>
|
||||
/// <returns></returns>
|
||||
private IconModel CreateIconModel(string iconName, string iconPath)
|
||||
{
|
||||
var sanitizer = new HtmlSanitizer();
|
||||
sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes);
|
||||
sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes);
|
||||
sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags);
|
||||
|
||||
try
|
||||
{
|
||||
var svgContent = File.ReadAllText(iconPath);
|
||||
var sanitizedString = sanitizer.Sanitize(svgContent);
|
||||
|
||||
var svg = new IconModel
|
||||
{
|
||||
Name = iconName,
|
||||
SvgString = sanitizedString
|
||||
};
|
||||
|
||||
return svg;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return _iconService.GetAllIcons();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ using Umbraco.Web.Composing;
|
||||
using Umbraco.Web.Features;
|
||||
using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.PublishedCache;
|
||||
using Umbraco.Web.Services;
|
||||
using Umbraco.Web.Trees;
|
||||
using Umbraco.Web.WebAssets;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
@@ -27,6 +28,7 @@ namespace Umbraco.Web.Editors
|
||||
private readonly IPublishedSnapshotService _publishedSnapshotService;
|
||||
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
|
||||
private readonly ILocalizationService _localizationService;
|
||||
private readonly IIconService _iconService;
|
||||
private readonly IUmbracoVersion _umbracoVersion;
|
||||
private readonly IContentSettings _contentSettings;
|
||||
private readonly TreeCollection _treeCollection;
|
||||
@@ -51,7 +53,8 @@ namespace Umbraco.Web.Editors
|
||||
ICookieManager cookieManager,
|
||||
IRuntimeSettings settings,
|
||||
ISecuritySettings securitySettings,
|
||||
IRuntimeMinifier runtimeMinifier)
|
||||
IRuntimeMinifier runtimeMinifier,
|
||||
IIconService iconService)
|
||||
{
|
||||
_features = features;
|
||||
_globalSettings = globalSettings;
|
||||
@@ -67,6 +70,7 @@ namespace Umbraco.Web.Editors
|
||||
_runtimeSettings = settings;
|
||||
_securitySettings = securitySettings;
|
||||
_runtimeMinifier = runtimeMinifier;
|
||||
_iconService = iconService;
|
||||
}
|
||||
|
||||
[UmbracoAuthorize(redirectToUmbracoLogin: true)]
|
||||
@@ -75,7 +79,7 @@ namespace Umbraco.Web.Editors
|
||||
{
|
||||
var availableLanguages = _localizationService.GetAllLanguages();
|
||||
|
||||
var model = new BackOfficePreviewModel(_features, _globalSettings, _umbracoVersion, availableLanguages, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings);
|
||||
var model = new BackOfficePreviewModel(_features, _globalSettings, _umbracoVersion, availableLanguages, _contentSettings, _treeCollection, _httpContextAccessor, _hostingEnvironment, _runtimeSettings, _securitySettings, _iconService);
|
||||
|
||||
if (model.PreviewExtendedHeaderView.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ using Umbraco.Web.AspNet;
|
||||
using Umbraco.Core.Diagnostics;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Web.Logging;
|
||||
using Umbraco.Web.Services;
|
||||
|
||||
namespace Umbraco.Web.Runtime
|
||||
{
|
||||
@@ -139,6 +140,8 @@ namespace Umbraco.Web.Runtime
|
||||
composition.Register<ISessionIdResolver>(factory => factory.GetInstance<AspNetSessionManager>(), Lifetime.Singleton);
|
||||
composition.Register<ISessionManager>(factory => factory.GetInstance<AspNetSessionManager>(), Lifetime.Singleton);
|
||||
|
||||
|
||||
composition.RegisterUnique<IIconService, IconService>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
98
src/Umbraco.Web/Services/IconService.cs
Normal file
98
src/Umbraco.Web/Services/IconService.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Ganss.XSS;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Hosting;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using File = System.IO.File;
|
||||
|
||||
namespace Umbraco.Web.Services
|
||||
{
|
||||
public class IconService : IIconService
|
||||
{
|
||||
private readonly IGlobalSettings _globalSettings;
|
||||
private readonly IHostingEnvironment _hostingEnvironment;
|
||||
|
||||
public IconService(IGlobalSettings globalSettings, IHostingEnvironment hostingEnvironment)
|
||||
{
|
||||
_globalSettings = globalSettings;
|
||||
_hostingEnvironment = hostingEnvironment;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public IList<IconModel> GetAllIcons()
|
||||
{
|
||||
var icons = new List<IconModel>();
|
||||
var directory = new DirectoryInfo(_hostingEnvironment.MapPath($"{_globalSettings.IconsPath}/"));
|
||||
var iconNames = directory.GetFiles("*.svg");
|
||||
|
||||
iconNames.OrderBy(f => f.Name).ToList().ForEach(iconInfo =>
|
||||
{
|
||||
var icon = GetIcon(iconInfo);
|
||||
|
||||
if (icon != null)
|
||||
{
|
||||
icons.Add(icon);
|
||||
}
|
||||
});
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IconModel GetIcon(string iconName)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(iconName)
|
||||
? null
|
||||
: CreateIconModel(iconName.StripFileExtension(), _hostingEnvironment.MapPath($"{_globalSettings.IconsPath}/{iconName}.svg"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IconModel using values from a FileInfo model
|
||||
/// </summary>
|
||||
/// <param name="fileInfo"></param>
|
||||
/// <returns></returns>
|
||||
private IconModel GetIcon(FileInfo fileInfo)
|
||||
{
|
||||
return fileInfo == null || string.IsNullOrWhiteSpace(fileInfo.Name)
|
||||
? null
|
||||
: CreateIconModel(fileInfo.Name.StripFileExtension(), fileInfo.FullName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an IconModel containing the icon name and SvgString
|
||||
/// </summary>
|
||||
/// <param name="iconName"></param>
|
||||
/// <param name="iconPath"></param>
|
||||
/// <returns></returns>
|
||||
private IconModel CreateIconModel(string iconName, string iconPath)
|
||||
{
|
||||
var sanitizer = new HtmlSanitizer();
|
||||
sanitizer.AllowedAttributes.UnionWith(Core.Constants.SvgSanitizer.Attributes);
|
||||
sanitizer.AllowedCssProperties.UnionWith(Core.Constants.SvgSanitizer.Attributes);
|
||||
sanitizer.AllowedTags.UnionWith(Core.Constants.SvgSanitizer.Tags);
|
||||
|
||||
try
|
||||
{
|
||||
var svgContent = File.ReadAllText(iconPath);
|
||||
var sanitizedString = sanitizer.Sanitize(svgContent);
|
||||
|
||||
var svg = new IconModel
|
||||
{
|
||||
Name = iconName,
|
||||
SvgString = sanitizedString
|
||||
};
|
||||
|
||||
return svg;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,6 +156,7 @@
|
||||
<Compile Include="PropertyEditors\Validation\ContentPropertyValidationResult.cs" />
|
||||
<Compile Include="PropertyEditors\Validation\ValidationResultConverter.cs" />
|
||||
<Compile Include="Security\IdentityFactoryMiddleware.cs" />
|
||||
<Compile Include="Services\IconService.cs" />
|
||||
<Compile Include="WebApi\Filters\OnlyLocalRequestsAttribute.cs" />
|
||||
<Compile Include="WebAssets\CDF\ClientDependencyRuntimeMinifier.cs" />
|
||||
<Compile Include="Models\NoNodesViewModel.cs" />
|
||||
@@ -195,7 +196,6 @@
|
||||
<Compile Include="Models\Mapping\MediaMapDefinition.cs" />
|
||||
<Compile Include="Models\Mapping\MemberMapDefinition.cs" />
|
||||
<Compile Include="Models\Membership\UmbracoMembershipMember.cs" />
|
||||
<Compile Include="Models\IconModel.cs" />
|
||||
<Compile Include="Mvc\HttpUmbracoFormRouteStringException.cs" />
|
||||
<Compile Include="Mvc\ModelBindingExceptionFilter.cs" />
|
||||
<Compile Include="Mvc\StatusCodeFilterAttribute.cs" />
|
||||
|
||||
Reference in New Issue
Block a user