#5294 Full path for DocType on Nested Content configuration (#5430)

This commit is contained in:
Mario Lopez
2019-10-25 01:49:04 +11:00
committed by Sebastiaan Janssen
parent dc54924b52
commit 4bc4b6946e
5 changed files with 4543 additions and 4431 deletions

View File

@@ -234,8 +234,46 @@
margin-left: 10px;
}
.form-horizontal .umb-nested-content--narrow .controls-row
{
.umb-nested-content__placeholder {
height: 22px;
padding: 4px 6px;
border: 1px dashed #d8d7d9;
background: 0 0;
cursor: pointer;
color: #1b264f;
-webkit-animation: fadeIn .5s;
animation: fadeIn .5s;
text-align: center;
&--selected {
border: 1px solid #d8d7d9;
text-align: left;
}
}
.umb-nested-content__placeholder-name{
font-size: 15px;
}
.umb-nested-content__placeholder:hover {
color: #2152a3;
border-color: #2152a3;
text-decoration: none;
}
.umb-nested-content__placeholder-icon-holder {
width: 20px;
text-align: center;
display: inline-block;
}
.umb-nested-content__placeholder-icon {
font-size: 18px;
vertical-align: middle;
}
.form-horizontal .umb-nested-content--narrow .controls-row {
margin-left: 40% !important;
}

View File

@@ -2,8 +2,46 @@
"$scope",
"Umbraco.PropertyEditors.NestedContent.Resources",
"overlayService",
"localizationService",
"iconHelper",
function ($scope, ncResources, overlayService, localizationService, iconHelper) {
var selectElementTypeModalTitle = "";
$scope.elemTypeTabs = [];
init();
function init() {
localizationService.localize("content_nestedContentSelectElementTypeModalTitle").then(function (value) {
selectElementTypeModalTitle = value;
});
ncResources.getContentTypes().then(function (elemTypes) {
$scope.model.elemTypes = elemTypes;
// convert legacy icons
iconHelper.formatContentTypeIcons($scope.model.elemTypes);
// Count doctype name occurrences
var elTypeNameOccurrences= _.countBy(elemTypes, 'name');
// Populate document type tab dictionary
// And append alias to name if multiple doctypes have the same name
elemTypes.forEach(function (value) {
$scope.elemTypeTabs[value.alias] = value.tabs;
if (elTypeNameOccurrences[value.name] > 1) {
value.name += " (" + value.alias + ")";
}
});
});
}
function ($scope, ncResources) {
$scope.add = function () {
$scope.model.value.push({
@@ -57,42 +95,66 @@
}
};
$scope.docTypeTabs = {};
ncResources.getContentTypes().then(function (docTypes) {
$scope.model.docTypes = docTypes;
// Count doctype name occurrences
var docTypeNameOccurrences = _.countBy(docTypes, 'name');
// Populate document type tab dictionary
// And append alias to name if multiple doctypes have the same name
docTypes.forEach(function (value) {
$scope.docTypeTabs[value.alias] = value.tabs;
value.displayName = value.name;
if (docTypeNameOccurrences[value.name] > 1) {
value.displayName += " (" + value.alias + ")";
}
$scope.placeholder = function (config) {
return _.find($scope.model.elemTypes, function (elType) {
return elType.alias === config.ncAlias;
});
});
}
$scope.selectableDocTypesFor = function (config) {
// return all doctypes that are:
$scope.selectableElemTypesFor = function (config) {
// return all elemTypes that are:
// 1. either already selected for this config, or
// 2. not selected in any other config
return _.filter($scope.model.docTypes, function (docType) {
return docType.alias === config.ncAlias || !_.find($scope.model.value, function(c) {
return docType.alias === c.ncAlias;
return _.filter($scope.model.elemTypes, function (elType) {
return elType.alias === config.ncAlias || !_.find($scope.model.value, function (c) {
return elType.alias === c.ncAlias;
});
});
}
$scope.canAdd = function () {
return !$scope.model.value || _.some($scope.model.elemTypes, function (elType) {
return !_.find($scope.model.value, function (c) {
return elType.alias === c.ncAlias;
});
});
}
$scope.openElemTypeModal = function ($event, config) {
//we have to add the alias to the objects (they are stored as ncAlias)
var selectedItems = _.each($scope.model.value, function (obj) {
obj.alias = obj.ncAlias;
return obj;
})
var elemTypeSelectorOverlay = {
view: "itempicker",
title: selectElementTypeModalTitle,
availableItems: $scope.selectableElemTypesFor(config),
selectedItems: selectedItems,
position: "target",
event: $event,
submit: function (model) {
config.ncAlias = model.selectedItem.alias;
overlayService.close();
},
close: function () {
overlayService.close();
}
};
overlayService.open(elemTypeSelectorOverlay);
}
if (!$scope.model.value) {
$scope.model.value = [];
$scope.add();
}
}
]);
@@ -141,7 +203,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
$scope.hasContentTypes = $scope.model.config.contentTypes.length > 0;
$scope.labels = {};
localizationService.localizeMany(["grid_addElement", "content_createEmpty"]).then(function(data) {
localizationService.localizeMany(["grid_addElement", "content_createEmpty"]).then(function (data) {
$scope.labels.grid_addElement = data[0];
$scope.labels.content_createEmpty = data[1];
});
@@ -179,14 +241,14 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
$scope.overlayMenu.show = false;
$scope.overlayMenu = null;
},
submit: function(model) {
if(model && model.selectedItem) {
submit: function (model) {
if (model && model.selectedItem) {
$scope.addNode(model.selectedItem.alias);
}
$scope.overlayMenu.show = false;
$scope.overlayMenu = null;
},
close: function() {
close: function () {
$scope.overlayMenu.show = false;
$scope.overlayMenu = null;
}
@@ -218,22 +280,22 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
icon: iconHelper.convertFromLegacyIcon(node.icon)
});
});
$scope.overlayMenu.title = $scope.overlayMenu.pasteItems.length > 0 ? $scope.labels.grid_addElement : $scope.labels.content_createEmpty;
$scope.overlayMenu.clickClearPaste = function($event) {
$scope.overlayMenu.clickClearPaste = function ($event) {
$event.stopPropagation();
$event.preventDefault();
clipboardService.clearEntriesOfType("elementType", contentTypeAliases);
$scope.overlayMenu.pasteItems = [];// This dialog is not connected via the clipboardService events, so we need to update manually.
};
if ($scope.overlayMenu.availableItems.length === 1 && $scope.overlayMenu.pasteItems.length === 0) {
// only one scaffold type - no need to display the picker
$scope.addNode($scope.scaffolds[0].contentTypeAlias);
return;
}
$scope.overlayMenu.show = true;
};
@@ -324,10 +386,10 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
if ($scope.nodes[idx].name !== name) {
$scope.nodes[idx].name = name;
}
return name;
};
$scope.getIcon = function (idx) {
var scaffold = $scope.getScaffold($scope.model.value[idx].ncContentTypeAlias);
return scaffold && scaffold.icon ? iconHelper.convertFromLegacyIcon(scaffold.icon) : "icon-folder";
@@ -335,7 +397,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
$scope.sortableOptions = {
axis: "y",
cursor: "move",
handle:'.umb-nested-content__header-bar',
handle: '.umb-nested-content__header-bar',
distance: 10,
opacity: 0.7,
tolerance: "pointer",
@@ -377,15 +439,15 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
return contentType.ncAlias === alias;
});
}
$scope.showCopy = clipboardService.isSupported();
$scope.showPaste = false;
$scope.clickCopy = function($event, node) {
$scope.clickCopy = function ($event, node) {
syncCurrentNode();
clipboardService.copy("elementType", node.contentTypeAlias, node);
$event.stopPropagation();
}
@@ -395,27 +457,27 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
if (newNode === undefined) {
return;
}
// generate a new key.
newNode.key = String.CreateGuid();
$scope.nodes.push(newNode);
$scope.setDirty();
//updateModel();// done by setting current node...
$scope.currentNode = newNode;
}
function checkAbilityToPasteContent() {
$scope.showPaste = clipboardService.hasEntriesOfType("elementType", contentTypeAliases);
}
eventsService.on("clipboardService.storageUpdate", checkAbilityToPasteContent);
var notSupported = [
"Umbraco.Tags",
"Umbraco.UploadField",
"Umbraco.ImageCropper"
"Umbraco.Tags",
"Umbraco.UploadField",
"Umbraco.ImageCropper"
];
// Initialize
@@ -495,24 +557,24 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
}
$scope.inited = true;
checkAbilityToPasteContent();
}
}
function createNode(scaffold, fromNcEntry) {
var node = angular.copy(scaffold);
node.key = fromNcEntry && fromNcEntry.key ? fromNcEntry.key : String.CreateGuid();
var variant = node.variants[0];
for (var t = 0; t < variant.tabs.length; t++) {
var tab = variant.tabs[t];
for (var p = 0; p < tab.properties.length; p++) {
var prop = tab.properties[p];
prop.propertyAlias = prop.alias;
prop.alias = $scope.model.alias + "___" + prop.alias;
// Force validation to occur server side as this is the
@@ -522,7 +584,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
mandatory: false,
pattern: ""
};
if (fromNcEntry && fromNcEntry[prop.propertyAlias]) {
prop.value = fromNcEntry[prop.propertyAlias];
}
@@ -533,7 +595,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
return node;
}
function convertNodeIntoNCEntry(node) {
var obj = {
key: node.key,
@@ -551,16 +613,16 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
}
return obj;
}
function syncCurrentNode() {
if ($scope.realCurrentNode) {
$scope.$broadcast("ncSyncVal", { key: $scope.realCurrentNode.key });
}
}
function updateModel() {
syncCurrentNode();
if ($scope.inited) {
var newValues = [];
for (var i = 0; i < $scope.nodes.length; i++) {
@@ -582,7 +644,7 @@ angular.module("umbraco").controller("Umbraco.PropertyEditors.NestedContent.Prop
$scope.$on("$destroy", function () {
unsubscribe();
});
}
]);

View File

@@ -3,7 +3,7 @@
<table class="table table-striped">
<thead>
<tr>
<th/>
<th />
<th>
<localize key="contentTypeEditor_elementType">Element Type</localize>
</th>
@@ -22,14 +22,22 @@
<i class="icon icon-navigation handle"></i>
</td>
<td>
<select id="{{model.alias}}_doctype_select"
ng-options="dt.alias as dt.displayName for dt in selectableDocTypesFor(config) | orderBy: 'name'"
ng-model="config.ncAlias" required></select>
{{ph = placeholder(config);""}}
<div class="umb-nested-content__placeholder" ng-class="{'umb-nested-content__placeholder--selected':ph}" ng-click="openElemTypeModal($event, config)">
<span class="umb-nested-content__placeholder-icon-holder" ng-if="ph">
<i class="umb-nested-content__placeholder-icon {{ ph.icon }}"></i>
</span>
<span class="umb-nested-content__placeholder-name" ng-if="ph">
{{ ph.name }}
</span>
<localize key="content_nestedContentAddElementType" ng-if="!ph">Add element type</localize>
</div>
</td>
<td>
<select id="{{model.alias}}_tab_select"
ng-options="t for t in docTypeTabs[config.ncAlias]"
ng-model="config.ncTabAlias" required></select>
ng-options="t for t in elemTypeTabs[config.ncAlias]"
ng-model="config.ncTabAlias" required></select>
</td>
<td>
<input type="text" ng-model="config.nameTemplate" />
@@ -49,15 +57,15 @@
<i class="icon icon-help-alt medium umb-nested-content__help-icon" ng-click="showHelpText = !showHelpText"></i>
</div>
</div>
<br/>
<br />
<div class="umb-nested-content__help-text" ng-show="showHelpText">
<p>
<b><localize key="general_group">Group</localize>:</b><br/>
<b><localize key="general_group">Group</localize>:</b><br />
Select the group whose properties should be displayed. If left blank, the first group on the element type will be used.
</p>
<p>
<b><localize key="template_template">Template</localize>:</b><br/>
Enter an angular expression to evaluate against each item for its name. Use <code ng-non-bindable>{{$index}}</code> to display the item index
<b><localize key="template_template">Template</localize>:</b><br />
Enter an angular expression to evaluate against each item for its name. Use <code ng-non-bindable>{{$index}}</code> to display the item index
</p>
</div>
</div>