Date: Thu, 12 Oct 2017 17:11:45 +1100
Subject: [PATCH 32/72] Fixes PostAddFolder
---
src/Umbraco.Web/Editors/MediaController.cs | 136 ++++++++++--------
.../Models/ContentEditing/PostedFolder.cs | 17 +++
src/Umbraco.Web/Umbraco.Web.csproj | 1 +
3 files changed, 93 insertions(+), 61 deletions(-)
create mode 100644 src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs
diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs
index 0b1a697eae..1364a8e2af 100644
--- a/src/Umbraco.Web/Editors/MediaController.cs
+++ b/src/Umbraco.Web/Editors/MediaController.cs
@@ -599,12 +599,14 @@ namespace Umbraco.Web.Editors
throw;
}
}
-
- [EnsureUserPermissionForMedia("folder.ParentId")]
- public MediaItemDisplay PostAddFolder(EntityBasic folder)
+
+ public MediaItemDisplay PostAddFolder(PostedFolder folder)
{
+ var intParentId = GetParentIdAsInt(folder.ParentId, validatePermissions:true);
+
var mediaService = ApplicationContext.Services.MediaService;
- var f = mediaService.CreateMedia(folder.Name, folder.ParentId, Constants.Conventions.MediaTypes.Folder);
+
+ var f = mediaService.CreateMedia(folder.Name, intParentId, Constants.Conventions.MediaTypes.Folder);
mediaService.Save(f, Security.CurrentUser.Id);
return Mapper.Map(f);
@@ -636,66 +638,15 @@ namespace Umbraco.Web.Editors
if (result.FileData.Count == 0)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
- }
-
+ }
+
//get the string json from the request
- int parentId; bool entityFound; GuidUdi parentUdi;
- string currentFolderId = result.FormData["currentFolder"];
- // test for udi
- if (GuidUdi.TryParse(currentFolderId, out parentUdi))
- {
- currentFolderId = parentUdi.Guid.ToString();
- }
-
- if (int.TryParse(currentFolderId, out parentId) == false)
- {
- // if a guid then try to look up the entity
- Guid idGuid;
- if (Guid.TryParse(currentFolderId, out idGuid))
- {
- var entity = Services.EntityService.GetByKey(idGuid);
- if (entity != null)
- {
- entityFound = true;
- parentId = entity.Id;
- }
- else
- {
- throw new EntityNotFoundException(currentFolderId, "The passed id doesn't exist");
- }
- }
- else
- {
- return Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer or Guid");
- }
-
- if (entityFound == false)
- {
- return Request.CreateValidationErrorResponse("The request was not formatted correctly, the currentFolder is not an integer or Guid");
- }
- }
-
-
- //ensure the user has access to this folder by parent id!
- if (CheckPermissions(
- new Dictionary(),
- Security.CurrentUser,
- Services.MediaService,
- Services.EntityService,
- parentId) == false)
- {
- return Request.CreateResponse(
- HttpStatusCode.Forbidden,
- new SimpleNotificationModel(new Notification(
- Services.TextService.Localize("speechBubbles/operationFailedHeader"),
- Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"),
- SpeechBubbleIcon.Warning)));
- }
-
+ string currentFolderId = result.FormData["currentFolder"];
+ int parentId = GetParentIdAsInt(currentFolderId, validatePermissions: true);
+
var tempFiles = new PostedFiles();
var mediaService = ApplicationContext.Services.MediaService;
-
-
+
//in case we pass a path with a folder in it, we will create it and upload media to it.
if (result.FormData.ContainsKey("path"))
{
@@ -830,6 +781,69 @@ namespace Umbraco.Web.Editors
return Request.CreateResponse(HttpStatusCode.OK, tempFiles);
}
+ ///
+ /// Given a parent id which could be a GUID, UDI or an INT, this will resolve the INT
+ ///
+ ///
+ ///
+ /// If true, this will check if the current user has access to the resolved integer parent id
+ /// and if that check fails an unauthorized exception will occur
+ ///
+ ///
+ private int GetParentIdAsInt(string parentId, bool validatePermissions)
+ {
+ int intParentId;
+ GuidUdi parentUdi;
+
+ // test for udi
+ if (GuidUdi.TryParse(parentId, out parentUdi))
+ {
+ parentId = parentUdi.Guid.ToString();
+ }
+
+ //if it's not an INT then we'll check for GUID
+ if (int.TryParse(parentId, out intParentId) == false)
+ {
+ // if a guid then try to look up the entity
+ Guid idGuid;
+ if (Guid.TryParse(parentId, out idGuid))
+ {
+ var entity = Services.EntityService.GetByKey(idGuid);
+ if (entity != null)
+ {
+ intParentId = entity.Id;
+ }
+ else
+ {
+ throw new EntityNotFoundException(parentId, "The passed id doesn't exist");
+ }
+ }
+ else
+ {
+ throw new HttpResponseException(
+ Request.CreateValidationErrorResponse("The request was not formatted correctly, the parentId is not an integer, Guid or UDI"));
+ }
+ }
+
+ //ensure the user has access to this folder by parent id!
+ if (validatePermissions && CheckPermissions(
+ new Dictionary(),
+ Security.CurrentUser,
+ Services.MediaService,
+ Services.EntityService,
+ intParentId) == false)
+ {
+ throw new HttpResponseException(Request.CreateResponse(
+ HttpStatusCode.Forbidden,
+ new SimpleNotificationModel(new Notification(
+ Services.TextService.Localize("speechBubbles/operationFailedHeader"),
+ Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"),
+ SpeechBubbleIcon.Warning))));
+ }
+
+ return intParentId;
+ }
+
///
/// Ensures the item can be moved/copied to the new location
///
diff --git a/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs b/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs
new file mode 100644
index 0000000000..35cd908787
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs
@@ -0,0 +1,17 @@
+using System.Runtime.Serialization;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ ///
+ /// Used to create a folder with the MediaController
+ ///
+ [DataContract]
+ public class PostedFolder
+ {
+ [DataMember(Name = "parentId")]
+ public string ParentId { get; set; }
+
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index c86b86db30..014d204d95 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -392,6 +392,7 @@
+
From d5447106a686edf748cc34eec0ec34c1ba387c81 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Thu, 12 Oct 2017 18:23:19 +1100
Subject: [PATCH 33/72] U4-10504 Previewing content results in the same
PrepareDocument (expensive) procedure to be executed 3 times
---
.../canvasdesigner.controller.js | 14 ++++++++++--
.../components/content/edit.controller.js | 4 ++--
src/Umbraco.Web/Editors/ContentController.cs | 22 +------------------
3 files changed, 15 insertions(+), 25 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js b/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js
index d23fdcbf84..cc45df2ce2 100644
--- a/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/canvasdesigner/canvasdesigner.controller.js
@@ -7,12 +7,22 @@ var app = angular.module("Umbraco.canvasdesigner", ['colorpicker', 'ui.slider',
.controller("Umbraco.canvasdesignerController", function ($scope, $http, $window, $timeout, $location, dialogService) {
+ var isInit = $location.search().init;
+ if (isInit === "true") {
+ //do not continue, this is the first load of this new window, if this is passed in it means it's been
+ //initialized by the content editor and then the content editor will actually re-load this window without
+ //this flag. This is a required trick to get around chrome popup mgr. We don't want to double load preview.aspx
+ //since that will double prepare the preview documents
+ return;
+ }
+
$scope.isOpen = false;
$scope.frameLoaded = false;
$scope.enableCanvasdesigner = 0;
$scope.googleFontFamilies = {};
- $scope.pageId = $location.search().id;
- $scope.pageUrl = "../dialogs/Preview.aspx?id=" + $location.search().id;
+ var pageId = $location.search().id;
+ $scope.pageId = pageId;
+ $scope.pageUrl = "../dialogs/Preview.aspx?id=" + pageId;
$scope.valueAreLoaded = false;
$scope.devices = [
{ name: "desktop", css: "desktop", icon: "icon-display", title: "Desktop" },
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
index 7d60a83b89..1a59c701d7 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js
@@ -208,9 +208,9 @@
if (!$scope.busy) {
// Chromes popup blocker will kick in if a window is opened
- // outwith the initial scoped request. This trick will fix that.
+ // without the initial scoped request. This trick will fix that.
//
- var previewWindow = $window.open('preview/?id=' + content.id, 'umbpreview');
+ var previewWindow = $window.open('preview/?init=true&id=' + content.id, 'umbpreview');
// Build the correct path so both /#/ and #/ work.
var redirect = Umbraco.Sys.ServerVariables.umbracoSettings.umbracoPath + '/preview/?id=' + content.id;
diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs
index 511b33f812..d53ee84e7c 100644
--- a/src/Umbraco.Web/Editors/ContentController.cs
+++ b/src/Umbraco.Web/Editors/ContentController.cs
@@ -643,9 +643,7 @@ namespace Umbraco.Web.Editors
ShowMessageForPublishStatus(publishStatus.Result, display);
break;
}
-
- UpdatePreviewContext(contentItem.PersistedContent.Id);
-
+
//If the item is new and the operation was cancelled, we need to return a different
// status code so the UI can handle it since it won't be able to redirect since there
// is no Id to redirect to!
@@ -875,24 +873,6 @@ namespace Umbraco.Web.Editors
}
}
- ///
- /// Checks if the user is currently in preview mode and if so will update the preview content for this item
- ///
- ///
- private void UpdatePreviewContext(int contentId)
- {
- var previewId = Request.GetPreviewCookieValue();
- if (previewId.IsNullOrWhiteSpace()) return;
- Guid id;
- if (Guid.TryParse(previewId, out id))
- {
- var d = new Document(contentId);
- var pc = new PreviewContent(UmbracoUser, id, false);
- pc.PrepareDocument(UmbracoUser, d, true);
- pc.SavePreviewSet();
- }
- }
-
///
/// Maps the dto property values to the persisted model
///
From 13055ad1f2e4771d3744d051e48dbc7b802c12d6 Mon Sep 17 00:00:00 2001
From: Claus
Date: Thu, 12 Oct 2017 11:35:08 +0200
Subject: [PATCH 34/72] U4-10524 Show warning in UI for any picker that is
referencing a trashed or deleted item
fixing the trash flag not getting mapped via automapper.
fixing up the ui for mediapicker.
fixing a small ui issue with the contentpicker and trashed content.
---
.../src/less/property-editors.less | 153 ++++++------
.../contentpicker/contentpicker.controller.js | 13 +-
.../mediapicker/mediapicker.controller.js | 58 +++--
.../mediapicker/mediapicker.html | 70 +++---
src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 65 +++---
src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 217 +++++++++---------
.../umbraco/config/lang/en_us.xml | 5 +
.../Models/ContentEditing/EntityBasic.cs | 3 -
.../Models/Mapping/EntityModelMapper.cs | 7 +-
9 files changed, 315 insertions(+), 276 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
index 8b10b2f91b..1a999b9c1c 100644
--- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less
+++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
@@ -126,21 +126,21 @@ ul.color-picker li a {
// Media picker
// --------------------------------------------------
.umb-mediapicker .add-link {
- display: inline-block;
- height: 120px;
- width: 120px;
- text-align: center;
- color: @gray-8;
- border: 2px @gray-8 dashed;
- line-height: 120px;
- text-decoration: none;
+ display: flex;
+ justify-content:center;
+ align-items:center;
+ width: 120px;
+ text-align: center;
+ color: @gray-8;
+ border: 2px @gray-8 dashed;
+ text-decoration: none;
- transition: all 150ms ease-in-out;
+ transition: all 150ms ease-in-out;
- &:hover {
- color: @turquoise-d1;
- border-color: @turquoise;
- }
+ &:hover {
+ color: @turquoise-d1;
+ border-color: @turquoise;
+ }
}
.umb-mediapicker .picked-image {
@@ -207,11 +207,10 @@ ul.color-picker li a {
.umb-mediapicker .umb-sortable-thumbnails li {
flex-direction: column;
- margin: 0;
+ margin: 0 5px 0 0;
padding: 5px;
-}
-
-
+}
+
.umb-sortable-thumbnails li:hover a {
display: flex;
justify-content: center;
@@ -219,16 +218,20 @@ ul.color-picker li a {
}
.umb-sortable-thumbnails li img {
- max-width:100%;
- max-height:100%;
- margin:auto;
- display:block;
- background-image: url(../img/checkered-background.png);
+ max-width:100%;
+ max-height:100%;
+ margin:auto;
+ display:block;
+ background-image: url(../img/checkered-background.png);
+}
+
+.umb-sortable-thumbnails li img.trashed {
+ opacity:0.3;
}
-.umb-sortable-thumbnails li img.noScale{
- max-width: none !important;
- max-height: none !important;
+.umb-sortable-thumbnails li img.noScale {
+ max-width: none !important;
+ max-height: none !important;
}
.umb-sortable-thumbnails .umb-icon-holder {
@@ -254,8 +257,8 @@ ul.color-picker li a {
}
.umb-sortable-thumbnails li:hover .umb-sortable-thumbnails__actions {
- opacity: 1;
- visibility: visible;
+ opacity: 1;
+ visibility: visible;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__action {
@@ -285,27 +288,27 @@ ul.color-picker li a {
// -------------------------------------------------
.umb-cropper{
- position: relative;
+ position: relative;
}
.umb-cropper img, .umb-cropper-gravity img{
- position: relative;
- max-width: 100%;
- height: auto;
- top: 0;
- left: 0;
+ position: relative;
+ max-width: 100%;
+ height: auto;
+ top: 0;
+ left: 0;
}
.umb-cropper img {
- max-width: none;
+ max-width: none;
}
.umb-cropper .overlay, .umb-cropper-gravity .overlay {
- top: 0;
- left: 0;
- cursor: move;
- z-index: @zindexCropperOverlay;
- position: absolute;
+ top: 0;
+ left: 0;
+ cursor: move;
+ z-index: @zindexCropperOverlay;
+ position: absolute;
}
.umb-cropper .viewport{
@@ -317,43 +320,43 @@ ul.color-picker li a {
}
.umb-cropper-gravity .viewport{
- overflow: hidden;
- position: relative;
- width: 100%;
- height: 100%;
+ overflow: hidden;
+ position: relative;
+ width: 100%;
+ height: 100%;
}
.umb-cropper .viewport:after {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: @zindexCropperOverlay - 1;
- -moz-opacity: .75;
- opacity: .75;
- filter: alpha(opacity=7);
- -webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
- -moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
- box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: @zindexCropperOverlay - 1;
+ -moz-opacity: .75;
+ opacity: .75;
+ filter: alpha(opacity=7);
+ -webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
+ -moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
+ box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
}
.umb-cropper-gravity .overlay{
- width: 14px;
- height: 14px;
- text-align: center;
- border-radius: 20px;
- background: @turquoise;
- border: 3px solid @white;
- opacity: 0.8;
+ width: 14px;
+ height: 14px;
+ text-align: center;
+ border-radius: 20px;
+ background: @turquoise;
+ border: 3px solid @white;
+ opacity: 0.8;
}
.umb-cropper-gravity .overlay i {
- font-size: 26px;
- line-height: 26px;
- opacity: 0.8 !important;
+ font-size: 26px;
+ line-height: 26px;
+ opacity: 0.8 !important;
}
.umb-cropper .crop-container {
@@ -361,16 +364,16 @@ ul.color-picker li a {
}
.umb-cropper .crop-slider {
- padding: 10px;
- border-top: 1px solid @gray-10;
- margin-top: 10px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-wrap: wrap;
- @media (min-width: 769px) {
+ padding: 10px;
+ border-top: 1px solid @gray-10;
+ margin-top: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ @media (min-width: 769px) {
padding: 10px 50px 10px 50px;
- }
+ }
}
.umb-cropper .crop-slider i {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
index 9b3316ec1a..ec83988719 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
-function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper) {
+function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper, localizationService) {
var unsubscribe;
@@ -54,7 +54,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
setSortingState($scope.renderModel);
});
- }
+ }
$scope.renderModel = [];
@@ -154,7 +154,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
}
}
-
if ($routeParams.section === "settings" && $routeParams.tree === "documentTypes") {
//if the content-picker is being rendered inside the document-type editor, we don't need to process the startnode query
dialogOptions.startNodeId = -1;
@@ -287,8 +286,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
entityResource.getUrl(entity.id, entityType).then(function(data){
// update url
angular.forEach($scope.renderModel, function(item){
- if(item.id === entity.id) {
- item.url = data;
+ if (item.id === entity.id) {
+ if (entity.trashed) {
+ item.url = localizationService.dictionary.general_recycleBin;
+ } else {
+ item.url = data;
+ }
}
});
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
index 8a7b20498d..28e034bdaf 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
- function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location) {
+ function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService) {
//check the pre-values for multi-picker
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
@@ -26,17 +26,44 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
// the mediaResource has server side auth configured for which the user must have
// access to the media section, if they don't they'll get auth errors. The entityResource
// acts differently in that it allows access if the user has access to any of the apps that
- // might require it's use. Therefore we need to use the metatData property to get at the thumbnail
+ // might require it's use. Therefore we need to use the metaData property to get at the thumbnail
// value.
- entityResource.getByIds(ids, "Media").then(function (medias) {
+ entityResource.getByIds(ids, "Media").then(function(medias) {
- _.each(medias, function (media, i) {
+ // The service only returns item results for ids that exist (deleted items are silently ignored).
+ // This results in the picked items value to be set to contain only ids of picked items that could actually be found.
+ // Since a referenced item could potentially be restored later on, instead of changing the selected values here based
+ // on whether the items exist during a save event - we should keep "placeholder" items for picked items that currently
+ // could not be fetched. This will preserve references and ensure that the state of an item does not differ depending
+ // on whether it is simply resaved or not.
+ // This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders
+ // when there is no match for a selected id. This will ensure that the values being set on save, are the same as before.
+
+ medias = _.map(ids,
+ function(id) {
+ var found = _.find(medias,
+ function(m) {
+ return m.udi === id || m.id === id;
+ });
+ if (found) {
+ return found;
+ } else {
+ return {
+ name: localizationService.dictionary.mediaPicker_deletedItem,
+ id: $scope.model.config.idType !== "udi" ? id : null,
+ udi: $scope.model.config.idType === "udi" ? id : null,
+ icon: "icon-picture",
+ thumbnail: null,
+ trashed: true
+ };
+ }
+ });
- //only show non-trashed items
- if (media.parentId >= -1) {
-
- if (!media.thumbnail) {
+ _.each(medias,
+ function(media, i) {
+ // if there is no thumbnail, try getting one if the media is not a placeholder item
+ if (!media.thumbnail && media.id) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -44,12 +71,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
if ($scope.model.config.idType === "udi") {
$scope.ids.push(media.udi);
- }
- else {
+ } else {
$scope.ids.push(media.id);
}
- }
- });
+ });
$scope.sync();
});
@@ -81,9 +106,9 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
show: true,
submit: function(model) {
- _.each(model.selectedImages, function(media, i) {
-
- if (!media.thumbnail) {
+ _.each(model.selectedImages, function(media, i) {
+ // if there is no thumbnail, try getting one if the media is not a placeholder item
+ if (!media.thumbnail && media.id) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -101,10 +126,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
$scope.mediaPickerOverlay.show = false;
$scope.mediaPickerOverlay = null;
-
}
};
-
};
$scope.sortableOptions = {
@@ -142,5 +165,4 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
//update the display val again if it has changed from the server
setupViewModel();
};
-
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
index f3aab992dd..70dd9ed2e5 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
@@ -1,47 +1,47 @@
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
index 23895db95b..297b760f19 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
@@ -90,7 +90,7 @@
NedarvSprog
- eller nedarv sprog fra forældre noder. Gælder også
+ eller nedarv sprog fra forældre noder. Gælder også
for den aktuelle node, medmindre et domæne nedenfor også indstiller et sprog.]]>
Domæner
@@ -383,15 +383,15 @@
- Du tilføjer flere sprog under 'sprog' i menuen til venstre
+ Du tilføjer flere sprog under 'sprog' i menuen til venstre
]]>
KulturnavnRediger navnet på ordbogselementet.
-
@@ -669,14 +669,14 @@
Din database er blevet fundet og identificeret somDatabase konfiguration
- installér knappen for at installere Umbraco %0% databasen
+ installér knappen for at installere Umbraco %0% databasen
]]>
installér knappen for at installere Umbraco %0% databasen]]>Næste for at fortsætte.]]>
- Databasen er ikke fundet. Kontrollér venligst at informationen i database forbindelsesstrengen i "web.config" filen er korrekt.
+ Databasen er ikke fundet. Kontrollér venligst at informationen i database forbindelsesstrengen i "web.config" filen er korrekt.
For at fortsætte bedes du venligst rette "web.config" filen (ved at bruge Visual Studio eller dit favoritprogram), scroll til bunden, tilføj forbindelsesstrengen til din database i feltet som hedder "umbracoDbDSN" og gem filen.
]]>
Kontakt venligst din ISP hvis det er nødvendigt. Hvis du installerer på en lokal maskine eller server kan du muligvis få informationerne fra din systemadministrator.]]>
@@ -724,7 +724,7 @@
Umbraco %0% er installeret og klar til brug/web.config filen og opdatére 'AppSetting' feltet UmbracoConfigurationStatus i bunden til '%0%'.]]>
- komme igang med det samme ved at klikke på "Start Umbraco" knappen nedenfor. Hvis du er ny med Umbraco, kan du finde masser af ressourcer på vores 'getting started' sider.
+ komme igang med det samme ved at klikke på "Start Umbraco" knappen nedenfor. Hvis du er ny med Umbraco, kan du finde masser af ressourcer på vores 'getting started' sider.
]]>
Start UmbracoFor at administrere dit website skal du blot åbne Umbraco administrationen og begynde at tilføje indhold, opdatere skabelonerne og stylesheets'ene eller tilføje ny funktionalitet.]]>
@@ -789,25 +789,25 @@
Rediger dine notificeringer for %0%
-
- Hej %0%
-
Dette er en automatisk mail for at informere dig om at opgaven '%1%'
- er blevet udførtpå siden '%2%' af brugeren '%3%'
-
+ Hej %0%
+
Dette er en automatisk mail for at informere dig om at opgaven '%1%'
+ er blevet udførtpå siden '%2%' af brugeren '%3%'
]]>
[%0%] Notificering om %1% udført på %2%
@@ -864,7 +864,7 @@ Mange hilsner fra Umbraco robotten
Pakken er på succesfuld vis blevet fjernetAfinstallér pakke
-
+
Bemærk: at dokumenter og medier som afhænger af denne pakke vil muligvis holde op med at virke, så vær forsigtig. Hvis i tvivl, kontakt personen som har udviklet pakken.]]>
Download opdatering fra opbevaringsbasen
@@ -912,13 +912,13 @@ Mange hilsner fra Umbraco robotten
Udgivelsen kunne ikke udgives da publiceringsdato er sat
-
-
Udgivelsen fejlede fordi en overordnet side ikke er publiceret
@@ -935,6 +935,11 @@ Mange hilsner fra Umbraco robotten
Du har ikke konfigureret nogen godkendte farver
+
+ Du har valgt et medie som er slettet eller lagt i papirkurven
+ Du har valgt medier som er slettede eller lagt i papirkurven
+ Slettet medie
+
indtast eksternt linkvælg en intern side
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index 30ebc137b9..48fd5a99c7 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -693,35 +693,35 @@
Your database has been found and is identified asDatabase configuration
- install button to install the Umbraco %0% database
+ install button to install the Umbraco %0% database
]]>
Next to proceed.]]>
- Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.
-
To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "UmbracoDbDSN" and save the file.
To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "UmbracoDbDSN" and save the file.
]]>
-
- Please contact your ISP if necessary.
+
+ Please contact your ISP if necessary.
If you're installing on a local machine or server you might need information from your system administrator.]]>
-
- Press the upgrade button to upgrade your database to Umbraco %0%
-
- Don't worry - no content will be deleted and everything will continue working afterwards!
-
+
+ Press the upgrade button to upgrade your database to Umbraco %0%
+
+ Don't worry - no content will be deleted and everything will continue working afterwards!
+
]]>
- Press Next to
+ Press Next to
proceed. ]]>
next to continue the configuration wizard]]>
@@ -736,65 +736,65 @@
More information on setting up permissions for Umbraco hereYou need to grant ASP.NET modify permissions to the following files/folders
- Your permission settings are almost perfect!
+ Your permission settings are almost perfect!
You can run Umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of Umbraco.]]>
How to ResolveClick here to read the text versionvideo tutorial on setting up folder permissions for Umbraco or read the text version.]]>
- Your permission settings might be an issue!
-
+ Your permission settings might be an issue!
+
You can run Umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of Umbraco.]]>
- Your permission settings are not ready for Umbraco!
-
+ Your permission settings are not ready for Umbraco!
+
In order to run Umbraco, you'll need to update your permission settings.]]>
- Your permission settings are perfect!
+ Your permission settings are perfect!
You are ready to run Umbraco and install packages!]]>
Resolving folder issueFollow this link for more information on problems with ASP.NET and creating foldersSetting up folder permissions
-
I want to start from scratch
- learn how)
- You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
+ learn how)
+ You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
]]>
You've just set up a clean Umbraco platform. What do you want to do next?Runway is installed
-
- This is our list of recommended modules, check off the ones you would like to install, or view the full list of modules
+
+ This is our list of recommended modules, check off the ones you would like to install, or view the full list of modules
]]>
Only recommended for experienced usersI want to start with a simple website
-
- "Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
- but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However,
- Runway offers an easy foundation based on best practices to get you started faster than ever.
- If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages.
-
-
- Included with Runway: Home page, Getting Started page, Installing Modules page.
- Optional Modules: Top Navigation, Sitemap, Contact, Gallery.
-
+
+ "Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
+ but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However,
+ Runway offers an easy foundation based on best practices to get you started faster than ever.
+ If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages.
+
+
+ Included with Runway: Home page, Getting Started page, Installing Modules page.
+ Optional Modules: Top Navigation, Sitemap, Contact, Gallery.
+
]]>
What is Runway
@@ -805,24 +805,24 @@
Step 5/5: Umbraco is ready to get you startedThank you for choosing Umbraco
- Browse your new site
+ Browse your new site
You installed Runway, so why not see how your new website looks.]]>
- Further help and information
+ Further help and information
Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the Umbraco terminology]]>
Umbraco %0% is installed and ready for use
- /web.config file and update the AppSetting key UmbracoConfigurationStatus in the bottom to the value of '%0%'.]]>
- started instantly by clicking the "Launch Umbraco" button below. If you are new to Umbraco,
+ started instantly by clicking the "Launch Umbraco" button below. If you are new to Umbraco,
you can find plenty of resources on our getting started pages.]]>
- Launch Umbraco
+ Launch Umbraco
To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]>
Connection to database failed.
@@ -830,8 +830,8 @@ To manage your website, simply open the Umbraco back office and start adding con
Umbraco Version 4Watch
- Umbraco %0% for a fresh install or upgrading from version 3.0.
-
+ Umbraco %0% for a fresh install or upgrading from version 3.0.
+
Press "next" to start the wizard.]]>
@@ -889,47 +889,47 @@ To manage your website, simply open the Umbraco back office and start adding con
Edit your notification for %0%
-
- Hi %0%
-
-
This is an automated mail to inform you that the task '%1%'
- has been performed on the page '%2%'
- by the user '%3%'
-
]]>
[%0%] Notification about %1% performed on %2%
@@ -937,9 +937,9 @@ To manage your website, simply open the Umbraco back office and start adding con
-
- button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
+
+ button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
]]>
Drop to upload
@@ -982,7 +982,7 @@ To manage your website, simply open the Umbraco back office and start adding con
Package namePackage doesn't contain any items
-
+
You can safely remove this from the system by clicking "uninstall package" below.]]>
No upgrades available
@@ -994,8 +994,8 @@ To manage your website, simply open the Umbraco back office and start adding con
The package was successfully uninstalledUninstall package
-
- Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
+
+ Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
so uninstall with caution. If in doubt, contact the package author.]]>
Download update from the repository
@@ -1042,28 +1042,28 @@ To manage your website, simply open the Umbraco back office and start adding con
-
-
-
-
-
Include unpublished subpages
@@ -1073,13 +1073,18 @@ To manage your website, simply open the Umbraco back office and start adding con
%0% and subpages have been publishedPublish %0% and all its subpages
- Publish to publish %0% and thereby making its content publicly available.
- You can publish this page and all its subpages by checking Include unpublished subpages below.
+ Publish to publish %0% and thereby making its content publicly available.
+ You can publish this page and all its subpages by checking Include unpublished subpages below.
]]>
You have not configured any approved colours
+
+
+ You have picked a media item currently deleted or in the recycle bin
+ You have picked media items currently deleted or in the recycle bin
+ Deleted itementer external link
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
index 93a0582c92..2ba7bf44f6 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
@@ -1079,6 +1079,11 @@ To manage your website, simply open the Umbraco back office and start adding con
You have not configured any approved colors
+
+ You have picked a media item currently deleted or in the recycle bin
+ You have picked media items currently deleted or in the recycle bin
+ Deleted item
+
enter external linkchoose internal page
diff --git a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
index 9f6e5b28da..12afceea05 100644
--- a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
@@ -2,10 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
-using System.Linq;
using System.Runtime.Serialization;
-using System.Text;
-using System.Threading.Tasks;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models.Validation;
diff --git a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
index 273dbd34f3..ec72c9839d 100644
--- a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
@@ -6,7 +6,6 @@ using Examine;
using Examine.LuceneEngine.Providers;
using Umbraco.Core;
using Umbraco.Core.Models;
-using Umbraco.Core.Models.EntityBase;
using Umbraco.Core.Models.Mapping;
using Umbraco.Core.Models.Membership;
using Umbraco.Web.Models.ContentEditing;
@@ -21,7 +20,7 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap()
.ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(x.NodeObjectTypeId), x.Key)))
.ForMember(basic => basic.Icon, expression => expression.MapFrom(entity => entity.ContentTypeIcon))
- .ForMember(dto => dto.Trashed, expression => expression.Ignore())
+ .ForMember(dto => dto.Trashed, expression => expression.MapFrom(x => x.Trashed))
.ForMember(x => x.Alias, expression => expression.Ignore())
.AfterMap((entity, basic) =>
{
@@ -98,8 +97,8 @@ namespace Umbraco.Web.Models.Mapping
else if (entity.NodeObjectTypeId == Constants.ObjectTypes.TemplateTypeGuid)
basic.Icon = "icon-newspaper-alt";
}
- });
-
+ });
+
config.CreateMap()
//default to document icon
.ForMember(x => x.Score, expression => expression.MapFrom(result => result.Score))
From 1ec07aa205051f167b8a5ea98df930230a30e835 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Thu, 12 Oct 2017 16:13:14 +0200
Subject: [PATCH 35/72] fixes breadcrumbs and search when start node is set
---
.../mediaPicker/mediapicker.controller.js | 71 ++++++++++++-------
1 file changed, 44 insertions(+), 27 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js
index a6a2ddcbab..ccb033a57c 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js
@@ -56,6 +56,46 @@ angular.module("umbraco")
$scope.target = dialogOptions.currentTarget;
}
+ function onInit() {
+ if ($scope.startNodeId !== -1) {
+ entityResource.getById($scope.startNodeId, "media")
+ .then(function (ent) {
+ $scope.startNodeId = ent.id;
+ run();
+ });
+ } else {
+ run();
+ }
+ }
+
+ function run() {
+ //default root item
+ if (!$scope.target) {
+ if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
+ entityResource.getById($scope.lastOpenedNode, "media")
+ .then(ensureWithinStartNode, gotoStartNode);
+ } else {
+ gotoStartNode();
+ }
+ } else {
+ //if a target is specified, go look it up - generally this target will just contain ids not the actual full
+ //media object so we need to look it up
+ var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
+ var altText = $scope.target.altText;
+ mediaResource.getById(id)
+ .then(function (node) {
+ $scope.target = node;
+ if (ensureWithinStartNode(node)) {
+ selectImage(node);
+ $scope.target.url = mediaHelper.resolveFile(node);
+ $scope.target.altText = altText;
+ $scope.openDetailsDialog();
+ }
+ },
+ gotoStartNode);
+ }
+ }
+
$scope.upload = function(v) {
angular.element(".umb-file-dropzone-directive .file-select").click();
};
@@ -107,7 +147,7 @@ angular.module("umbraco")
if (folder.id > 0) {
entityResource.getAncestors(folder.id, "media")
- .then(function(anc) {
+ .then(function(anc) {
$scope.path = _.filter(anc,
function(f) {
return f.path.indexOf($scope.startNodeId) !== -1;
@@ -218,32 +258,6 @@ angular.module("umbraco")
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
}
- //default root item
- if (!$scope.target) {
- if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
- entityResource.getById($scope.lastOpenedNode, "media")
- .then(ensureWithinStartNode, gotoStartNode);
- } else {
- gotoStartNode();
- }
- } else {
- //if a target is specified, go look it up - generally this target will just contain ids not the actual full
- //media object so we need to look it up
- var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
- var altText = $scope.target.altText;
- mediaResource.getById(id)
- .then(function(node) {
- $scope.target = node;
- if (ensureWithinStartNode(node)) {
- selectImage(node);
- $scope.target.url = mediaHelper.resolveFile(node);
- $scope.target.altText = altText;
- $scope.openDetailsDialog();
- }
- },
- gotoStartNode);
- }
-
$scope.openDetailsDialog = function() {
$scope.mediaPickerDetailsOverlay = {};
@@ -368,4 +382,7 @@ angular.module("umbraco")
}
}
}
+
+ onInit();
+
});
\ No newline at end of file
From b1f2c5d93ac7f6fee2fc7f5bfafc6460b9d543a2 Mon Sep 17 00:00:00 2001
From: Bjarne Fyrstenborg
Date: Thu, 12 Oct 2017 23:46:02 +0200
Subject: [PATCH 36/72] Add better function to get initials from name
---
.../directives/components/umbavatar.directive.js | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js
index 7fad3e8a74..7dd2f0d7a3 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbavatar.directive.js
@@ -66,9 +66,13 @@ Use this directive to render an avatar.
function getNameInitials(name) {
if(name) {
- var initials = name.match(/\b\w/g) || [];
- initials = ((initials.shift() || '') + (initials.pop() || '')).toUpperCase();
- return initials;
+ var names = name.split(' '),
+ initials = names[0].substring(0, 1);
+
+ if (names.length > 1) {
+ initials += names[names.length - 1].substring(0, 1);
+ }
+ return initials.toUpperCase();
}
return null;
}
From 62ce7f61329e9d7489df406de16ef124512223e4 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Fri, 13 Oct 2017 16:33:49 +1100
Subject: [PATCH 37/72] U4-10519 Legacy create is broken
---
src/Umbraco.Web/UI/LegacyDialogHandler.cs | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web/UI/LegacyDialogHandler.cs b/src/Umbraco.Web/UI/LegacyDialogHandler.cs
index c51a8bb08b..0c3d09f1a2 100644
--- a/src/Umbraco.Web/UI/LegacyDialogHandler.cs
+++ b/src/Umbraco.Web/UI/LegacyDialogHandler.cs
@@ -126,8 +126,10 @@ namespace Umbraco.Web.UI
{
var task = GetTaskForOperation(httpContext, umbracoUser, Operation.Create, nodeType);
if (task == null)
- throw new InvalidOperationException(
- string.Format("Could not task for operation {0} for node type {1}", Operation.Create, nodeType));
+ {
+ //if no task was found it will use the default task and we cannot validate the application assigned so return true
+ return true;
+ }
var dialogTask = task as LegacyDialogTask;
if (dialogTask != null)
@@ -154,8 +156,10 @@ namespace Umbraco.Web.UI
{
var task = GetTaskForOperation(httpContext, umbracoUser, Operation.Delete, nodeType);
if (task == null)
- throw new InvalidOperationException(
- string.Format("Could not task for operation {0} for node type {1}", Operation.Delete, nodeType));
+ {
+ //if no task was found it will use the default task and we cannot validate the application assigned so return true
+ return true;
+ }
var dialogTask = task as LegacyDialogTask;
if (dialogTask != null)
From ca57b9c5e69e24cc61929bfe572a51d14a893ce9 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Fri, 13 Oct 2017 16:50:39 +1100
Subject: [PATCH 38/72] fixes issue with js exceptions
---
.../propertyeditors/mediapicker/mediapicker.controller.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
index 28e034bdaf..70ac49fb7a 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
@@ -63,7 +63,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
_.each(medias,
function(media, i) {
// if there is no thumbnail, try getting one if the media is not a placeholder item
- if (!media.thumbnail && media.id) {
+ if (!media.thumbnail && media.id && media.metaData) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -108,7 +108,7 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
_.each(model.selectedImages, function(media, i) {
// if there is no thumbnail, try getting one if the media is not a placeholder item
- if (!media.thumbnail && media.id) {
+ if (!media.thumbnail && media.id && media.metaData) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
From a2e6da24914bbb9f0d9ff8737a291b478f3ab448 Mon Sep 17 00:00:00 2001
From: Warren Buckley
Date: Fri, 13 Oct 2017 11:19:39 +0100
Subject: [PATCH 39/72] Fix in PowerShell build - The 7Zip tool download was
giving two paths & thus break the build script
---
build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1 | 1 +
1 file changed, 1 insertion(+)
diff --git a/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1 b/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
index d1aaf7582f..2df42e5fd8 100644
--- a/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
+++ b/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
@@ -40,6 +40,7 @@ function Get-UmbracoBuildEnv
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
$file = ls -path "$dir" -name 7za.exe -recurse
+ $file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
mv "$dir\$file" $sevenZip
Remove-Directory $dir
}
From fd8daa398f4faa4d6516632fd381578386179b55 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Mon, 16 Oct 2017 16:22:10 +1100
Subject: [PATCH 40/72] U4-10538 Disable Ping on front-end nodes when load
balancing
---
src/Umbraco.Web/Scheduling/KeepAlive.cs | 15 ++++++++++++++-
src/Umbraco.Web/Scheduling/ScheduledPublishing.cs | 4 ++--
2 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/Umbraco.Web/Scheduling/KeepAlive.cs b/src/Umbraco.Web/Scheduling/KeepAlive.cs
index 763e28b608..f4beb9d5b8 100644
--- a/src/Umbraco.Web/Scheduling/KeepAlive.cs
+++ b/src/Umbraco.Web/Scheduling/KeepAlive.cs
@@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Umbraco.Core;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.Logging;
+using Umbraco.Core.Sync;
namespace Umbraco.Web.Scheduling
{
@@ -20,9 +21,21 @@ namespace Umbraco.Web.Scheduling
_appContext = appContext;
}
+ private ILogger Logger { get { return _appContext.ProfilingLogger.Logger; } }
+
public override async Task PerformRunAsync(CancellationToken token)
{
if (_appContext == null) return true; // repeat...
+
+ switch (_appContext.GetCurrentServerRole())
+ {
+ case ServerRole.Slave:
+ Logger.Debug("Does not run on slave servers.");
+ return true; // DO repeat, server role can change
+ case ServerRole.Unknown:
+ Logger.Debug("Does not run on servers with unknown role.");
+ return true; // DO repeat, server role can change
+ }
// ensure we do not run if not main domain, but do NOT lock it
if (_appContext.MainDom.IsMainDom == false)
@@ -31,7 +44,7 @@ namespace Umbraco.Web.Scheduling
return false; // do NOT repeat, going down
}
- using (DisposableTimer.DebugDuration(() => "Keep alive executing", () => "Keep alive complete"))
+ using (_appContext.ProfilingLogger.DebugDuration("Keep alive executing", "Keep alive complete"))
{
string umbracoAppUrl = null;
diff --git a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
index 46a756e0ad..919a531549 100644
--- a/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
+++ b/src/Umbraco.Web/Scheduling/ScheduledPublishing.cs
@@ -31,7 +31,7 @@ namespace Umbraco.Web.Scheduling
private ILogger Logger { get { return _appContext.ProfilingLogger.Logger; } }
- public override async Task PerformRunAsync(CancellationToken token)
+ public override bool PerformRun()
{
if (_appContext == null) return true; // repeat...
@@ -94,7 +94,7 @@ namespace Umbraco.Web.Scheduling
public override bool IsAsync
{
- get { return true; }
+ get { return false; }
}
}
}
\ No newline at end of file
From 2a0cc71d0666a496b9e6441de8ecbab73cfcde83 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Mon, 16 Oct 2017 17:05:33 +1100
Subject: [PATCH 41/72] U4-10539 - reverts merge issue that reverted the fix
for U4-9262
---
.../Views/Partials/Grid/Bootstrap2.cshtml | 28 ++++++++++++-------
.../Views/Partials/Grid/Bootstrap3.cshtml | 28 ++++++++++++-------
.../Partials/Grid/Editors/TextString.cshtml | 4 +--
3 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml
index 8b189ae1a0..1437d4f14b 100644
--- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml
@@ -60,21 +60,29 @@
JObject cfg = contentItem.config;
if(cfg != null)
- foreach (JProperty property in cfg.Properties()) {
- attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
+ foreach (JProperty property in cfg.Properties())
+ {
+ var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
+ attrs.Add(property.Name + "=\"" + propertyValue + "\"");
}
-
+
JObject style = contentItem.styles;
- if (style != null) {
- var cssVals = new List();
- foreach (JProperty property in style.Properties())
- cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
+ if (style != null) {
+ var cssVals = new List();
+ foreach (JProperty property in style.Properties())
+ {
+ var propertyValue = property.Value.ToString();
+ if (string.IsNullOrWhiteSpace(propertyValue) == false)
+ {
+ cssVals.Add(property.Name + ":" + propertyValue + ";");
+ }
+ }
- if (cssVals.Any())
- attrs.Add("style='" + string.Join(" ", cssVals) + "'");
+ if (cssVals.Any())
+ attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
}
-
+
return new MvcHtmlString(string.Join(" ", attrs));
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml
index e672aa2a11..7b4f602b26 100644
--- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml
@@ -60,21 +60,29 @@
JObject cfg = contentItem.config;
if(cfg != null)
- foreach (JProperty property in cfg.Properties()) {
- attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
+ foreach (JProperty property in cfg.Properties())
+ {
+ var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
+ attrs.Add(property.Name + "=\"" + propertyValue + "\"");
}
-
+
JObject style = contentItem.styles;
- if (style != null) {
- var cssVals = new List();
- foreach (JProperty property in style.Properties())
- cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
+ if (style != null) {
+ var cssVals = new List();
+ foreach (JProperty property in style.Properties())
+ {
+ var propertyValue = property.Value.ToString();
+ if (string.IsNullOrWhiteSpace(propertyValue) == false)
+ {
+ cssVals.Add(property.Name + ":" + propertyValue + ";");
+ }
+ }
- if (cssVals.Any())
- attrs.Add("style='" + string.Join(" ", cssVals) + "'");
+ if (cssVals.Any())
+ attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
}
-
+
return new MvcHtmlString(string.Join(" ", attrs));
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml
index 0cac4eb1ff..4408cc4322 100644
--- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml
@@ -4,8 +4,8 @@
@if (Model.editor.config.markup != null)
{
string markup = Model.editor.config.markup.ToString();
-
- markup = markup.Replace("#value#", Model.value.ToString());
+ var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
+ markup = markup.Replace("#value#", umbracoHelper.ReplaceLineBreaksForHtml(HttpUtility.HtmlEncode(Model.value.ToString())));
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
From 916bc6badbdfc1668944dd79c41298cdb052befa Mon Sep 17 00:00:00 2001
From: Shannon
Date: Mon, 16 Oct 2017 17:05:33 +1100
Subject: [PATCH 42/72] U4-10539 - reverts merge issue that reverted the fix
for U4-9262
(cherry picked from commit 2a0cc71d0666a496b9e6441de8ecbab73cfcde83)
---
.../Views/Partials/Grid/Bootstrap2.cshtml | 28 ++++++++++++-------
.../Views/Partials/Grid/Bootstrap3.cshtml | 28 ++++++++++++-------
.../Partials/Grid/Editors/TextString.cshtml | 4 +--
3 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml
index 8b189ae1a0..1437d4f14b 100644
--- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap2.cshtml
@@ -60,21 +60,29 @@
JObject cfg = contentItem.config;
if(cfg != null)
- foreach (JProperty property in cfg.Properties()) {
- attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
+ foreach (JProperty property in cfg.Properties())
+ {
+ var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
+ attrs.Add(property.Name + "=\"" + propertyValue + "\"");
}
-
+
JObject style = contentItem.styles;
- if (style != null) {
- var cssVals = new List();
- foreach (JProperty property in style.Properties())
- cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
+ if (style != null) {
+ var cssVals = new List();
+ foreach (JProperty property in style.Properties())
+ {
+ var propertyValue = property.Value.ToString();
+ if (string.IsNullOrWhiteSpace(propertyValue) == false)
+ {
+ cssVals.Add(property.Name + ":" + propertyValue + ";");
+ }
+ }
- if (cssVals.Any())
- attrs.Add("style='" + string.Join(" ", cssVals) + "'");
+ if (cssVals.Any())
+ attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
}
-
+
return new MvcHtmlString(string.Join(" ", attrs));
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml
index e672aa2a11..7b4f602b26 100644
--- a/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Bootstrap3.cshtml
@@ -60,21 +60,29 @@
JObject cfg = contentItem.config;
if(cfg != null)
- foreach (JProperty property in cfg.Properties()) {
- attrs.Add(property.Name + "='" + property.Value.ToString() + "'");
+ foreach (JProperty property in cfg.Properties())
+ {
+ var propertyValue = HttpUtility.HtmlAttributeEncode(property.Value.ToString());
+ attrs.Add(property.Name + "=\"" + propertyValue + "\"");
}
-
+
JObject style = contentItem.styles;
- if (style != null) {
- var cssVals = new List();
- foreach (JProperty property in style.Properties())
- cssVals.Add(property.Name + ":" + property.Value.ToString() + ";");
+ if (style != null) {
+ var cssVals = new List();
+ foreach (JProperty property in style.Properties())
+ {
+ var propertyValue = property.Value.ToString();
+ if (string.IsNullOrWhiteSpace(propertyValue) == false)
+ {
+ cssVals.Add(property.Name + ":" + propertyValue + ";");
+ }
+ }
- if (cssVals.Any())
- attrs.Add("style='" + string.Join(" ", cssVals) + "'");
+ if (cssVals.Any())
+ attrs.Add("style=\"" + HttpUtility.HtmlAttributeEncode(string.Join(" ", cssVals)) + "\"");
}
-
+
return new MvcHtmlString(string.Join(" ", attrs));
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml b/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml
index 0cac4eb1ff..4408cc4322 100644
--- a/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml
+++ b/src/Umbraco.Web.UI/Views/Partials/Grid/Editors/TextString.cshtml
@@ -4,8 +4,8 @@
@if (Model.editor.config.markup != null)
{
string markup = Model.editor.config.markup.ToString();
-
- markup = markup.Replace("#value#", Model.value.ToString());
+ var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
+ markup = markup.Replace("#value#", umbracoHelper.ReplaceLineBreaksForHtml(HttpUtility.HtmlEncode(Model.value.ToString())));
markup = markup.Replace("#style#", Model.editor.config.style.ToString());
From b094bfad29561849cf1aae8e1286baf2dfec92f6 Mon Sep 17 00:00:00 2001
From: Claus
Date: Mon, 16 Oct 2017 13:05:20 +0200
Subject: [PATCH 43/72] U4-10533 Show warning in UI for the link picker that is
referencing a trashed or deleted item
---
.../contentpicker/contentpicker.controller.js | 3 +-
.../contentpicker/contentpicker.html | 3 +
src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 64 ++++++++++---------
src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 4 ++
.../umbraco/config/lang/en_us.xml | 4 ++
5 files changed, 47 insertions(+), 31 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
index ec83988719..229ec614de 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
@@ -54,7 +54,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
setSortingState($scope.renderModel);
});
- }
+ }
$scope.renderModel = [];
@@ -333,6 +333,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
"icon": item.icon,
"path": item.path,
"url": item.url,
+ "trashed": item.trashed,
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html
index 75cc74f02d..1755840cc8 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html
@@ -1,5 +1,8 @@
+
+
+
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
index 297b760f19..4a189642b6 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
@@ -90,7 +90,7 @@
NedarvSprog
- eller nedarv sprog fra forældre noder. Gælder også
+ eller nedarv sprog fra forældre noder. Gælder også
for den aktuelle node, medmindre et domæne nedenfor også indstiller et sprog.]]>
Domæner
@@ -383,15 +383,15 @@
- Du tilføjer flere sprog under 'sprog' i menuen til venstre
+ Du tilføjer flere sprog under 'sprog' i menuen til venstre
]]>
KulturnavnRediger navnet på ordbogselementet.
-
@@ -669,14 +669,14 @@
Din database er blevet fundet og identificeret somDatabase konfiguration
- installér knappen for at installere Umbraco %0% databasen
+ installér knappen for at installere Umbraco %0% databasen
]]>
installér knappen for at installere Umbraco %0% databasen]]>Næste for at fortsætte.]]>
- Databasen er ikke fundet. Kontrollér venligst at informationen i database forbindelsesstrengen i "web.config" filen er korrekt.
+ Databasen er ikke fundet. Kontrollér venligst at informationen i database forbindelsesstrengen i "web.config" filen er korrekt.
For at fortsætte bedes du venligst rette "web.config" filen (ved at bruge Visual Studio eller dit favoritprogram), scroll til bunden, tilføj forbindelsesstrengen til din database i feltet som hedder "umbracoDbDSN" og gem filen.
]]>
Kontakt venligst din ISP hvis det er nødvendigt. Hvis du installerer på en lokal maskine eller server kan du muligvis få informationerne fra din systemadministrator.]]>
@@ -724,7 +724,7 @@
Umbraco %0% er installeret og klar til brug/web.config filen og opdatére 'AppSetting' feltet UmbracoConfigurationStatus i bunden til '%0%'.]]>
- komme igang med det samme ved at klikke på "Start Umbraco" knappen nedenfor. Hvis du er ny med Umbraco, kan du finde masser af ressourcer på vores 'getting started' sider.
+ komme igang med det samme ved at klikke på "Start Umbraco" knappen nedenfor. Hvis du er ny med Umbraco, kan du finde masser af ressourcer på vores 'getting started' sider.
]]>
Start UmbracoFor at administrere dit website skal du blot åbne Umbraco administrationen og begynde at tilføje indhold, opdatere skabelonerne og stylesheets'ene eller tilføje ny funktionalitet.]]>
@@ -789,25 +789,25 @@
Rediger dine notificeringer for %0%
-
- Hej %0%
-
Dette er en automatisk mail for at informere dig om at opgaven '%1%'
- er blevet udførtpå siden '%2%' af brugeren '%3%'
-
+ Hej %0%
+
Dette er en automatisk mail for at informere dig om at opgaven '%1%'
+ er blevet udførtpå siden '%2%' af brugeren '%3%'
]]>
[%0%] Notificering om %1% udført på %2%
@@ -864,7 +864,7 @@ Mange hilsner fra Umbraco robotten
Pakken er på succesfuld vis blevet fjernetAfinstallér pakke
-
+
Bemærk: at dokumenter og medier som afhænger af denne pakke vil muligvis holde op med at virke, så vær forsigtig. Hvis i tvivl, kontakt personen som har udviklet pakken.]]>
Download opdatering fra opbevaringsbasen
@@ -912,13 +912,13 @@ Mange hilsner fra Umbraco robotten
Udgivelsen kunne ikke udgives da publiceringsdato er sat
-
-
Udgivelsen fejlede fordi en overordnet side ikke er publiceret
@@ -935,6 +935,10 @@ Mange hilsner fra Umbraco robotten
Du har ikke konfigureret nogen godkendte farver
+
+ Du har valgt et dokument som er slettet eller lagt i papirkurven
+ Du har valgt dokumenter som er slettede eller lagt i papirkurven
+
Du har valgt et medie som er slettet eller lagt i papirkurvenDu har valgt medier som er slettede eller lagt i papirkurven
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index 48fd5a99c7..9134d96d59 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -1081,6 +1081,10 @@ To manage your website, simply open the Umbraco back office and start adding con
You have not configured any approved colours
+
+ You have picked a content item currently deleted or in the recycle bin
+ You have picked content items currently deleted or in the recycle bin
+
You have picked a media item currently deleted or in the recycle binYou have picked media items currently deleted or in the recycle bin
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
index 2ba7bf44f6..58c2d2eefc 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
@@ -1079,6 +1079,10 @@ To manage your website, simply open the Umbraco back office and start adding con
You have not configured any approved colors
+
+ You have picked a content item currently deleted or in the recycle bin
+ You have picked content items currently deleted or in the recycle bin
+
You have picked a media item currently deleted or in the recycle binYou have picked media items currently deleted or in the recycle bin
From 4bd263e7bcc5fb09678e2a552a06cae2913bce45 Mon Sep 17 00:00:00 2001
From: Claus
Date: Mon, 16 Oct 2017 13:52:17 +0200
Subject: [PATCH 44/72] U4-10524 Show warning in UI for the media/content
picker that is referencing a trashed or deleted item
U4-10533 Show warning in UI for the link picker that is referencing a trashed or deleted item
cherrypicked from dev-v7.
---
.../src/less/property-editors.less | 149 +++++++++---------
.../contentpicker/contentpicker.controller.js | 12 +-
.../contentpicker/contentpicker.html | 3 +
.../mediapicker/mediapicker.controller.js | 56 +++++--
.../mediapicker/mediapicker.html | 70 ++++----
src/Umbraco.Web.UI/umbraco/config/lang/da.xml | 9 ++
src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 9 ++
.../umbraco/config/lang/en_us.xml | 9 ++
.../Models/ContentEditing/EntityBasic.cs | 3 -
.../Models/Mapping/EntityModelMapper.cs | 2 +-
10 files changed, 189 insertions(+), 133 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
index 2388aae2b2..723a365eb0 100644
--- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less
+++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
@@ -126,21 +126,21 @@ ul.color-picker li a {
// Media picker
// --------------------------------------------------
.umb-mediapicker .add-link {
- display: inline-block;
- height: 120px;
- width: 120px;
- text-align: center;
- color: @gray-8;
- border: 2px @gray-8 dashed;
- line-height: 120px;
- text-decoration: none;
+ display: flex;
+ justify-content:center;
+ align-items:center;
+ width: 120px;
+ text-align: center;
+ color: @gray-8;
+ border: 2px @gray-8 dashed;
+ text-decoration: none;
- transition: all 150ms ease-in-out;
+ transition: all 150ms ease-in-out;
- &:hover {
- color: @turquoise-d1;
- border-color: @turquoise;
- }
+ &:hover {
+ color: @turquoise-d1;
+ border-color: @turquoise;
+ }
}
.umb-mediapicker .picked-image {
@@ -207,11 +207,10 @@ ul.color-picker li a {
.umb-mediapicker .umb-sortable-thumbnails li {
flex-direction: column;
- margin: 0;
+ margin: 0 5px 0 0;
padding: 5px;
}
-
.umb-sortable-thumbnails li:hover a {
display: flex;
justify-content: center;
@@ -219,16 +218,20 @@ ul.color-picker li a {
}
.umb-sortable-thumbnails li img {
- max-width:100%;
- max-height:100%;
- margin:auto;
- display:block;
- background-image: url(../img/checkered-background.png);
+ max-width:100%;
+ max-height:100%;
+ margin:auto;
+ display:block;
+ background-image: url(../img/checkered-background.png);
}
-.umb-sortable-thumbnails li img.noScale{
- max-width: none !important;
- max-height: none !important;
+.umb-sortable-thumbnails li img.trashed {
+ opacity:0.3;
+}
+
+.umb-sortable-thumbnails li img.noScale {
+ max-width: none !important;
+ max-height: none !important;
}
.umb-sortable-thumbnails .umb-icon-holder {
@@ -254,8 +257,8 @@ ul.color-picker li a {
}
.umb-sortable-thumbnails li:hover .umb-sortable-thumbnails__actions {
- opacity: 1;
- visibility: visible;
+ opacity: 1;
+ visibility: visible;
}
.umb-sortable-thumbnails .umb-sortable-thumbnails__action {
@@ -285,27 +288,27 @@ ul.color-picker li a {
// -------------------------------------------------
.umb-cropper{
- position: relative;
+ position: relative;
}
.umb-cropper img, .umb-cropper-gravity img{
- position: relative;
- max-width: 100%;
- height: auto;
- top: 0;
- left: 0;
+ position: relative;
+ max-width: 100%;
+ height: auto;
+ top: 0;
+ left: 0;
}
.umb-cropper img {
- max-width: none;
+ max-width: none;
}
.umb-cropper .overlay, .umb-cropper-gravity .overlay {
- top: 0;
- left: 0;
- cursor: move;
- z-index: 6001;
- position: absolute;
+ top: 0;
+ left: 0;
+ cursor: move;
+ z-index: 6001;
+ position: absolute;
}
.umb-cropper .viewport{
@@ -317,43 +320,43 @@ ul.color-picker li a {
}
.umb-cropper-gravity .viewport{
- overflow: hidden;
- position: relative;
- width: 100%;
- height: 100%;
+ overflow: hidden;
+ position: relative;
+ width: 100%;
+ height: 100%;
}
.umb-cropper .viewport:after {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 5999;
- -moz-opacity: .75;
- opacity: .75;
- filter: alpha(opacity=7);
- -webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
- -moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
- box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ z-index: 5999;
+ -moz-opacity: .75;
+ opacity: .75;
+ filter: alpha(opacity=7);
+ -webkit-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
+ -moz-box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
+ box-shadow: inset 0 0 0 20px white,inset 0 0 0 21px rgba(0,0,0,.1),inset 0 0 20px 21px rgba(0,0,0,.2);
}
.umb-cropper-gravity .overlay{
- width: 14px;
- height: 14px;
- text-align: center;
- border-radius: 20px;
- background: @turquoise;
- border: 3px solid @white;
- opacity: 0.8;
+ width: 14px;
+ height: 14px;
+ text-align: center;
+ border-radius: 20px;
+ background: @turquoise;
+ border: 3px solid @white;
+ opacity: 0.8;
}
.umb-cropper-gravity .overlay i {
- font-size: 26px;
- line-height: 26px;
- opacity: 0.8 !important;
+ font-size: 26px;
+ line-height: 26px;
+ opacity: 0.8 !important;
}
.umb-cropper .crop-container {
@@ -361,16 +364,16 @@ ul.color-picker li a {
}
.umb-cropper .crop-slider {
- padding: 10px;
- border-top: 1px solid @gray-10;
- margin-top: 10px;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-wrap: wrap;
- @media (min-width: 769px) {
+ padding: 10px;
+ border-top: 1px solid @gray-10;
+ margin-top: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-wrap: wrap;
+ @media (min-width: 769px) {
padding: 10px 50px 10px 50px;
- }
+ }
}
.umb-cropper .crop-slider i {
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
index 9b3316ec1a..229ec614de 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
-function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper) {
+function contentPickerController($scope, entityResource, editorState, iconHelper, $routeParams, angularHelper, navigationService, $location, miniEditorHelper, localizationService) {
var unsubscribe;
@@ -154,7 +154,6 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
}
}
-
if ($routeParams.section === "settings" && $routeParams.tree === "documentTypes") {
//if the content-picker is being rendered inside the document-type editor, we don't need to process the startnode query
dialogOptions.startNodeId = -1;
@@ -287,8 +286,12 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
entityResource.getUrl(entity.id, entityType).then(function(data){
// update url
angular.forEach($scope.renderModel, function(item){
- if(item.id === entity.id) {
- item.url = data;
+ if (item.id === entity.id) {
+ if (entity.trashed) {
+ item.url = localizationService.dictionary.general_recycleBin;
+ } else {
+ item.url = data;
+ }
}
});
});
@@ -330,6 +333,7 @@ function contentPickerController($scope, entityResource, editorState, iconHelper
"icon": item.icon,
"path": item.path,
"url": item.url,
+ "trashed": item.trashed,
"published": (item.metaData && item.metaData.IsPublished === false && entityType === "Document") ? false : true
// only content supports published/unpublished content so we set everything else to published so the UI looks correct
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html
index 75cc74f02d..1755840cc8 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.html
@@ -1,5 +1,8 @@
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
index 6652c52cc0..21a0717779 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
@@ -1,7 +1,7 @@
//this controller simply tells the dialogs service to open a mediaPicker window
//with a specified callback, this callback will receive an object with a selection on it
angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerController",
- function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location) {
+ function ($rootScope, $scope, dialogService, entityResource, mediaResource, mediaHelper, $timeout, userService, $location, localizationService) {
//check the pre-values for multi-picker
var multiPicker = $scope.model.config.multiPicker && $scope.model.config.multiPicker !== '0' ? true : false;
@@ -25,17 +25,44 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
// the mediaResource has server side auth configured for which the user must have
// access to the media section, if they don't they'll get auth errors. The entityResource
// acts differently in that it allows access if the user has access to any of the apps that
- // might require it's use. Therefore we need to use the metatData property to get at the thumbnail
+ // might require it's use. Therefore we need to use the metaData property to get at the thumbnail
// value.
- entityResource.getByIds(ids, "Media").then(function (medias) {
+ entityResource.getByIds(ids, "Media").then(function(medias) {
- _.each(medias, function (media, i) {
+ // The service only returns item results for ids that exist (deleted items are silently ignored).
+ // This results in the picked items value to be set to contain only ids of picked items that could actually be found.
+ // Since a referenced item could potentially be restored later on, instead of changing the selected values here based
+ // on whether the items exist during a save event - we should keep "placeholder" items for picked items that currently
+ // could not be fetched. This will preserve references and ensure that the state of an item does not differ depending
+ // on whether it is simply resaved or not.
+ // This is done by remapping the int/guid ids into a new array of items, where we create "Deleted item" placeholders
+ // when there is no match for a selected id. This will ensure that the values being set on save, are the same as before.
+
+ medias = _.map(ids,
+ function(id) {
+ var found = _.find(medias,
+ function(m) {
+ return m.udi === id || m.id === id;
+ });
+ if (found) {
+ return found;
+ } else {
+ return {
+ name: localizationService.dictionary.mediaPicker_deletedItem,
+ id: $scope.model.config.idType !== "udi" ? id : null,
+ udi: $scope.model.config.idType === "udi" ? id : null,
+ icon: "icon-picture",
+ thumbnail: null,
+ trashed: true
+ };
+ }
+ });
- //only show non-trashed items
- if (media.parentId >= -1) {
-
- if (!media.thumbnail) {
+ _.each(medias,
+ function(media, i) {
+ // if there is no thumbnail, try getting one if the media is not a placeholder item
+ if (!media.thumbnail && media.id && media.metaData) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -43,12 +70,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
if ($scope.model.config.idType === "udi") {
$scope.ids.push(media.udi);
- }
- else {
+ } else {
$scope.ids.push(media.id);
}
- }
- });
+ });
$scope.sync();
});
@@ -80,8 +105,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
submit: function(model) {
_.each(model.selectedImages, function(media, i) {
-
- if (!media.thumbnail) {
+ // if there is no thumbnail, try getting one if the media is not a placeholder item
+ if (!media.thumbnail && media.id && media.metaData) {
media.thumbnail = mediaHelper.resolveFileFromEntity(media, true);
}
@@ -99,10 +124,8 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
$scope.mediaPickerOverlay.show = false;
$scope.mediaPickerOverlay = null;
-
}
};
-
};
$scope.sortableOptions = {
@@ -140,5 +163,4 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
//update the display val again if it has changed from the server
setupViewModel();
};
-
});
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
index f3aab992dd..70dd9ed2e5 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
@@ -1,47 +1,47 @@
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
index d01bea3d36..d64e8b82ed 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/da.xml
@@ -784,6 +784,15 @@ Mange hilsner fra Umbraco robotten
Du har ikke konfigureret nogen godkendte farver
+
+ Du har valgt et dokument som er slettet eller lagt i papirkurven
+ Du har valgt dokumenter som er slettede eller lagt i papirkurven
+
+
+ Du har valgt et medie som er slettet eller lagt i papirkurven
+ Du har valgt medier som er slettede eller lagt i papirkurven
+ Slettet medie
+
indtast eksternt linkvælg en intern side
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index 1b71237ea4..4169c88335 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -952,6 +952,15 @@ To manage your website, simply open the Umbraco back office and start adding con
You have not configured any approved colours
+
+ You have picked a content item currently deleted or in the recycle bin
+ You have picked content items currently deleted or in the recycle bin
+
+
+ You have picked a media item currently deleted or in the recycle bin
+ You have picked media items currently deleted or in the recycle bin
+ Deleted item
+
enter external linkchoose internal page
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
index c271ce8f65..13e0ebdad5 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en_us.xml
@@ -1011,6 +1011,15 @@ To manage your website, simply open the Umbraco back office and start adding con
You have not configured any approved colors
+
+ You have picked a content item currently deleted or in the recycle bin
+ You have picked content items currently deleted or in the recycle bin
+
+
+ You have picked a media item currently deleted or in the recycle bin
+ You have picked media items currently deleted or in the recycle bin
+ Deleted item
+
enter external linkchoose internal page
diff --git a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
index 9f6e5b28da..12afceea05 100644
--- a/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
+++ b/src/Umbraco.Web/Models/ContentEditing/EntityBasic.cs
@@ -2,10 +2,7 @@
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
-using System.Linq;
using System.Runtime.Serialization;
-using System.Text;
-using System.Threading.Tasks;
using Newtonsoft.Json;
using Umbraco.Core;
using Umbraco.Core.Models.Validation;
diff --git a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
index 5be9d550e5..3d825ab055 100644
--- a/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/EntityModelMapper.cs
@@ -20,7 +20,7 @@ namespace Umbraco.Web.Models.Mapping
config.CreateMap()
.ForMember(x => x.Udi, expression => expression.MapFrom(x => Udi.Create(UmbracoObjectTypesExtensions.GetUdiType(x.NodeObjectTypeId), x.Key)))
.ForMember(basic => basic.Icon, expression => expression.MapFrom(entity => entity.ContentTypeIcon))
- .ForMember(dto => dto.Trashed, expression => expression.Ignore())
+ .ForMember(dto => dto.Trashed, expression => expression.MapFrom(x => x.Trashed))
.ForMember(x => x.Alias, expression => expression.Ignore())
.AfterMap((entity, basic) =>
{
From 5df4d3509d569d48ab43d8e2b988cf34558a9585 Mon Sep 17 00:00:00 2001
From: Warren Buckley
Date: Fri, 13 Oct 2017 11:19:39 +0100
Subject: [PATCH 45/72] Fix in PowerShell build - The 7Zip tool download was
giving two paths & thus break the build script
(cherry picked from commit a2e6da24914bbb9f0d9ff8737a291b478f3ab448)
---
build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1 | 1 +
1 file changed, 1 insertion(+)
diff --git a/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1 b/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
index d1aaf7582f..2df42e5fd8 100644
--- a/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
+++ b/build/Modules/Umbraco.Build/Get-UmbracoBuildEnv.ps1
@@ -40,6 +40,7 @@ function Get-UmbracoBuildEnv
&$nuget install 7-Zip.CommandLine -OutputDirectory $path -Verbosity quiet
$dir = ls "$path\7-Zip.CommandLine.*" | sort -property Name -descending | select -first 1
$file = ls -path "$dir" -name 7za.exe -recurse
+ $file = ls -path "$dir" -name 7za.exe -recurse | select -first 1 #A select is because there is tools\7za.exe & tools\x64\7za.exe
mv "$dir\$file" $sevenZip
Remove-Directory $dir
}
From 80f172e3fbeff02e2d9cccb902a3a913d427d716 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Mon, 16 Oct 2017 14:56:43 +0200
Subject: [PATCH 46/72] Bump version to 7.7.3
---
src/SolutionInfo.cs | 4 ++--
src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +-
src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs
index 662f0b666a..433a1e9a39 100644
--- a/src/SolutionInfo.cs
+++ b/src/SolutionInfo.cs
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyFileVersion("7.7.2")]
-[assembly: AssemblyInformationalVersion("7.7.2")]
\ No newline at end of file
+[assembly: AssemblyFileVersion("7.7.3")]
+[assembly: AssemblyInformationalVersion("7.7.3")]
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
index 3bd45dabf2..4cd24ed56c 100644
--- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
- private static readonly Version Version = new Version("7.7.2");
+ private static readonly Version Version = new Version("7.7.3");
///
/// Gets the current version of Umbraco.
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index da10edda09..1a1b6bf7d3 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -1027,9 +1027,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
TrueTrue
- 7720
+ 7730/
- http://localhost:7720
+ http://localhost:7730FalseFalse
From fb8c519f71c6672e7d256f4310b6e74b8d3ec244 Mon Sep 17 00:00:00 2001
From: Mads Rasmussen
Date: Wed, 11 Oct 2017 10:18:40 +0200
Subject: [PATCH 47/72] fixes: U4-10521 Creating new folders from the media
picker no longer works
(cherry picked from commit 1cc3b3960188a77580e49d493b55cdffe1d4c869)
# Conflicts:
# src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html
---
.../src/less/components/umb-breadcrumbs.less | 7 +++++++
.../src/views/common/overlays/mediaPicker/mediapicker.html | 2 +-
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less
index 2cad03a2ab..14a707a5bf 100644
--- a/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less
+++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-breadcrumbs.less
@@ -35,3 +35,10 @@
margin-right: 5px;
color: @gray-7;
}
+
+input.umb-breadcrumbs__add-ancestor {
+ height: 25px;
+ margin-top: -2px;
+ margin-left: 3px;
+ width: 100px;
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html
index ab745f0f75..2af3b1d834 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html
@@ -55,7 +55,7 @@
Date: Thu, 12 Oct 2017 16:13:14 +0200
Subject: [PATCH 48/72] fixes breadcrumbs and search when start node is set
(cherry picked from commit 1ec07aa205051f167b8a5ea98df930230a30e835)
---
.../mediaPicker/mediapicker.controller.js | 71 ++++++++++++-------
1 file changed, 44 insertions(+), 27 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js
index fb38581eac..37872ebd68 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js
@@ -55,6 +55,46 @@ angular.module("umbraco")
$scope.target = dialogOptions.currentTarget;
}
+ function onInit() {
+ if ($scope.startNodeId !== -1) {
+ entityResource.getById($scope.startNodeId, "media")
+ .then(function (ent) {
+ $scope.startNodeId = ent.id;
+ run();
+ });
+ } else {
+ run();
+ }
+ }
+
+ function run() {
+ //default root item
+ if (!$scope.target) {
+ if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
+ entityResource.getById($scope.lastOpenedNode, "media")
+ .then(ensureWithinStartNode, gotoStartNode);
+ } else {
+ gotoStartNode();
+ }
+ } else {
+ //if a target is specified, go look it up - generally this target will just contain ids not the actual full
+ //media object so we need to look it up
+ var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
+ var altText = $scope.target.altText;
+ mediaResource.getById(id)
+ .then(function (node) {
+ $scope.target = node;
+ if (ensureWithinStartNode(node)) {
+ selectImage(node);
+ $scope.target.url = mediaHelper.resolveFile(node);
+ $scope.target.altText = altText;
+ $scope.openDetailsDialog();
+ }
+ },
+ gotoStartNode);
+ }
+ }
+
$scope.upload = function(v) {
angular.element(".umb-file-dropzone-directive .file-select").click();
};
@@ -106,7 +146,7 @@ angular.module("umbraco")
if (folder.id > 0) {
entityResource.getAncestors(folder.id, "media")
- .then(function(anc) {
+ .then(function(anc) {
$scope.path = _.filter(anc,
function(f) {
return f.path.indexOf($scope.startNodeId) !== -1;
@@ -215,32 +255,6 @@ angular.module("umbraco")
$scope.gotoFolder({ id: $scope.startNodeId, name: "Media", icon: "icon-folder" });
}
- //default root item
- if (!$scope.target) {
- if ($scope.lastOpenedNode && $scope.lastOpenedNode !== -1) {
- entityResource.getById($scope.lastOpenedNode, "media")
- .then(ensureWithinStartNode, gotoStartNode);
- } else {
- gotoStartNode();
- }
- } else {
- //if a target is specified, go look it up - generally this target will just contain ids not the actual full
- //media object so we need to look it up
- var id = $scope.target.udi ? $scope.target.udi : $scope.target.id
- var altText = $scope.target.altText;
- mediaResource.getById(id)
- .then(function(node) {
- $scope.target = node;
- if (ensureWithinStartNode(node)) {
- selectImage(node);
- $scope.target.url = mediaHelper.resolveFile(node);
- $scope.target.altText = altText;
- $scope.openDetailsDialog();
- }
- },
- gotoStartNode);
- }
-
$scope.openDetailsDialog = function() {
$scope.mediaPickerDetailsOverlay = {};
@@ -365,4 +379,7 @@ angular.module("umbraco")
}
}
}
+
+ onInit();
+
});
\ No newline at end of file
From cefd9e7323ce4ebd84fa8fd7a868869004264dd7 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Thu, 12 Oct 2017 17:11:45 +1100
Subject: [PATCH 49/72] Fixes PostAddFolder
(cherry picked from commit c5d874464a9e2ae9d3b423ed172b764d37a46576)
# Conflicts:
# src/Umbraco.Web/Editors/MediaController.cs
---
src/Umbraco.Web/Editors/MediaController.cs | 93 ++++++++++++++-----
.../Models/ContentEditing/PostedFolder.cs | 17 ++++
src/Umbraco.Web/Umbraco.Web.csproj | 1 +
3 files changed, 89 insertions(+), 22 deletions(-)
create mode 100644 src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs
diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs
index 3ca4195a26..ee6b175355 100644
--- a/src/Umbraco.Web/Editors/MediaController.cs
+++ b/src/Umbraco.Web/Editors/MediaController.cs
@@ -413,7 +413,69 @@ namespace Umbraco.Web.Editors
}
return Request.CreateResponse(HttpStatusCode.OK);
- }
+ }
+
+ ///
+ /// Given a parent id which could be a GUID, UDI or an INT, this will resolve the INT
+ ///
+ ///
+ ///
+ /// If true, this will check if the current user has access to the resolved integer parent id
+ /// and if that check fails an unauthorized exception will occur
+ ///
+ ///
+ private int GetParentIdAsInt(string parentId, bool validatePermissions)
+ {
+ int intParentId;
+ GuidUdi parentUdi;
+
+ // test for udi
+ if (GuidUdi.TryParse(parentId, out parentUdi))
+ {
+ parentId = parentUdi.Guid.ToString();
+ }
+
+ //if it's not an INT then we'll check for GUID
+ if (int.TryParse(parentId, out intParentId) == false)
+ {
+ // if a guid then try to look up the entity
+ Guid idGuid;
+ if (Guid.TryParse(parentId, out idGuid))
+ {
+ var entity = Services.EntityService.GetByKey(idGuid);
+ if (entity != null)
+ {
+ intParentId = entity.Id;
+ }
+ else
+ {
+ throw new EntityNotFoundException(parentId, "The passed id doesn't exist");
+ }
+ }
+ else
+ {
+ throw new HttpResponseException(
+ Request.CreateValidationErrorResponse("The request was not formatted correctly, the parentId is not an integer, Guid or UDI"));
+ }
+ }
+
+ //ensure the user has access to this folder by parent id!
+ if (CheckPermissions(
+ new Dictionary(),
+ Security.CurrentUser,
+ Services.MediaService,
+ intParentId) == false)
+ {
+ throw new HttpResponseException(Request.CreateResponse(
+ HttpStatusCode.Forbidden,
+ new SimpleNotificationModel(new Notification(
+ Services.TextService.Localize("speechBubbles/operationFailedHeader"),
+ Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"),
+ SpeechBubbleIcon.Warning))));
+ }
+
+ return intParentId;
+ }
///
/// Change the sort order for media
@@ -574,11 +636,13 @@ namespace Umbraco.Web.Editors
}
}
- [EnsureUserPermissionForMedia("folder.ParentId")]
- public MediaItemDisplay PostAddFolder(EntityBasic folder)
+ public MediaItemDisplay PostAddFolder(PostedFolder folder)
{
- var mediaService = ApplicationContext.Services.MediaService;
- var f = mediaService.CreateMedia(folder.Name, folder.ParentId, Constants.Conventions.MediaTypes.Folder);
+ var intParentId = GetParentIdAsInt(folder.ParentId, validatePermissions: true);
+
+ var mediaService = ApplicationContext.Services.MediaService;
+
+ var f = mediaService.CreateMedia(folder.Name, intParentId, Constants.Conventions.MediaTypes.Folder);
mediaService.Save(f, Security.CurrentUser.Id);
return Mapper.Map(f);
@@ -649,21 +713,6 @@ namespace Umbraco.Web.Editors
}
}
-
- //ensure the user has access to this folder by parent id!
- if (CheckPermissions(
- new Dictionary(),
- Security.CurrentUser,
- Services.MediaService, parentId) == false)
- {
- return Request.CreateResponse(
- HttpStatusCode.Forbidden,
- new SimpleNotificationModel(new Notification(
- Services.TextService.Localize("speechBubbles/operationFailedHeader"),
- Services.TextService.Localize("speechBubbles/invalidUserPermissionsText"),
- SpeechBubbleIcon.Warning)));
- }
-
var tempFiles = new PostedFiles();
var mediaService = ApplicationContext.Services.MediaService;
@@ -793,8 +842,8 @@ namespace Umbraco.Web.Editors
if (origin.Value == "blueimp")
{
return Request.CreateResponse(HttpStatusCode.OK,
- tempFiles,
- //Don't output the angular xsrf stuff, blue imp doesn't like that
+ tempFiles,
+ //Don't output the angular xsrf stuff, blue imp doesn't like that
new JsonMediaTypeFormatter());
}
}
diff --git a/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs b/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs
new file mode 100644
index 0000000000..35cd908787
--- /dev/null
+++ b/src/Umbraco.Web/Models/ContentEditing/PostedFolder.cs
@@ -0,0 +1,17 @@
+using System.Runtime.Serialization;
+
+namespace Umbraco.Web.Models.ContentEditing
+{
+ ///
+ /// Used to create a folder with the MediaController
+ ///
+ [DataContract]
+ public class PostedFolder
+ {
+ [DataMember(Name = "parentId")]
+ public string ParentId { get; set; }
+
+ [DataMember(Name = "name")]
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj
index 16059f4e12..6b38bf6901 100644
--- a/src/Umbraco.Web/Umbraco.Web.csproj
+++ b/src/Umbraco.Web/Umbraco.Web.csproj
@@ -361,6 +361,7 @@
+
From dc937ec9425840e516ae0d4ee194e8f3916406c9 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Mon, 16 Oct 2017 16:13:47 +0200
Subject: [PATCH 50/72] Fix the "Add media" box no longer being square
---
src/Umbraco.Web.UI.Client/src/less/property-editors.less | 4 ++++
.../src/views/propertyeditors/mediapicker/mediapicker.html | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
index 723a365eb0..9f536a7f0d 100644
--- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less
+++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
@@ -165,6 +165,10 @@ ul.color-picker li a {
text-decoration: none;
}
+.umb-mediapicker .add-link-square {
+ height: 120px;
+}
+
.umb-thumbnails{
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
index 70dd9ed2e5..3ef1430cd3 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.html
@@ -32,7 +32,7 @@
-
+
From 529ae961ffa31b4d768f0792901cd10db729d69c Mon Sep 17 00:00:00 2001
From: Stephan
Date: Mon, 16 Oct 2017 16:16:43 +0200
Subject: [PATCH 51/72] U4-5322 - add labels to color picker
---
.../PropertyEditors/PreValueEditor.cs | 30 ++--
.../ColorPickerValueConverter.cs | 62 +++++++-
.../src/less/property-editors.less | 38 ++++-
.../colorpicker/colorpicker.controller.js | 138 ++++++++++++++++--
.../colorpicker/colorpicker.html | 8 +-
.../colorpicker/colorpicker.prevalues.html | 5 +-
.../multicolorpicker.controller.js | 52 +++++--
.../ColorListPreValueEditor.cs | 97 +++++++++++-
8 files changed, 362 insertions(+), 68 deletions(-)
diff --git a/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs b/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs
index d773eed2e9..0c8bec8f2e 100644
--- a/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/PreValueEditor.cs
@@ -178,29 +178,25 @@ namespace Umbraco.Core.PropertyEditors
return result;
}
- private void ConvertItemsToJsonIfDetected(IDictionary result)
+ protected void ConvertItemsToJsonIfDetected(IDictionary result)
{
- //now we're going to try to see if any of the values are JSON, if they are we'll convert them to real JSON objects
- // so they can be consumed as real json in angular!
+ // convert values that are Json to true Json objects that can be consumed by Angular
var keys = result.Keys.ToArray();
for (var i = 0; i < keys.Length; i++)
{
- if (result[keys[i]] is string)
+ if ((result[keys[i]] is string) == false) continue;
+
+ var asString = result[keys[i]].ToString();
+ if (asString.DetectIsJson() == false) continue;
+
+ try
{
- var asString = result[keys[i]].ToString();
- if (asString.DetectIsJson())
- {
- try
- {
- var json = JsonConvert.DeserializeObject(asString);
- result[keys[i]] = json;
- }
- catch
- {
- //swallow this exception, we thought it was json but it really isn't so continue returning a string
- }
- }
+ result[keys[i]] = JsonConvert.DeserializeObject(asString);
+ }
+ catch
+ {
+ // swallow this exception, we thought it was Json but it really isn't so continue returning a string
}
}
}
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs
index 987640716b..b0d2e0809d 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ColorPickerValueConverter.cs
@@ -1,13 +1,14 @@
using System;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
namespace Umbraco.Core.PropertyEditors.ValueConverters
{
[DefaultPropertyValueConverter]
- [PropertyValueType(typeof(string))]
- [PropertyValueCache(PropertyCacheValue.All, PropertyCacheLevel.Content)]
- public class ColorPickerValueConverter : PropertyValueConverterBase
+ public class ColorPickerValueConverter : PropertyValueConverterBase, IPropertyValueConverterMeta
{
public override bool IsConverter(PublishedPropertyType propertyType)
{
@@ -18,11 +19,60 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
return false;
}
+ public Type GetPropertyValueType(PublishedPropertyType propertyType)
+ {
+ return UseLabel(propertyType) ? typeof(PickedColor) : typeof(string);
+ }
+
+ public PropertyCacheLevel GetPropertyCacheLevel(PublishedPropertyType propertyType, PropertyCacheValue cacheValue)
+ {
+ return PropertyCacheLevel.Content;
+ }
+
+ private bool UseLabel(PublishedPropertyType propertyType)
+ {
+ var preValues = ApplicationContext.Current.Services.DataTypeService.GetPreValuesCollectionByDataTypeId(propertyType.DataTypeId);
+ PreValue preValue;
+ return preValues.PreValuesAsDictionary.TryGetValue("useLabel", out preValue) && preValue.Value == "1";
+ }
+
public override object ConvertDataToSource(PublishedPropertyType propertyType, object source, bool preview)
{
- // make sure it's a string
- return source == null ? string.Empty : source.ToString();
+ var useLabel = UseLabel(propertyType);
+
+ if (source == null) return useLabel ? null : string.Empty;
+
+ var ssource = source.ToString();
+ if (ssource.DetectIsJson())
+ {
+ try
+ {
+ var jo = JsonConvert.DeserializeObject(ssource);
+ if (useLabel) return new PickedColor(jo["value"].ToString(), jo["label"].ToString());
+ return jo["value"].ToString();
+ }
+ catch { /* not json finally */ }
+ }
+
+ if (useLabel) return new PickedColor(ssource, ssource);
+ return ssource;
+ }
+
+ public class PickedColor
+ {
+ public PickedColor(string color, string label)
+ {
+ Color = color;
+ Label = label;
+ }
+
+ public string Color { get; private set; }
+ public string Label { get; private set; }
+
+ public override string ToString()
+ {
+ return Color;
+ }
}
-
}
}
diff --git a/src/Umbraco.Web.UI.Client/src/less/property-editors.less b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
index 8b10b2f91b..c2072a1d50 100644
--- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less
+++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less
@@ -109,16 +109,48 @@ ul.color-picker li a {
}
/* pre-value editor */
-
+/*.control-group.color-picker-preval:before {
+ content: "";
+ display: inline-block;
+ vertical-align: middle;
+ height: 100%;
+}*/
+
+/*.control-group.color-picker-preval div.thumbnail {
+ display: inline-block;
+ vertical-align: middle;
+}*/
+.control-group.color-picker-preval div.color-picker-prediv {
+ display: inline-block;
+ width: 60%;
+}
+
.control-group.color-picker-preval pre {
display: inline;
margin-right: 20px;
margin-left: 10px;
+ width: 50%;
+ white-space: nowrap;
+ overflow: hidden;
+ margin-bottom: 0;
+ vertical-align: middle;
}
+.control-group.color-picker-preval btn {
+ //vertical-align: middle;
+}
+
+.control-group.color-picker-preval input[type="text"] {
+ min-width: 40%;
+ width: 40%;
+ display: inline-block;
+ margin-right: 20px;
+ margin-top: 1px;
+}
+
.control-group.color-picker-preval label {
- border:solid @white 1px;
- padding:6px;
+ border: solid @white 1px;
+ padding: 6px;
}
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js
index f14492e88a..7d847dbc83 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js
@@ -1,25 +1,131 @@
-function ColorPickerController($scope) {
- $scope.toggleItem = function (color) {
- if ($scope.model.value == color) {
- $scope.model.value = "";
- //this is required to re-validate
- $scope.propertyForm.modelValue.$setViewValue($scope.model.value);
- }
- else {
- $scope.model.value = color;
- //this is required to re-validate
- $scope.propertyForm.modelValue.$setViewValue($scope.model.value);
- }
- };
+function ColorPickerController($scope) {
+
+ $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
+
+ if ($scope.isConfigured) {
+
+ for (var key in $scope.model.config.items) {
+ if (!$scope.model.config.items[key].hasOwnProperty("value"))
+ $scope.model.config.items[key] = { value: $scope.model.config.items[key], label: $scope.model.config.items[key] };
+ }
+
+ $scope.model.useLabel = isTrue($scope.model.config.useLabel);
+ initActiveColor();
+ }
+
+ $scope.toggleItem = function (color) {
+
+ var currentColor = $scope.model.value.hasOwnProperty("value")
+ ? $scope.model.value.value
+ : $scope.model.value;
+
+ var newColor;
+ if (currentColor === color.value) {
+ // deselect
+ $scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : "";
+ newColor = "";
+ }
+ else {
+ // select
+ $scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value;
+ newColor = color.value;
+ }
+
+ // this is required to re-validate
+ $scope.propertyForm.modelValue.$setViewValue(newColor);
+ };
+
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected)
- $scope.validateMandatory = function () {
+ $scope.validateMandatory = function () {
+ var isValid = !$scope.model.validation.mandatory || (
+ $scope.model.value != null
+ && $scope.model.value != ""
+ && (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "")
+ );
return {
- isValid: !$scope.model.validation.mandatory || ($scope.model.value != null && $scope.model.value != ""),
+ isValid: isValid,
errorMsg: "Value cannot be empty",
errorKey: "required"
};
}
- $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
+ $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0;
+
+ // A color is active if it matches the value and label of the model.
+ // If the model doesn't store the label, ignore the label during the comparison.
+ $scope.isActiveColor = function (color) {
+
+ // no value
+ if (!$scope.model.value)
+ return false;
+
+ // Complex color (value and label)?
+ if (!$scope.model.value.hasOwnProperty("value"))
+ return $scope.model.value === color.value;
+
+ return $scope.model.value.value === color.value && $scope.model.value.label === color.label;
+ };
+
+ // Finds the color best matching the model's color,
+ // and sets the model color to that one. This is useful when
+ // either the value or label was changed on the data type.
+ function initActiveColor() {
+
+ // no value
+ if (!$scope.model.value)
+ return;
+
+ // Complex color (value and label)?
+ if (!$scope.model.value.hasOwnProperty("value"))
+ return;
+
+ var modelColor = $scope.model.value.value;
+ var modelLabel = $scope.model.value.label;
+
+ // Check for a full match or partial match.
+ var foundItem = null;
+
+ // Look for a fully matching color.
+ for (var key in $scope.model.config.items) {
+ var item = $scope.model.config.items[key];
+ if (item.value == modelColor && item.label == modelLabel) {
+ foundItem = item;
+ break;
+ }
+ }
+
+ // Look for a color with a matching value.
+ if (!foundItem) {
+ for (var key in $scope.model.config.items) {
+ var item = $scope.model.config.items[key];
+ if (item.value == modelColor) {
+ foundItem = item;
+ break;
+ }
+ }
+ }
+
+ // Look for a color with a matching label.
+ if (!foundItem) {
+ for (var key in $scope.model.config.items) {
+ var item = $scope.model.config.items[key];
+ if (item.label == modelLabel) {
+ foundItem = item;
+ break;
+ }
+ }
+ }
+
+ // If a match was found, set it as the active color.
+ if (foundItem) {
+ $scope.model.value.value = foundItem.value;
+ $scope.model.value.label = foundItem.label;
+ }
+ }
+
+ // figures out if a value is trueish enough
+ function isTrue(bool) {
+ return !!bool && bool !== "0" && angular.lowercase(bool) !== "false";
+ }
}
angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController);
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html
index a493fffdd8..46b624adcc 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.html
@@ -5,10 +5,10 @@
From f46ef0b006139e16be551595ab79e87e04435a9e Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Fri, 6 Oct 2017 15:14:41 +0200
Subject: [PATCH 53/72] U4-10506 Importing a specially crafted document type
file can cause XXE attack
(cherry picked from commit 5dde2efe0d2b3a47d17439e03acabb7ea2befb64)
---
.../umbraco/dialogs/importDocumenttype.aspx.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs
index 27c1724bff..147e7604c1 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/importDocumenttype.aspx.cs
@@ -70,10 +70,11 @@ namespace umbraco.presentation.umbraco.dialogs
private void import_Click(object sender, EventArgs e)
{
var xd = new XmlDocument();
+ xd.XmlResolver = null;
xd.Load(tempFile.Value);
var userId = base.getUser().Id;
-
+
var element = XElement.Parse(xd.InnerXml);
var importContentTypes = ApplicationContext.Current.Services.PackagingService.ImportContentTypes(element, userId);
var contentType = importContentTypes.FirstOrDefault();
@@ -104,7 +105,8 @@ namespace umbraco.presentation.umbraco.dialogs
documentTypeFile.PostedFile.SaveAs(fileName);
var xd = new XmlDocument();
- xd.Load(fileName);
+ xd.XmlResolver = null;
+ xd.Load(fileName);
dtName.Text = xd.DocumentElement.SelectSingleNode("//DocumentType/Info/Name").FirstChild.Value;
dtAlias.Text = xd.DocumentElement.SelectSingleNode("//DocumentType/Info/Alias").FirstChild.Value;
From fd577afe2c05a95226594ebe26f49e414ef31a70 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Fri, 6 Oct 2017 14:38:07 +0200
Subject: [PATCH 54/72] Html encode nodenames to prevent XSS attacks. Fixes
U4-10497 XSS Vulnerability in page name.
(cherry picked from commit fe2b86b681455ac975b294652064b2718d4e2ba2)
---
src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs | 2 +-
.../umbraco.presentation/umbraco/dialogs/notifications.aspx.cs | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs b/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs
index 7e09d0b425..ababea628a 100644
--- a/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs
+++ b/src/Umbraco.Web.UI/umbraco/dialogs/Publish.aspx.cs
@@ -30,7 +30,7 @@ namespace Umbraco.Web.UI.Umbraco.Dialogs
}
DocumentId = doc.Id;
- PageName = doc.Name;
+ PageName = Server.HtmlEncode(doc.Name);
DocumentPath = doc.Path;
}
diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/notifications.aspx.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/notifications.aspx.cs
index 97dc8d84d3..9010a70164 100644
--- a/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/notifications.aspx.cs
+++ b/src/Umbraco.Web/umbraco.presentation/umbraco/dialogs/notifications.aspx.cs
@@ -26,7 +26,7 @@ namespace umbraco.dialogs
protected void Page_Load(object sender, EventArgs e)
{
Button1.Text = ui.Text("update");
- pane_form.Text = ui.Text("notifications", "editNotifications", node.Text, base.getUser());
+ pane_form.Text = ui.Text("notifications", "editNotifications", Server.HtmlEncode(node.Text), base.getUser());
}
#region Web Form Designer generated code
From c5a55b17e6b1a10b92d922c6a21ea5c1d80e9a7a Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Tue, 17 Oct 2017 10:08:37 +0200
Subject: [PATCH 55/72] Manually applying U4-10369: Split out
ConfigureUmbracoAuthentication method
---
src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
index 5773d88f73..61568e3cb8 100644
--- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
+++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
@@ -46,12 +46,8 @@ namespace Umbraco.Web
///
protected virtual void ConfigureMiddleware(IAppBuilder app)
{
- //Ensure owin is configured for Umbraco back office authentication. If you have any front-end OWIN
- // cookie configuration, this must be declared after it.
+ // Configure OWIN for authentication.
app
- .UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
- .UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
- .UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize)
.UseSignalR()
.FinalizeMiddlewareConfiguration();
}
@@ -68,6 +64,20 @@ namespace Umbraco.Web
Core.Security.MembershipProviderExtensions.GetUsersMembershipProvider().AsUmbracoMembershipProvider());
}
+ ///
+ /// Configure external/OAuth login providers
+ ///
+ ///
+ protected virtual void ConfigureUmbracoAuthentication(IAppBuilder app)
+ {
+ // Ensure owin is configured for Umbraco back office authentication.
+ // Front-end OWIN cookie configuration must be declared after this code.
+ app
+ .UseUmbracoBackOfficeCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
+ .UseUmbracoBackOfficeExternalCookieAuthentication(ApplicationContext, PipelineStage.Authenticate)
+ .UseUmbracoPreviewAuthentication(ApplicationContext, PipelineStage.Authorize);
+ }
+
///
/// Raised when the middleware has been configured
///
From 461ce64feb031298b78d91e73572391b58a5835a Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Tue, 17 Oct 2017 10:57:18 +0200
Subject: [PATCH 56/72] Bump version to 7.6.10
---
src/SolutionInfo.cs | 4 ++--
src/Umbraco.Core/Configuration/UmbracoVersion.cs | 2 +-
src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/SolutionInfo.cs b/src/SolutionInfo.cs
index a333fa499d..5de3f4ec9a 100644
--- a/src/SolutionInfo.cs
+++ b/src/SolutionInfo.cs
@@ -11,5 +11,5 @@ using System.Resources;
[assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyFileVersion("7.6.9")]
-[assembly: AssemblyInformationalVersion("7.6.9")]
\ No newline at end of file
+[assembly: AssemblyFileVersion("7.6.10")]
+[assembly: AssemblyInformationalVersion("7.6.10")]
\ No newline at end of file
diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
index 1c1724ae84..26b70ac6b6 100644
--- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
{
public class UmbracoVersion
{
- private static readonly Version Version = new Version("7.6.9");
+ private static readonly Version Version = new Version("7.6.10");
///
/// Gets the current version of Umbraco.
diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
index 15d48f8f1e..9979a69cfb 100644
--- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
+++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj
@@ -2379,9 +2379,9 @@ xcopy "$(ProjectDir)"..\packages\SqlServerCE.4.0.0.1\x86\*.* "$(TargetDir)x86\"
TrueTrue
- 7690
+ 7610/
- http://localhost:7690
+ http://localhost:7610FalseFalse
From 9411a22a0d90d10ccc9b76a150342cb8cec632b5 Mon Sep 17 00:00:00 2001
From: Sebastiaan Janssen
Date: Tue, 17 Oct 2017 11:04:01 +0200
Subject: [PATCH 57/72] Don't forget to call the ConfigureUmbracoAuthentication
method
---
src/Umbraco.Web/UmbracoDefaultOwinStartup.cs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
index 61568e3cb8..a3b9dac101 100644
--- a/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
+++ b/src/Umbraco.Web/UmbracoDefaultOwinStartup.cs
@@ -46,7 +46,9 @@ namespace Umbraco.Web
///
protected virtual void ConfigureMiddleware(IAppBuilder app)
{
- // Configure OWIN for authentication.
+ // Configure OWIN for authentication.
+ ConfigureUmbracoAuthentication(app);
+
app
.UseSignalR()
.FinalizeMiddlewareConfiguration();
From 7de8f5a59a37343dbbc5b7171762ca681d9daa88 Mon Sep 17 00:00:00 2001
From: Robert
Date: Tue, 17 Oct 2017 12:09:55 +0200
Subject: [PATCH 58/72] Added missing width and height to the "show password"
icon
Not having the height and width on the icon, caused IE 11 to shrink the icon which looked a bit off.
---
src/Umbraco.Web.UI.Client/src/less/pages/login.less | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/less/pages/login.less b/src/Umbraco.Web.UI.Client/src/less/pages/login.less
index da91c07623..2fe214bf07 100644
--- a/src/Umbraco.Web.UI.Client/src/less/pages/login.less
+++ b/src/Umbraco.Web.UI.Client/src/less/pages/login.less
@@ -121,7 +121,6 @@
}
.password-toggle {
-
position: relative;
display: block;
user-select: none;
@@ -149,11 +148,10 @@
}
[type="text"] + a {
- background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M29.6.4C29 0 28 0 27.4.4L21 6.8c-1.4-.5-3-.8-5-.8C9 6 3 10 0 16c1.3 2.6 3 4.8 5.4 6.5l-5 5c-.5.5-.5 1.5 0 2 .3.4.7.5 1 .5s1 0 1.2-.4l27-27C30 2 30 1 29.6.4zM13 10c1.3 0 2.4 1 2.8 2L12 15.8c-1-.4-2-1.5-2-2.8 0-1.7 1.3-3 3-3zm-9.6 6c1.2-2 2.8-3.5 4.7-4.7l.7-.2c-.4 1-.6 2-.6 3 0 1.8.6 3.4 1.6 4.7l-2 2c-1.6-1.2-3-2.7-4-4.4zM24 13.8c0-.8 0-1.7-.4-2.4l-10 10c.7.3 1.6.4 2.4.4 4.4 0 8-3.6 8-8z'/%3E%3Cpath fill='%23444' d='M26 9l-2.2 2.2c2 1.3 3.6 3 4.8 4.8-1.2 2-2.8 3.5-4.7 4.7-2.7 1.5-5.4 2.3-8 2.3-1.4 0-2.6 0-3.8-.4L10 25c2 .6 4 1 6 1 7 0 13-4 16-10-1.4-2.8-3.5-5.2-6-7z'/%3E%3C/svg%3E");
+ background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M29.6.4C29 0 28 0 27.4.4L21 6.8c-1.4-.5-3-.8-5-.8C9 6 3 10 0 16c1.3 2.6 3 4.8 5.4 6.5l-5 5c-.5.5-.5 1.5 0 2 .3.4.7.5 1 .5s1 0 1.2-.4l27-27C30 2 30 1 29.6.4zM13 10c1.3 0 2.4 1 2.8 2L12 15.8c-1-.4-2-1.5-2-2.8 0-1.7 1.3-3 3-3zm-9.6 6c1.2-2 2.8-3.5 4.7-4.7l.7-.2c-.4 1-.6 2-.6 3 0 1.8.6 3.4 1.6 4.7l-2 2c-1.6-1.2-3-2.7-4-4.4zM24 13.8c0-.8 0-1.7-.4-2.4l-10 10c.7.3 1.6.4 2.4.4 4.4 0 8-3.6 8-8z'/%3E%3Cpath fill='%23444' d='M26 9l-2.2 2.2c2 1.3 3.6 3 4.8 4.8-1.2 2-2.8 3.5-4.7 4.7-2.7 1.5-5.4 2.3-8 2.3-1.4 0-2.6 0-3.8-.4L10 25c2 .6 4 1 6 1 7 0 13-4 16-10-1.4-2.8-3.5-5.2-6-7z'/%3E%3C/svg%3E");
}
[type="password"] + a {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath fill='%23444' d='M16 6C9 6 3 10 0 16c3 6 9 10 16 10s13-4 16-10c-3-6-9-10-16-10zm8 5.3c1.8 1.2 3.4 2.8 4.6 4.7-1.2 2-2.8 3.5-4.7 4.7-3 1.5-6 2.3-8 2.3s-6-.8-8-2.3C6 19.5 4 18 3 16c1.5-2 3-3.5 5-4.7l.6-.2C8 12 8 13 8 14c0 4.5 3.5 8 8 8s8-3.5 8-8c0-1-.3-2-.6-2.6l.4.3zM16 13c0 1.7-1.3 3-3 3s-3-1.3-3-3 1.3-3 3-3 3 1.3 3 3z'/%3E%3C/svg%3E");
}
-
}
From 11342ff1dfd3da2a82426291281849e4785bcb36 Mon Sep 17 00:00:00 2001
From: Stephan
Date: Tue, 17 Oct 2017 14:04:24 +0200
Subject: [PATCH 59/72] U4-8652 - accept exceptions when loading some
assemblies
---
src/Umbraco.Core/TypeFinder.cs | 50 ++++++++++++++++++++++++++++++++--
1 file changed, 48 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs
index ab2b24392e..6d85ea5a8a 100644
--- a/src/Umbraco.Core/TypeFinder.cs
+++ b/src/Umbraco.Core/TypeFinder.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Configuration;
using System.IO;
using System.Linq;
using System.Reflection;
@@ -21,6 +22,38 @@ namespace Umbraco.Core
{
private static volatile HashSet _localFilteredAssemblyCache;
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
+ private static readonly List NotifiedLoadExceptionAssemblies = new List();
+ private static string[] _assembliesAcceptingLoadExceptions;
+
+ private static string[] AssembliesAcceptingLoadExceptions
+ {
+ get
+ {
+ if (_assembliesAcceptingLoadExceptions != null)
+ return _assembliesAcceptingLoadExceptions;
+
+ var s = ConfigurationManager.AppSettings["Umbraco.AssembliesAcceptingLoadExceptions"];
+ return _assembliesAcceptingLoadExceptions = string.IsNullOrWhiteSpace(s)
+ ? new string[0]
+ : s.Split(',').Select(x => x.Trim()).ToArray();
+ }
+ }
+
+ private static bool AcceptsLoadExceptions(Assembly a)
+ {
+ if (AssembliesAcceptingLoadExceptions.Length == 0)
+ return false;
+ if (AssembliesAcceptingLoadExceptions.Length == 1 && AssembliesAcceptingLoadExceptions[0] == "*")
+ return true;
+ var name = a.GetName().Name; // simple name of the assembly
+ return AssembliesAcceptingLoadExceptions.Any(pattern =>
+ {
+ if (pattern.Length > name.Length) return false; // pattern longer than name
+ if (pattern.Length == name.Length) return pattern.InvariantEquals(name); // same length, must be identical
+ if (pattern[pattern.Length] != '.') return false; // pattern is shorter than name, must end with dot
+ return name.StartsWith(pattern); // and name must start with pattern
+ });
+ }
///
/// lazily load a reference to all assemblies and only local assemblies.
@@ -528,9 +561,22 @@ namespace Umbraco.Core
AppendCouldNotLoad(sb, a, getAll);
foreach (var loaderException in rex.LoaderExceptions.WhereNotNull())
AppendLoaderException(sb, loaderException);
+
+ var ex = new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
- // rethrow with new message
- throw new ReflectionTypeLoadException(rex.Types, rex.LoaderExceptions, sb.ToString());
+ // rethrow with new message, unless accepted
+ if (AcceptsLoadExceptions(a) == false) throw ex;
+
+ // log a warning, and return what we can
+ lock (NotifiedLoadExceptionAssemblies)
+ {
+ if (NotifiedLoadExceptionAssemblies.Contains(a.FullName) == false)
+ {
+ NotifiedLoadExceptionAssemblies.Add(a.FullName);
+ LogHelper.WarnWithException(typeof(TypeFinder), "Could not load all types from " + a.GetName().Name + ".", ex);
+ }
+ }
+ return rex.Types.WhereNotNull().ToArray();
}
}
From 24b147e2a6ac92a5c06148a12e4fc4d6aaea3848 Mon Sep 17 00:00:00 2001
From: Stephan
Date: Tue, 17 Oct 2017 14:39:47 +0200
Subject: [PATCH 60/72] U4-10554 - warn if closing page with changes
---
.../validation/valformmanager.directive.js | 20 +++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
index 9a00d5718c..ab22894a21 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
@@ -3,7 +3,7 @@
* @name umbraco.directives.directive:valFormManager
* @restrict A
* @require formController
-* @description Used to broadcast an event to all elements inside this one to notify that form validation has
+* @description Used to broadcast an event to all elements inside this one to notify that form validation has
* changed. If we don't use this that means you have to put a watch for each directive on a form's validation
* changing which would result in much higher processing. We need to actually watch the whole $error collection of a form
* because just watching $valid or $invalid doesn't acurrately trigger form validation changing.
@@ -12,7 +12,7 @@
* Another thing this directive does is to ensure that any .control-group that contains form elements that are invalid will
* be marked with the 'error' css class. This ensures that labels included in that control group are styled correctly.
**/
-function valFormManager(serverValidationManager, $rootScope, $log, $timeout, notificationsService, eventsService, $routeParams) {
+function valFormManager(serverValidationManager, $rootScope, $log, $timeout, notificationsService, eventsService, $routeParams, $window) {
return {
require: "form",
restrict: "A",
@@ -43,7 +43,7 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
return formCtrl.$error;
}, function (e) {
scope.$broadcast("valStatusChanged", { form: formCtrl });
-
+
//find all invalid elements' .control-group's and apply the error class
var inError = element.find(".control-group .ng-invalid").closest(".control-group");
inError.addClass("error");
@@ -53,12 +53,12 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
noInError.removeClass("error");
}, true);
-
+
var className = attr.valShowValidation ? attr.valShowValidation : "show-validation";
var savingEventName = attr.savingEvent ? attr.savingEvent : "formSubmitting";
var savedEvent = attr.savedEvent ? attr.savingEvent : "formSubmitted";
- //This tracks if the user is currently saving a new item, we use this to determine
+ //This tracks if the user is currently saving a new item, we use this to determine
// if we should display the warning dialog that they are leaving the page - if a new item
// is being saved we never want to display that dialog, this will also cause problems when there
// are server side validation issues.
@@ -85,7 +85,7 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
element.removeClass(className);
//clear form state as at this point we retrieve new data from the server
- //and all validation will have cleared at this point
+ //and all validation will have cleared at this point
formCtrl.$setPristine();
}));
@@ -117,11 +117,19 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
});
unsubscribe.push(locationEvent);
+ var savedUnloadHandler = $window.onbeforeunload;
+ $window.onbeforeunload = function () {
+ if (formCtrl.$dirty) {
+ return "You have unsaved changes."; // most browsers won't display it anyways
+ }
+ }
+
//Ensure to remove the event handler when this instance is destroyted
scope.$on('$destroy', function() {
for (var u in unsubscribe) {
unsubscribe[u]();
}
+ $window.onbeforeunload = savedUnloadHandler;
});
$timeout(function(){
From 353b8f21cd86585a364eba31b5355b4531ef7bc7 Mon Sep 17 00:00:00 2001
From: Stephan
Date: Tue, 17 Oct 2017 16:04:31 +0200
Subject: [PATCH 61/72] U4-7317 - select default template
---
src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
index 1809bffd3d..724ba26b9e 100644
--- a/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
+++ b/src/Umbraco.Web/Models/Mapping/ContentModelMapper.cs
@@ -107,7 +107,7 @@ namespace Umbraco.Web.Models.Mapping
}
//fill in the template config to be passed to the template drop down.
- var templateItemConfig = new Dictionary {{"", localizedText.Localize("general/choose")}};
+ var templateItemConfig = new Dictionary();
foreach (var t in content.ContentType.AllowedTemplates
.Where(t => t.Alias.IsNullOrWhiteSpace() == false && t.Name.IsNullOrWhiteSpace() == false))
{
@@ -158,7 +158,9 @@ namespace Umbraco.Web.Models.Mapping
{
Alias = string.Format("{0}template", Constants.PropertyEditors.InternalGenericPropertiesPrefix),
Label = localizedText.Localize("template/template"),
- Value = display.TemplateAlias,
+ Value = string.IsNullOrEmpty(display.TemplateAlias)
+ ? (content.ContentType.DefaultTemplate == null ? "" : content.ContentType.DefaultTemplate.Alias)
+ : display.TemplateAlias,
View = "dropdown", //TODO: Hard coding until we make a real dropdown property editor to lookup
Config = new Dictionary
{
From 0688835ac0a35e3ae76fc0db2566fdd2266e7c23 Mon Sep 17 00:00:00 2001
From: Claus
Date: Tue, 17 Oct 2017 23:44:03 +0200
Subject: [PATCH 62/72] fixing bug in U4-10524 Show warning in UI for the
media/content picker that is referencing a trashed or deleted item
---
.../propertyeditors/mediapicker/mediapicker.controller.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
index f550d30c4c..91777bfc3e 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
@@ -44,7 +44,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
function(id) {
var found = _.find(medias,
function(m) {
- return m.udi === id || m.id === id;
+ // We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
+ // it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
+ // compares and be completely sure it works.
+ return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
});
if (found) {
return found;
From 9c50e1c48dab639d7d97b0df2dfaa4a017db6e12 Mon Sep 17 00:00:00 2001
From: Claus
Date: Tue, 17 Oct 2017 23:52:34 +0200
Subject: [PATCH 63/72] fixing bug in U4-10524 Show warning in UI for the
media/content picker that is referencing a trashed or deleted item
---
.../propertyeditors/mediapicker/mediapicker.controller.js | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
index 21a0717779..27a1e85823 100644
--- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/mediapicker/mediapicker.controller.js
@@ -43,7 +43,10 @@ angular.module('umbraco').controller("Umbraco.PropertyEditors.MediaPickerControl
function(id) {
var found = _.find(medias,
function(m) {
- return m.udi === id || m.id === id;
+ // We could use coercion (two ='s) here .. but not sure if this works equally well in all browsers and
+ // it's prone to someone "fixing" it at some point without knowing the effects. Rather use toString()
+ // compares and be completely sure it works.
+ return m.udi.toString() === id.toString() || m.id.toString() === id.toString();
});
if (found) {
return found;
From b06d30c0f92af5514b4b259fec00226e6e5670ab Mon Sep 17 00:00:00 2001
From: Stephan
Date: Wed, 18 Oct 2017 09:29:50 +0200
Subject: [PATCH 64/72] U4-10554 - cross-browser
---
.../validation/valformmanager.directive.js | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
index ab22894a21..a8c3261924 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js
@@ -117,19 +117,27 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not
});
unsubscribe.push(locationEvent);
- var savedUnloadHandler = $window.onbeforeunload;
- $window.onbeforeunload = function () {
+ // try to do it in the most cross-browser way
+ // some browsers will display their own custom message
+ // and some will just ignore this completely
+ function onBeforeUnload(e) {
if (formCtrl.$dirty) {
- return "You have unsaved changes."; // most browsers won't display it anyways
+ var message = "You have unsaved changes.";
+ e.returnValue = message;
+ return message;
+ } else {
+ return null;
}
}
+ $window.addEventListener("beforeunload", onBeforeUnload);
+
//Ensure to remove the event handler when this instance is destroyted
scope.$on('$destroy', function() {
for (var u in unsubscribe) {
unsubscribe[u]();
}
- $window.onbeforeunload = savedUnloadHandler;
+ $window.removeEventListener("beforeunload", onBeforeUnload);
});
$timeout(function(){
From dd5560f00b5d0deb292bc8c5c179687d8b3d534b Mon Sep 17 00:00:00 2001
From: Stephan
Date: Wed, 18 Oct 2017 10:11:23 +0200
Subject: [PATCH 65/72] U4-8616 - minor cleanup
---
.../src/common/services/assets.service.js | 80 ++++++++-----------
1 file changed, 33 insertions(+), 47 deletions(-)
diff --git a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js
index 0d1c2b30f9..16330f5493 100644
--- a/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js
+++ b/src/Umbraco.Web.UI.Client/src/common/services/assets.service.js
@@ -2,12 +2,12 @@
* @ngdoc service
* @name umbraco.services.assetsService
*
- * @requires $q
+ * @requires $q
* @requires angularHelper
- *
+ *
* @description
* Promise-based utillity service to lazy-load client-side dependencies inside angular controllers.
- *
+ *
* ##usage
* To use, simply inject the assetsService into any controller that needs it, and make
* sure the umbraco.services module is accesible - which it should be by default.
@@ -18,7 +18,7 @@
* //this code executes when the dependencies are done loading
* });
* });
- *
+ *
*
* You can also load individual files, which gives you greater control over what attibutes are passed to the file, as well as timeout
*
@@ -38,7 +38,7 @@
* //loadcss cannot determine when the css is done loading, so this will trigger instantly
* });
* });
- *
+ *
*/
angular.module('umbraco.services')
.factory('assetsService', function ($q, $log, angularHelper, umbRequestHelper, $rootScope, $http) {
@@ -79,7 +79,7 @@ angular.module('umbraco.services')
}
},
- /**
+ /**
Internal method. This is called when the application is loading and the user is already authenticated, or once the user is authenticated.
There's a few assets the need to be loaded for the application to function but these assets require authentication to load.
*/
@@ -110,10 +110,10 @@ angular.module('umbraco.services')
*
* @description
* Injects a file as a stylesheet into the document head
- *
+ *
* @param {String} path path to the css file to load
* @param {Scope} scope optional scope to pass into the loader
- * @param {Object} keyvalue collection of attributes to pass to the stylesheet element
+ * @param {Object} keyvalue collection of attributes to pass to the stylesheet element
* @param {Number} timeout in milliseconds
* @returns {Promise} Promise object which resolves when the file has loaded
*/
@@ -151,10 +151,10 @@ angular.module('umbraco.services')
*
* @description
* Injects a file as a javascript into the document
- *
+ *
* @param {String} path path to the js file to load
* @param {Scope} scope optional scope to pass into the loader
- * @param {Object} keyvalue collection of attributes to pass to the script element
+ * @param {Object} keyvalue collection of attributes to pass to the script element
* @param {Number} timeout in milliseconds
* @returns {Promise} Promise object which resolves when the file has loaded
*/
@@ -195,7 +195,7 @@ angular.module('umbraco.services')
*
* @description
* Injects a collection of css and js files
- *
+ *
*
* @param {Array} pathArray string array of paths to the files to load
* @param {Scope} scope optional scope to pass into the loader
@@ -211,7 +211,8 @@ angular.module('umbraco.services')
// Check to see if there's anything to load, resolve promise if not
var nonEmpty = _.reject(pathArray, function (item) {
return item === undefined || item === "";
- });
+ });
+
if (nonEmpty.length === 0) {
var deferred = $q.defer();
promise = deferred.promise;
@@ -233,8 +234,8 @@ angular.module('umbraco.services')
assets.push(asset);
}
- //we need to always push to the promises collection to monitor correct
- //execution
+ //we need to always push to the promises collection to monitor correct
+ //execution
promises.push(asset.deferred.promise);
}
});
@@ -250,45 +251,30 @@ angular.module('umbraco.services')
var jsAssets = _.filter(assets,
function (asset) {
return asset.path.match(/(\.js$|\.js\?)/ig);
- });
-
+ });
+
+ function assetLoaded(asset) {
+ asset.state = "loaded";
+ if (!scope) {
+ asset.deferred.resolve(true);
+ return;
+ }
+ angularHelper.safeApply(scope,
+ function () {
+ asset.deferred.resolve(true);
+ });
+ }
+
if (cssAssets.length > 0) {
var cssPaths = _.map(cssAssets, function (asset) { return appendRnd(asset.path) });
- LazyLoad.css(cssPaths,
- function () {
- _.each(cssAssets,
- function (asset) {
- asset.state = "loaded";
- if (!scope) {
- asset.deferred.resolve(true);
- return;
- }
- angularHelper.safeApply(scope,
- function () {
- asset.deferred.resolve(true);
- });
- });
- });
+ LazyLoad.css(cssPaths, function() { _.each(cssAssets, assetLoaded); });
}
if (jsAssets.length > 0) {
var jsPaths = _.map(jsAssets, function (asset) { return appendRnd(asset.path) });
- LazyLoad.js(jsPaths,
- function () {
- _.each(jsAssets,
- function (asset) {
- asset.state = "loaded";
- if (!scope) {
- asset.deferred.resolve(true);
- return;
- }
- angularHelper.safeApply(scope,
- function () {
- asset.deferred.resolve(true);
- });
- });
- });
- }
+ LazyLoad.js(jsPaths, function () { _.each(jsAssets, assetLoaded); });
+ }
+
return promise;
}
};
From 4c7358d63b4b169cadb0e8c6f417fa7c69483b4b Mon Sep 17 00:00:00 2001
From: Stephan
Date: Wed, 18 Oct 2017 12:17:58 +0200
Subject: [PATCH 66/72] U4-8960 - minor fixes
---
src/Umbraco.Core/IO/IOHelper.cs | 29 ++++++++++++++++++++++-------
src/Umbraco.Core/TypeFinder.cs | 6 +-----
2 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/src/Umbraco.Core/IO/IOHelper.cs b/src/Umbraco.Core/IO/IOHelper.cs
index 04d390a3cc..a58d983667 100644
--- a/src/Umbraco.Core/IO/IOHelper.cs
+++ b/src/Umbraco.Core/IO/IOHelper.cs
@@ -13,13 +13,28 @@ using Umbraco.Core.Configuration;
namespace Umbraco.Core.IO
{
public static class IOHelper
- {
- public static bool IAmUnitTestingSoNeverUseHttpContextEver = false;
+ {
+ ///
+ /// Gets or sets a value forcing Umbraco to consider it is non-hosted.
+ ///
+ /// This should always be false, unless unit testing.
+ public static bool ForceNotHosted { get; set; }
private static string _rootDir = "";
// static compiled regex for faster performance
private readonly static Regex ResolveUrlPattern = new Regex("(=[\"\']?)(\\W?\\~(?:.(?![\"\']?\\s+(?:\\S+)=|[>\"\']))+.)[\"\']?", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
+
+ ///
+ /// Gets a value indicating whether Umbraco is hosted.
+ ///
+ public static bool IsHosted
+ {
+ get
+ {
+ return ForceNotHosted == false && (HttpContext.Current != null || HostingEnvironment.IsHosted);
+ }
+ }
public static char DirSepChar
{
@@ -74,14 +89,14 @@ namespace Umbraco.Core.IO
internal static string ResolveUrlsFromTextString(string text)
{
if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString)
- {
+ {
using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
{
// find all relative urls (ie. urls that contain ~)
var tags = ResolveUrlPattern.Matches(text);
-
+
foreach (Match tag in tags)
- {
+ {
string url = "";
if (tag.Groups[1].Success)
url = tag.Groups[1].Value;
@@ -100,7 +115,7 @@ namespace Umbraco.Core.IO
public static string MapPath(string path, bool useHttpContext)
{
if (path == null) throw new ArgumentNullException("path");
- useHttpContext = useHttpContext && IAmUnitTestingSoNeverUseHttpContextEver == false;
+ useHttpContext = useHttpContext && IsHosted;
// Check if the path is already mapped
if ((path.Length >= 2 && path[1] == Path.VolumeSeparatorChar)
@@ -306,7 +321,7 @@ namespace Umbraco.Core.IO
var debugFolder = Path.Combine(binFolder, "debug");
if (Directory.Exists(debugFolder))
return debugFolder;
-#endif
+#endif
var releaseFolder = Path.Combine(binFolder, "release");
if (Directory.Exists(releaseFolder))
return releaseFolder;
diff --git a/src/Umbraco.Core/TypeFinder.cs b/src/Umbraco.Core/TypeFinder.cs
index 0f69ee5ba5..043c4aa361 100644
--- a/src/Umbraco.Core/TypeFinder.cs
+++ b/src/Umbraco.Core/TypeFinder.cs
@@ -5,9 +5,7 @@ using System.Linq;
using System.Reflection;
using System.Security;
using System.Text;
-using System.Web;
using System.Web.Compilation;
-using System.Web.Hosting;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -19,8 +17,6 @@ namespace Umbraco.Core
///
public static class TypeFinder
{
- public static bool IAmUnitTestingSoNeverUseHttpContextEver = false;
-
private static volatile HashSet _localFilteredAssemblyCache;
private static readonly object LocalFilteredAssemblyCacheLocker = new object();
@@ -47,7 +43,7 @@ namespace Umbraco.Core
HashSet assemblies = null;
try
{
- var isHosted = (HttpContext.Current != null || HostingEnvironment.IsHosted) && IAmUnitTestingSoNeverUseHttpContextEver == false;
+ var isHosted = IOHelper.IsHosted;
try
{
From 507e3ece98386eb293058bac047a8a2a190d275b Mon Sep 17 00:00:00 2001
From: Richard Thompson
Date: Wed, 18 Oct 2017 15:36:17 +0100
Subject: [PATCH 67/72] Removed duplicate translations
Removed duplicate definition of English translations
---
src/Umbraco.Web.UI/umbraco/config/lang/en.xml | 241 +++++++++---------
1 file changed, 116 insertions(+), 125 deletions(-)
diff --git a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
index a3b12c2e78..3cb67797de 100644
--- a/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
+++ b/src/Umbraco.Web.UI/umbraco/config/lang/en.xml
@@ -87,14 +87,14 @@
Domain '%0%' has been updatedEdit Current Domains
-
InheritCulture
- or inherit culture from parent nodes. Will also apply
+ or inherit culture from parent nodes. Will also apply
to the current node, unless a domain below applies too.]]>
Domains
@@ -351,11 +351,11 @@
Number of columnsNumber of rows
- Set a placeholder id by setting an ID on your placeholder you can inject content into this template from child templates,
+ Set a placeholder id by setting an ID on your placeholder you can inject content into this template from child templates,
by referring this ID using a <asp:content /> element.]]>
- Select a placeholder id from the list below. You can only
+ Select a placeholder id from the list below. You can only
choose Id's from the current template's master.]]>
Click on the image to see full size
@@ -397,15 +397,15 @@
- %0%' below You can add additional languages under the 'languages' in the menu on the left
+ %0%' below You can add additional languages under the 'languages' in the menu on the left
]]>
Culture NameEdit the key of the dictionary item.
-
@@ -693,35 +693,35 @@
Your database has been found and is identified asDatabase configuration
- install button to install the Umbraco %0% database
+ install button to install the Umbraco %0% database
]]>
Next to proceed.]]>
- Database not found! Please check that the information in the "connection string" of the "web.config" file is correct.
-
To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "UmbracoDbDSN" and save the file.
To proceed, please edit the "web.config" file (using Visual Studio or your favourite text editor), scroll to the bottom, add the connection string for your database in the key named "UmbracoDbDSN" and save the file.
]]>
-
- Please contact your ISP if necessary.
+
+ Please contact your ISP if necessary.
If you're installing on a local machine or server you might need information from your system administrator.]]>
-
- Press the upgrade button to upgrade your database to Umbraco %0%
-
- Don't worry - no content will be deleted and everything will continue working afterwards!
-
+
+ Press the upgrade button to upgrade your database to Umbraco %0%
+
+ Don't worry - no content will be deleted and everything will continue working afterwards!
+
]]>
- Press Next to
+ Press Next to
proceed. ]]>
next to continue the configuration wizard]]>
@@ -736,65 +736,65 @@
More information on setting up permissions for Umbraco hereYou need to grant ASP.NET modify permissions to the following files/folders
- Your permission settings are almost perfect!
+ Your permission settings are almost perfect!
You can run Umbraco without problems, but you will not be able to install packages which are recommended to take full advantage of Umbraco.]]>
How to ResolveClick here to read the text versionvideo tutorial on setting up folder permissions for Umbraco or read the text version.]]>
- Your permission settings might be an issue!
-
+ Your permission settings might be an issue!
+
You can run Umbraco without problems, but you will not be able to create folders or install packages which are recommended to take full advantage of Umbraco.]]>
- Your permission settings are not ready for Umbraco!
-
+ Your permission settings are not ready for Umbraco!
+
In order to run Umbraco, you'll need to update your permission settings.]]>
- Your permission settings are perfect!
+ Your permission settings are perfect!
You are ready to run Umbraco and install packages!]]>
Resolving folder issueFollow this link for more information on problems with ASP.NET and creating foldersSetting up folder permissions
-
I want to start from scratch
- learn how)
- You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
+ learn how)
+ You can still choose to install Runway later on. Please go to the Developer section and choose Packages.
]]>
You've just set up a clean Umbraco platform. What do you want to do next?Runway is installed
-
- This is our list of recommended modules, check off the ones you would like to install, or view the full list of modules
+
+ This is our list of recommended modules, check off the ones you would like to install, or view the full list of modules
]]>
Only recommended for experienced usersI want to start with a simple website
-
- "Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
- but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However,
- Runway offers an easy foundation based on best practices to get you started faster than ever.
- If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages.
-
-
- Included with Runway: Home page, Getting Started page, Installing Modules page.
- Optional Modules: Top Navigation, Sitemap, Contact, Gallery.
-
+
+ "Runway" is a simple website providing some basic document types and templates. The installer can set up Runway for you automatically,
+ but you can easily edit, extend or remove it. It's not necessary and you can perfectly use Umbraco without it. However,
+ Runway offers an easy foundation based on best practices to get you started faster than ever.
+ If you choose to install Runway, you can optionally select basic building blocks called Runway Modules to enhance your Runway pages.
+
+
+ Included with Runway: Home page, Getting Started page, Installing Modules page.
+ Optional Modules: Top Navigation, Sitemap, Contact, Gallery.
+
]]>
What is Runway
@@ -805,24 +805,24 @@
Step 5/5: Umbraco is ready to get you startedThank you for choosing Umbraco
- Browse your new site
+ Browse your new site
You installed Runway, so why not see how your new website looks.]]>
- Further help and information
+ Further help and information
Get help from our award winning community, browse the documentation or watch some free videos on how to build a simple site, how to use packages and a quick guide to the Umbraco terminology]]>
Umbraco %0% is installed and ready for use
- /web.config file and update the AppSetting key UmbracoConfigurationStatus in the bottom to the value of '%0%'.]]>
- started instantly by clicking the "Launch Umbraco" button below. If you are new to Umbraco,
+ started instantly by clicking the "Launch Umbraco" button below. If you are new to Umbraco,
you can find plenty of resources on our getting started pages.]]>
- Launch Umbraco
+ Launch Umbraco
To manage your website, simply open the Umbraco back office and start adding content, updating the templates and stylesheets or add new functionality]]>
Connection to database failed.
@@ -830,8 +830,8 @@ To manage your website, simply open the Umbraco back office and start adding con
Umbraco Version 4Watch
- Umbraco %0% for a fresh install or upgrading from version 3.0.
-
+ Umbraco %0% for a fresh install or upgrading from version 3.0.
+
Press "next" to start the wizard.]]>
@@ -889,47 +889,47 @@ To manage your website, simply open the Umbraco back office and start adding con
Edit your notification for %0%
-
- Hi %0%
-
-
This is an automated mail to inform you that the task '%1%'
- has been performed on the page '%2%'
- by the user '%3%'
-
]]>
[%0%] Notification about %1% performed on %2%
@@ -937,9 +937,9 @@ To manage your website, simply open the Umbraco back office and start adding con
-
- button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
+
+ button and locating the package. Umbraco packages usually have a ".umb" or ".zip" extension.
]]>
Drop to upload
@@ -982,7 +982,7 @@ To manage your website, simply open the Umbraco back office and start adding con
Package namePackage doesn't contain any items
-
+
You can safely remove this from the system by clicking "uninstall package" below.]]>
No upgrades available
@@ -994,8 +994,8 @@ To manage your website, simply open the Umbraco back office and start adding con
The package was successfully uninstalledUninstall package
-
- Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
+
+ Notice: any documents, media etc depending on the items you remove, will stop working, and could lead to system instability,
so uninstall with caution. If in doubt, contact the package author.]]>
Download update from the repository
@@ -1042,28 +1042,28 @@ To manage your website, simply open the Umbraco back office and start adding con
-
-
-
-
-
Include unpublished subpages
@@ -1073,22 +1073,13 @@ To manage your website, simply open the Umbraco back office and start adding con
%0% and subpages have been publishedPublish %0% and all its subpages
- Publish to publish %0% and thereby making its content publicly available.
- You can publish this page and all its subpages by checking Include unpublished subpages below.
+ Publish to publish %0% and thereby making its content publicly available.
+ You can publish this page and all its subpages by checking Include unpublished subpages below.
]]>
You have not configured any approved colours
-
-
- You have picked a content item currently deleted or in the recycle bin
- You have picked content items currently deleted or in the recycle bin
-
-
- You have picked a media item currently deleted or in the recycle bin
- You have picked media items currently deleted or in the recycle bin
- Deleted itemYou have picked a content item currently deleted or in the recycle bin
@@ -1889,4 +1880,4 @@ To manage your website, simply open the Umbraco back office and start adding con
characters left
-
\ No newline at end of file
+
From f85532f15eaf55938ac22519c1dcde38852d9797 Mon Sep 17 00:00:00 2001
From: Shannon
Date: Fri, 20 Oct 2017 00:56:34 +1100
Subject: [PATCH 68/72] U4-10566 The legacy API Member.PopulateGroups throws an
exception
---
src/umbraco.cms/businesslogic/member/Member.cs | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/umbraco.cms/businesslogic/member/Member.cs b/src/umbraco.cms/businesslogic/member/Member.cs
index 71c8eda701..c46e4d914c 100644
--- a/src/umbraco.cms/businesslogic/member/Member.cs
+++ b/src/umbraco.cms/businesslogic/member/Member.cs
@@ -773,14 +773,20 @@ namespace umbraco.cms.businesslogic.member
{
var temp = new Hashtable();
+ var groupIds = new List();
+
using (var sqlHelper = Application.SqlHelper)
using (var dr = sqlHelper.ExecuteReader(
"select memberGroup from cmsMember2MemberGroup where member = @id",
sqlHelper.CreateParameter("@id", Id)))
{
while (dr.Read())
- temp.Add(dr.GetInt("memberGroup"),
- new MemberGroup(dr.GetInt("memberGroup")));
+ groupIds.Add(dr.GetInt("memberGroup"));
+ }
+
+ foreach (var groupId in groupIds)
+ {
+ temp.Add(groupId, new MemberGroup(groupId));
}
_groups = temp;
}
From edfe2122276f58f0c1bf16e27eb2c12b84b7b7e7 Mon Sep 17 00:00:00 2001
From: Stephan
Date: Fri, 20 Oct 2017 15:35:30 +0200
Subject: [PATCH 69/72] Fix login issue
---
src/Umbraco.Tests/App.config | 5 +
.../components/umbpasswordtoggle.directive.js | 3 +
.../views/common/dialogs/login.controller.js | 22 ++-
.../src/views/common/dialogs/login.html | 5 +-
.../config/splashes/noNodes.aspx | 159 ++++++++++++++----
.../config/umbracoSettings.config | 58 +++----
6 files changed, 181 insertions(+), 71 deletions(-)
diff --git a/src/Umbraco.Tests/App.config b/src/Umbraco.Tests/App.config
index 09fd6b24f3..a5295ad028 100644
--- a/src/Umbraco.Tests/App.config
+++ b/src/Umbraco.Tests/App.config
@@ -63,6 +63,11 @@
+
+
+
+
+
diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpasswordtoggle.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpasswordtoggle.directive.js
index 30cfaf88b2..d75b9e2de0 100644
--- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpasswordtoggle.directive.js
+++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpasswordtoggle.directive.js
@@ -1,6 +1,9 @@
(function () {
'use strict';
+ // comes from https://codepen.io/jakob-e/pen/eNBQaP
+ // works fine with Angular 1.6.5 - alas not with 1.1.5 - binding issue
+
function PasswordToggleDirective($compile) {
var directive = {
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js
index 18158a5ff2..3712324132 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js
@@ -16,7 +16,13 @@
maxFileSize: Umbraco.Sys.ServerVariables.umbracoSettings.maxFileSize + "KB",
acceptedFileTypes: mediaHelper.formatFileTypes(Umbraco.Sys.ServerVariables.umbracoSettings.imageFileTypes),
uploaded: false
- }
+ }
+ $scope.togglePassword = function () {
+ console.log('toggle');
+ var elem = $("form[name='loginForm'] input[name='password']");
+ console.log(elem);
+ elem.attr("type", (elem.attr("type") === "text" ? "password" : "text"));
+ }
function init() {
// Check if it is a new user
@@ -48,7 +54,7 @@
]).then(function () {
$scope.inviteStep = Number(inviteVal);
-
+
});
}
}
@@ -82,7 +88,7 @@
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total, 10);
// set percentage property on file
- $scope.avatarFile.uploadProgress = progressPercentage;
+ $scope.avatarFile.uploadProgress = progressPercentage;
}
}).success(function (data, status, headers, config) {
@@ -149,11 +155,11 @@
//error
formHelper.handleError(err);
-
+
$scope.invitedUserPasswordModel.buttonState = "error";
});
- }
+ }
};
var setFieldFocus = function (form, field) {
@@ -180,7 +186,7 @@
}
function resetInputValidation() {
- $scope.confirmPassword = "";
+ $scope.confirmPassword = "";
$scope.password = "";
$scope.login = "";
if ($scope.loginForm) {
@@ -255,7 +261,7 @@
//TODO: Do validation properly like in the invite password update
- //if the login and password are not empty we need to automatically
+ //if the login and password are not empty we need to automatically
// validate them - this is because if there are validation errors on the server
// then the user has to change both username & password to resubmit which isn't ideal,
// so if they're not empty, we'll just make sure to set them to valid.
@@ -289,7 +295,7 @@
});
//setup a watch for both of the model values changing, if they change
- // while the form is invalid, then revalidate them so that the form can
+ // while the form is invalid, then revalidate them so that the form can
// be submitted again.
$scope.loginForm.username.$viewChangeListeners.push(function () {
if ($scope.loginForm.username.$invalid) {
diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html
index a1913d76e7..6505af4de9 100644
--- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html
+++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.html
@@ -149,8 +149,9 @@
We have created a bunch of 'how-to' videos, to get you easily started with Umbraco. Learn how to build projects in just a couple of minutes. Easiest CMS in the world.
We have created a bunch of 'how-to' videos, to get you easily started with Umbraco. Learn how to build projects in just a couple of minutes. Easiest CMS in the world.
-
-
Be a part of the community
-
The Umbraco community is the best of its kind, be sure to visit, and if you have any questions, we're sure that you can get your answers from the community.
The Umbraco community is the best of its kind, be sure to visit, and if you have any questions, we’re sure that you can get your answers from the community.