Merge remote-tracking branch 'origin/temp8' into temp8-IAction-cleanup
# Conflicts: # src/Umbraco.Tests/Composing/ActionCollectionTests.cs # src/Umbraco.Web/Models/Trees/MenuItem.cs # src/Umbraco.Web/_Legacy/Actions/Action.cs # src/Umbraco.Web/_Legacy/Actions/ActionAssignDomain.cs # src/Umbraco.Web/_Legacy/Actions/ActionBrowse.cs # src/Umbraco.Web/_Legacy/Actions/ActionChangeDocType.cs # src/Umbraco.Web/_Legacy/Actions/ActionCopy.cs # src/Umbraco.Web/_Legacy/Actions/ActionCreateBlueprintFromContent.cs # src/Umbraco.Web/_Legacy/Actions/ActionDelete.cs # src/Umbraco.Web/_Legacy/Actions/ActionEmptyTranscan.cs # src/Umbraco.Web/_Legacy/Actions/ActionExport.cs # src/Umbraco.Web/_Legacy/Actions/ActionImport.cs # src/Umbraco.Web/_Legacy/Actions/ActionMove.cs # src/Umbraco.Web/_Legacy/Actions/ActionNew.cs # src/Umbraco.Web/_Legacy/Actions/ActionNotify.cs # src/Umbraco.Web/_Legacy/Actions/ActionNull.cs # src/Umbraco.Web/_Legacy/Actions/ActionPackage.cs # src/Umbraco.Web/_Legacy/Actions/ActionPackageCreate.cs # src/Umbraco.Web/_Legacy/Actions/ActionProtect.cs # src/Umbraco.Web/_Legacy/Actions/ActionPublish.cs # src/Umbraco.Web/_Legacy/Actions/ActionRePublish.cs # src/Umbraco.Web/_Legacy/Actions/ActionRefresh.cs # src/Umbraco.Web/_Legacy/Actions/ActionRestore.cs # src/Umbraco.Web/_Legacy/Actions/ActionRights.cs # src/Umbraco.Web/_Legacy/Actions/ActionRollback.cs # src/Umbraco.Web/_Legacy/Actions/ActionSort.cs # src/Umbraco.Web/_Legacy/Actions/ActionToPublish.cs # src/Umbraco.Web/_Legacy/Actions/ActionTranslate.cs # src/Umbraco.Web/_Legacy/Actions/ActionUnPublish.cs # src/Umbraco.Web/_Legacy/Actions/ActionUpdate.cs # src/Umbraco.Web/_Legacy/Actions/ContextMenuSeperator.cs # src/Umbraco.Web/_Legacy/Actions/IAction.cs # src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionDeleteRelationType.cs # src/Umbraco.Web/umbraco.presentation/umbraco/developer/RelationTypes/TreeMenu/ActionNewRelationType.cs
This commit is contained in:
@@ -28,11 +28,11 @@ namespace Umbraco.Core.Models
|
||||
/// Initializes a new instance of the <see cref="ContentCultureInfos"/> class.
|
||||
/// </summary>
|
||||
/// <remarks>Used for cloning, without change tracking.</remarks>
|
||||
private ContentCultureInfos(string culture, string name, DateTime date)
|
||||
: this(culture)
|
||||
internal ContentCultureInfos(ContentCultureInfos other)
|
||||
: this(other.Culture)
|
||||
{
|
||||
_name = name;
|
||||
_date = date;
|
||||
_name = other.Name;
|
||||
_date = other.Date;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -61,7 +61,7 @@ namespace Umbraco.Core.Models
|
||||
/// <inheritdoc />
|
||||
public object DeepClone()
|
||||
{
|
||||
return new ContentCultureInfos(Culture, Name, Date);
|
||||
return new ContentCultureInfos(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -24,8 +24,12 @@ namespace Umbraco.Core.Models
|
||||
public ContentCultureInfosCollection(IEnumerable<ContentCultureInfos> items)
|
||||
: base(x => x.Culture, StringComparer.InvariantCultureIgnoreCase)
|
||||
{
|
||||
// make sure to add *copies* and not the original items,
|
||||
// as items can be modified by AddOrUpdate, and therefore
|
||||
// the new collection would be impacted by changes made
|
||||
// to the old collection
|
||||
foreach (var item in items)
|
||||
Add(item);
|
||||
Add(new ContentCultureInfos(item));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -368,6 +368,11 @@ namespace Umbraco.Core.Services
|
||||
/// <para>A publishing document is a document with values that are being published, i.e.
|
||||
/// that have been published or cleared via <see cref="IContent.PublishCulture"/> and
|
||||
/// <see cref="IContent.UnpublishCulture"/>.</para>
|
||||
/// <para>When one needs to publish or unpublish a single culture, or all cultures, using <see cref="SaveAndPublish"/>
|
||||
/// and <see cref="Unpublish"/> is the way to go. But if one needs to, say, publish two cultures and unpublish a third
|
||||
/// one, in one go, then one needs to invoke <see cref="IContent.PublishCulture"/> and <see cref="IContent.UnpublishCulture"/>
|
||||
/// on the content itself - this prepares the content, but does not commit anything - and then, invoke
|
||||
/// <see cref="SavePublishing"/> to actually commit the changes to the database.</para>
|
||||
/// <para>The document is *always* saved, even when publishing fails.</para>
|
||||
/// </remarks>
|
||||
PublishResult SavePublishing(IContent content, int userId = 0, bool raiseEvents = true);
|
||||
@@ -375,11 +380,30 @@ namespace Umbraco.Core.Services
|
||||
/// <summary>
|
||||
/// Saves and publishes a document branch.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Unless specified, all cultures are re-published. Otherwise, one culture can be specified. To act on more
|
||||
/// that one culture, see the other overload of this method.</para>
|
||||
/// <para>The <paramref name="force"/> parameter determines which documents are published. When <c>false</c>,
|
||||
/// only those documents that are already published, are republished. When <c>true</c>, all documents are
|
||||
/// published.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<PublishResult> SaveAndPublishBranch(IContent content, bool force, string culture = "*", int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
/// Saves and publishes a document branch.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The <paramref name="force"/> parameter determines which documents are published. When <c>false</c>,
|
||||
/// only those documents that are already published, are republished. When <c>true</c>, all documents are
|
||||
/// published.</para>
|
||||
/// <para>The <paramref name="editing"/> parameter is a function which determines whether a document has
|
||||
/// values to publish (else there is no need to publish it). If one wants to publish only a selection of
|
||||
/// cultures, one may want to check that only properties for these cultures have changed. Otherwise, other
|
||||
/// cultures may trigger an unwanted republish.</para>
|
||||
/// <para>The <paramref name="publishCultures"/> parameter is a function to execute to publish cultures, on
|
||||
/// each document. It can publish all, one, or a selection of cultures. It returns a boolean indicating
|
||||
/// whether the cultures could be published.</para>
|
||||
/// </remarks>
|
||||
IEnumerable<PublishResult> SaveAndPublishBranch(IContent content, bool force, Func<IContent, bool> editing, Func<IContent, bool> publishCultures, int userId = 0);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1272,12 +1272,49 @@ namespace Umbraco.Core.Services.Implement
|
||||
|
||||
bool IsEditing(IContent c, string l)
|
||||
=> c.PublishName != c.Name ||
|
||||
c.PublishedCultures.Any(x => c.GetCultureName(x) != c.GetPublishName(x)) ||
|
||||
c.Properties.Any(x => x.Values.Where(y => culture == "*" || y.Culture == l).Any(y => !y.EditedValue.Equals(y.PublishedValue)));
|
||||
c.PublishedCultures.Where(x => x.InvariantEquals(l)).Any(x => c.GetCultureName(x) != c.GetPublishName(x)) ||
|
||||
c.Properties.Any(x => x.Values.Where(y => culture == "*" || y.Culture.InvariantEquals(l)).Any(y => !y.EditedValue.Equals(y.PublishedValue)));
|
||||
|
||||
return SaveAndPublishBranch(content, force, document => IsEditing(document, culture), document => document.PublishCulture(culture), userId);
|
||||
}
|
||||
|
||||
// fixme - make this public once we know it works + document
|
||||
private IEnumerable<PublishResult> SaveAndPublishBranch(IContent content, bool force, string[] cultures, int userId = 0)
|
||||
{
|
||||
// note: EditedValue and PublishedValue are objects here, so it is important to .Equals()
|
||||
// and not to == them, else we would be comparing references, and that is a bad thing
|
||||
|
||||
cultures = cultures ?? Array.Empty<string>();
|
||||
|
||||
// determines whether the document is edited, and thus needs to be published,
|
||||
// for the specified cultures (it may be edited for other cultures and that
|
||||
// should not trigger a publish).
|
||||
bool IsEdited(IContent c)
|
||||
{
|
||||
if (cultures.Length == 0)
|
||||
{
|
||||
// nothing = everything
|
||||
return c.PublishName != c.Name ||
|
||||
c.PublishedCultures.Any(x => c.GetCultureName(x) != c.GetPublishName(x)) ||
|
||||
c.Properties.Any(x => x.Values.Any(y => !y.EditedValue.Equals(y.PublishedValue)));
|
||||
}
|
||||
|
||||
return c.PublishName != c.Name ||
|
||||
c.PublishedCultures.Where(x => cultures.Contains(x, StringComparer.InvariantCultureIgnoreCase)).Any(x => c.GetCultureName(x) != c.GetPublishName(x)) ||
|
||||
c.Properties.Any(x => x.Values.Where(y => cultures.Contains(y.Culture, StringComparer.InvariantCultureIgnoreCase)).Any(y => !y.EditedValue.Equals(y.PublishedValue)));
|
||||
}
|
||||
|
||||
// publish the specified cultures
|
||||
bool PublishCultures(IContent c)
|
||||
{
|
||||
return cultures.Length == 0
|
||||
? c.PublishCulture() // nothing = everything
|
||||
: cultures.All(c.PublishCulture);
|
||||
}
|
||||
|
||||
return SaveAndPublishBranch(content, force, IsEdited, PublishCultures, userId);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IEnumerable<PublishResult> SaveAndPublishBranch(IContent document, bool force,
|
||||
Func<IContent, bool> editing, Func<IContent, bool> publishCultures, int userId = 0)
|
||||
|
||||
@@ -203,7 +203,14 @@ namespace Umbraco.Tests.Persistence
|
||||
Assert.IsNotNull(e1);
|
||||
Assert.IsInstanceOf<SqlCeLockTimeoutException>(e1);
|
||||
|
||||
Assert.IsNull(e2);
|
||||
// the assertion below depends on timing conditions - on a fast enough environment,
|
||||
// thread1 dies (deadlock) and frees thread2, which succeeds - however on a slow
|
||||
// environment (CI) both threads can end up dying due to deadlock - so, cannot test
|
||||
// that e2 is null - but if it's not, can test that it's a timeout
|
||||
//
|
||||
//Assert.IsNull(e2);
|
||||
if (e2 != null)
|
||||
Assert.IsInstanceOf<SqlCeLockTimeoutException>(e2);
|
||||
}
|
||||
|
||||
private void DeadLockTestThread(int id1, int id2, EventWaitHandle myEv, WaitHandle otherEv, ref Exception exception)
|
||||
|
||||
+12
@@ -13,6 +13,18 @@
|
||||
//expose the property/methods for other directives to use
|
||||
this.content = $scope.content;
|
||||
|
||||
$scope.activeVariant = _.find(this.content.variants, variant => {
|
||||
return variant.active;
|
||||
});
|
||||
|
||||
$scope.defaultVariant = _.find(this.content.variants, variant => {
|
||||
return variant.language.isDefault;
|
||||
});
|
||||
|
||||
$scope.unlockInvariantValue = function(property) {
|
||||
property.unlockInvariantValue = !property.unlockInvariantValue;
|
||||
};
|
||||
|
||||
$scope.$watch("tabbedContentForm.$dirty",
|
||||
function (newValue, oldValue) {
|
||||
if (newValue === true) {
|
||||
|
||||
+3
-1
@@ -7,7 +7,9 @@ angular.module("umbraco.directives")
|
||||
.directive('umbProperty', function (umbPropEditorHelper, userService) {
|
||||
return {
|
||||
scope: {
|
||||
property: "="
|
||||
property: "=",
|
||||
showInherit: "<",
|
||||
inheritsFrom: "<"
|
||||
},
|
||||
transclude: true,
|
||||
restrict: 'E',
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ function umbPropEditor(umbPropEditorHelper) {
|
||||
scope: {
|
||||
model: "=",
|
||||
isPreValue: "@",
|
||||
preview: "@"
|
||||
preview: "<"
|
||||
},
|
||||
|
||||
require: "^^form",
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
angular.module("umbraco.directives")
|
||||
.directive('disableTabindex', function (tabbableService) {
|
||||
|
||||
return {
|
||||
restrict: 'A', //Can only be used as an attribute,
|
||||
scope: {
|
||||
"disableTabindex": "<"
|
||||
},
|
||||
link: function (scope, element, attrs) {
|
||||
|
||||
if(scope.disableTabindex) {
|
||||
//Select the node that will be observed for mutations (native DOM element not jQLite version)
|
||||
var targetNode = element[0];
|
||||
|
||||
//Watch for DOM changes - so when the property editor subview loads in
|
||||
//We can be notified its updated the child elements inside the DIV we are watching
|
||||
var observer = new MutationObserver(domChange);
|
||||
|
||||
// Options for the observer (which mutations to observe)
|
||||
var config = { attributes: true, childList: true, subtree: false };
|
||||
|
||||
function domChange(mutationsList, observer){
|
||||
for(var mutation of mutationsList) {
|
||||
|
||||
//DOM items have been added or removed
|
||||
if (mutation.type == 'childList') {
|
||||
|
||||
//Check if any child items in mutation.target contain an input
|
||||
var childInputs = tabbableService.tabbable(mutation.target);
|
||||
|
||||
//For each item in childInputs - override or set HTML attribute tabindex="-1"
|
||||
angular.forEach(childInputs, function(element){
|
||||
angular.element(element).attr('tabindex', '-1');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Start observing the target node for configured mutations
|
||||
//GO GO GO
|
||||
observer.observe(targetNode, config);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -0,0 +1,223 @@
|
||||
//tabbable JS Lib (Wrapped in angular service)
|
||||
//https://github.com/davidtheclark/tabbable
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
function tabbableService() {
|
||||
|
||||
var candidateSelectors = [
|
||||
'input',
|
||||
'select',
|
||||
'textarea',
|
||||
'a[href]',
|
||||
'button',
|
||||
'[tabindex]',
|
||||
'audio[controls]',
|
||||
'video[controls]',
|
||||
'[contenteditable]:not([contenteditable="false"])'
|
||||
];
|
||||
var candidateSelector = candidateSelectors.join(',');
|
||||
|
||||
var matches = typeof Element === 'undefined'
|
||||
? function () {}
|
||||
: Element.prototype.matches || Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
|
||||
|
||||
function tabbable(el, options) {
|
||||
options = options || {};
|
||||
|
||||
var elementDocument = el.ownerDocument || el;
|
||||
var regularTabbables = [];
|
||||
var orderedTabbables = [];
|
||||
|
||||
var untouchabilityChecker = new UntouchabilityChecker(elementDocument);
|
||||
var candidates = el.querySelectorAll(candidateSelector);
|
||||
|
||||
if (options.includeContainer) {
|
||||
if (matches.call(el, candidateSelector)) {
|
||||
candidates = Array.prototype.slice.apply(candidates);
|
||||
candidates.unshift(el);
|
||||
}
|
||||
}
|
||||
|
||||
var i, candidate, candidateTabindex;
|
||||
for (i = 0; i < candidates.length; i++) {
|
||||
candidate = candidates[i];
|
||||
|
||||
if (!isNodeMatchingSelectorTabbable(candidate, untouchabilityChecker)) continue;
|
||||
|
||||
candidateTabindex = getTabindex(candidate);
|
||||
if (candidateTabindex === 0) {
|
||||
regularTabbables.push(candidate);
|
||||
} else {
|
||||
orderedTabbables.push({
|
||||
documentOrder: i,
|
||||
tabIndex: candidateTabindex,
|
||||
node: candidate
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var tabbableNodes = orderedTabbables
|
||||
.sort(sortOrderedTabbables)
|
||||
.map(function(a) { return a.node })
|
||||
.concat(regularTabbables);
|
||||
|
||||
return tabbableNodes;
|
||||
}
|
||||
|
||||
tabbable.isTabbable = isTabbable;
|
||||
tabbable.isFocusable = isFocusable;
|
||||
|
||||
function isNodeMatchingSelectorTabbable(node, untouchabilityChecker) {
|
||||
if (
|
||||
!isNodeMatchingSelectorFocusable(node, untouchabilityChecker)
|
||||
|| isNonTabbableRadio(node)
|
||||
|| getTabindex(node) < 0
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isTabbable(node, untouchabilityChecker) {
|
||||
if (!node) throw new Error('No node provided');
|
||||
if (matches.call(node, candidateSelector) === false) return false;
|
||||
return isNodeMatchingSelectorTabbable(node, untouchabilityChecker);
|
||||
}
|
||||
|
||||
function isNodeMatchingSelectorFocusable(node, untouchabilityChecker) {
|
||||
untouchabilityChecker = untouchabilityChecker || new UntouchabilityChecker(node.ownerDocument || node);
|
||||
if (
|
||||
node.disabled
|
||||
|| isHiddenInput(node)
|
||||
|| untouchabilityChecker.isUntouchable(node)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var focusableCandidateSelector = candidateSelectors.concat('iframe').join(',');
|
||||
function isFocusable(node, untouchabilityChecker) {
|
||||
if (!node) throw new Error('No node provided');
|
||||
if (matches.call(node, focusableCandidateSelector) === false) return false;
|
||||
return isNodeMatchingSelectorFocusable(node, untouchabilityChecker);
|
||||
}
|
||||
|
||||
function getTabindex(node) {
|
||||
var tabindexAttr = parseInt(node.getAttribute('tabindex'), 10);
|
||||
if (!isNaN(tabindexAttr)) return tabindexAttr;
|
||||
// Browsers do not return `tabIndex` correctly for contentEditable nodes;
|
||||
// so if they don't have a tabindex attribute specifically set, assume it's 0.
|
||||
if (isContentEditable(node)) return 0;
|
||||
return node.tabIndex;
|
||||
}
|
||||
|
||||
function sortOrderedTabbables(a, b) {
|
||||
return a.tabIndex === b.tabIndex ? a.documentOrder - b.documentOrder : a.tabIndex - b.tabIndex;
|
||||
}
|
||||
|
||||
// Array.prototype.find not available in IE.
|
||||
function find(list, predicate) {
|
||||
for (var i = 0, length = list.length; i < length; i++) {
|
||||
if (predicate(list[i])) return list[i];
|
||||
}
|
||||
}
|
||||
|
||||
function isContentEditable(node) {
|
||||
return node.contentEditable === 'true';
|
||||
}
|
||||
|
||||
function isInput(node) {
|
||||
return node.tagName === 'INPUT';
|
||||
}
|
||||
|
||||
function isHiddenInput(node) {
|
||||
return isInput(node) && node.type === 'hidden';
|
||||
}
|
||||
|
||||
function isRadio(node) {
|
||||
return isInput(node) && node.type === 'radio';
|
||||
}
|
||||
|
||||
function isNonTabbableRadio(node) {
|
||||
return isRadio(node) && !isTabbableRadio(node);
|
||||
}
|
||||
|
||||
function getCheckedRadio(nodes) {
|
||||
for (var i = 0; i < nodes.length; i++) {
|
||||
if (nodes[i].checked) {
|
||||
return nodes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isTabbableRadio(node) {
|
||||
if (!node.name) return true;
|
||||
// This won't account for the edge case where you have radio groups with the same
|
||||
// in separate forms on the same page.
|
||||
var radioSet = node.ownerDocument.querySelectorAll('input[type="radio"][name="' + node.name + '"]');
|
||||
var checked = getCheckedRadio(radioSet);
|
||||
return !checked || checked === node;
|
||||
}
|
||||
|
||||
// An element is "untouchable" if *it or one of its ancestors* has
|
||||
// `visibility: hidden` or `display: none`.
|
||||
function UntouchabilityChecker(elementDocument) {
|
||||
this.doc = elementDocument;
|
||||
// Node cache must be refreshed on every check, in case
|
||||
// the content of the element has changed. The cache contains tuples
|
||||
// mapping nodes to their boolean result.
|
||||
this.cache = [];
|
||||
}
|
||||
|
||||
// getComputedStyle accurately reflects `visibility: hidden` of ancestors
|
||||
// but not `display: none`, so we need to recursively check parents.
|
||||
UntouchabilityChecker.prototype.hasDisplayNone = function hasDisplayNone(node, nodeComputedStyle) {
|
||||
if (node === this.doc.documentElement) return false;
|
||||
|
||||
// Search for a cached result.
|
||||
var cached = find(this.cache, function(item) {
|
||||
return item === node;
|
||||
});
|
||||
if (cached) return cached[1];
|
||||
|
||||
nodeComputedStyle = nodeComputedStyle || this.doc.defaultView.getComputedStyle(node);
|
||||
|
||||
var result = false;
|
||||
|
||||
if (nodeComputedStyle.display === 'none') {
|
||||
result = true;
|
||||
} else if (node.parentNode) {
|
||||
result = this.hasDisplayNone(node.parentNode);
|
||||
}
|
||||
|
||||
this.cache.push([node, result]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
UntouchabilityChecker.prototype.isUntouchable = function isUntouchable(node) {
|
||||
if (node === this.doc.documentElement) return false;
|
||||
var computedStyle = this.doc.defaultView.getComputedStyle(node);
|
||||
if (this.hasDisplayNone(node, computedStyle)) return true;
|
||||
return computedStyle.visibility === 'hidden';
|
||||
}
|
||||
|
||||
//module.exports = tabbable;
|
||||
|
||||
////////////
|
||||
|
||||
var service = {
|
||||
tabbable: tabbable,
|
||||
isTabbable: isTabbable,
|
||||
isFocusable: isFocusable
|
||||
};
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
angular.module('umbraco.services').factory('tabbableService', tabbableService);
|
||||
|
||||
})();
|
||||
@@ -194,7 +194,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
|
||||
$rootScope.emptySection = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}));
|
||||
|
||||
//Listen for section state changes
|
||||
@@ -222,10 +222,21 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar
|
||||
});
|
||||
}));
|
||||
|
||||
evts.push(eventsService.on("editors.languages.languageCreated", function (e, args) {
|
||||
loadLanguages().then(function (languages) {
|
||||
$scope.languages = languages;
|
||||
});
|
||||
//Emitted when a language is created or an existing one saved/edited
|
||||
evts.push(eventsService.on("editors.languages.languageSaved", function (e, args) {
|
||||
console.log('lang event listen args', args);
|
||||
if(args.isNew){
|
||||
//A new language has been created - reload languages for tree
|
||||
loadLanguages().then(function (languages) {
|
||||
$scope.languages = languages;
|
||||
});
|
||||
}
|
||||
else if(args.language.isDefault){
|
||||
//A language was saved and was set to be the new default (refresh the tree, so its at the top)
|
||||
loadLanguages().then(function (languages) {
|
||||
$scope.languages = languages;
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
//This reacts to clicks passed to the body element which emits a global call to close all dialogs
|
||||
|
||||
@@ -170,6 +170,7 @@
|
||||
|
||||
// Utilities
|
||||
@import "utilities/layout/_display.less";
|
||||
@import "utilities/theme/_opacity.less";
|
||||
@import "utilities/typography/_text-decoration.less";
|
||||
@import "utilities/typography/_white-space.less";
|
||||
@import "utilities/_flexbox.less";
|
||||
|
||||
@@ -201,7 +201,6 @@ a.umb-variant-switcher__toggle {
|
||||
|
||||
.umb-variant-switcher__name {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.umb-variant-switcher__state {
|
||||
|
||||
@@ -51,6 +51,15 @@
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.umb-action {
|
||||
&.-opens-dialog {
|
||||
.menu-label:after {
|
||||
// adds an ellipsis (...) after the menu label for actions that open a dialog
|
||||
content: '\2026';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.umb-actions-child {
|
||||
|
||||
.umb-action {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
.umb-property-editor.-not-clickable {
|
||||
.umb-property-editor--preview {
|
||||
pointer-events: none;
|
||||
}
|
||||
user-select: none;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
|
||||
Opacity
|
||||
|
||||
*/
|
||||
|
||||
.o-100 { opacity: 1; }
|
||||
.o-90 { opacity: 0.9; }
|
||||
.o-80 { opacity: 0.8; }
|
||||
.o-70 { opacity: 0.7; }
|
||||
.o-60 { opacity: 0.6; }
|
||||
.o-50 { opacity: 0.5; }
|
||||
.o-40 { opacity: 0.4; }
|
||||
.o-30 { opacity: 0.3; }
|
||||
.o-20 { opacity: 0.2; }
|
||||
.o-10 { opacity: 0.1; }
|
||||
.o-05 { opacity: 0.05; }
|
||||
.o-025 { opacity: 0.025; }
|
||||
.o-0 { opacity: 0; }
|
||||
+4
-5
@@ -16,24 +16,23 @@
|
||||
<umb-box-content>
|
||||
<div class="umb-insert-code-boxes">
|
||||
<div ng-if="model.allowedTypes.umbracoField" class="umb-insert-code-box" ng-click="vm.openPageFieldOverlay()">
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertPageField" /></div>
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertPageField" />...</div>
|
||||
<div class="umb-insert-code-box__description"><localize key="template_insertPageFieldDesc" /></div>
|
||||
</div>
|
||||
<div ng-if="model.allowedTypes.partial" class="umb-insert-code-box" ng-click="vm.openPartialOverlay()">
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertPartialView" /></div>
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertPartialView" />...</div>
|
||||
<div class="umb-insert-code-box__description">
|
||||
<localize key="template_insertPartialViewDesc" />
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="model.allowedTypes.macro" class="umb-insert-code-box" ng-click="vm.openMacroPicker()">
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertMacro" /></div>
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertMacro" />...</div>
|
||||
<div class="umb-insert-code-box__description">
|
||||
<localize key="template_insertMacroDesc" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div ng-if="model.allowedTypes.dictionary" class="umb-insert-code-box" ng-click="vm.openDictionaryItemOverlay()">
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertDictionaryItem" /></div>
|
||||
<div class="umb-insert-code-box__title"><localize key="template_insertDictionaryItem" />...</div>
|
||||
<div class="umb-insert-code-box__description"><localize key="template_insertDictionaryItemDesc" /></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<div class='umb-modalcolumn-body'>
|
||||
<ul class="umb-actions">
|
||||
<li data-element="action-{{action.alias}}" ng-click="executeMenuItem(action)" class="umb-action" ng-class="{sep:action.seperator}" ng-repeat="action in menuActions">
|
||||
<li data-element="action-{{action.alias}}" ng-click="executeMenuItem(action)" class="umb-action" ng-class="{sep:action.seperator, '-opens-dialog': action.opensDialog}" ng-repeat="action in menuActions">
|
||||
<a class="umb-action-link" prevent-default>
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
@@ -13,4 +13,4 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<ins class="umb-language-picker__expand" ng-class="{'icon-navigation-down': !page.languageSelectorIsOpen, 'icon-navigation-up': page.languageSelectorIsOpen}" class="icon-navigation-right"> </ins>
|
||||
</div>
|
||||
<div class="umb-language-picker__dropdown" ng-if="page.languageSelectorIsOpen">
|
||||
<a class="umb-language-picker__dropdown-item" ng-class="{'umb-language-picker__dropdown-item--current': language.active}" ng-click="selectLanguage(language)" ng-repeat="language in languages" href="">{{language.name}}</a>
|
||||
<a class="umb-language-picker__dropdown-item" ng-class="{'umb-language-picker__dropdown-item--current': language.active, 'bold': language.isDefault}" ng-click="selectLanguage(language)" ng-repeat="language in languages" href="">{{language.name}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,8 +8,20 @@
|
||||
</div>
|
||||
|
||||
<div class="umb-expansion-panel__content" ng-show="group.open">
|
||||
<umb-property data-element="property-{{property.alias}}" ng-repeat="property in group.properties track by property.alias" property="property">
|
||||
<umb-property-editor model="property"></umb-property-editor>
|
||||
<umb-property
|
||||
data-element="property-{{property.alias}}"
|
||||
ng-repeat="property in group.properties track by property.alias"
|
||||
property="property"
|
||||
show-inherit="content.variants.length > 1 && !property.culture && !activeVariant.language.isDefault"
|
||||
inherits-from="defaultVariant.language.name">
|
||||
|
||||
<div ng-class="{'o-40 cursor-not-allowed': content.variants.length > 1 && !activeVariant.language.isDefault && !property.culture && !property.unlockInvariantValue}">
|
||||
<umb-property-editor
|
||||
model="property"
|
||||
preview="content.variants.length > 1 && !activeVariant.language.isDefault && !property.culture && !property.unlockInvariantValue">
|
||||
</umb-property-editor>
|
||||
</div>
|
||||
|
||||
</umb-property>
|
||||
</div>
|
||||
|
||||
|
||||
+2
-2
@@ -41,7 +41,7 @@
|
||||
<umb-dropdown ng-if="vm.dropdownOpen" style="width: 100%; max-height: 250px; overflow-y: scroll; margin-top: 5px;" on-close="vm.dropdownOpen = false" umb-keyboard-list>
|
||||
<umb-dropdown-item class="umb-variant-switcher__item" ng-class="{'umb-variant-switcher_item--current': variant.active, 'umb-variant-switcher_item--not-allowed': variantIsOpen(variant.language.culture)}" ng-repeat="variant in variants">
|
||||
<a href="" class="umb-variant-switcher__name-wrapper" ng-click="selectVariant($event, variant)" prevent-default>
|
||||
<span class="umb-variant-switcher__name">{{variant.language.name}}</span>
|
||||
<span class="umb-variant-switcher__name" ng-class="{'bold': variant.language.isDefault}">{{variant.language.name}}</span>
|
||||
<umb-variant-state variant="variant" class="umb-variant-switcher__state"></umb-variant-state>
|
||||
</a>
|
||||
<div ng-if="splitViewOpen !== true && !variant.active" class="umb-variant-switcher__split-view" ng-click="openInSplitView($event, variant)">Open in split view</div>
|
||||
@@ -72,7 +72,7 @@
|
||||
<umb-editor-menu
|
||||
data-element="editor-actions"
|
||||
current-node="menu.currentNode"
|
||||
current-section="{{menu.currentSection}}">
|
||||
current-section="{{menu.currentNode.section}}">
|
||||
</umb-editor-menu>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<!-- actions -->
|
||||
<ul class="dropdown-menu umb-actions" role="menu" aria-labelledby="dLabel">
|
||||
<li class="umb-action" ng-class="{sep:action.seperator}" ng-repeat="action in actions">
|
||||
<li class="umb-action" ng-class="{'sep':action.seperatorm, '-opens-dialog': action.opensDialog}" ng-repeat="action in actions">
|
||||
|
||||
<!-- How does this reference executeMenuItem() i really don't think that this is very clear -->
|
||||
<a prevent-default
|
||||
@@ -17,7 +17,6 @@
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<div class="umb-property-editor db" ng-class="{'-not-clickable': preview}">
|
||||
<div ng-include="propertyEditorView"></div>
|
||||
<div class="umb-property-editor db" ng-class="{'umb-property-editor--preview': preview}">
|
||||
<div disable-tabindex="preview">
|
||||
<div ng-include="propertyEditorView"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,13 @@
|
||||
<div class="umb-el-wrap">
|
||||
|
||||
<label class="control-label" ng-hide="property.hideLabel" for="{{property.alias}}" ng-attr-title="{{propertyAlias}}">
|
||||
|
||||
<small ng-if="showInherit" class="db" style="padding-top: 0; margin-bottom: 5px;">
|
||||
<localize key="contentTypeEditor_inheritedFrom"></localize> {{inheritsFrom}}
|
||||
</small>
|
||||
|
||||
{{property.label}}
|
||||
|
||||
<span ng-if="property.validation.mandatory">
|
||||
<strong class="umb-control-required">*</strong>
|
||||
</span>
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
label-key="contentTypeEditor_compositions"
|
||||
icon="icon-merge"
|
||||
action="openCompositionsDialog()"
|
||||
size="xs">
|
||||
size="xs"
|
||||
add-ellipsis="true">
|
||||
</umb-button>
|
||||
|
||||
<umb-button
|
||||
@@ -157,7 +158,7 @@
|
||||
<div class="umb-validation-label" ng-message="valServerField">{{propertyTypeForm.groupName.errorMsg}}</div>
|
||||
<div class="umb-validation-label" ng-message="required"><localize key="contentTypeEditor_requiredLabel"></localize></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="umb-group-builder__property-meta-description">
|
||||
@@ -229,11 +230,11 @@
|
||||
</div>
|
||||
|
||||
<ng-form name="propertyEditorPreviewForm" umb-disable-form-validation>
|
||||
<umb-property-editor
|
||||
ng-if="property.view !== undefined"
|
||||
model="property"
|
||||
preview="true">
|
||||
</umb-property-editor>
|
||||
<umb-property-editor
|
||||
ng-if="property.view !== undefined"
|
||||
model="property"
|
||||
preview="true">
|
||||
</umb-property-editor>
|
||||
</ng-form>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<a href="" class="umb-action-link" ng-click="showCreateFolder()">
|
||||
<i class="large icon icon-folder"></i>
|
||||
<span class="menu-label">
|
||||
<localize key="create_newFolder">New folder</localize>
|
||||
<localize key="create_newFolder">New folder</localize>...
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<a href="" ng-click="showCreateDocTypeCollection()" class="umb-action-link">
|
||||
<i class="large icon icon-thumbnail-list"></i>
|
||||
<span class="menu-label">
|
||||
Document Type Collection
|
||||
Document Type Collection...
|
||||
<!-- <localize key="content_documentType_collection">Document Type Collection</localize>-->
|
||||
</span>
|
||||
</a>
|
||||
@@ -33,7 +33,7 @@
|
||||
<li data-element="action-folder" ng-if="model.allowCreateFolder" class="umb-action">
|
||||
<a href="" ng-click="showCreateFolder()" class="umb-action-link">
|
||||
<i class="large icon icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
<span class="menu-label"><localize key="general_folder"></localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -48,7 +48,8 @@
|
||||
"shortcuts_toggleListView",
|
||||
"shortcuts_toggleAllowAsRoot",
|
||||
"shortcuts_addChildNode",
|
||||
"shortcuts_addTemplate"
|
||||
"shortcuts_addTemplate",
|
||||
"shortcuts_toggleAllowCultureVariants"
|
||||
];
|
||||
|
||||
onInit();
|
||||
@@ -81,6 +82,7 @@
|
||||
vm.labels.allowAsRoot = values[11];
|
||||
vm.labels.addChildNode = values[12];
|
||||
vm.labels.addTemplate = values[13];
|
||||
vm.labels.allowCultureVariants = values[14];
|
||||
|
||||
var buttons = [
|
||||
{
|
||||
@@ -161,6 +163,10 @@
|
||||
{
|
||||
"description": vm.labels.addChildNode,
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }]
|
||||
},
|
||||
{
|
||||
"description": vm.labels.allowCultureVariants,
|
||||
"keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
+12
-2
@@ -23,7 +23,8 @@
|
||||
|
||||
vm.addChild = addChild;
|
||||
vm.removeChild = removeChild;
|
||||
vm.toggle = toggle;
|
||||
vm.toggleAllowAsRoot = toggleAllowAsRoot;
|
||||
vm.toggleAllowCultureVariants = toggleAllowCultureVariants;
|
||||
|
||||
/* ---------- INIT ---------- */
|
||||
|
||||
@@ -86,7 +87,7 @@
|
||||
/**
|
||||
* Toggle the $scope.model.allowAsRoot value to either true or false
|
||||
*/
|
||||
function toggle(){
|
||||
function toggleAllowAsRoot(){
|
||||
if($scope.model.allowAsRoot){
|
||||
$scope.model.allowAsRoot = false;
|
||||
return;
|
||||
@@ -95,6 +96,15 @@
|
||||
$scope.model.allowAsRoot = true;
|
||||
}
|
||||
|
||||
function toggleAllowCultureVariants() {
|
||||
if ($scope.model.allowCultureVariant) {
|
||||
$scope.model.allowCultureVariant = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.model.allowCultureVariant = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.DocumentType.PermissionsController", PermissionsController);
|
||||
|
||||
+22
-22
@@ -10,11 +10,10 @@
|
||||
<small><localize key="contentTypeEditor_allowAsRootDescription" /></small>
|
||||
</div>
|
||||
<div class="sub-view-column-right">
|
||||
<umb-toggle
|
||||
data-element="permissions-allow-as-root"
|
||||
checked="model.allowAsRoot"
|
||||
on-click="vm.toggle()"
|
||||
hotkey="alt+shift+r">
|
||||
<umb-toggle data-element="permissions-allow-as-root"
|
||||
checked="model.allowAsRoot"
|
||||
on-click="vm.toggleAllowAsRoot()"
|
||||
hotkey="alt+shift+r">
|
||||
</umb-toggle>
|
||||
</div>
|
||||
|
||||
@@ -28,14 +27,13 @@
|
||||
</div>
|
||||
|
||||
<div class="sub-view-column-right">
|
||||
<umb-child-selector
|
||||
selected-children="vm.selectedChildren"
|
||||
available-children="vm.contentTypes"
|
||||
parent-name="model.name"
|
||||
parent-icon="model.icon"
|
||||
parent-id="model.id"
|
||||
on-add="vm.addChild"
|
||||
on-remove="vm.removeChild">
|
||||
<umb-child-selector selected-children="vm.selectedChildren"
|
||||
available-children="vm.contentTypes"
|
||||
parent-name="model.name"
|
||||
parent-icon="model.icon"
|
||||
parent-id="model.id"
|
||||
on-add="vm.addChild"
|
||||
on-remove="vm.removeChild">
|
||||
</umb-child-selector>
|
||||
</div>
|
||||
|
||||
@@ -44,18 +42,20 @@
|
||||
<div class="sub-view-columns">
|
||||
|
||||
<div class="sub-view-column-left">
|
||||
<h5>Content Type Variation</h5>
|
||||
<small>Define the rules for how this content type's properties can be varied</small>
|
||||
</div>
|
||||
<div class="sub-view-column-right">
|
||||
<label class="checkbox no-indent">
|
||||
<input type="checkbox" ng-model="model.allowCultureVariant" />
|
||||
Allow varying by Culture
|
||||
</label>
|
||||
<h5><localize key="contentTypeEditor_variantsHeading" /></h5>
|
||||
<small><localize key="contentTypeEditor_variantsDescription" /></small>
|
||||
</div>
|
||||
|
||||
<div class="sub-view-column-right">
|
||||
<umb-toggle data-element="permissions-allow-culture-variant"
|
||||
checked="model.allowCultureVariant"
|
||||
on-click="vm.toggleAllowCultureVariants()"
|
||||
hotkey="alt+shift+v">
|
||||
</umb-toggle>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
</umb-box-content>
|
||||
</umb-box>
|
||||
</div>
|
||||
|
||||
@@ -113,11 +113,9 @@
|
||||
notificationsService.success(value);
|
||||
});
|
||||
|
||||
// emit event when language is created
|
||||
if($routeParams.create) {
|
||||
var args = { language: lang };
|
||||
eventsService.emit("editors.languages.languageCreated", args);
|
||||
}
|
||||
// emit event when language is created or updated/saved
|
||||
var args = { language: lang, isNew: $routeParams.create ? true : false };
|
||||
eventsService.emit("editors.languages.languageSaved", args);
|
||||
|
||||
back();
|
||||
|
||||
@@ -129,7 +127,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
function back() {
|
||||
@@ -145,7 +143,7 @@
|
||||
}
|
||||
|
||||
function toggleDefault() {
|
||||
|
||||
|
||||
// it shouldn't be possible to uncheck the default language
|
||||
if(vm.initIsDefault) {
|
||||
return;
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<tr ng-repeat="language in vm.languages" ng-click="vm.editLanguage(language)" style="cursor: pointer;">
|
||||
<td>
|
||||
<i class="icon-globe" style="color: #BBBABF; margin-right: 5px;"></i>
|
||||
<span class="bold">{{ language.name }}</span>
|
||||
<span ng-class="{'bold': language.isDefault}">{{ language.name }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span>{{ language.culture }}</span>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<li class="umb-action">
|
||||
<a href="" class="umb-action-link" ng-click="showCreateFolder()">
|
||||
<i class="large icon icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
<span class="menu-label"><localize key="general_folder"></localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
<li class="umb-action">
|
||||
<a href="" class="umb-action-link" ng-click="vm.showCreateFromSnippet()">
|
||||
<i class="large icon icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newPartialViewMacroFromSnippet">>New partial view macro from snippet</localize></span>
|
||||
<span class="menu-label"><localize key="create_newPartialViewMacroFromSnippet">>New partial view macro from snippet</localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="umb-action">
|
||||
<a href="" class="umb-action-link" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
<span class="menu-label"><localize key="general_folder"></localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
<li class="umb-action">
|
||||
<a href="" class="umb-action-link" ng-click="vm.showCreateFromSnippet()">
|
||||
<i class="large icon icon-article"></i>
|
||||
<span class="menu-label"><localize key="create_newPartialViewFromSnippet">New partial view from snippet</localize></span>
|
||||
<span class="menu-label"><localize key="create_newPartialViewFromSnippet">New partial view from snippet</localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="umb-action">
|
||||
<a href="" class="umb-action-link" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
<span class="menu-label"><localize key="general_folder"></localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<li class="umb-action">
|
||||
<a href="" class="umb-action-link" ng-click="vm.showCreateFolder()">
|
||||
<i class="large icon icon-folder"></i>
|
||||
<span class="menu-label"><localize key="general_folder"></localize></span>
|
||||
<span class="menu-label"><localize key="general_folder"></localize>...</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
@@ -681,6 +681,7 @@
|
||||
<key alias="moveLineDown">Move Lines Down</key>
|
||||
<key alias="generalHeader">General</key>
|
||||
<key alias="editorHeader">Editor</key>
|
||||
<key alias="toggleAllowCultureVariants">Toggle allow culture variants</key>
|
||||
</area>
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Background colour</key>
|
||||
@@ -1484,6 +1485,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="tabHasNoSortOrder">tab has no sort order</key>
|
||||
<key alias="compositionUsageHeading">Where is this composition used?</key>
|
||||
<key alias="compositionUsageSpecification">This composition is currently used in the composition of the following content types:</key>
|
||||
<key alias="variantsHeading">Allow varying by culture</key>
|
||||
<key alias="variantsDescription">Allow editors to create content of this type in different languages</key>
|
||||
<key alias="allowVaryByCulture">Allow varying by culture</key>
|
||||
</area>
|
||||
<area alias="modelsBuilder">
|
||||
<key alias="buildingModels">Building models</key>
|
||||
|
||||
@@ -701,6 +701,7 @@
|
||||
<key alias="moveLineDown">Move Lines Down</key>
|
||||
<key alias="generalHeader">General</key>
|
||||
<key alias="editorHeader">Editor</key>
|
||||
<key alias="toggleAllowCultureVariants">Toggle allow culture variants</key>
|
||||
</area>
|
||||
<area alias="graphicheadline">
|
||||
<key alias="backgroundcolor">Background color</key>
|
||||
@@ -1506,6 +1507,9 @@ To manage your website, simply open the Umbraco back office and start adding con
|
||||
<key alias="tabHasNoSortOrder">tab has no sort order</key>
|
||||
<key alias="compositionUsageHeading">Where is this composition used?</key>
|
||||
<key alias="compositionUsageSpecification">This composition is currently used in the composition of the following content types:</key>
|
||||
<key alias="variantsHeading">Allow varying by culture</key>
|
||||
<key alias="variantsDescription">Allow editors to create content of this type in different languages</key>
|
||||
<key alias="allowVaryByCulture">Allow varying by culture</key>
|
||||
</area>
|
||||
<area alias="languages">
|
||||
<key alias="addLanguage">Add language</key>
|
||||
|
||||
@@ -52,6 +52,18 @@ namespace Umbraco.Web.Models.Mapping
|
||||
variant.Name = source.GetCultureName(x.IsoCode);
|
||||
}
|
||||
|
||||
//Put the default language first in the list & then sort rest by a-z
|
||||
var defaultLang = variants.SingleOrDefault(x => x.Language.IsDefault);
|
||||
|
||||
//Remove the default lang from the list for now
|
||||
variants.Remove(defaultLang);
|
||||
|
||||
//Sort the remaining languages a-z
|
||||
variants = variants.OrderBy(x => x.Name).ToList();
|
||||
|
||||
//Insert the default lang as the first item
|
||||
variants.Insert(0, defaultLang);
|
||||
|
||||
return variants;
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -28,7 +28,21 @@ namespace Umbraco.Web.Models.Mapping
|
||||
{
|
||||
public IEnumerable<Language> Convert(IEnumerable<ILanguage> source, IEnumerable<Language> destination, ResolutionContext context)
|
||||
{
|
||||
return source.Select(x => context.Mapper.Map<ILanguage, Language>(x, null, context)).OrderBy(x => x.Name);
|
||||
var langs = source.Select(x => context.Mapper.Map<ILanguage, Language>(x, null, context)).ToList();
|
||||
|
||||
//Put the default language first in the list & then sort rest by a-z
|
||||
var defaultLang = langs.SingleOrDefault(x => x.IsDefault);
|
||||
|
||||
//Remove the default lang from the list for now
|
||||
langs.Remove(defaultLang);
|
||||
|
||||
//Sort the remaining languages a-z
|
||||
langs = langs.OrderBy(x => x.Name).ToList();
|
||||
|
||||
//Insert the default lang as the first item
|
||||
langs.Insert(0, defaultLang);
|
||||
|
||||
return langs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ namespace Umbraco.Web.Models.Trees
|
||||
SeperatorBefore = false;
|
||||
Icon = action.Icon;
|
||||
Action = action;
|
||||
OpensDialog = legacyMenu.OpensDialog;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -85,6 +86,10 @@ namespace Umbraco.Web.Models.Trees
|
||||
|
||||
[DataMember(Name = "cssclass")]
|
||||
public string Icon { get; set; }
|
||||
|
||||
[DataMember(Name = "opensDialog")]
|
||||
public bool OpensDialog { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constants
|
||||
|
||||
Reference in New Issue
Block a user