From 05e8cfa9f456435cf5f1fca150e131e4f18440ee Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 11 Aug 2021 09:54:19 +0200 Subject: [PATCH] Add dropzone to convert a group to a tab --- .../components/umbgroupsbuilder.directive.js | 79 ++++++++++++++----- .../directives/util/umbDroppable.directive.js | 10 ++- .../less/components/umb-group-builder.less | 20 +++++ .../views/components/umb-groups-builder.html | 9 ++- .../Umbraco/config/lang/en_us.xml | 1 + 5 files changed, 94 insertions(+), 25 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js index 22b3f17a9e..fe1ee4c4f0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbgroupsbuilder.directive.js @@ -33,7 +33,14 @@ properties: [] }; - eventBindings.push(scope.$watchCollection('model.groups', newValue => { + let tabsInitialized = false; + + eventBindings.push(scope.$watchCollection('model.groups', (newValue, oldValue) => { + // we only want to run this logic when new groups are added or removed + if (newValue.length === oldValue.length && tabsInitialized) { + tabsInitialized = true; + return; + } contentEditingHelper.defineParentAliasOnGroups(newValue); contentEditingHelper.relocateDisorientedGroups(newValue); @@ -60,6 +67,8 @@ } else if (!scope.openTabAlias && scope.tabs.length > 0) { scope.openTabAlias = scope.tabs[0].alias; } + + tabsInitialized = true; })); function activate() { @@ -110,27 +119,31 @@ handle: ".umb-group-builder__group-handle", items: ".umb-group-builder__group-sortable", stop: (e, ui) => { - const groupKey = ui.item[0].dataset.groupKey ? ui.item[0].dataset.groupKey : false; const group = groupKey ? scope.model.groups.find(group => group.key === groupKey) : {}; - // Update aliases - const parentAlias = scope.openTabAlias, - oldAlias = group.alias || null, // null when group comes from root aka. 'generic' - newAlias = contentEditingHelper.updateParentAlias(oldAlias, parentAlias); + // the code also runs when you convert a group to a tab. + // We want to make sure it only run when groups are reordered + if (group && group.type === TYPE_GROUP) { - // Check alias is unique - // TODO: we should properly do this on hover, to let user know it cant be moved. - if (isAliasUnique(newAlias) === false) { - return; + // Update aliases + const parentAlias = scope.openTabAlias, + oldAlias = group.alias || null, // null when group comes from root aka. 'generic' + newAlias = contentEditingHelper.updateParentAlias(oldAlias, parentAlias); + + // Check alias is unique + // TODO: we should properly do this on hover, to let user know it cant be moved. + if (isAliasUnique(newAlias) === false) { + return; + } + + group.alias = newAlias; + group.parentAlias = parentAlias; + contentEditingHelper.updateDescendingAliases(scope.model.groups, oldAlias, newAlias); + + const groupsInTab = scope.model.groups.filter(group => group.parentAlias === parentAlias); + updateSortOrder(groupsInTab); } - - group.alias = newAlias; - group.parentAlias = parentAlias; - contentEditingHelper.updateDescendingAliases(scope.model.groups, oldAlias, newAlias); - - const groupsInTab = scope.model.groups.filter(group => group.parentAlias === parentAlias); - updateSortOrder(groupsInTab); } }; @@ -148,13 +161,39 @@ } }; + scope.droppableOptionsConvert = { + accept: '.umb-group-builder__group-sortable', + tolerance : 'pointer', + drop: (evt, ui) => { + const groupKey = ui.draggable[0].dataset.groupKey ? ui.draggable[0].dataset.groupKey : false; + const group = groupKey ? scope.model.groups.find(group => group.key === groupKey) : {}; + + if (group) { + scope.convertGroupToTab(group); + } + } + }; + + scope.convertGroupToTab = function (group) { + if (!group) { + return; + } + + group.type = TYPE_TAB; + const newAlias = contentEditingHelper.generateLocalAlias(group.name); + group.alias = createUniqueAlias(newAlias); + group.parentAlias = null; + scope.tabs.push(group); + scope.$broadcast('umbOverflowChecker.checkOverflow'); + scope.$broadcast('umbOverflowChecker.scrollTo', { position: 'end' }); + } + scope.sortableRequestedTabAlias = null; scope.sortableRequestedTabTimeout = null; scope.droppableOptionsTab = { accept: '.umb-group-builder__property-sortable, .umb-group-builder__group-sortable', tolerance : 'pointer', over: (evt, ui) => { - const hoveredTabAlias = evt.target.dataset.tabAlias || null; // if group @@ -339,7 +378,7 @@ } checkGenericTabVisibility(); - + scope.$broadcast('umbOverflowChecker.checkOverflow'); }; scope.openCompositionsDialog = () => { @@ -502,8 +541,8 @@ scope.openTabAlias = tab.alias; - scope.$broadcast('umbOverflowChecker.scrollTo', { position: 'end' }); scope.$broadcast('umbOverflowChecker.checkOverflow'); + scope.$broadcast('umbOverflowChecker.scrollTo', { position: 'end' }); }; scope.removeTab = (tab, indexInTabs) => { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/util/umbDroppable.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/util/umbDroppable.directive.js index a01f20db24..5b4719edc0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/util/umbDroppable.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/util/umbDroppable.directive.js @@ -1,10 +1,12 @@ angular.module("umbraco.directives") - .directive('umbDroppable', function () { + .directive('umbDroppable', function ($timeout) { return { - restrict: 'A', + restrict: 'A', link: function (scope, element, attrs) { - const options = scope.$eval(attrs.umbDroppable) - element.droppable(options); + $timeout(() => { + const options = scope.$eval(attrs.umbDroppable) + element.droppable(options); + }); } } }); diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less index 55df2c6025..55a4c86d7a 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-group-builder.less @@ -927,3 +927,23 @@ input.umb-group-builder__group-sort-value { width: 100%; } } + +// Convert to tab dropzone +.umb-group-builder__convert-dropzone { + display: inline-block; + border: 1px dashed @gray-7; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 2px 15px; + border-radius: @baseBorderRadius; + opacity: 0; + + &.ui-droppable-hover { + border-color: @black; + } + + &.ui-droppable-active { + opacity: 1; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html index 9cf1189cbd..94c8aab85b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-groups-builder.html @@ -3,11 +3,11 @@ -
+
  • +
    + +
    + This will also delete all items below this tab. This will also delete all items below this group. Add tab + Convert to tab Add language