Add dropzone to convert a group to a tab

This commit is contained in:
Mads Rasmussen
2021-08-11 09:54:19 +02:00
parent 99ffbed7a6
commit 05e8cfa9f4
5 changed files with 94 additions and 25 deletions

View File

@@ -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) => {

View File

@@ -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);
});
}
}
});

View File

@@ -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;
}
}

View File

@@ -3,11 +3,11 @@
<umb-editor-sub-header class="umb-group-builder__toolbar" appearance="white">
<umb-editor-sub-header-content-left class="left">
<div class="umb-group-builder__tabs" ng-if="(sortingMode && tabs.length > 0) || (!sortingMode)">
<button ng-show="overflow.left > 0" class="btn-reset umb-group-builder__tabs-overflow umb-group-builder__tabs-overflow--left" ng-click="moveTabsOverflowLeft()">
<span class="caret"></span>
</button>
<ul class="umb-group-builder__tabs-list" ui-sortable="sortableOptionsTab" ng-model="tabs" umb-overflow-checker on-overflow="setTabOverflowState(overflowLeft, overflowRight)">
<li ng-if="hasGenericTab" umb-droppable="droppableOptionsTab" data-tab-alias="{{genericTab.alias}}">
<umb-content-type-tab
@@ -52,6 +52,13 @@
</umb-editor-sub-header-content-left>
<umb-editor-sub-header-content-right class="right">
<div
ng-if="sortingMode"
class="umb-group-builder__convert-dropzone"
umb-droppable="droppableOptionsConvert">
<localize key="contentTypeEditor_convertToTab" />
</div>
<umb-button
style="margin-right: 5px;"
alias="compositions"