From 30be9269492707c3a9bbaf364a2f2624d026d85c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 23 Jan 2020 14:50:58 +0100 Subject: [PATCH] Refactorying of umb-editor, splitview, variants --- .../content/umbtabbedcontent.directive.js | 30 ++- .../content/umbvariantcontent.directive.js | 10 +- .../umbvariantcontenteditors.directive.js | 184 +++--------------- .../umbeditorcontentheader.directive.js | 58 ++---- .../components/editor/umbeditorsubview.js | 3 +- .../content/umb-content-node-info.html | 10 +- .../content/umb-tabbed-content.html | 10 +- .../content/umb-variant-content-editors.html | 3 +- .../content/umb-variant-content.html | 13 +- .../editor/umb-editor-content-header.html | 20 +- .../apps/content/content.controller.js | 9 +- .../views/content/apps/content/content.html | 5 +- 12 files changed, 101 insertions(+), 254 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js index 06f426889f..1d17b044f9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbtabbedcontent.directive.js @@ -4,7 +4,7 @@ /** This directive is used to render out the current variant tabs and properties and exposes an API for other directives to consume */ function tabbedContentDirective($timeout) { - function link($scope, $element, $attrs) { + function link($scope, $element) { var appRootNode = $element[0]; @@ -19,8 +19,8 @@ var viewFocusY = scrollableNode.scrollTop + scrollableNode.clientHeight * .5; - for(var i in $scope.content.tabs) { - var group = $scope.content.tabs[i]; + for(var i in $scope.variant.tabs) { + var group = $scope.variant.tabs[i]; var node = propertyGroupNodesDictionary[group.id]; if (viewFocusY >= node.offsetTop && viewFocusY <= node.offsetTop + node.clientHeight) { setActiveAnchor(group); @@ -32,18 +32,18 @@ function setActiveAnchor(tab) { if (tab.active !== true) { - var i = $scope.content.tabs.length; + var i = $scope.variant.tabs.length; while(i--) { - $scope.content.tabs[i].active = false; + $scope.variant.tabs[i].active = false; } tab.active = true; } } function getActiveAnchor() { - var i = $scope.content.tabs.length; + var i = $scope.variant.tabs.length; while(i--) { - if ($scope.content.tabs[i].active === true) - return $scope.content.tabs[i]; + if ($scope.variant.tabs[i].active === true) + return $scope.variant.tabs[i]; } return false; } @@ -120,14 +120,11 @@ //expose the property/methods for other directives to use this.content = $scope.content; - this.activeVariant = _.find(this.content.variants, variant => { - return variant.active; - }); - - $scope.activeVariant = this.activeVariant; + console.log($scope) + console.log(this.content); $scope.defaultVariant = _.find(this.content.variants, variant => { - return variant.language.isDefault; + return variant.language && variant.language.isDefault; }); $scope.unlockInvariantValue = function(property) { @@ -137,7 +134,7 @@ $scope.$watch("tabbedContentForm.$dirty", function (newValue, oldValue) { if (newValue === true) { - $scope.content.isDirty = true; + $scope.variant.isDirty = true; } } ); @@ -150,7 +147,8 @@ controller: controller, link: link, scope: { - content: "=" + content: "=", + variant: "=" } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js index 24bcefa6b8..3c7ffa2a54 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontent.directive.js @@ -7,9 +7,9 @@ var umbVariantContent = { templateUrl: 'views/components/content/umb-variant-content.html', bindings: { - content: "<", - page: "<", - editor: "<", + content: "=", + page: "=", + editor: "=", editorIndex: "<", editorCount: "<", onCloseSplitView: "&", @@ -24,7 +24,7 @@ controller: umbVariantContentController }; - function umbVariantContentController($scope, $element, $location) { + function umbVariantContentController($scope) { var unsubscribe = []; @@ -43,7 +43,7 @@ function onInit() { // disable the name field if the active content app is not "Content" vm.nameDisabled = false; - angular.forEach(vm.editor.content.apps, function(app){ + angular.forEach(vm.content.apps, function(app){ if(app.active && app.alias !== "umbContent" && app.alias !== "umbInfo" && app.alias !== "umbListView") { vm.nameDisabled = true; } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js index 17bf716e39..b47c95f207 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbvariantcontenteditors.directive.js @@ -8,7 +8,7 @@ templateUrl: 'views/components/content/umb-variant-content-editors.html', bindings: { page: "<", - content: "<", // TODO: Not sure if this should be = since we are changing the 'active' property of a variant + content: "=", // TODO: Not sure if this should be = since we are changing the 'active' property of a variant culture: "<", segment: "<", onSelectApp: "&?", @@ -47,6 +47,9 @@ /** Called when the component initializes */ function onInit() { prevContentDateUpdated = angular.copy(vm.content.updateDate); + _.each(vm.content.variants, function (v) { + v.active = false;// needs to be set before used for it to be re-active. + }); setActiveVariant(); } @@ -95,21 +98,14 @@ && (v.segment === vm.segment) ) { - v.active = true; activeVariant = v; } - else { - v.active = false; - } }); if (!activeVariant) { - // Set the first variant to active if we can't find it. - // If the content item is invariant, then only one item exists in the array. - vm.content.variants[0].active = true; activeVariant = vm.content.variants[0]; } - insertVariantEditor(0, initVariant(activeVariant, 0)); + insertVariantEditor(0, activeVariant); if (vm.editors.length > 1) { //now re-sync any other editor content (i.e. if split view is open) @@ -118,7 +114,7 @@ var variant = _.find(vm.content.variants, function (v) { return (!v.language || v.language.culture === vm.editors[s].content.language.culture) && v.segment === vm.editors[s].content.segment; }); - vm.editors[s].content = initVariant(variant, s); + vm.editors[s].content = variant; } } @@ -131,6 +127,10 @@ */ function insertVariantEditor(index, variant) { + if (vm.editors[index]) { + vm.editors[index].content.active = false; + } + variant.active = true; var variantCulture = variant.language ? variant.language.culture : "invariant"; var variantSegment = variant.segment; @@ -140,6 +140,7 @@ //check if the segment at the index is the same, if it's null an editor will be added var currentSegment = vm.editors.length === 0 || vm.editors.length <= index ? null : vm.editors[index].segment; + if (currentCulture !== variantCulture || currentSegment !== variantSegment) { //Not the current culture which means we need to modify the array. @@ -157,151 +158,30 @@ vm.editors[index].content = variant; } } - - function initVariant(variant, editorIndex) { - - //The model that is assigned to the editor contains the current content variant along - //with a copy of the contentApps. This is required because each editor renders it's own - //header and content apps section and the content apps contains the view for editing content itself - //and we need to assign a view model to the subView so that it is scoped to the current - //editor so that split views work. - - //copy the apps from the main model if not assigned yet to the variant - if (!variant.apps) { - variant.apps = angular.copy(vm.content.apps); - } - - //if this is a variant it has a culture/language or segment than we need to assign the variant drop down - if (variant.language || variant.segment !== null) { - //if the variant list that defines the header drop down isn't assigned to the variant then assign it now - if (!variant.variants) { - variant.variants = _.map(vm.content.variants, - function (v) { - return _.pick(v, "active", "language", "segment", "state"); - }); - } - else { - //merge the scope variants on top of the header variants collection (handy when needing to refresh) - angular.extend(variant.variants, - _.map(vm.content.variants, - function (v) { - return _.pick(v, "active", "language", "segment", "state"); - })); - } - - //ensure the current culture is set as the active one - for (var i = 0; i < variant.variants.length; i++) { - if ( - (!variant.variants[i].language || variant.variants[i].language.culture === variant.language.culture) - && - variant.variants[i].segment === variant.segment - ) { - variant.variants[i].active = true; - } - else { - variant.variants[i].active = false; - } - } - - /* - //SEGMENTS_TODO: Remove this part if not used. - var variantId = variantHelper.getId(variant); - // keep track of the open variants across the different split views - // push the first variant then update the variant index based on the editor index - if (vm.openVariants && vm.openVariants.length === 0) { - vm.openVariants.push(variantId); - } else { - vm.openVariants[editorIndex] = variantId; - } - */ - } - - //then assign the variant to a view model to the content app - var contentApp = _.find(variant.apps, function (a) { - return a.alias === "umbContent"; - }); - - if (contentApp) { - //The view model for the content app is simply the index of the variant being edited - var variantIndex = vm.content.variants.indexOf(variant); - contentApp.viewModel = variantIndex; - } - - // make sure the same app it set to active in the new variant - if(activeAppAlias) { - angular.forEach(variant.apps, function(app) { - app.active = false; - if(app.alias === activeAppAlias) { - app.active = true; - } - }); - } - - return variant; - } - function getCultureFromVariant(variant) { - return variant.language ? variant.language.culture : null; - } /** * Adds a new editor to the editors array to show content in a split view * @param {any} selectedVariant */ function openSplitView(selectedVariant) { - //Find the whole variant model based on the culture that was chosen - var variant = _.find(vm.content.variants, function (v) { - return getCultureFromVariant(v) === getCultureFromVariant(selectedVariant) && v.segment === selectedVariant.segment; - }); - - insertVariantEditor(vm.editors.length, initVariant(variant, vm.editors.length)); - - //only the content app can be selected since no other apps are shown, and because we copy all of these apps - //to the "editors" we need to update this across all editors - for (var e = 0; e < vm.editors.length; e++) { - var editor = vm.editors[e]; - for (var i = 0; i < editor.content.apps.length; i++) { - var app = editor.content.apps[i]; - if (app.alias === "umbContent") { - app.active = true; - // tell the world that the app has changed (but do it only once) - if (e === 0) { - selectApp(app); - } - } - else { - app.active = false; - } - } - } - - // TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular - editor.collapsed = true; - editor.loading = true; - $timeout(function () { - editor.collapsed = false; - editor.loading = false; - splitViewChanged(); - }, 100); + insertVariantEditor(vm.editors.length, selectedVariant); + + splitViewChanged(); + } /** Closes the split view */ function closeSplitView(editorIndex) { // TODO: hacking animation states - these should hopefully be easier to do when we upgrade angular var editor = vm.editors[editorIndex]; - editor.loading = true; - editor.collapsed = true; - $timeout(function () { - vm.editors.splice(editorIndex, 1); - //remove variant from open variants - - // SEGMENTS_TODO: Test this scenario. - - //update the current culture to reflect the last open variant (closing the split view corresponds to selecting the other variant) - //$location.search({"cculture": vm.openVariants[0].language, "csegment": vm.openVariants[0]}); - $location.search({"cculture": vm.editors[0].content.language ? vm.editors[0].content.language.culture : null, "csegment": vm.editors[0].content.segment}); - splitViewChanged(); - }, 400); + vm.editors.splice(editorIndex, 1); + editor.content.active = false; + + //update the current culture to reflect the last open variant (closing the split view corresponds to selecting the other variant) + + $location.search({"cculture": vm.editors[0].content.language ? vm.editors[0].content.language.culture : null, "csegment": vm.editors[0].content.segment}); + splitViewChanged(); } /** @@ -314,6 +194,7 @@ var variantCulture = variant.language ? variant.language.culture : "invariant"; var variantSegment = variant.segment || null; + // Check if we already have this editor open, if so, do nothing. if (vm.editors.find((editor) => (!editor.content.language || editor.content.language.culture === variantCulture) && editor.content.segment === variantSegment)) { return; } @@ -327,25 +208,8 @@ } else { - //Update the 'active' variant for this editor - var editor = vm.editors[editorIndex]; - //set all variant drop down items as inactive for this editor and then set the selected one as active - for (var i = 0; i < editor.content.variants.length; i++) { - editor.content.variants[i].active = false; - } - variant.active = true; - - - //get the variant content model and initialize the editor with that - var contentVariant = _.find(vm.content.variants, - function (v) { - return (!v.language || v.language.culture === variantCulture) && v.segment === variantSegment; - }); - editor.content = initVariant(contentVariant, editorIndex); - - //update the editors collection - insertVariantEditor(editorIndex, contentVariant); + insertVariantEditor(editorIndex, variant); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorcontentheader.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorcontentheader.directive.js index c52e309580..cbc090c821 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorcontentheader.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditorcontentheader.directive.js @@ -5,6 +5,9 @@ function link(scope) { + console.log("scope.content", scope.content); + console.log("scope.content.variants", scope.content.variants); + var unsubscribe = []; if (!scope.serverValidationNameField) { @@ -14,7 +17,7 @@ scope.serverValidationAliasField = "Alias"; } - scope.isNew = scope.content.state == "NotCreated"; + scope.isNew = scope.editorContent.state == "NotCreated"; localizationService.localizeMany([ scope.isNew ? "placeholders_a11yCreateItem" : "placeholders_a11yEdit", @@ -23,7 +26,7 @@ scope.a11yMessage = data[0]; scope.a11yName = data[1]; if (!scope.isNew) { - scope.a11yMessage += " " + scope.content.name; + scope.a11yMessage += " " + scope.editorContent.name; } else { var name = editorState.current.contentTypeName; @@ -32,8 +35,8 @@ } }); scope.vm = {}; + scope.vm.hasVariants = false; scope.vm.dropdownOpen = false; - scope.vm.currentVariant = ""; scope.vm.variantsWithError = []; scope.vm.defaultVariant = null; @@ -42,7 +45,6 @@ function checkErrorsOnOtherVariants() { var check = false; angular.forEach(scope.content.variants, function (variant) { - // SEGMENTS_TODO: Check that this correction is okay, can we even see the active var here? if (variant.active !== true && scope.variantHasError(variant)) { check = true; } @@ -51,7 +53,6 @@ } function onVariantValidation(valid, errors, allErrors, culture, segment) { - // SEGMENTS_TODO: See wether we can use errors, allErrors? var index = scope.vm.variantsWithError.findIndex((item) => item.culture === culture && item.segment === segment) if(valid === true) { if (index !== -1) { @@ -67,14 +68,17 @@ function onInit() { - // find default. + // find default + check if we have variants. angular.forEach(scope.content.variants, function (variant) { if (variant.language !== null && variant.language.isDefault) { scope.vm.defaultVariant = variant; } + if (variant.language !== null || variant.segment !== null) { + scope.vm.hasVariants = true; + } }); - setCurrentVariant(); + checkErrorsOnOtherVariants(); angular.forEach(scope.content.apps, (app) => { if (app.alias === "umbContent") { @@ -93,15 +97,6 @@ } - function setCurrentVariant() { - angular.forEach(scope.content.variants, function (variant) { - if (variant.active) { - scope.vm.currentVariant = variant; - checkErrorsOnOtherVariants(); - } - }); - } - function getCultureFromVariant(variant) { return variant.language ? variant.language.culture : null; } @@ -146,40 +141,28 @@ scope.onOpenInSplitView({ "variant": variant }); } }; - - /** - * keep track of open variants - this is used to prevent the same variant to be open in more than one split view - * @param {any} variant - */ - scope.variantIsOpen = function (variant) { - - // SEGMENTS_TODO: ... does this work? - if (scope.content.variants.find((v) => variant.active === true && (getCultureFromVariant(v) === getCultureFromVariant(variant)) && variant.segment === variant.segment)) { - console.log("VARIANT IS OPEN") - return; - } - console.log("VARIANT IS closed", scope.content.variants) - } /** * Check whether a variant has a error, used to display errors in variant switcher. * @param {any} culture */ scope.variantHasError = function(variant) { - // if we are looking for the default language we also want to check for invariant. - if (variant.language.culture === scope.vm.defaultVariant.language.culture && variant.segment === null) { - if(scope.vm.variantsWithError.find((item) => item.culture === "invariant" && item.segment === null) !== undefined) { - return true; + if(variant.language) { + // if we are looking for the variant with default language then we also want to check for invariant variant. + if (variant.language.culture === scope.vm.defaultVariant.language.culture && variant.segment === null) { + if(scope.vm.variantsWithError.find((item) => item.culture === "invariant" && item.segment === null) !== undefined) { + return true; + } } } - if(scope.vm.variantsWithError.find((item) => item.culture === variant.language.culture && item.segment === variant.segment) !== undefined) { + if(scope.vm.variantsWithError.find((item) => (!variant.language || item.culture === variant.language.culture) && item.segment === variant.segment) !== undefined) { return true; } return false; } onInit(); - + /* //watch for the active culture changing, if it changes, update the current variant if (scope.content.variants) { scope.$watch(function () { @@ -196,7 +179,7 @@ } }); } - + */ scope.$on('$destroy', function () { for (var u in unsubscribe) { unsubscribe[u](); @@ -216,6 +199,7 @@ menu: "=", hideActionsMenu: " - +
- @@ -79,7 +79,7 @@
- {{ item.comment }} - +
@@ -126,7 +126,7 @@
- + diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html index 8d7bdad873..85ba05ee16 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-tabbed-content.html @@ -1,6 +1,6 @@ 
-
+
{{ group.label }}
@@ -11,13 +11,13 @@ data-element="property-{{property.alias}}" ng-repeat="property in group.properties track by property.alias" property="property" - show-inherit="content.variants.length > 1 && ((!activeVariant.language.isDefault && !property.culture) || (activeVariant.segment && !property.segment)) && !property.unlockInvariantValue" + show-inherit="content.variants.length > 1 && ((!variant.language.isDefault && !property.culture) || (variant.segment && !property.segment)) && !property.unlockInvariantValue" inherits-from="defaultVariant.language.name"> -
+
+ preview="content.variants.length > 1 && ((!variant.language.isDefault && !property.culture) || (variant.segment && !property.segment)) && !property.unlockInvariantValue">
@@ -27,7 +27,7 @@
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content-editors.html b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content-editors.html index 45517d4f70..61860f1855 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content-editors.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/content/umb-variant-content-editors.html @@ -1,7 +1,6 @@ 
+ ng-repeat="editor in vm.editors track by editor.culture+'.'+editor.segment"> - + - +
@@ -33,14 +34,14 @@
-
- +
+
diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html index 7c871de069..d06ca697cb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-content-header.html @@ -39,25 +39,25 @@ autocomplete="off" maxlength="255" /> - - + - - + + - - +
Open in split view
diff --git a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js index 572a083cbe..00eca43059 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.controller.js @@ -16,17 +16,16 @@ vm.loading = true; function onInit() { - //get the variant by index (see notes above) - vm.content = $scope.content.variants[$scope.model.viewModel]; + serverValidationManager.notify(); vm.loading = false; timeout = null;// ensure timeout is set to null, so we know that its not running anymore. //if this variant has a culture/language assigned, then we need to watch it since it will change //if the language drop down changes and we need to re-init - if (vm.content.language) { + if ($scope.variant.language) { unbindLanguageWatcher = $scope.$watch(function () { - return vm.content.language.culture; + return $scope.variant.language.culture; }, function (newVal, oldVal) { if (newVal !== oldVal) { requestUpdate(); @@ -37,7 +36,7 @@ } unbindSegmentWatcher = $scope.$watch(function () { - return vm.content.segment; + return $scope.variant.segment; }, function (newVal, oldVal) { if (newVal !== oldVal) { requestUpdate(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html index d391f2cd95..d49b78b8a4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/apps/content/content.html @@ -2,7 +2,8 @@ + variant="variant" + content="content"> - +