diff --git a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js index 49a90f273e..fc28567ea3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js +++ b/src/Umbraco.Web.UI.Client/src/common/mocks/resources/_utils.js @@ -313,6 +313,7 @@ angular.module('umbraco.mocks'). label: "Content", id: 2, properties: [ + { alias: "testproperty", label: "Test property", view: "textbox", value: "asdfghjk" }, { alias: "valTest", label: "Validation test", view: "validationtest", value: "asdfasdf" }, { alias: "bodyText", label: "Body Text", description: "Here you enter the primary article contents", view: "rte", value: "

askjdkasj lasjd

", config: {} }, { alias: "textarea", label: "textarea", view: "textarea", value: "ajsdka sdjkds", config: { rows: 4 } }, diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.block.component.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockeditor.block.component.html similarity index 100% rename from src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.block.component.html rename to src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockeditor.block.component.html diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.block.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockeditor.block.component.js similarity index 51% rename from src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.block.component.js rename to src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockeditor.block.component.js index 330d8f7b69..c3397e9433 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.block.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockeditor/blockeditor.block.component.js @@ -2,10 +2,10 @@ "use strict"; angular .module("umbraco") - .component("blockListPropertyEditorBlock", { - templateUrl: "views/propertyeditors/blocklist/blocklist.block.component.html", + .component("blockEditorBlock", { + templateUrl: "views/propertyeditors/blockeditor/blockeditor.block.component.html", transclude: true, - controller: BlockListBlockController, + controller: BlockEditorBlockBlockController, controllerAs: "vm", bindings: { block: "=", @@ -16,7 +16,7 @@ } }); - function BlockListBlockController($scope, blockEditorService) { + function BlockEditorBlockBlockController($scope, blockEditorService) { var unsubscribe = []; var vm = this; @@ -32,9 +32,10 @@ for (var p = 0; p < tab.properties.length; p++) { var prop = tab.properties[p]; - // Sadly we need to deep watch, cause its our only way to make sure that complex values gets synced. Alternative solution would be to sync on a broadcasted event, fired on Save and Copy eventually more. - // But to minimize the watch we only watch the value of properties. But because we are deep watching it means that we are watching everything of nested block editors, so this would only have a performance improvement for first levels of block editors. - // New thoughts, since the value of a property editors is just a pointer (if not primative) then we could properly live without deep watching? cause they reference the same?.. Lets investigate.. + // Watch value of property since this is the only value we want to keep synced. + // Do notice that it is not performing a deep watch, meaning that we are only watching primatives and changes directly to the object of property-value. + // But we like to sync non-primative values as well! Yes, and this does happen, just not through this code, but through the nature of JavaScript. + // Non-primative values act as references to the same data and are therefor synced. unsubscribe.push($scope.$watch("vm.block.content.variants[0].tabs["+t+"].properties["+p+"].value", createPropWatcher(prop))); } } @@ -47,8 +48,6 @@ // sync data: vm.block.contentModel[prop.alias] = prop.value; - //vm.blockEditorApi.sync(); - // update label: updateLabel(); } @@ -58,20 +57,6 @@ function updateLabel() { vm.block.label = blockEditorService.getBlockLabel(vm.block); } - - /** - * Listening for properties - */ - /* - function onBlockEditorValueUpdated($event) { - // Lets sync the value of the property that the event comes from, if we know that.. - - //$event.stopPropagation(); - //$event.preventDefault(); - }; - - unsubscribe.push($scope.$on("blockEditorValueUpdated", onBlockEditorValueUpdated)); - */ $scope.$on("$destroy", function () { for (const subscription of unsubscribe) { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.html index 3761b42561..2004becba7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.html @@ -14,7 +14,7 @@ > - +
@@ -32,7 +32,7 @@ -
+ diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.js index 617f92350d..9904a0132b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.js @@ -54,7 +54,7 @@ vm.model.value = vm.model.value || {}; modelObject = blockEditorService.createModelObject(vm.model.value, vm.model.editor, vm.model.config.blocks); - modelObject.loadScaffolding().then(loaded); + modelObject.loadScaffolding().then(onLoaded); copyAllBlocksAction = { labelKey: "clipboard_labelForCopyAllEntries", @@ -90,7 +90,7 @@ } } - function loaded() { + function onLoaded() { vm.layout = modelObject.getLayout(); @@ -105,7 +105,7 @@ vm.availableContentTypes = modelObject.getAvailableAliasesForBlockContent(); vm.availableBlockTypes = modelObject.getAvailableBlocksForItemPicker(); - $scope.$apply(); + $scope.$evalAsync(); } @@ -375,7 +375,7 @@ scroll: true, start: function (ev, ui) { runtimeSortVars.moveFromIndex = ui.item.index(); - $scope.$apply(function () { + $scope.$evalAsync(function () { vm.sorting = true; }); }, @@ -394,7 +394,7 @@ vm.layout.splice(moveToIndex, 0, movedEntry); } - $scope.$apply(function () { + $scope.$evalAsync(function () { vm.sorting = false; }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less index 02670e88b0..2ab2c37d3b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blocklist/blocklist.component.less @@ -16,25 +16,25 @@ position: relative; width: 100%; - .umb-block-list__block--head { + /*.umb-block-list__block--head { opacity: 0; transition: opacity 120ms; - } - .umb-block-list__block--actions { + }*/ + > ng-transclude > .umb-block-list__block--actions { opacity: 0; transition: opacity 120ms; } &:hover, &:focus, &:focus-within { - .umb-block-list__block--head { + /*.umb-block-list__block--head { opacity: 1; - } + }*/ - .umb-block-list__block--actions { + > ng-transclude > .umb-block-list__block--actions { opacity: 1; } } - + /* &:focus, &:focus-within { .umb-block-list__block--head { &::before { @@ -42,8 +42,9 @@ } } } + */ } - +/* .umb-block-list__block--head { position: absolute; top: 0; @@ -77,7 +78,7 @@ label.umb-block-list__block--head { cursor: grab; } - +*/ .umb-block-list__block--actions { position: absolute; top: 10px; diff --git a/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js b/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js index 6bfc7aea34..b51ba1f9ee 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/common/services/block-editor-service.spec.js @@ -1,15 +1,19 @@ describe('blockEditorService tests', function () { - var blockEditorService, contentResource; + var blockEditorService, contentResource, $rootScope, $componentController; beforeEach(module('umbraco.services')); beforeEach(module('umbraco.resources')); beforeEach(module('umbraco.mocks')); + beforeEach(module('umbraco')); - beforeEach(inject(function ($injector, mocksUtils) { + beforeEach(inject(function ($injector, mocksUtils, _$rootScope_, _$componentController_) { mocksUtils.disableAuth(); + $rootScope = _$rootScope_; + $componentController = _$componentController_; + contentResource = $injector.get("contentResource"); spyOn(contentResource, "getScaffold").and.callFake( function () { @@ -36,7 +40,7 @@ { udi: 1234, contentTypeAlias: "testAlias", - testvalue: "myTestValue" + testproperty: "myTestValue" } ] }; @@ -75,7 +79,7 @@ }); - it('getLayoutEntry has right values', function (done) { + it('getLayoutEntry has values', function (done) { var modelObject = blockEditorService.createModelObject(propertyModelMock, "Umbraco.TestBlockEditor", [blockConfigurationMock]); @@ -94,7 +98,7 @@ }); - it('getBlockModel provide value', function (done) { + it('getBlockModel has values', function (done) { var modelObject = blockEditorService.createModelObject(propertyModelMock, "Umbraco.TestBlockEditor", [blockConfigurationMock]); @@ -102,13 +106,76 @@ modelObject.loadScaffolding().then(() => { var layout = modelObject.getLayout(); - expect(layout).not.toBeUndefined(); var blockModel = modelObject.getBlockModel(layout[0]); expect(blockModel).not.toBeUndefined(); - expect(blockModel[0].udi).toBe(propertyModelMock.data[0].udi); - expect(blockModel[0].testvalue).toBe(propertyModelMock.data[0].testvalue); + expect(blockModel.contentModel.udi).toBe(propertyModelMock.data[0].udi); + expect(blockModel.content.variants[0].tabs[0].properties[0].value).toBe(propertyModelMock.data[0].testproperty); + + done(); + }); + + }); + + + it('getBlockModel syncs primative values', function (done) { + + var propertyModel = angular.copy(propertyModelMock); + + var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockConfigurationMock]); + + modelObject.loadScaffolding().then(() => { + + var layout = modelObject.getLayout(); + + var blockModel = modelObject.getBlockModel(layout[0]); + + blockEditorBlockComponenet = $componentController("blockEditorBlock", null, {"block": blockModel, "blockEditorApi": {}, "class": "testClass"}); + blockEditorBlockComponenet.$onInit(); + + blockModel.content.variants[0].tabs[0].properties[0].value = "anotherTestValue"; + + $rootScope.$digest();// invoke angularJS Store. + + expect(blockModel.contentModel).toBe(propertyModel.data[0]); + expect(blockModel.contentModel.testproperty).toBe("anotherTestValue"); + expect(propertyModel.data[0].testproperty).toBe("anotherTestValue"); + + // + + done(); + }); + + }); + + + it('getBlockModel syncs values of object', function (done) { + + var propertyModel = angular.copy(propertyModelMock); + + var complexValue = {"list": ["A", "B", "C"]}; + propertyModel.data[0].testproperty = complexValue; + + + var modelObject = blockEditorService.createModelObject(propertyModel, "Umbraco.TestBlockEditor", [blockConfigurationMock]); + + modelObject.loadScaffolding().then(() => { + + var layout = modelObject.getLayout(); + + var blockModel = modelObject.getBlockModel(layout[0]); + + blockEditorBlockComponenet = $componentController("blockEditorBlock", null, {"block": blockModel, "blockEditorApi": {}, "class": "testClass"}); + blockEditorBlockComponenet.$onInit(); + + blockModel.content.variants[0].tabs[0].properties[0].value.list[0] = "AA"; + blockModel.content.variants[0].tabs[0].properties[0].value.list.push("D"); + + $rootScope.$digest();// invoke angularJS Store. + + expect(propertyModel.data[0].testproperty.list[0]).toBe("AA"); + expect(propertyModel.data[0].testproperty.list.length).toBe(4); done(); });