Fixed up the file uploading and the readonly property editors and saving/updating their data/control based on the data changed on the server side.
U4-2680 Fix file uploading
This commit is contained in:
@@ -28,6 +28,19 @@ namespace Umbraco.Core
|
||||
[UmbracoWillObsolete("Do not use this constants. See IShortStringHelper.CleanStringForSafeAliasJavaScriptCode.")]
|
||||
public const string UmbracoInvalidFirstCharacters = "01234567890";
|
||||
|
||||
/// <summary>
|
||||
/// This tries to detect a json string, this is not a fail safe way but it is quicker than doing
|
||||
/// a try/catch when deserializing when it is not json.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool DetectIsJson(this string input)
|
||||
{
|
||||
input = input.Trim();
|
||||
return input.StartsWith("{") && input.EndsWith("}")
|
||||
|| input.StartsWith("[") && input.EndsWith("]");
|
||||
}
|
||||
|
||||
internal static string ReplaceNonAlphanumericChars(this string input, char replacement)
|
||||
{
|
||||
//any character that is not alphanumeric, convert to a hyphen
|
||||
|
||||
@@ -94,6 +94,17 @@
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.trimEnd) {
|
||||
|
||||
/** trims the end of the string*/
|
||||
String.prototype.trimEnd = function (str) {
|
||||
if (this.endsWith(str)) {
|
||||
return this.substring(0, this.length - str.length);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
}
|
||||
|
||||
if (!String.prototype.utf8Encode) {
|
||||
|
||||
|
||||
@@ -1,22 +1,24 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbFileUpload
|
||||
* @function
|
||||
* @restrict AE
|
||||
* @element ANY
|
||||
* @scope
|
||||
**/
|
||||
function umbFileUpload() {
|
||||
return {
|
||||
scope: true, //create a new scope
|
||||
link: function (scope, el, attrs) {
|
||||
el.bind('change', function (event) {
|
||||
var files = event.target.files;
|
||||
//emit event upward
|
||||
scope.$emit("filesSelected", { files: files });
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbFileUpload
|
||||
* @function
|
||||
* @restrict A
|
||||
* @scope
|
||||
* @description
|
||||
* Listens for file input control changes and emits events when files are selected for use in other controllers.
|
||||
**/
|
||||
function umbFileUpload() {
|
||||
return {
|
||||
restrict: "A",
|
||||
scope: true, //create a new scope
|
||||
link: function (scope, el, attrs) {
|
||||
el.bind('change', function (event) {
|
||||
var files = event.target.files;
|
||||
//emit event upward
|
||||
scope.$emit("filesSelected", { files: files });
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive("umbFileUpload", umbFileUpload);
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* @ngdoc directive
|
||||
* @name umbraco.directives.directive:umbFileUpload
|
||||
* @function
|
||||
* @restrict A
|
||||
* @scope
|
||||
* @description
|
||||
* A single file upload field that will reset itself based on the object passed in for the rebuild parameter. This
|
||||
* is required because the only way to reset an upload control is to replace it's html.
|
||||
**/
|
||||
function umbSingleFileUpload($compile) {
|
||||
return {
|
||||
restrict: "E",
|
||||
scope: {
|
||||
rebuild: "="
|
||||
},
|
||||
replace: true,
|
||||
template: "<div><input type='file' umb-file-upload /></div>",
|
||||
link: function (scope, el, attrs) {
|
||||
|
||||
scope.$watch("rebuild", function (newVal, oldVal) {
|
||||
if (newVal && newVal !== oldVal) {
|
||||
//recompile it!
|
||||
el.html("<input type='file' umb-file-upload />");
|
||||
$compile(el.contents())(scope);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('umbraco.directives').directive("umbSingleFileUpload", umbSingleFileUpload);
|
||||
@@ -38,10 +38,14 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
* @description
|
||||
* re-binds all changed property values to the origContent object from the newContent object and returns an array of changed properties.
|
||||
*/
|
||||
reBindChangedProperties: function (allOrigProps, allNewProps) {
|
||||
reBindChangedProperties: function (origContent, newContent) {
|
||||
|
||||
var changed = [];
|
||||
|
||||
//get a list of properties since they are contained in tabs
|
||||
var allOrigProps = this.getAllProps(origContent);
|
||||
var allNewProps = this.getAllProps(newContent);
|
||||
|
||||
function getNewProp(alias) {
|
||||
if (alias.startsWith("_umb_")) {
|
||||
return null;
|
||||
@@ -54,7 +58,7 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
for (var p in allOrigProps) {
|
||||
var newProp = getNewProp(allOrigProps[p].alias);
|
||||
if (newProp && !_.isEqual(allOrigProps[p].value, newProp.value)) {
|
||||
//they have changed so set the origContent prop's value to the new value
|
||||
//they have changed so set the origContent prop to the new one
|
||||
allOrigProps[p].value = newProp.value;
|
||||
changed.push(allOrigProps[p]);
|
||||
}
|
||||
@@ -134,9 +138,6 @@ function contentEditingHelper($location, $routeParams, notificationsService, ser
|
||||
if (!args.allNewProps && !angular.isArray(args.allNewProps)) {
|
||||
throw "args.allNewProps must be a valid array";
|
||||
}
|
||||
if (!args.allOrigProps && !angular.isArray(args.allOrigProps)) {
|
||||
throw "args.allOrigProps must be a valid array";
|
||||
}
|
||||
|
||||
//When the status is a 403 status, we have validation errors.
|
||||
//Otherwise the error is probably due to invalid data (i.e. someone mucking around with the ids or something).
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @ngdoc service
|
||||
* @name umbraco.services.fileManager
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Used by editors to manage any files that require uploading with the posted data, normally called by property editors
|
||||
* that need to attach files.
|
||||
*/
|
||||
function fileManager() {
|
||||
|
||||
var fileCollection = [];
|
||||
|
||||
return {
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.fileManager#addFiles
|
||||
* @methodOf umbraco.services.fileManager
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Attaches files to the current manager for the current editor for a particular property, if an empty array is set
|
||||
* for the files collection that effectively clears the files for the specified editor.
|
||||
*/
|
||||
setFiles: function(propertyId, files) {
|
||||
//this will clear the files for the current property and then add the new ones for the current property
|
||||
fileCollection = _.reject(fileCollection, function (item) {
|
||||
return item.id === propertyId;
|
||||
});
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
//save the file object to the files collection
|
||||
fileCollection.push({ id: propertyId, file: files[i] });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.fileManager#getFiles
|
||||
* @methodOf umbraco.services.fileManager
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Returns all of the files attached to the file manager
|
||||
*/
|
||||
getFiles: function() {
|
||||
return fileCollection;
|
||||
},
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.fileManager#clearFiles
|
||||
* @methodOf umbraco.services.fileManager
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Removes all files from the manager
|
||||
*/
|
||||
clearFiles: function () {
|
||||
fileCollection = [];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('fileManager', fileManager);
|
||||
@@ -63,7 +63,7 @@ function MainController($scope, $routeParams, $rootScope, $timeout, $http, notif
|
||||
|
||||
if($scope.user.avatar){
|
||||
$http.get($scope.user.avatar).then(function(){
|
||||
alert($scope.user.avatar);
|
||||
//alert($scope.user.avatar);
|
||||
$scope.avatar = $scope.user.avatar;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,8 +6,11 @@
|
||||
* @description
|
||||
* The controller for the content editor
|
||||
*/
|
||||
function ContentEditController($scope, $routeParams, $location, contentResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper) {
|
||||
function ContentEditController($scope, $routeParams, $location, contentResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager) {
|
||||
|
||||
//initialize the file manager
|
||||
fileManager.clearFiles();
|
||||
|
||||
if ($routeParams.create) {
|
||||
//we are creating so get an empty content item
|
||||
contentResource.getScaffold($routeParams.id, $routeParams.doctype)
|
||||
@@ -31,18 +34,6 @@ function ContentEditController($scope, $routeParams, $location, contentResource,
|
||||
});
|
||||
}
|
||||
|
||||
$scope.files = [];
|
||||
$scope.addFiles = function (propertyId, files) {
|
||||
//this will clear the files for the current property and then add the new ones for the current property
|
||||
$scope.files = _.reject($scope.files, function (item) {
|
||||
return item.id == propertyId;
|
||||
});
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
//save the file object to the scope's files collection
|
||||
$scope.files.push({ id: propertyId, file: files[i] });
|
||||
}
|
||||
};
|
||||
|
||||
//TODO: Need to figure out a way to share the saving and event broadcasting with all editors!
|
||||
|
||||
$scope.saveAndPublish = function () {
|
||||
@@ -55,7 +46,7 @@ function ContentEditController($scope, $routeParams, $location, contentResource,
|
||||
|
||||
serverValidationManager.reset();
|
||||
|
||||
contentResource.publish($scope.content, $routeParams.create, $scope.files)
|
||||
contentResource.publish($scope.content, $routeParams.create, fileManager.getFiles())
|
||||
.then(function (data) {
|
||||
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
@@ -91,7 +82,7 @@ function ContentEditController($scope, $routeParams, $location, contentResource,
|
||||
|
||||
serverValidationManager.reset();
|
||||
|
||||
contentResource.save($scope.content, $routeParams.create, $scope.files)
|
||||
contentResource.save($scope.content, $routeParams.create, fileManager.getFiles())
|
||||
.then(function (data) {
|
||||
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
* @description
|
||||
* The controller for the media editor
|
||||
*/
|
||||
function mediaEditController($scope, $routeParams, mediaResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper) {
|
||||
function mediaEditController($scope, $routeParams, mediaResource, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager) {
|
||||
|
||||
//initialize the file manager
|
||||
fileManager.clearFiles();
|
||||
|
||||
if ($routeParams.create) {
|
||||
|
||||
@@ -30,18 +33,6 @@ function mediaEditController($scope, $routeParams, mediaResource, notificationsS
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$scope.files = [];
|
||||
$scope.addFiles = function (propertyId, files) {
|
||||
//this will clear the files for the current property and then add the new ones for the current property
|
||||
$scope.files = _.reject($scope.files, function (item) {
|
||||
return item.id == propertyId;
|
||||
});
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
//save the file object to the scope's files collection
|
||||
$scope.files.push({ id: propertyId, file: files[i] });
|
||||
}
|
||||
};
|
||||
|
||||
$scope.save = function () {
|
||||
|
||||
@@ -53,28 +44,22 @@ function mediaEditController($scope, $routeParams, mediaResource, notificationsS
|
||||
|
||||
serverValidationManager.reset();
|
||||
|
||||
mediaResource.save($scope.content, $routeParams.create, $scope.files)
|
||||
mediaResource.save($scope.content, $routeParams.create, fileManager.getFiles())
|
||||
.then(function (data) {
|
||||
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
newContent: data,
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(
|
||||
contentEditingHelper.getAllProps($scope.content),
|
||||
contentEditingHelper.getAllProps(data))
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, data)
|
||||
});
|
||||
|
||||
}, function (err) {
|
||||
|
||||
var allNewProps = contentEditingHelper.getAllProps(err.data);
|
||||
var allOrigProps = contentEditingHelper.getAllProps($scope.content);
|
||||
|
||||
contentEditingHelper.handleSaveError({
|
||||
err: err,
|
||||
redirectOnFailure: true,
|
||||
allNewProps: allNewProps,
|
||||
allOrigProps: contentEditingHelper.getAllProps($scope.content),
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties(allOrigProps, allNewProps)
|
||||
allNewProps: contentEditingHelper.getAllProps(err.data),
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data)
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -4,41 +4,64 @@
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for the file upload property editor
|
||||
* The controller for the file upload property editor. It is important to note that the $scope.model.value
|
||||
* doesn't necessarily depict what is saved for this property editor. $scope.model.value can be empty when we
|
||||
* are submitting files because in that case, we are adding files to the fileManager which is what gets peristed
|
||||
* on the server. However, when we are clearing files, we are setting $scope.model.value to "{clearFiles: true}"
|
||||
* to indicate on the server that we are removing files for this property. We will keep the $scope.model.value to
|
||||
* be the name of the file selected (if it is a newly selected file) or keep it to be it's original value, this allows
|
||||
* for the editors to check if the value has changed and to re-bind the property if that is true.
|
||||
*
|
||||
*/
|
||||
function fileUploadController($scope, $element, $compile, umbImageHelper) {
|
||||
function fileUploadController($scope, $element, $compile, umbImageHelper, fileManager) {
|
||||
|
||||
/** Clears the file collections when content is saving (if we need to clear) or after saved */
|
||||
function clearFiles() {
|
||||
//TODO: There should be a better way! We don't want to have to know about the parent scope
|
||||
//clear the parent files collection (we don't want to upload any!)
|
||||
$scope.$parent.addFiles($scope.id, []);
|
||||
function clearFiles() {
|
||||
//clear the files collection (we don't want to upload any!)
|
||||
fileManager.setFiles($scope.id, []);
|
||||
//clear the current files
|
||||
$scope.files = [];
|
||||
}
|
||||
|
||||
//clear the current files
|
||||
$scope.files = [];
|
||||
|
||||
//create the property to show the list of files currently saved
|
||||
if ($scope.model.value != "") {
|
||||
|
||||
var images = $scope.model.value.split(",");
|
||||
/** this method is used to initialize the data and to re-initialize it if the server value is changed */
|
||||
function initialize(index)
|
||||
{
|
||||
if (!index) {
|
||||
index = 1;
|
||||
}
|
||||
|
||||
$scope.persistedFiles = _.map(images, function (item) {
|
||||
return { file: item, isImage: umbImageHelper.detectIfImageByExtension(item) };
|
||||
//this is used in order to tell the umb-single-file-upload directive to
|
||||
//rebuild the html input control (and thus clearing the selected file) since
|
||||
//that is the only way to manipulate the html for the file input control.
|
||||
$scope.rebuildInput = {
|
||||
index: index
|
||||
};
|
||||
//clear the current files
|
||||
$scope.files = [];
|
||||
//store the original value so we can restore it if the user clears and then cancels clearing.
|
||||
$scope.originalValue = $scope.model.value;
|
||||
|
||||
//create the property to show the list of files currently saved
|
||||
if ($scope.model.value != "") {
|
||||
|
||||
var images = $scope.model.value.split(",");
|
||||
|
||||
$scope.persistedFiles = _.map(images, function (item) {
|
||||
return { file: item, isImage: umbImageHelper.detectIfImageByExtension(item) };
|
||||
});
|
||||
}
|
||||
else {
|
||||
$scope.persistedFiles = [];
|
||||
}
|
||||
|
||||
_.each($scope.persistedFiles, function (file) {
|
||||
file.thumbnail = umbImageHelper.getThumbnailFromPath(file.file);
|
||||
});
|
||||
|
||||
$scope.clearFiles = false;
|
||||
}
|
||||
else {
|
||||
$scope.persistedFiles = [];
|
||||
}
|
||||
|
||||
_.each($scope.persistedFiles, function (file) {
|
||||
file.thumbnail = umbImageHelper.getThumbnailFromPath(file.file);
|
||||
});
|
||||
|
||||
$scope.clearFiles = false;
|
||||
|
||||
initialize();
|
||||
|
||||
//listen for clear files changes to set our model to be sent up to the server
|
||||
$scope.$watch("clearFiles", function (isCleared) {
|
||||
@@ -47,25 +70,48 @@ function fileUploadController($scope, $element, $compile, umbImageHelper) {
|
||||
clearFiles();
|
||||
}
|
||||
else {
|
||||
$scope.model.value = "";
|
||||
//reset to original value
|
||||
$scope.model.value = $scope.originalValue;
|
||||
}
|
||||
});
|
||||
|
||||
//listen for when a file is selected
|
||||
$scope.$on("filesSelected", function (event, args) {
|
||||
$scope.$apply(function () {
|
||||
//set the parent files collection
|
||||
$scope.$parent.addFiles($scope.model.id, args.files);
|
||||
//set the files collection
|
||||
fileManager.setFiles($scope.model.id, args.files);
|
||||
//clear the current files
|
||||
$scope.files = [];
|
||||
var newVal = "";
|
||||
for (var i = 0; i < args.files.length; i++) {
|
||||
//save the file object to the scope's files collection
|
||||
$scope.files.push({ id: $scope.model.id, file: args.files[i] });
|
||||
newVal += args.files[i].name + ",";
|
||||
}
|
||||
//set clear files to false, this will reset the model too
|
||||
$scope.clearFiles = false;
|
||||
//set the model value to be the concatenation of files selected. Please see the notes
|
||||
// in the description of this controller, it states that this value isn't actually used for persistence,
|
||||
// but we need to set it to something so that the editor and the server can detect that it's been changed.
|
||||
$scope.model.value = "{selectedFiles: '" + newVal.trimEnd(",") + "'}";
|
||||
});
|
||||
});
|
||||
|
||||
//listen for when the model value has changed
|
||||
$scope.$watch("model.value", function(newVal, oldVal) {
|
||||
//cannot just check for !newVal because it might be an empty string which we
|
||||
//want to look for.
|
||||
if (newVal !== null && newVal !== undefined && newVal !== oldVal) {
|
||||
//now we need to check if we need to re-initialize our structure which is kind of tricky
|
||||
// since we only want to do that if the server has changed the value, not if this controller
|
||||
// has changed the value. There's only 2 scenarios where we change the value internall so
|
||||
// we know what those values can be, if they are not either of them, then we'll re-initialize.
|
||||
|
||||
if (newVal !== "{clearFiles: true}" && newVal !== $scope.originalValue && !newVal.startsWith("{selectedFiles:")) {
|
||||
initialize($scope.rebuildInput.index + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
angular.module("umbraco").controller('Umbraco.Editors.FileUploadController', fileUploadController);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<div ng-hide="clearFiles">
|
||||
<div class="file-uploader">
|
||||
<input type="file" umb-file-upload multiple />
|
||||
<umb-single-file-upload rebuild="rebuildInput"></umb-single-file-upload>
|
||||
</div>
|
||||
<ul ng-show="files.length > 0">
|
||||
<li ng-repeat="file in files">{{file.file.name}}</li>
|
||||
@@ -18,7 +18,7 @@
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<input type="checkbox" name="myPackage_clearFiles" ng-model="clearFiles" />
|
||||
<label for="myPackage_clearFiles">Clear files</label>
|
||||
<input type="checkbox" id="clearFiles-{{model.id}}" name="clearFiles" ng-model="clearFiles" />
|
||||
<label for="clearFiles-{{model.id}}">Clear files</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,48 @@
|
||||
angular.module('umbraco').controller("Umbraco.Editors.ReadOnlyValueController",
|
||||
function($rootScope, $scope, $filter){
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name Umbraco.Editors.ReadOnlyValueController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for the readonlyvalue property editor.
|
||||
* This controller offer more functionality than just a simple label as it will be able to apply formatting to the
|
||||
* value to be displayed. This means that we also have to apply more complex logic of watching the model value when
|
||||
* it changes because we are creating a new scope value called displayvalue which will never change based on the server data.
|
||||
* In some cases after a form submission, the server will modify the data that has been persisted, especially in the cases of
|
||||
* readonlyvalues so we need to ensure that after the form is submitted that the new data is reflected here.
|
||||
*/
|
||||
function ReadOnlyValueController($rootScope, $scope, $filter) {
|
||||
|
||||
if ($scope.model.config &&
|
||||
angular.isArray($scope.model.config) &&
|
||||
$scope.model.config.length > 0 &&
|
||||
$scope.model.config[0] &&
|
||||
$scope.model.config.filter)
|
||||
{
|
||||
|
||||
if ($scope.model.config.format) {
|
||||
$scope.displayvalue = $filter($scope.model.config.filter)($scope.model.value, $scope.model.config.format);
|
||||
}
|
||||
else {
|
||||
$scope.displayvalue = $filter($scope.model.config.filter)($scope.model.value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$scope.displayvalue = $scope.model.value;
|
||||
}
|
||||
});
|
||||
function formatDisplayValue() {
|
||||
|
||||
if ($scope.model.config &&
|
||||
angular.isArray($scope.model.config) &&
|
||||
$scope.model.config.length > 0 &&
|
||||
$scope.model.config[0] &&
|
||||
$scope.model.config.filter) {
|
||||
|
||||
if ($scope.model.config.format) {
|
||||
$scope.displayvalue = $filter($scope.model.config.filter)($scope.model.value, $scope.model.config.format);
|
||||
} else {
|
||||
$scope.displayvalue = $filter($scope.model.config.filter)($scope.model.value);
|
||||
}
|
||||
} else {
|
||||
$scope.displayvalue = $scope.model.value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//format the display value on init:
|
||||
formatDisplayValue();
|
||||
|
||||
$scope.$watch("model.value", function (newVal, oldVal) {
|
||||
//cannot just check for !newVal because it might be an empty string which we
|
||||
//want to look for.
|
||||
if (newVal !== null && newVal !== undefined && newVal !== oldVal) {
|
||||
//update the display val again
|
||||
formatDisplayValue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
angular.module('umbraco').controller("Umbraco.Editors.ReadOnlyValueController", ReadOnlyValueController);
|
||||
@@ -36,23 +36,7 @@ describe('edit content controller tests', function () {
|
||||
}));
|
||||
|
||||
describe('content edit controller save and publish', function () {
|
||||
|
||||
it('it should define the default properties on construction', function () {
|
||||
expect(scope.files).toNotBe(undefined);
|
||||
});
|
||||
|
||||
it('adding a file adds to the collection', function () {
|
||||
scope.addFiles(123, ["testFile"]);
|
||||
expect(scope.files.length).toBe(1);
|
||||
});
|
||||
|
||||
it('adding a file with the same property id replaces the existing one', function () {
|
||||
scope.addFiles(123, ["testFile"]);
|
||||
scope.addFiles(123, ["testFile2"]);
|
||||
expect(scope.files.length).toBe(1);
|
||||
expect(scope.files[0].file).toBe("testFile2");
|
||||
});
|
||||
|
||||
it('it should have an content object', function() {
|
||||
|
||||
//controller should have a content object
|
||||
|
||||
@@ -218,9 +218,7 @@ describe('contentEditingHelper tests', function () {
|
||||
newContent.tabs[1].properties[2].value = "origValue4";
|
||||
|
||||
//act
|
||||
var changed = contentEditingHelper.reBindChangedProperties(
|
||||
contentEditingHelper.getAllProps(origContent),
|
||||
contentEditingHelper.getAllProps(newContent));
|
||||
var changed = contentEditingHelper.reBindChangedProperties(origContent, newContent);
|
||||
|
||||
//assert
|
||||
expect(changed.length).toBe(2);
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
describe('file manager tests', function () {
|
||||
var fileManager;
|
||||
|
||||
beforeEach(module('umbraco.services'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
fileManager = $injector.get('fileManager');
|
||||
}));
|
||||
|
||||
describe('file management', function () {
|
||||
|
||||
it('adding a file adds to the collection', function () {
|
||||
fileManager.setFiles(123, ["testFile"]);
|
||||
expect(fileManager.getFiles().length).toBe(1);
|
||||
});
|
||||
|
||||
it('adding a file with the same property id replaces the existing one', function () {
|
||||
fileManager.setFiles(123, ["testFile"]);
|
||||
fileManager.setFiles(123, ["testFile2"]);
|
||||
expect(fileManager.getFiles().length).toBe(1);
|
||||
expect(fileManager.getFiles()[0].file).toBe("testFile2");
|
||||
});
|
||||
|
||||
it('clears all files', function () {
|
||||
fileManager.setFiles(123, ["testFile"]);
|
||||
fileManager.setFiles(234, ["testFile"]);
|
||||
expect(fileManager.getFiles().length).toBe(2);
|
||||
fileManager.clearFiles();
|
||||
expect(fileManager.getFiles().length).toBe(0);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -66,20 +66,39 @@ namespace Umbraco.Web.PropertyEditors
|
||||
UmbracoSettings.ImageAutoFillImageProperties.SelectSingleNode(
|
||||
string.Format("uploadField [@alias = \"{0}\"]", p.Alias));
|
||||
|
||||
if (uploadFieldConfigNode != null && p.Value != null && p.Value is string && ((string)p.Value).IsNullOrWhiteSpace() == false)
|
||||
if (uploadFieldConfigNode != null)
|
||||
{
|
||||
//there might be multiple, we can only process the first one!
|
||||
var split = ((string) p.Value).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (split.Any())
|
||||
//now we need to check if there is a value
|
||||
if (p.Value is string && ((string) p.Value).IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
var umbracoFile = new UmbracoMediaFile(IOHelper.MapPath(split[0]));
|
||||
FillProperties(uploadFieldConfigNode, model, umbracoFile);
|
||||
//there might be multiple, we can only process the first one!
|
||||
var split = ((string) p.Value).Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (split.Any())
|
||||
{
|
||||
var umbracoFile = new UmbracoMediaFile(IOHelper.MapPath(split[0]));
|
||||
FillProperties(uploadFieldConfigNode, model, umbracoFile);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//there's no value so need to reset to zero
|
||||
ResetProperties(uploadFieldConfigNode, model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResetProperties(XmlNode uploadFieldConfigNode, IContentBase content)
|
||||
{
|
||||
// only add dimensions to web images
|
||||
UpdateContentProperty(uploadFieldConfigNode, content, "widthFieldAlias", string.Empty);
|
||||
UpdateContentProperty(uploadFieldConfigNode, content, "heightFieldAlias", string.Empty);
|
||||
|
||||
UpdateContentProperty(uploadFieldConfigNode, content, "lengthFieldAlias", string.Empty);
|
||||
UpdateContentProperty(uploadFieldConfigNode, content, "extensionFieldAlias", string.Empty);
|
||||
}
|
||||
|
||||
private static void FillProperties(XmlNode uploadFieldConfigNode, IContentBase content, UmbracoMediaFile um)
|
||||
{
|
||||
// only add dimensions to web images
|
||||
|
||||
@@ -28,7 +28,12 @@ namespace Umbraco.Web.PropertyEditors
|
||||
/// <summary>
|
||||
/// Overrides the deserialize value so that we can save the file accordingly
|
||||
/// </summary>
|
||||
/// <param name="editorValue"></param>
|
||||
/// <param name="editorValue">
|
||||
/// This is value passed in from the editor. We normally don't care what the editorValue.Value is set to because
|
||||
/// we are more interested in the files collection associated with it, however we do care about the value if we
|
||||
/// are clearing files. By default the editorValue.Value will just be set to the name of the file (but again, we
|
||||
/// just ignore this and deal with the file collection in editorValue.AdditionalData.ContainsKey("files") )
|
||||
/// </param>
|
||||
/// <param name="currentValue">
|
||||
/// The current value persisted for this property. This will allow us to determine if we want to create a new
|
||||
/// file path or use the existing file path.
|
||||
@@ -36,16 +41,20 @@ namespace Umbraco.Web.PropertyEditors
|
||||
/// <returns></returns>
|
||||
public override object DeserializeValue(ContentPropertyData editorValue, object currentValue)
|
||||
{
|
||||
if (currentValue == null)
|
||||
{
|
||||
currentValue = string.Empty;
|
||||
}
|
||||
|
||||
//if the value is the same then just return the current value
|
||||
if (currentValue != null && editorValue.Value == currentValue.ToString())
|
||||
//if the value is the same then just return the current value so we don't re-process everything
|
||||
if (string.IsNullOrEmpty(currentValue.ToString()) == false && editorValue.Value == currentValue.ToString())
|
||||
{
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
//check the editorValue value to see if we need to clear the files or not
|
||||
//check the editorValue value to see if we need to clear the files or not.
|
||||
var clear = false;
|
||||
if (editorValue.Value.IsNullOrWhiteSpace() == false)
|
||||
if (editorValue.Value.IsNullOrWhiteSpace() == false && editorValue.Value.StartsWith("{clearFiles:"))
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -59,7 +68,7 @@ namespace Umbraco.Web.PropertyEditors
|
||||
}
|
||||
|
||||
var currentPersistedValues = new string[] {};
|
||||
if (currentValue != null)
|
||||
if (string.IsNullOrEmpty(currentValue.ToString()) == false)
|
||||
{
|
||||
currentPersistedValues = currentValue.ToString().Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user