diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js index 1f5aaaa1c2..97d11879e9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js @@ -1,36 +1,49 @@ /** -* @ngdoc directive -* @name umbraco.directives.directive:valSubView -* @restrict A -* @description Used to show validation warnings for a editor sub view to indicate that the section content has validation errors in its data. -* In order for this directive to work, the valFormManager directive must be placed on the containing form. + * @ngdoc directive + * @name umbraco.directives.directive:valSubView + * @restrict A + * @description Used to show validation warnings for a editor sub view (used in conjunction with: + * umb-editor-sub-view or umb-editor-sub-views) to indicate that the section content has validation errors in its data. + * In order for this directive to work, the valFormManager directive must be placed on the containing form. + * When applied to **/ (function () { 'use strict'; + // Since this is a directive applied as an attribute, the value of that attribtue is the 'model' object property + // of the current inherited scope that the hasError/errorClass properties will apply to. + // This directive cannot have it's own scope because it's an attribute applied to another scoped directive. + // Due to backwards compatibility we can't really change this, ideally this would have it's own scope/properties. + function valSubViewDirective() { - function controller($scope, $element) { + function controller($scope, $element, $attrs) { + + var model = $scope.model; // this is the default and required for backwards compat + if ($attrs && $attrs.valSubView) { + // get the property to use + model = $scope[$attrs.valSubView]; + } + //expose api return { valStatusChanged: function (args) { - // TODO: Verify this is correct, does $scope.model ever exist? - if ($scope.model) { + if (model) { if (!args.form.$valid) { var subViewContent = $element.find(".ng-invalid"); if (subViewContent.length > 0) { - $scope.model.hasError = true; - $scope.model.errorClass = args.showValidation ? 'show-validation' : null; + model.hasError = true; + model.errorClass = args.showValidation ? 'show-validation' : null; } else { - $scope.model.hasError = false; - $scope.model.errorClass = null; + model.hasError = false; + model.errorClass = null; } } else { - $scope.model.hasError = false; - $scope.model.errorClass = null; + model.hasError = false; + model.errorClass = null; } } } @@ -40,12 +53,18 @@ function link(scope, el, attr, ctrl) { //if there are no containing form or valFormManager controllers, then we do nothing - if (!ctrl || !Utilities.isArray(ctrl) || ctrl.length !== 2 || !ctrl[0] || !ctrl[1]) { + if (!ctrl[1]) { return; } + var model = scope.model; // this is the default and required for backwards compat + if (attr && attr.valSubView) { + // get the property to use + model = scope[attr.valSubView]; + } + var valFormManager = ctrl[1]; - scope.model.hasError = false; + model.hasError = false; //listen for form validation changes valFormManager.onValidationStatusChanged(function (evt, args) { @@ -54,14 +73,14 @@ var subViewContent = el.find(".ng-invalid"); if (subViewContent.length > 0) { - scope.model.hasError = true; + model.hasError = true; } else { - scope.model.hasError = false; + model.hasError = false; } } else { - scope.model.hasError = false; + model.hasError = false; } }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js index 2c6ff25845..e23afbabfe 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/blockeditormodelobject.service.js @@ -14,7 +14,7 @@ 'use strict'; - function blockEditorModelObjectFactory($interpolate, udiService, contentResource) { + function blockEditorModelObjectFactory($interpolate, udiService, contentResource, localizationService) { /** * Simple mapping from property model content entry to editing model, @@ -214,6 +214,17 @@ return dataItems.find(entry => entry.udi === udi) || null; } + /** + * Set the udi and key property for the content item + * @param {any} contentData + * @param {any} udi + */ + function ensureUdiAndKey(contentData, udi) { + contentData.udi = udi; + // Change the content.key to the GUID part of the udi, else it's just random which we don't want, it must be consistent + contentData.key = udiService.getKey(udi); + } + /** * Used to highlight unsupported properties for the user, changes unsupported properties into a unsupported-property. */ @@ -222,7 +233,15 @@ "Umbraco.UploadField", "Umbraco.ImageCropper" ]; - function replaceUnsupportedProperties(scaffold) { + + + /** + * Formats the content apps and ensures unsupported property's have the notsupported view + * @param {any} scaffold + */ + function formatScaffoldData(scaffold) { + + // deal with not supported props scaffold.variants.forEach((variant) => { variant.tabs.forEach((tab) => { tab.properties.forEach((property) => { @@ -232,7 +251,34 @@ }); }); }); - return scaffold; + + // replace view of content app + var contentApp = scaffold.apps.find(entry => entry.alias === "umbContent"); + if (contentApp) { + contentApp.view = "views/common/infiniteeditors/blockeditor/blockeditor.content.html"; + } + + // remove info app + var infoAppIndex = scaffold.apps.findIndex(entry => entry.alias === "umbInfo"); + if (infoAppIndex >= 0) { + scaffold.apps.splice(infoAppIndex, 1); + } + + // add the settings app + return localizationService.localize("blockEditor_tabBlockSettings").then( + function (settingsName) { + var settingsTab = { + "name": settingsName, + "alias": "settings", + "icon": "icon-settings", + "view": "views/common/infiniteeditors/blockeditor/blockeditor.settings.html", + "hasError": false + }; + scaffold.apps.push(settingsTab); + + return scaffold; + } + ); } /** @@ -337,7 +383,10 @@ tasks.push(contentResource.getScaffoldByKey(-20, contentTypeKey).then(scaffold => { // this.scaffolds might not exists anymore, this happens if this instance has been destroyed before the load is complete. if (this.scaffolds) { - this.scaffolds.push(replaceUnsupportedProperties(scaffold)); + return formatScaffoldData(scaffold).then(s => this.scaffolds.push(s)); + } + else { + return Promise.resolve(); } })); })); @@ -483,9 +532,7 @@ // make basics from scaffold blockObject.content = Utilities.copy(contentScaffold); - blockObject.content.udi = contentUdi; - // Change the content.key to the GUID part of the udi, else it's just random which we don't want, it must be consistent - blockObject.content.key = udiService.getKey(contentUdi); + ensureUdiAndKey(blockObject.content, contentUdi); mapToElementModel(blockObject.content, dataModel); @@ -514,9 +561,7 @@ // make basics from scaffold blockObject.settings = Utilities.copy(settingsScaffold); - blockObject.settings.udi = settingsUdi; - // Change the settings.key to the GUID part of the udi, else it's just random which we don't want, it must be consistent - blockObject.settings.key = udiService.getKey(settingsUdi); + ensureUdiAndKey(blockObject.settings, settingsUdi); mapToElementModel(blockObject.settings, settingsData); } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js index 3a70c34170..f515cbb4ba 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/blockeditor/blockeditor.controller.js @@ -3,9 +3,9 @@ angular.module("umbraco") function ($scope, localizationService, formHelper) { var vm = this; - vm.model = $scope.model; vm.model = $scope.model; vm.tabs = []; + localizationService.localizeMany([ vm.model.liveEditing ? "prompt_discardChanges" : "general_close", vm.model.liveEditing ? "buttons_confirmActionConfirm" : "buttons_submitChanges" @@ -14,16 +14,13 @@ angular.module("umbraco") vm.submitLabel = data[1]; }); - if ($scope.model.content && $scope.model.content.variants) { + if (vm.model.content && vm.model.content.variants) { - var apps = $scope.model.content.apps; + var apps = vm.model.content.apps; - vm.tabs = apps; - - // replace view of content app. + // configure the content app based on settings var contentApp = apps.find(entry => entry.alias === "umbContent"); if (contentApp) { - contentApp.view = "views/common/infiniteeditors/blockeditor/blockeditor.content.html"; if (vm.model.hideContent) { apps.splice(apps.indexOf(contentApp), 1); } else if (vm.model.openSettings !== true) { @@ -31,27 +28,16 @@ angular.module("umbraco") } } - // remove info app: - var infoAppIndex = apps.findIndex(entry => entry.alias === "umbInfo"); - apps.splice(infoAppIndex, 1); - - } - - if (vm.model.settings && vm.model.settings.variants) { - localizationService.localize("blockEditor_tabBlockSettings").then( - function (settingsName) { - var settingsTab = { - "name": settingsName, - "alias": "settings", - "icon": "icon-settings", - "view": "views/common/infiniteeditors/blockeditor/blockeditor.settings.html" - }; - vm.tabs.push(settingsTab); + if (vm.model.settings && vm.model.settings.variants) { + var settingsApp = apps.find(entry => entry.alias === "settings"); + if (settingsApp) { if (vm.model.openSettings) { - settingsTab.active = true; + settingsApp.active = true; } } - ); + } + + vm.tabs = apps; } vm.submitAndClose = function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-view.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-view.html index 2cddbe0967..807c8c7ebc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-view.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-view.html @@ -1,6 +1,6 @@
+ val-sub-view="model">
+ val-sub-view="subView">