Skip to content

Commit edab350

Browse files
Merge branch 'v8/8.10' into v8/8.11
2 parents 8b04c32 + 1d3d834 commit edab350

File tree

15 files changed

+201
-206
lines changed

15 files changed

+201
-206
lines changed

build/NuSpecs/UmbracoCms.Web.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.1,4.999999)" />
4343
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.1,4.999999)" />
4444
<dependency id="System.Threading.Tasks.Dataflow" version="[4.9.0,4.999999)" />
45-
<dependency id="HtmlSanitizer" version="[4.0.217,4.999999)" />
45+
<dependency id="HtmlSanitizer" version="[5.0.376,5.999999)" />
4646

4747
</group>
4848

src/Umbraco.Core/IO/SystemDirectories.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public class SystemDirectories
2525

2626
public static string AppPlugins => "~/App_Plugins";
2727

28+
public static string AppPluginIcons => "/Backoffice/Icons";
29+
2830
public static string MvcViews => "~/Views";
2931

3032
public static string PartialViews => MvcViews + "/Partials/";
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
1+
using System;
12
using System.Collections.Generic;
3+
using System.ComponentModel;
24
using Umbraco.Core.Models;
35

46
namespace Umbraco.Core.Services
57
{
68
public interface IIconService
79
{
810
/// <summary>
9-
/// Gets an IconModel containing the icon name and SvgString according to an icon name found at the global icons path
11+
/// Gets the svg string for the icon name found at the global icons path
1012
/// </summary>
1113
/// <param name="iconName"></param>
1214
/// <returns></returns>
@@ -15,7 +17,15 @@ public interface IIconService
1517
/// <summary>
1618
/// Gets a list of all svg icons found at at the global icons path.
1719
/// </summary>
18-
/// <returns></returns>
20+
/// <returns>A list of <see cref="IconModel"/></returns>
21+
[Obsolete("This method should not be used - use GetIcons instead")]
22+
[EditorBrowsable(EditorBrowsableState.Never)]
1923
IList<IconModel> GetAllIcons();
24+
25+
/// <summary>
26+
/// Gets a list of all svg icons found at at the global icons path.
27+
/// </summary>
28+
/// <returns></returns>
29+
IReadOnlyDictionary<string, string> GetIcons();
2030
}
2131
}

src/Umbraco.Web.UI.Client/src/common/directives/components/umbicon.directive.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ Icon with additional attribute. It can be treated like any other dom element
7575

7676
iconHelper.getIcon(icon)
7777
.then(data => {
78-
if (data !== null && data.svgString !== undefined) {
78+
if (data && data.svgString) {
7979
// Watch source SVG string
80-
//icon.svgString.$$unwrapTrustedValue();
8180
scope.svgString = data.svgString;
8281
}
8382
});

src/Umbraco.Web.UI.Client/src/common/services/iconhelper.service.js

Lines changed: 59 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
* @name umbraco.services.iconHelper
44
* @description A helper service for dealing with icons, mostly dealing with legacy tree icons
55
**/
6-
function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
6+
function iconHelper($http, $q, $sce, $timeout) {
77

8-
var converter = [
8+
const converter = [
99
{ oldIcon: ".sprNew", newIcon: "add" },
1010
{ oldIcon: ".sprDelete", newIcon: "remove" },
1111
{ oldIcon: ".sprMove", newIcon: "enter" },
@@ -85,15 +85,61 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
8585
{ oldIcon: ".sprTreeDeveloperPython", newIcon: "icon-linux" }
8686
];
8787

88-
var collectedIcons;
88+
let collectedIcons;
8989

90-
var imageConverter = [
91-
{oldImage: "contour.png", newIcon: "icon-umb-contour"}
92-
];
90+
let imageConverter = [
91+
{oldImage: "contour.png", newIcon: "icon-umb-contour"}
92+
];
93+
94+
const iconCache = [];
95+
const promiseQueue = [];
96+
let resourceLoadStatus = "none";
97+
98+
/**
99+
* This is the same approach as use for loading the localized text json
100+
* We don't want multiple requests for the icon collection, so need to track
101+
* the current request state, and resolve the queued requests once the icons arrive
102+
* Subsequent requests are returned immediately as the icons are cached into
103+
*/
104+
function init() {
105+
const deferred = $q.defer();
106+
107+
if (resourceLoadStatus === "loaded") {
108+
deferred.resolve(iconCache);
109+
return deferred.promise;
110+
}
111+
112+
if (resourceLoadStatus === "loading") {
113+
promiseQueue.push(deferred);
114+
return deferred.promise;
115+
}
93116

94-
var iconCache = [];
95-
var liveRequests = [];
96-
var allIconsRequested = false;
117+
resourceLoadStatus = "loading";
118+
119+
$http({ method: "GET", url: Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetIcons' })
120+
.then(function (response) {
121+
resourceLoadStatus = "loaded";
122+
123+
for (const [key, value] of Object.entries(response.data.Data)) {
124+
iconCache.push({name: key, svgString: $sce.trustAsHtml(value)})
125+
}
126+
127+
deferred.resolve(iconCache);
128+
129+
//ensure all other queued promises are resolved
130+
for (let p in promiseQueue) {
131+
promiseQueue[p].resolve(iconCache);
132+
}
133+
}, function (err) {
134+
deferred.reject("Something broke");
135+
//ensure all other queued promises are resolved
136+
for (let p in promiseQueue) {
137+
promiseQueue[p].reject("Something broke");
138+
}
139+
});
140+
141+
return deferred.promise;
142+
}
97143

98144
return {
99145

@@ -187,67 +233,12 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
187233

188234
/** Gets a single IconModel */
189235
getIcon: function(iconName) {
190-
return $q((resolve, reject) => {
191-
var icon = this._getIconFromCache(iconName);
192-
193-
if(icon !== undefined) {
194-
resolve(icon);
195-
} else {
196-
var iconRequestPath = Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetIcon?iconName=' + iconName;
197-
198-
// If the current icon is being requested, wait a bit so that we don't have to make another http request and can instead get the icon from the cache.
199-
// This is a bit rough and ready and could probably be improved used an event based system
200-
if(liveRequests.indexOf(iconRequestPath) >= 0) {
201-
setTimeout(() => {
202-
resolve(this.getIcon(iconName));
203-
}, 10);
204-
} else {
205-
liveRequests.push(iconRequestPath);
206-
// TODO - fix bug where Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl is undefinied when help icon
207-
umbRequestHelper.resourcePromise(
208-
$http.get(iconRequestPath)
209-
,'Failed to retrieve icon: ' + iconName)
210-
.then(icon => {
211-
if(icon) {
212-
var trustedIcon = this.defineIcon(icon.Name, icon.SvgString);
213-
214-
liveRequests = _.filter(liveRequests, iconRequestPath);
215-
216-
resolve(trustedIcon);
217-
}
218-
})
219-
.catch(err => {
220-
console.warn(err);
221-
});
222-
};
223-
224-
}
225-
});
236+
return init().then(icons => icons.find(i => i.name === iconName));
226237
},
227238

228239
/** Gets all the available icons in the backoffice icon folder and returns them as an array of IconModels */
229240
getAllIcons: function() {
230-
return $q((resolve, reject) => {
231-
if(allIconsRequested === false) {
232-
allIconsRequested = true;
233-
234-
umbRequestHelper.resourcePromise(
235-
$http.get(Umbraco.Sys.ServerVariables.umbracoUrls.iconApiBaseUrl + 'GetAllIcons')
236-
,'Failed to retrieve icons')
237-
.then(icons => {
238-
icons.forEach(icon => {
239-
this.defineIcon(icon.Name, icon.SvgString);
240-
});
241-
242-
resolve(iconCache);
243-
})
244-
.catch(err => {
245-
console.warn(err);
246-
});;
247-
} else {
248-
resolve(iconCache);
249-
}
250-
});
241+
return init().then(icons => icons);
251242
},
252243

253244
/** LEGACY - Return a list of icons from icon fonts, optionally filter them */
@@ -312,9 +303,8 @@ function iconHelper($http, $q, $sce, $timeout, umbRequestHelper) {
312303
},
313304

314305
/** Returns the cached icon or undefined */
315-
_getIconFromCache: function(iconName) {
316-
return _.find(iconCache, {name: iconName});
317-
}
306+
_getIconFromCache: iconName => iconCache.find(icon => icon.name === iconName)
307+
318308
};
319309
}
320310
angular.module('umbraco.services').factory('iconHelper', iconHelper);

src/Umbraco.Web.UI/Umbraco/Views/Default.cshtml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,6 @@
121121
@Html.AngularValueResetPasswordCodeInfoScript(ViewData["PasswordResetCode"])
122122
@Html.AngularValueTinyMceAssets()
123123
124-
app.run(["iconHelper", function (iconHelper) {
125-
@* 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. *@
126-
iconHelper.defineIcon("icon-check", '@Html.Raw(Model.IconCheckData)');
127-
iconHelper.defineIcon("icon-delete", '@Html.Raw(Model.IconDeleteData)');
128-
}]);
129-
130124
//required for the noscript trick
131125
document.getElementById("mainwrapper").style.display = "inherit";
132126

src/Umbraco.Web/Editors/BackOfficeController.cs

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
1-
using System;
1+
using Microsoft.AspNet.Identity;
2+
using Microsoft.AspNet.Identity.Owin;
3+
using Microsoft.Owin.Security;
4+
using Newtonsoft.Json;
5+
using System;
26
using System.Collections.Generic;
37
using System.Globalization;
48
using System.Linq;
59
using System.Threading;
610
using System.Threading.Tasks;
711
using System.Web.Mvc;
812
using System.Web.UI;
9-
using Microsoft.AspNet.Identity;
10-
using Microsoft.AspNet.Identity.Owin;
11-
using Microsoft.Owin.Security;
12-
using Newtonsoft.Json;
1313
using Umbraco.Core;
1414
using Umbraco.Core.Cache;
1515
using Umbraco.Core.Configuration;
1616
using Umbraco.Core.Logging;
1717
using Umbraco.Core.Manifest;
1818
using Umbraco.Core.Models.Identity;
19-
using Umbraco.Web.Models;
20-
using Umbraco.Web.Mvc;
2119
using Umbraco.Core.Services;
2220
using Umbraco.Web.Composing;
2321
using Umbraco.Web.Features;
2422
using Umbraco.Web.JavaScript;
23+
using Umbraco.Web.Models;
24+
using Umbraco.Web.Mvc;
2525
using Umbraco.Web.Security;
26-
using Umbraco.Web.Services;
2726
using Constants = Umbraco.Core.Constants;
2827
using JArray = Newtonsoft.Json.Linq.JArray;
2928

@@ -40,11 +39,9 @@ public class BackOfficeController : UmbracoController
4039
private readonly ManifestParser _manifestParser;
4140
private readonly UmbracoFeatures _features;
4241
private readonly IRuntimeState _runtimeState;
43-
private readonly IIconService _iconService;
4442
private BackOfficeUserManager<BackOfficeIdentityUser> _userManager;
4543
private BackOfficeSignInManager _signInManager;
4644

47-
[Obsolete("Use the constructor that injects IIconService.")]
4845
public BackOfficeController(
4946
ManifestParser manifestParser,
5047
UmbracoFeatures features,
@@ -55,37 +52,11 @@ public BackOfficeController(
5552
IProfilingLogger profilingLogger,
5653
IRuntimeState runtimeState,
5754
UmbracoHelper umbracoHelper)
58-
: this(manifestParser,
59-
features,
60-
globalSettings,
61-
umbracoContextAccessor,
62-
services,
63-
appCaches,
64-
profilingLogger,
65-
runtimeState,
66-
umbracoHelper,
67-
Current.IconService)
68-
{
69-
70-
}
71-
72-
public BackOfficeController(
73-
ManifestParser manifestParser,
74-
UmbracoFeatures features,
75-
IGlobalSettings globalSettings,
76-
IUmbracoContextAccessor umbracoContextAccessor,
77-
ServiceContext services,
78-
AppCaches appCaches,
79-
IProfilingLogger profilingLogger,
80-
IRuntimeState runtimeState,
81-
UmbracoHelper umbracoHelper,
82-
IIconService iconService)
8355
: base(globalSettings, umbracoContextAccessor, services, appCaches, profilingLogger, umbracoHelper)
8456
{
8557
_manifestParser = manifestParser;
8658
_features = features;
8759
_runtimeState = runtimeState;
88-
_iconService = iconService;
8960
}
9061

9162
protected BackOfficeSignInManager SignInManager => _signInManager ?? (_signInManager = OwinContext.GetBackOfficeSignInManager());
@@ -100,7 +71,7 @@ public BackOfficeController(
10071
/// <returns></returns>
10172
public async Task<ActionResult> Default()
10273
{
103-
var backofficeModel = new BackOfficeModel(_features, GlobalSettings, _iconService);
74+
var backofficeModel = new BackOfficeModel(_features, GlobalSettings);
10475
return await RenderDefaultOrProcessExternalLoginAsync(
10576
() => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", backofficeModel),
10677
() => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/Default.cshtml", backofficeModel));
@@ -186,7 +157,7 @@ public async Task<ActionResult> AuthorizeUpgrade()
186157
{
187158
return await RenderDefaultOrProcessExternalLoginAsync(
188159
//The default view to render when there is no external login info or errors
189-
() => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/AuthorizeUpgrade.cshtml", new BackOfficeModel(_features, GlobalSettings, _iconService)),
160+
() => View(GlobalSettings.Path.EnsureEndsWith('/') + "Views/AuthorizeUpgrade.cshtml", new BackOfficeModel(_features, GlobalSettings)),
190161
//The ActionResult to perform if external login is successful
191162
() => Redirect("/"));
192163
}
Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,19 @@
11
using System;
22
using Umbraco.Core.Configuration;
3-
using Umbraco.Core.Services;
4-
using Umbraco.Web.Composing;
53
using Umbraco.Web.Features;
64

75
namespace Umbraco.Web.Editors
86
{
9-
107
public class BackOfficeModel
118
{
129

13-
14-
[Obsolete("Use the overload that injects IIconService.")]
15-
public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings) : this(features, globalSettings, Current.IconService)
16-
{
17-
18-
}
19-
public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings, IIconService iconService)
10+
public BackOfficeModel(UmbracoFeatures features, IGlobalSettings globalSettings)
2011
{
2112
Features = features;
2213
GlobalSettings = globalSettings;
23-
IconCheckData = iconService.GetIcon("icon-check")?.SvgString;
24-
IconDeleteData = iconService.GetIcon("icon-delete")?.SvgString;
2514
}
2615

2716
public UmbracoFeatures Features { get; }
2817
public IGlobalSettings GlobalSettings { get; }
29-
public string IconCheckData { get; }
30-
public string IconDeleteData { get; }
3118
}
3219
}

0 commit comments

Comments
 (0)