WIP committing a change for the file upload to convert to a component but will revert because using a directive to get the culture isn't going to work because a property can be invariant so the property itself needs to know it's own culture, not just the culture of the current variant.

This commit is contained in:
Shannon
2018-08-07 11:41:57 +10:00
parent 7f09814973
commit bd2414bc49
5 changed files with 149 additions and 112 deletions

View File

@@ -94,6 +94,7 @@ Use this directive to render an umbraco button. The directive can be used to gen
}
});
//TODO: This doesn't seem necessary?
UmbButtonController.$inject = ['$timeout'];
function UmbButtonController($timeout) {

View File

@@ -43,9 +43,9 @@ function fileManager() {
metaData = args.metaData;
}
//this will clear the files for the current property and then add the new ones for the current property
//this will clear the files for the current property/culture and then add the new ones for the current property
fileCollection = _.reject(fileCollection, function (item) {
return item.alias === args.propertyAlias;
return item.alias === args.propertyAlias && (!args.culture || args.culture === item.culture);
});
for (var i = 0; i < args.files.length; i++) {
//save the file object to the files collection

View File

@@ -7,33 +7,61 @@
* @function
*
* @description
* 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.
* The controller for the file upload property editor.
*
*/
function fileUploadController($scope, $element, $compile, imageHelper, fileManager, umbRequestHelper, mediaHelper, angularHelper) {
/* 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.
* */
var vm = this;
vm.$onInit = onInit;
vm.$onChanges = onChanges;
vm.$postLink = postLink;
vm.validateMandatory = validateMandatory;
/** Clears the file collections when content is saving (if we need to clear) or after saved */
function clearFiles() {
//clear the files collection (we don't want to upload any!)
fileManager.setFiles({
propertyAlias: $scope.model.alias,
propertyAlias: vm.propertyAlias,
culture: vm.culture,
files: []
});
//clear the current files
$scope.files = [];
vm.files = [];
if ($scope.fileUploadForm) {
if ($scope.fileUploadForm.fileCount) {
angularHelper.revalidateNgModel($scope, $scope.fileUploadForm.fileCount);
if (vm.fileUploadForm) {
if (vm.fileUploadForm.fileCount) {
angularHelper.revalidateNgModel($scope, vm.fileUploadForm.fileCount);
}
}
}
/** Called when the component initializes */
function onInit() {
//check if there's a tabbed-content controller available and get the culture
vm.culture = (vm.tabbedContentCtrl && vm.tabbedContentCtrl.content.language) ? vm.tabbedContentCtrl.content.language.culture : null;
$scope.$watch(function () {
return vm.clearFiles;
}, clearFilesWatch);
$scope.$on("filesSelected", onFilesSelected);
}
/** Called when the component has linked all elements, this is when the form controller is available */
function postLink() {
initialize();
}
/** this method is used to initialize the data and to re-initialize it if the server value is changed */
@@ -48,28 +76,28 @@
//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 = {
vm.rebuildInput = {
index: index
};
//clear the current files
$scope.files = [];
vm.files = [];
//store the original value so we can restore it if the user clears and then cancels clearing.
$scope.originalValue = $scope.model.value;
vm.originalValue = vm.modelValue;
//create the property to show the list of files currently saved
if ($scope.model.value != "" && $scope.model.value != undefined) {
if (vm.modelValue != "" && vm.modelValue != undefined) {
var images = $scope.model.value.split(",");
var images = vm.modelValue.split(",");
$scope.persistedFiles = _.map(images, function (item) {
vm.persistedFiles = _.map(images, function (item) {
return { file: item, isImage: imageHelper.detectIfImageByExtension(item) };
});
}
else {
$scope.persistedFiles = [];
vm.persistedFiles = [];
}
_.each($scope.persistedFiles, function (file) {
_.each(vm.persistedFiles, function (file) {
var thumbnailUrl = umbRequestHelper.getApiUrl(
"imagesApiBaseUrl",
@@ -82,115 +110,120 @@
file.extension = extension.toLowerCase();
});
$scope.clearFiles = false;
vm.clearFiles = false;
}
initialize();
// Method required by the valPropertyValidator directive (returns true if the property editor has at least one file selected)
$scope.validateMandatory = function () {
/** Method required by the valPropertyValidator directive (returns true if the property editor has at least one file selected) */
function validateMandatory() {
return {
isValid: !$scope.model.validation.mandatory || ((($scope.persistedFiles != null && $scope.persistedFiles.length > 0) || ($scope.files != null && $scope.files.length > 0)) && !$scope.clearFiles),
isValid: !vm.validation.mandatory || (((vm.persistedFiles != null && vm.persistedFiles.length > 0) || (vm.files != null && vm.files.length > 0)) && !vm.clearFiles),
errorMsg: "Value cannot be empty",
errorKey: "required"
};
}
//listen for clear files changes to set our model to be sent up to the server
$scope.$watch("clearFiles", function (newVal, oldVal) {
if (newVal == true) {
$scope.model.value = { clearFiles: true };
/**
* listen for clear files changes to set our model to be sent up to the server
* @param {any} newVal
* @param {any} oldVal
*/
function clearFilesWatch(newVal, oldVal) {
//TODO: Call a callback method instead of setting the value directly inside this component
if (newVal === true) {
vm.modelValue = { clearFiles: true };
clearFiles();
}
else if (newVal !== oldVal) {
//reset to original value
$scope.model.value = $scope.originalValue;
vm.modelValue = vm.originalValue;
//this is required to re-validate
if ($scope.fileUploadForm) {
angularHelper.revalidateNgModel($scope, $scope.fileUploadForm.fileCount);
if (vm.fileUploadForm) {
angularHelper.revalidateNgModel($scope, vm.fileUploadForm.fileCount);
}
}
});
}
/**
* Watch for model changes
* @param {any} changes
*/
function onChanges(changes) {
if (changes.modelValue && !changes.modelValue.isFirstChange()
&& changes.modelValue.currentValue !== null && changes.modelValue.currentValue !== undefined
&& changes.modelValue.currentValue !== changes.modelValue.previousValue) {
//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) {
// here we need to check if the value change needs to trigger an update in the UI.
// if the value is only changed in the controller and not in the server values, we do not
// want to trigger an update yet.
// we can however no longer rely on checking values in the controller vs. values from the server
// to determine whether to update or not, since you could potentially be uploading a file with
// the exact same name - in that case we need to reinitialize to show the newly uploaded file.
if (newVal.clearFiles !== true && !newVal.selectedFiles) {
initialize($scope.rebuildInput.index + 1);
if (changes.modelValue.currentValue.clearFiles !== true && !changes.modelValue.currentValue.selectedFiles) {
initialize(vm.rebuildInput.index + 1);
}
}
});
}
/**
* listen for when a file is selected
* @param {any} event
* @param {any} args
*/
function onFilesSelected(event, args) {
//set the files collection
fileManager.setFiles({
propertyAlias: vm.propertyAlias,
files: args.files,
culture: vm.culture
});
//clear the current files
vm.files = [];
var newVal = "";
for (var i = 0; i < args.files.length; i++) {
//save the file object to the files collection
vm.files.push({ alias: vm.propertyAlias, file: args.files[i] });
newVal += args.files[i].name + ",";
}
//this is required to re-validate
angularHelper.revalidateNgModel($scope, vm.fileUploadForm.fileCount);
//set clear files to false, this will reset the model too
vm.clearFiles = false;
//TODO: Call a callback method instead of setting the value directly inside this component
//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 so that the editor and the server can detect that it's been changed, and it is used for validation.
vm.modelValue = { selectedFiles: newVal.trimEnd(",") };
//need to explicity setDirty here as file upload field can't track dirty & we can't use the fileCount (hidden field/model)
vm.fileUploadForm.$setDirty();
}
};
/**
* Directive used to capture the tabbed-content directive to get the current variant culture
* @param {any} fileManager
* @param {any} angularHelper
*/
function umbFileUploadEditorDirective(fileManager, angularHelper) {
var directive = {
require: '?^^tabbedContent',
restrict: 'E',
replace: true,
templateUrl: 'views/propertyeditors/fileupload/fileupload.directive.html',
controller: 'Umbraco.PropertyEditors.FileUploadController',
scope: {
model: "=",
},
link: function (scope, element, attrs, ctrl) {
//listen for when a file is selected
scope.$on("filesSelected", function (event, args) {
//check if there's a tabbed-content controller available and get the culture
var culture = (ctrl && ctrl.content.language) ? ctrl.content.language.culture : null;
//set the files collection
fileManager.setFiles({
propertyAlias: scope.model.alias,
files: args.files,
culture: culture
});
//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({ alias: scope.model.alias, file: args.files[i] });
newVal += args.files[i].name + ",";
}
//this is required to re-validate
angularHelper.revalidateNgModel(scope, scope.fileUploadForm.fileCount);
//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 so that the editor and the server can detect that it's been changed, and it is used for validation.
scope.model.value = { selectedFiles: newVal.trimEnd(",") };
//need to explicity setDirty here as file upload field can't track dirty & we can't use the fileCount (hidden field/model)
scope.fileUploadForm.$setDirty();
});
}
};
return directive;
}
var umbFileUploadEditorComponent = {
templateUrl: 'views/propertyeditors/fileupload/umbfileuploadeditor.component.html',
require: {
tabbedContentCtrl: '?^^tabbedContent'
},
bindings: {
modelValue: "=",
propertyAlias: "@",
validation: "<"
},
controllerAs: 'vm',
controller: fileUploadController
};
angular.module("umbraco")
.controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController)
.directive('umbFileUploadEditor', umbFileUploadEditorDirective)
//.controller('Umbraco.PropertyEditors.FileUploadController', fileUploadController)
.component('umbFileUploadEditor', umbFileUploadEditorComponent)
.run(function (mediaHelper, umbRequestHelper, assetsService) {
if (mediaHelper && mediaHelper.registerFileResolver) {

View File

@@ -1,3 +1,6 @@
<div>
<umb-file-upload-editor model="model"></umb-file-upload-editor>
<umb-file-upload-editor model-value="model.value"
property-alias="{{model.alias}}"
validation="model.validation">
</umb-file-upload-editor>
</div>

View File

@@ -1,8 +1,8 @@
<div class="umb-property-editor umb-fileupload">
<ng-form name="fileUploadForm">
<div ng-show="persistedFiles.length > 0">
<ng-form name="vm.fileUploadForm">
<div ng-show="vm.persistedFiles.length > 0">
<ul class="thumbnails">
<li class="span4 thumbnail" ng-repeat="file in persistedFiles">
<li class="span4 thumbnail" ng-repeat="file in vm.persistedFiles">
<a href="{{file.file}}" target="_blank" ng-switch on="file.isImage">
<img ng-src="{{file.thumbnail}}" ng-switch-when="true" alt="{{file.file}}" />
<img ng-src="{{file.file}}" ng-switch-when="false" ng-if="file.extension == 'svg'" alt="{{file.file}}" />
@@ -17,22 +17,22 @@
</li>
</ul>
<input type="checkbox" id="clearFiles-{{model.id}}" name="clearFiles" ng-model="clearFiles" />
<label for="clearFiles-{{model.id}}" class="inline" style="font-size: 13px; vertical-align: top;">
<input type="checkbox" id="clearFiles-{{vm.model.id}}" name="clearFiles" ng-model="vm.clearFiles" />
<label for="clearFiles-{{vm.model.id}}" class="inline" style="font-size: 13px; vertical-align: top;">
<localize key="content_uploadClear">Clear files</localize>
</label>
<hr />
</div>
<div ng-hide="clearFiles">
<div ng-hide="vm.clearFiles">
<div class="file-uploader">
<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>
<ul ng-show="vm.files.length > 0">
<li ng-repeat="file in vm.files">{{file.file.name}}</li>
</ul>
</div>
<input type="hidden" name="fileCount" ng-model="files.length" val-property-validator="validateMandatory" no-dirty-check />
<input type="hidden" name="fileCount" ng-model="vm.files.length" val-property-validator="vm.validateMandatory" no-dirty-check />
</ng-form>
</div>