From 2bd2f1283147b808682f0cb1eccbda0648ac3c40 Mon Sep 17 00:00:00 2001 From: perploug Date: Mon, 17 Feb 2014 16:12:21 +0100 Subject: [PATCH] ImageCropper Upload enabled The cropper can now fully replace the upload datatype --- .../ContentImagingCropElement.cs | 8 +- .../UmbracoSettings/IImagingCrop.cs | 2 - .../UmbracoSettings/ContentElementTests.cs | 2 - .../directives/html/umbpanel.directive.js | 4 + .../imaging/umbimagecrop.directive.js | 6 -- .../imaging/umbimagegravity.directive.js | 14 +++ .../common/services/cropperhelper.service.js | 38 +++++-- .../src/less/animations.less | 9 +- .../src/less/property-editors.less | 10 +- .../src/less/tipmenu.less | 5 + .../directives/imaging/umb-image-crop.html | 1 - .../directives/imaging/umb-image-gravity.html | 2 +- .../imagecropper/imagecropper.controller.js | 100 +++++++++++------- .../imagecropper/imagecropper.html | 42 +++++--- src/Umbraco.Web.UI/Umbraco.Web.UI.csproj | 17 +++ .../config/umbracoSettings.config | 9 ++ src/Umbraco.Web.UI/packages.config | 5 +- src/Umbraco.Web.UI/web.Template.config | 18 +++- .../Editors/BackOfficeController.cs | 5 + .../ImageCropperPropertyEditor.cs | 10 ++ src/Umbraco.Web/Umbraco.Web.csproj | 6 ++ 21 files changed, 225 insertions(+), 88 deletions(-) diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingCropElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingCropElement.cs index 7a8f2a3ad4..86a4cda18e 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingCropElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentImagingCropElement.cs @@ -11,18 +11,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings get { return (string)base["mediaTypeAlias"]; } } - [ConfigurationProperty("focalPointProperty", IsRequired = true)] + [ConfigurationProperty("focalPointProperty", IsRequired = false)] public string FocalPointProperty { get { return (string)base["focalPointProperty"]; } } - [ConfigurationProperty("fileProperty", IsRequired = true)] - public string FileProperty - { - get { return (string)base["fileProperty"]; } - } - [ConfigurationCollection(typeof(ContentImagingCropSizeCollection))] [ConfigurationProperty("", IsDefaultCollection = true)] public ContentImagingCropSizeCollection CropSizeCollection diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingCrop.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingCrop.cs index e6e8a243f4..025a264a1d 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingCrop.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IImagingCrop.cs @@ -8,8 +8,6 @@ namespace Umbraco.Core.Configuration.UmbracoSettings string FocalPointProperty { get; } - string FileProperty { get; } - IEnumerable CropSizes { get; } } } \ No newline at end of file diff --git a/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs b/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs index 9c3e599431..904f819cb7 100644 --- a/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs +++ b/src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs @@ -23,12 +23,10 @@ namespace Umbraco.Tests.Configurations.UmbracoSettings { Assert.AreEqual("image", SettingsSection.Content.ImageCrops.Crops.First().MediaTypeAlias); Assert.AreEqual("umbracoFocalPoint", SettingsSection.Content.ImageCrops.Crops.First().FocalPointProperty); - Assert.AreEqual("umbracoFile", SettingsSection.Content.ImageCrops.Crops.First().FileProperty); Assert.AreEqual(3, SettingsSection.Content.ImageCrops.Crops.First().CropSizes.Count()); Assert.AreEqual("custom", SettingsSection.Content.ImageCrops.Crops.Last().MediaTypeAlias); Assert.AreEqual("customPoint", SettingsSection.Content.ImageCrops.Crops.Last().FocalPointProperty); - Assert.AreEqual("customFile", SettingsSection.Content.ImageCrops.Crops.Last().FileProperty); Assert.AreEqual(2, SettingsSection.Content.ImageCrops.Crops.Last().CropSizes.Count()); } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbpanel.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbpanel.directive.js index 294270bcdc..79524e06e6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/html/umbpanel.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/html/umbpanel.directive.js @@ -47,6 +47,10 @@ angular.module("umbraco.directives.html") var winHeight = $(window).height(); scope.$watch(function () { + if(!bar){ + bar = $(".tab-content .active .umb-tab-buttons")[0] || $(".tab-content .umb-tab-buttons")[0]; + } + var bottom = bar.offsetTop + bar.offsetHeight; return bottom > winHeight; }, function(val) { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js index 1a31a2e53f..14424b7d89 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagecrop.directive.js @@ -175,13 +175,7 @@ angular.module("umbraco.directives") scope.dimensions.image.left = left; scope.dimensions.image.top = top; }; - - - - - - //sets scope.crop to the recalculated % based crop var calculateCropBox = function(){ scope.crop = cropperHelper.pixelsToCoordinates(scope.dimensions.image, scope.dimensions.cropper.width, scope.dimensions.cropper.height, scope.dimensions.margin); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js index 7a311e5a0e..2e05e662ad 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/imaging/umbimagegravity.directive.js @@ -60,14 +60,28 @@ angular.module("umbraco.directives") scope.center.top = (scope.dimensions.top+10) / scope.dimensions.height; }; + var lazyEndEvent = _.debounce(function(){ + scope.$apply(function(){ + scope.$emit("imageFocalPointStop"); + }); + }, 2000); + + //Drag and drop positioning, using jquery ui draggable //TODO ensure that the point doesnt go outside the box $overlay.draggable({ containment: "parent", + start: function(){ + scope.$apply(function(){ + scope.$emit("imageFocalPointStart"); + }); + }, stop: function() { scope.$apply(function(){ calculateGravity(); }); + + lazyEndEvent(); } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js index 15868c0010..2b21bdaa65 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/cropperhelper.service.js @@ -1,10 +1,31 @@ /** * @ngdoc service -* @name umbraco.services.mediaHelper -* @description A helper object used for dealing with media items +* @name umbraco.services.cropperHelper +* @description A helper object used for dealing with image cropper data **/ -function cropperHelper(umbRequestHelper) { +function cropperHelper(umbRequestHelper, $http) { var service = { + + /** + * @ngdoc method + * @name umbraco.services.cropperHelper#configuration + * @methodOf umbraco.services.cropperHelper + * + * @description + * Returns a collection of plugins available to the tinyMCE editor + * + */ + configuration: function (mediaTypeAlias) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "imageCropperApiBaseUrl", + "GetConfiguration", + [{ mediaTypeAlias: mediaTypeAlias}])), + 'Failed to retreive tinymce configuration'); + }, + + //utill for getting either min/max aspect ratio to scale image after calculateAspectRatioFit : function(srcWidth, srcHeight, maxWidth, maxHeight, maximize) { var ratio = [maxWidth / srcWidth, maxHeight / srcHeight ]; @@ -31,10 +52,10 @@ function cropperHelper(umbRequestHelper) { var coordinates_px = service.coordinatesToPixels(coordinates, originalSize, offset); var _offset = offset || 0; - var x = coordinates.x1 + Math.abs(coordinates.x2); - var left_of_x = originalSize.width - (originalSize.width * x); + var x = 1 - (coordinates.x1 + Math.abs(coordinates.x2)); + var left_of_x = originalSize.width * x; var ratio = viewPort.width / left_of_x; - + var style = { position: "absolute", top: -(coordinates_px.y1*ratio)+ _offset, @@ -69,8 +90,9 @@ function cropperHelper(umbRequestHelper) { var x1_px = Math.abs(image.left-offset); var y1_px = Math.abs(image.top-offset); - var x2_px = (x1_px + width) - image.width; - var y2_px = (y1_px + height) - image.height; + var x2_px = image.width - (x1_px + width); + var y2_px = image.height - (y1_px + height); + //crop coordinates in % var crop = {}; diff --git a/src/Umbraco.Web.UI.Client/src/less/animations.less b/src/Umbraco.Web.UI.Client/src/less/animations.less index 73592f74d0..20cb52b109 100644 --- a/src/Umbraco.Web.UI.Client/src/less/animations.less +++ b/src/Umbraco.Web.UI.Client/src/less/animations.less @@ -1,21 +1,23 @@ // Animations // ------------------------- -.fade-hide, .fade-show { +.fade-hide, .fade-show , .fade-leave, .fade-enter { -webkit-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.3s; -moz-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.3s; -o-transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.3s; transition: all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.3s; } -.fade-hide { +.fade-enter { opacity: 1; } + .fade-hide.fade-hide-active { opacity: 0; } -.fade-show { +.fade-leave { opacity: 0; } + .fade-show.fade-show-active { opacity: 1; } @@ -63,6 +65,7 @@ display: block; position: relative; } + @-webkit-keyframes leave { to { opacity: 0; 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 17a0116b00..1f504e721a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/property-editors.less +++ b/src/Umbraco.Web.UI.Client/src/less/property-editors.less @@ -245,12 +245,13 @@ ul.color-picker li a { } .umb-cropper-gravity .overlay{ - width: 26px; - height: 26px; + width: 14px; + height: 14px; text-align: center; border-radius: 20px; - opacity: 0.6; - background: white; + background: @blue; + border: 3px solid white; + opacity: 0.8; } .umb-cropper-gravity .overlay i{ @@ -312,6 +313,7 @@ ul.color-picker li a { left: 0; bottom: 0; height: 100%; + width: 100%; } diff --git a/src/Umbraco.Web.UI.Client/src/less/tipmenu.less b/src/Umbraco.Web.UI.Client/src/less/tipmenu.less index c1c5059319..e92b1019e1 100644 --- a/src/Umbraco.Web.UI.Client/src/less/tipmenu.less +++ b/src/Umbraco.Web.UI.Client/src/less/tipmenu.less @@ -12,4 +12,9 @@ .tipmenu:hover .tooltip a{ color: white; +} + +.tipmenu .tooltip-inner{ + margin-left:auto; + margin-right:auto; } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html index 953627637f..878900c434 100644 --- a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html +++ b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-crop.html @@ -1,5 +1,4 @@
-
diff --git a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html index cdceab1335..65abba4523 100644 --- a/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html +++ b/src/Umbraco.Web.UI.Client/src/views/directives/imaging/umb-image-gravity.html @@ -4,7 +4,7 @@
- +
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 68b99efd33..44ab278db2 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 @@ -1,57 +1,81 @@ //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.ImageCropperController", - function($rootScope, $scope, mediaHelper, $timeout, editorState) { - - //check the pre-values for multi-picker - var multiPicker = $scope.model.config.multiPicker !== '0' ? true : false; + function($rootScope, $routeParams, $scope, mediaHelper, cropperHelper, $timeout, editorState, umbRequestHelper, fileManager) { - //used to reference the part of the data we will either crop or "point" - $scope.currentCrop = undefined; - $scope.currentPoint = undefined; - - var imgPath = mediaHelper.getImagePropertyValue({imageModel: editorState.current}); + cropperHelper.configuration("Image").then(function(config){ + + //move previously saved value to the editor + if($scope.model.value){ + //backwards compat with the old file upload (incase some-one swaps them..) + if(angular.isString($scope.model.value)){ + config.src = $scope.model.value; + $scope.model.value = config; + } + $scope.imageSrc = $scope.model.value.src; + } + //crop a specific crop $scope.crop = function(crop){ $scope.currentCrop = crop; $scope.currentPoint = undefined; }; + //done cropping $scope.done = function(){ $scope.currentCrop = undefined; $scope.currentPoint = undefined; }; + //crop a specific crop + $scope.clear = function(crop){ + //clear current uploaded files + fileManager.setFiles($scope.model.alias, []); + + //clear the ui + $scope.imageSrc = undefined; + if($scope.model.value.src){ + delete $scope.model.value.src; + } + }; - //Data sample - if(!$scope.model.value){ - $scope.model.value = { - //image to crops - src: imgPath, + //show previews + $scope.togglePreviews = function(){ + if($scope.showPreviews){ + $scope.showPreviews = false; + $scope.tempShowPreviews = false; + }else{ + $scope.showPreviews = true; + } + }; - //global intrestpoint, used if no crop is specified - center: {left: 0.5, top: 0.4}, - crops:{ - thumbnail: - { - //crop dimensions - width: 100, - height: 100, - //crops in percentages - crop:{ - "x1": 0.31731772342645215, - "y1": 0.17420325244997603, - "x2": -0.36246473116627076, - "y2": -0.30226197981593617 - } - }, - highrise: - { - width: 90, - height: 340 - } - } - }; - } + $scope.$on("imageFocalPointStart", function(){ + $scope.tempShowPreviews = true; + }); + + $scope.$on("imageFocalPointStop", function(){ + $scope.tempShowPreviews = false; + }); + + //on image selected, update the cropper + $scope.$on("filesSelected", function (ev, args) { + $scope.model.value = config; + + if(args.files && args.files[0]){ + + fileManager.setFiles($scope.model.alias, args.files); + + var reader = new FileReader(); + reader.onload = function (e) { + $scope.$apply(function(){ + $scope.imageSrc = e.target.result; + }); + }; + + reader.readAsDataURL(args.files[0]); + } + }); + + }); }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html index 6081e9fb6e..7c806b0095 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.html @@ -1,43 +1,57 @@
+ + + +

Click to upload

+ +
-
+
-
+
+ crop="currentCrop.coordinates" + center="model.value.focalPoint" + src="imageSrc" />
Done
-
    +
    • -
      +
      - Reset + Reset
    • diff --git a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj index 7c8a047d30..f247296790 100644 --- a/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj +++ b/src/Umbraco.Web.UI/Umbraco.Web.UI.csproj @@ -127,11 +127,24 @@ False ..\packages\Examine.0.1.52.2941\lib\Examine.dll + + ..\packages\ImageProcessor.1.8.3.0\lib\net45\ImageProcessor.dll + + + False + ..\packages\ImageProcessor.Web.3.1.1.0\lib\net45\ImageProcessor.Web.dll + False ..\packages\log4net-mediumtrust.2.0.0\lib\log4net.dll + + ..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.dll + + + ..\packages\Microsoft.Bcl.Async.1.0.165\lib\net45\Microsoft.Threading.Tasks.Extensions.dll + ..\packages\Microsoft.Web.Helpers.1.0.0\lib\Microsoft.Web.Helpers.dll @@ -174,6 +187,7 @@ + True @@ -666,6 +680,9 @@ BaseRestExtensions.config + + + log4net.config diff --git a/src/Umbraco.Web.UI/config/umbracoSettings.config b/src/Umbraco.Web.UI/config/umbracoSettings.config index a4910bc60c..c12a772216 100644 --- a/src/Umbraco.Web.UI/config/umbracoSettings.config +++ b/src/Umbraco.Web.UI/config/umbracoSettings.config @@ -15,6 +15,15 @@ umbracoExtension + + + + + + + + + diff --git a/src/Umbraco.Web.UI/packages.config b/src/Umbraco.Web.UI/packages.config index 624719c5ee..d897305d0a 100644 --- a/src/Umbraco.Web.UI/packages.config +++ b/src/Umbraco.Web.UI/packages.config @@ -4,6 +4,8 @@ + + @@ -15,6 +17,7 @@ + @@ -25,4 +28,4 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web.UI/web.Template.config b/src/Umbraco.Web.UI/web.Template.config index ae9bf281d7..c4dcbd4821 100644 --- a/src/Umbraco.Web.UI/web.Template.config +++ b/src/Umbraco.Web.UI/web.Template.config @@ -6,7 +6,14 @@
      -
      +
      + + +
      +
      +
      + +
      @@ -29,6 +36,12 @@ + + + + + + + + diff --git a/src/Umbraco.Web/Editors/BackOfficeController.cs b/src/Umbraco.Web/Editors/BackOfficeController.cs index 37ded874a8..719b6529e6 100644 --- a/src/Umbraco.Web/Editors/BackOfficeController.cs +++ b/src/Umbraco.Web/Editors/BackOfficeController.cs @@ -182,6 +182,11 @@ namespace Umbraco.Web.Editors "rteApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetConfiguration()) }, + { + "imageCropperApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( + controller => controller.GetConfiguration(string.Empty)) + }, + { "stylesheetApiBaseUrl", Url.GetUmbracoApiServiceBaseUrl( controller => controller.GetAll()) diff --git a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs index 4598f49d1f..b58b49872c 100644 --- a/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs +++ b/src/Umbraco.Web/PropertyEditors/ImageCropperPropertyEditor.cs @@ -11,5 +11,15 @@ namespace Umbraco.Web.PropertyEditors [PropertyEditor(Constants.PropertyEditors.ImageCropperAlias, "Image Cropper", "imagecropper", ValueType = "JSON", HideLabel = false)] public class ImageCropperPropertyEditor : PropertyEditor { + + /// + /// Creates our custom value editor + /// + /// + protected override PropertyValueEditor CreateValueEditor() + { + var baseEditor = base.CreateValueEditor(); + return new ImageCropperPropertyValueEditor(baseEditor); + } } } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 38eb9c59d5..2b4aad6550 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -304,6 +304,7 @@ + @@ -344,7 +345,11 @@ + + + + @@ -408,6 +413,7 @@ +