diff --git a/src/Umbraco.Core/Dynamics/DynamicInstanceHelper.cs b/src/Umbraco.Core/Dynamics/DynamicInstanceHelper.cs index 91004fa114..95ed389a7a 100644 --- a/src/Umbraco.Core/Dynamics/DynamicInstanceHelper.cs +++ b/src/Umbraco.Core/Dynamics/DynamicInstanceHelper.cs @@ -117,13 +117,12 @@ namespace Umbraco.Core.Dynamics } catch (Exception ex) { - var sb = new StringBuilder("An error occurred finding an executing an extension method for type "); - sb.Append(typeof (T)); - sb.Append("Types searched for extension methods were "); - foreach(var t in findExtensionMethodsOnTypes) - { - sb.Append(t + ","); - } + var sb = new StringBuilder(); + sb.AppendFormat("An error occurred finding and executing extension method \"{0}\" ", binder.Name); + sb.AppendFormat("for type \"{0}\". ", typeof (T)); + sb.Append("Types searched for extension methods were "); + sb.Append(string.Join(", ", findExtensionMethodsOnTypes)); + sb.Append("."); LogHelper.Error(sb.ToString(), ex); var mresult = new TryInvokeMemberResult(null, TryInvokeMemberSuccessReason.FoundExtensionMethod); return Attempt.Fail(mresult, ex); @@ -171,7 +170,7 @@ namespace Umbraco.Core.Dynamics } else { - throw new MissingMethodException(); + throw new MissingMethodException(typeof(T).FullName, name); } return result; } diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs index ace2178a55..cf78e3a5cb 100644 --- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs +++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs @@ -248,6 +248,9 @@ namespace Umbraco.Core.Persistence.Migrations.Initial { _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 3, Alias = "", SortOrder = 0, DataTypeNodeId = -87, Value = ",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|" }); _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 4, Alias = "group", SortOrder = 0, DataTypeNodeId = 1041, Value = "default" }); + + //default's for MultipleMediaPickerAlias picker + _database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1045, Value = "1" }); } private void CreateUmbracoRelationTypeData() diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index 8e0ca3fa75..55766f15a2 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -1264,8 +1264,8 @@ namespace Umbraco.Core.Services if (SendingToPublish.IsRaisedEventCancelled(new SendToPublishEventArgs(content), this)) return false; - //TODO: Do some stuff here.. ... what is it supposed to do ? - // pretty sure all that legacy stuff did was raise an event? and we no longer have IActionHandlers so no worries there. + //Save before raising event + Save(content, userId); SentToPublish.RaiseEvent(new SendToPublishEventArgs(content, false), this); diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index fd3e94336f..3b426a2a0d 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -207,10 +207,11 @@ namespace Umbraco.Core.Services if (user == null) throw new ArgumentNullException("user"); var provider = MembershipProviderExtensions.GetUsersMembershipProvider(); - if (provider.IsUmbracoMembershipProvider()) - { - provider.ChangePassword(user.Username, "", password); - } + + if (provider.IsUmbracoMembershipProvider() == false) + throw new NotSupportedException("When using a non-Umbraco membership provider you must change the user password by using the MembershipProvider.ChangePassword method"); + + provider.ChangePassword(user.Username, "", password); //go re-fetch the member and update the properties that may have changed var result = GetByUsername(user.Username); @@ -221,8 +222,6 @@ namespace Umbraco.Core.Services user.LastPasswordChangeDate = result.LastPasswordChangeDate; user.UpdateDate = user.UpdateDate; } - - throw new NotSupportedException("When using a non-Umbraco membership provider you must change the user password by using the MembershipProvider.ChangePassword method"); } /// 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 fb45b83fa0..89bc626d6a 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,6 +1,11 @@ function ColorPickerController($scope) { - $scope.selectItem = function (color) { - $scope.model.value = color; + $scope.toggleItem = function (color) { + if ($scope.model.value == color) { + $scope.model.value = ""; + } + else { + $scope.model.value = color; + } }; $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0; } 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 f8395296b7..d2bf2cf87c 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 @@ -6,7 +6,7 @@
  • - +
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js index 7aa65473a6..9106e2b334 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/fileupload/fileupload.controller.js @@ -25,6 +25,9 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag /** this method is used to initialize the data and to re-initialize it if the server value is changed */ function initialize(index) { + + clearFiles(); + if (!index) { index = 1; } @@ -116,9 +119,6 @@ function fileUploadController($scope, $element, $compile, imageHelper, fileManag initialize($scope.rebuildInput.index + 1); } - //if (newVal !== "{clearFiles: true}" && newVal !== $scope.originalValue && !newVal.startsWith("{selectedFiles:")) { - // initialize($scope.rebuildInput.index + 1); - //} } }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js index 7189ca504a..42eee9b4a8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.controller.js @@ -88,6 +88,13 @@ angular.module('umbraco') } }); + + //here we declare a special method which will be called whenever the value has changed from the server + $scope.model.onValueChanged = function (newVal, oldVal) { + //clear current uploaded files + fileManager.setFiles($scope.model.alias, []); + }; + var unsubscribe = $scope.$on("formSubmitting", function () { $scope.done(); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js index 48a7dbd611..692d2dbc99 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.controller.js @@ -71,6 +71,12 @@ //initiate slider, add event handler and get the instance reference (stored in data) var slider = $element.find('.slider-item').slider({ + max: $scope.model.config.maxVal, + min: $scope.model.config.minVal, + orientation: $scope.model.config.orientation, + selection: "after", + step: $scope.model.config.step, + tooltip: "show", //set the slider val - we cannot do this with data- attributes when using ranges value: sliderVal }).on('slideStop', function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html index ce05e865fb..66fc61153a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/slider/slider.html @@ -1,11 +1,5 @@ 
    - +
    \ No newline at end of file diff --git a/src/Umbraco.Web/Editors/ContentController.cs b/src/Umbraco.Web/Editors/ContentController.cs index dcc198ac0f..1e3f3ba7a3 100644 --- a/src/Umbraco.Web/Editors/ContentController.cs +++ b/src/Umbraco.Web/Editors/ContentController.cs @@ -274,16 +274,16 @@ namespace Umbraco.Web.Editors if (contentItem.Action == ContentSaveAction.Save || contentItem.Action == ContentSaveAction.SaveNew) { //save the item - Services.ContentService.Save(contentItem.PersistedContent, (int)Security.CurrentUser.Id); + Services.ContentService.Save(contentItem.PersistedContent, Security.CurrentUser.Id); } else if (contentItem.Action == ContentSaveAction.SendPublish || contentItem.Action == ContentSaveAction.SendPublishNew) { - Services.ContentService.SendToPublication(contentItem.PersistedContent, UmbracoUser.Id); + Services.ContentService.SendToPublication(contentItem.PersistedContent, Security.CurrentUser.Id); } else { //publish the item and check if it worked, if not we will show a diff msg below - publishStatus = Services.ContentService.SaveAndPublishWithStatus(contentItem.PersistedContent, (int)Security.CurrentUser.Id); + publishStatus = Services.ContentService.SaveAndPublishWithStatus(contentItem.PersistedContent, Security.CurrentUser.Id); } diff --git a/src/Umbraco.Web/Models/PartialViewMacroModelExtensions.cs b/src/Umbraco.Web/Models/PartialViewMacroModelExtensions.cs new file mode 100644 index 0000000000..0c35e9d6ef --- /dev/null +++ b/src/Umbraco.Web/Models/PartialViewMacroModelExtensions.cs @@ -0,0 +1,38 @@ +using Umbraco.Core; + +namespace Umbraco.Web.Models +{ + /// + /// Extension methods for the PartialViewMacroModel object + /// + public static class PartialViewMacroModelExtensions + { + /// + /// Attempt to get a Marco parameter from a PartialViewMacroModel and return a default value otherwise + /// + /// + /// + /// + /// Parameter value if available, the default value that was passed otherwise. + public static T GetParameterValue(this PartialViewMacroModel partialViewMacroModel, string parameterAlias, T defaultValue) + { + if (partialViewMacroModel.MacroParameters.ContainsKey(parameterAlias) == false || string.IsNullOrEmpty(partialViewMacroModel.MacroParameters[parameterAlias].ToString())) + return defaultValue; + + var attempt = partialViewMacroModel.MacroParameters[parameterAlias].TryConvertTo(typeof(T)); + + return attempt.Success ? (T) attempt.Result : defaultValue; + } + + /// + /// Attempt to get a Marco parameter from a PartialViewMacroModel + /// + /// + /// + /// Parameter value if available, the default value for the type otherwise. + public static T GetParameterValue(this PartialViewMacroModel partialViewMacroModel, string parameterAlias) + { + return partialViewMacroModel.GetParameterValue(parameterAlias, default(T)); + } + } +} diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs index 2f06aaebcd..72b5aa1e62 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyValueEditor.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.IO; +using Umbraco.Core.Logging; using Umbraco.Core.Media; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; @@ -50,11 +51,22 @@ namespace Umbraco.Web.PropertyEditors JObject oldJson = null; //get the old src path - if (currentValue != null) + if (string.IsNullOrEmpty(currentValue.ToString()) == false) { - oldJson = currentValue as JObject; + try + { + oldJson = JObject.Parse(currentValue.ToString()); + } + catch (Exception ex) + { + //for some reason the value is invalid so continue as if there was no value there + LogHelper.WarnWithException("Could not parse current db value to a JObject", ex); + } + if (oldJson != null && oldJson["src"] != null) + { oldFile = oldJson["src"].Value(); + } } //get the new src path @@ -62,7 +74,9 @@ namespace Umbraco.Web.PropertyEditors { newJson = editorValue.Value as JObject; if (newJson != null && newJson["src"] != null) + { newFile = newJson["src"].Value(); + } } //compare old and new src path diff --git a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs index 8842715bd3..152db6ec97 100644 --- a/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs +++ b/src/Umbraco.Web/PublishedCache/XmlPublishedCache/PublishedMediaCache.cs @@ -514,47 +514,36 @@ namespace Umbraco.Web.PublishedCache.XmlPublishedCache _contentType = PublishedContentType.Get(PublishedItemType.Media, _documentTypeAlias); _properties = new Collection(); + //handle content type properties + //make sure we create them even if there's no value + foreach (var propertyType in _contentType.PropertyTypes) + { + var alias = propertyType.PropertyTypeAlias; + _keysAdded.Add(alias); + string value; + const bool isPreviewing = false; // false :: never preview a media + var property = valueDictionary.TryGetValue(alias, out value) == false + ? new XmlPublishedProperty(propertyType, isPreviewing) + : new XmlPublishedProperty(propertyType, isPreviewing, value); + _properties.Add(property); + } + //loop through remaining values that haven't been applied - foreach (var i in valueDictionary.Where(x => !_keysAdded.Contains(x.Key))) + foreach (var i in valueDictionary.Where(x => + _keysAdded.Contains(x.Key) == false // not already processed + && IgnoredKeys.Contains(x.Key) == false)) // not ignorable { - IPublishedProperty property = null; - - // must ignore those - if (IgnoredKeys.Contains(i.Key)) continue; - if (i.Key.InvariantStartsWith("__")) - { + { // no type for that one, dunno how to convert - property = new PropertyResult(i.Key, i.Value, PropertyResultType.CustomProperty); - } + IPublishedProperty property = new PropertyResult(i.Key, i.Value, PropertyResultType.CustomProperty); + _properties.Add(property); + } else { - // use property type to ensure proper conversion - var propertyType = _contentType.GetPropertyType(i.Key); - - // note: this is where U4-4144 and -3665 were born - // - // because propertyType is null, the XmlPublishedProperty ctor will throw - // it's null because i.Key is not a valid property alias for the type... - // the alias is case insensitive (verified) so it means it really is not - // a correct alias. - // - // in every cases this is after a ConvertFromXPathNavigator, so it means - // that we get some properties from the XML that are not valid properties. - // no idea which property. could come from the cache in library, could come - // from so many places really. - - // workaround: just ignore that property - if (propertyType == null) - { - LogHelper.Warn("Dropping property \"" + i.Key + "\" because it does not belong to the content type."); - continue; - } - - property = new XmlPublishedProperty(propertyType, false, i.Value); // false :: never preview a media + // this is a property that does not correspond to anything, ignore and log + LogHelper.Warn("Dropping property \"" + i.Key + "\" because it does not belong to the content type."); } - - _properties.Add(property); } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 47bbcc3421..8adbb1208c 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -354,6 +354,7 @@ + diff --git a/src/umbraco.cms/Actions/ActionImport.cs b/src/umbraco.cms/Actions/ActionImport.cs index 71469c964d..85ccd10c2d 100644 --- a/src/umbraco.cms/Actions/ActionImport.cs +++ b/src/umbraco.cms/Actions/ActionImport.cs @@ -65,7 +65,7 @@ namespace umbraco.BusinessLogic.Actions { get { - return "upload-alt"; + return "page-up"; } } diff --git a/src/umbraco.cms/businesslogic/web/Document.cs b/src/umbraco.cms/businesslogic/web/Document.cs index 599b76a2ff..3819b3cf9f 100644 --- a/src/umbraco.cms/businesslogic/web/Document.cs +++ b/src/umbraco.cms/businesslogic/web/Document.cs @@ -749,7 +749,7 @@ namespace umbraco.cms.businesslogic.web #region Public Methods /// - /// Executes handlers and events for the Send To Publication action. + /// Saves and executes handlers and events for the Send To Publication action. /// /// The User public bool SendToPublication(User u) diff --git a/src/umbraco.editorControls/imagecropper/ImageInfo.cs b/src/umbraco.editorControls/imagecropper/ImageInfo.cs index 054b8f676c..6d142bf90e 100644 --- a/src/umbraco.editorControls/imagecropper/ImageInfo.cs +++ b/src/umbraco.editorControls/imagecropper/ImageInfo.cs @@ -33,9 +33,12 @@ namespace umbraco.editorControls.imagecropper //This get's the IFileSystem's path based on the URL (i.e. /media/blah/blah.jpg ) Path = _fs.GetRelativePath(relativePath); - + image = Image.FromStream(_fs.OpenFile(Path)); - Name = _fs.GetFileName(Path); + + var fileName = _fs.GetFileName(Path); + Name = fileName.Substring(0, fileName.LastIndexOf('.')); + DateStamp = _fs.GetLastModified(Path).Date; Width = image.Width; Height = image.Height; @@ -75,12 +78,10 @@ namespace umbraco.editorControls.imagecropper { crop = preset.Fit(this); } - - var tmpName = Name.Substring(0, Name.LastIndexOf('.')); - + ImageTransform.Execute( Path, - String.Format("{0}_{1}", tmpName, preset.Name), + String.Format("{0}_{1}", Name, preset.Name), crop.X, crop.Y, crop.X2 - crop.X,