From 916e495dc4923281153a895e42c13bb48b2e4cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20M=C3=B6ller?= Date: Tue, 12 Sep 2023 08:26:49 +0200 Subject: [PATCH] Fixes: #14486 - Some sr-only texts not localized (#14750) * Add visuallyHiddenTexts area and keys to swedish Translations contributed by @plannero * Add missing localizations. * Revert prettier formatting * Format in visual studio * Change default UpgradeUnattended value to true (#13281) * add labels to default en.xml + small glitch fix --- .../EmbeddedResources/Lang/en.xml | 2 + .../EmbeddedResources/Lang/en_us.xml | 2 + .../EmbeddedResources/Lang/sv.xml | 54 ++ .../components/tree/umbtree.directive.js | 757 +++++++++--------- .../views/components/tree/umb-tree-item.html | 58 +- .../src/views/components/tree/umb-tree.html | 122 ++- 6 files changed, 522 insertions(+), 473 deletions(-) diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml index da5208e892..b153fbe62a 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en.xml @@ -2520,6 +2520,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Add image caption Search content tree Maximum amount + Expand child items for + Open context node for References diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml index 57cf89bc2d..ea9be49ae7 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/en_us.xml @@ -2624,6 +2624,8 @@ To manage your website, simply open the Umbraco backoffice and start adding cont Add image caption Search content tree Maximum amount + Expand child items for + Open context node for References diff --git a/src/Umbraco.Core/EmbeddedResources/Lang/sv.xml b/src/Umbraco.Core/EmbeddedResources/Lang/sv.xml index 0d8050da52..b47b335016 100644 --- a/src/Umbraco.Core/EmbeddedResources/Lang/sv.xml +++ b/src/Umbraco.Core/EmbeddedResources/Lang/sv.xml @@ -240,6 +240,60 @@ Komma igång Installera Umbraco Forms + + Backa + Aktiv layout: + Hoppa till + grupp + godkänd + varning + underkänd + förslag + Godkänd + Underkänd + Öppna sökfunktion (backoffice) + Öppna/stäng hjälpfunktion + Öppna/stäng personliga inställningar + Redigera språk och värdnamn för %0% + Skapa en ny nod under %0% + Ändra behörigheter för %0% + Redigera behörigheter för %0% + Ändra sortering av %0% + Skapa innehållsmall baserad på %0% + Öppna kontextmeny för + Aktuellt språk + Byt språk till + Skapa ny mapp + Del av vy + Del av vy (makro) + Medlem + Datatyp + Sök bland omdirigeringar + Sök bland användargrupper + Sök bland användare + Skapa post + Skapa + Redigera + Namn + Lägg till ny rad + Visa fler alternativ + Sök i Umbraco backoffice + Sök efter innehåll, media etc i hela Umbraco. + När det finns automatförslag, använd pil upp eller ner, eller använd tabbtangenten. Använd enter för att välja. + + Sökväg: + Hittad i + Har översättning + Saknar översättning + Post i ordlista + Välj ett av alternativen för att redigera noden. + Utför %0% på noden %1% + Lägg till bildtext + Sök i innehållsträdet + Maximalt värde + Visa underliggande noder för + Öppna kontext för + Stanna Ignorera ändringar diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index a39475f4da..54119f8df7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -3,406 +3,415 @@ * @name umbraco.directives.directive:umbTree * @restrict E **/ -function umbTreeDirective($q, treeService, notificationsService) { +function umbTreeDirective($q, treeService, notificationsService, localizationService) { - return { - restrict: 'E', - replace: true, - terminal: false, - templateUrl: 'views/components/tree/umb-tree.html', - scope: { - section: '@', - treealias: '@', - hideoptions: '@', - hideheader: '@', - cachekey: '@', - isdialog: '@', - onlyInitialized: '@', - //Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value" - customtreeparams: '@', - enablecheckboxes: '@', - enablelistviewsearch: '@', - enablelistviewexpand: '@', - api: '=?', - onInit: '&?' + return { + restrict: 'E', + replace: true, + terminal: false, + templateUrl: 'views/components/tree/umb-tree.html', + scope: { + section: '@', + treealias: '@', + hideoptions: '@', + hideheader: '@', + cachekey: '@', + isdialog: '@', + onlyInitialized: '@', + //Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value" + customtreeparams: '@', + enablecheckboxes: '@', + enablelistviewsearch: '@', + enablelistviewexpand: '@', + api: '=?', + onInit: '&?' + }, + controller: function ($scope, $element) { + + var vm = this; + + var registeredCallbacks = { + treeNodeExpanded: [], + treeNodeSelect: [], + treeLoaded: [], + treeSynced: [], + treeOptionsClick: [], + treeNodeAltSelect: [] + }; + + //this is the API exposed by this directive, for either hosting controllers or for other directives + vm.callbacks = { + treeNodeExpanded: function (f) { + registeredCallbacks.treeNodeExpanded.push(f); }, - controller: function ($scope, $element) { + treeNodeSelect: function (f) { + registeredCallbacks.treeNodeSelect.push(f); + }, + treeLoaded: function (f) { + registeredCallbacks.treeLoaded.push(f); + }, + treeSynced: function (f) { + registeredCallbacks.treeSynced.push(f); + }, + treeOptionsClick: function (f) { + registeredCallbacks.treeOptionsClick.push(f); + }, + treeNodeAltSelect: function (f) { + registeredCallbacks.treeNodeAltSelect.push(f); + } + }; + vm.emitEvent = emitEvent; + vm.load = load; + vm.reloadNode = reloadNode; + vm.syncTree = syncTree; + vm.loadChildren = loadChildren; + vm.hasTree = hasTree; - var vm = this; + $scope.labels = { + openContextNode: "Open context node for" + }; - var registeredCallbacks = { - treeNodeExpanded: [], - treeNodeSelect: [], - treeLoaded: [], - treeSynced: [], - treeOptionsClick: [], - treeNodeAltSelect: [] - }; + //wire up the exposed api object for hosting controllers + if ($scope.api) { + $scope.api.callbacks = vm.callbacks; + $scope.api.load = vm.load; + $scope.api.reloadNode = vm.reloadNode; + $scope.api.syncTree = vm.syncTree; + $scope.api.hasTree = vm.hasTree; + } - //this is the API exposed by this directive, for either hosting controllers or for other directives - vm.callbacks = { - treeNodeExpanded: function (f) { - registeredCallbacks.treeNodeExpanded.push(f); - }, - treeNodeSelect: function (f) { - registeredCallbacks.treeNodeSelect.push(f); - }, - treeLoaded: function (f) { - registeredCallbacks.treeLoaded.push(f); - }, - treeSynced: function (f) { - registeredCallbacks.treeSynced.push(f); - }, - treeOptionsClick: function (f) { - registeredCallbacks.treeOptionsClick.push(f); - }, - treeNodeAltSelect: function (f) { - registeredCallbacks.treeNodeAltSelect.push(f); - } - }; - vm.emitEvent = emitEvent; - vm.load = load; - vm.reloadNode = reloadNode; - vm.syncTree = syncTree; - vm.loadChildren = loadChildren; - vm.hasTree = hasTree; + //flag to track the last loaded section when the tree 'un-loads'. We use this to determine if we should + // re-load the tree again. For example, if we hover over 'content' the content tree is shown. Then we hover + // outside of the tree and the tree 'un-loads'. When we re-hover over 'content', we don't want to re-load the + // entire tree again since we already still have it in memory. Of course if the section is different we will + // reload it. This saves a lot on processing if someone is navigating in and out of the same section many times + // since it saves on data retreival and DOM processing. + // TODO: This isn't used!? + var lastSection = ""; - //wire up the exposed api object for hosting controllers - if ($scope.api) { - $scope.api.callbacks = vm.callbacks; - $scope.api.load = vm.load; - $scope.api.reloadNode = vm.reloadNode; - $scope.api.syncTree = vm.syncTree; - $scope.api.hasTree = vm.hasTree; - } - - //flag to track the last loaded section when the tree 'un-loads'. We use this to determine if we should - // re-load the tree again. For example, if we hover over 'content' the content tree is shown. Then we hover - // outside of the tree and the tree 'un-loads'. When we re-hover over 'content', we don't want to re-load the - // entire tree again since we already still have it in memory. Of course if the section is different we will - // reload it. This saves a lot on processing if someone is navigating in and out of the same section many times - // since it saves on data retreival and DOM processing. - // TODO: This isn't used!? - var lastSection = ""; - - /** Helper function to emit tree events */ - function emitEvent(eventName, args) { - if (registeredCallbacks[eventName] && Utilities.isArray(registeredCallbacks[eventName])) { - // call it - registeredCallbacks[eventName].forEach(c => c(args)); - } - } + /** Helper function to emit tree events */ + function emitEvent(eventName, args) { + if (registeredCallbacks[eventName] && Utilities.isArray(registeredCallbacks[eventName])) { + // call it + registeredCallbacks[eventName].forEach(c => c(args)); + } + } - /** - * Re-loads the tree with the updated parameters - * @param {any} args either a string representing the 'section' or an object containing: 'section', 'treeAlias', 'customTreeParams', 'cacheKey' - */ - function load(args) { - if (Utilities.isString(args)) { - $scope.section = args; - } - else if (args) { - if (args.section) { - $scope.section = args.section; - } - if (args.customTreeParams) { - $scope.customtreeparams = args.customTreeParams; - } - if (args.treeAlias) { - $scope.treealias = args.treeAlias; - } - if (args.cacheKey) { - $scope.cachekey = args.cacheKey; - } - } + /** + * Re-loads the tree with the updated parameters + * @param {any} args either a string representing the 'section' or an object containing: 'section', 'treeAlias', 'customTreeParams', 'cacheKey' + */ + function load(args) { + if (Utilities.isString(args)) { + $scope.section = args; + } + else if (args) { + if (args.section) { + $scope.section = args.section; + } + if (args.customTreeParams) { + $scope.customtreeparams = args.customTreeParams; + } + if (args.treeAlias) { + $scope.treealias = args.treeAlias; + } + if (args.cacheKey) { + $scope.cachekey = args.cacheKey; + } + } - return loadTree(); - } + return loadTree(); + } - function reloadNode(node) { + function reloadNode(node) { - if (!node) { - node = $scope.currentNode; - } + if (!node) { + node = $scope.currentNode; + } - if (node) { - return $scope.loadChildren(node, true); - } + if (node) { + return $scope.loadChildren(node, true); + } - return $q.reject(); - } + return $q.reject(); + } - /** - * Used to do the tree syncing - * @param {any} args - * @returns a promise with an object containing 'node' and 'activate' - */ - function syncTree(args) { - if (!args) { - throw "args cannot be null"; - } - if (!args.path) { - throw "args.path cannot be null"; - } + /** + * Used to do the tree syncing + * @param {any} args + * @returns a promise with an object containing 'node' and 'activate' + */ + function syncTree(args) { + if (!args) { + throw "args cannot be null"; + } + if (!args.path) { + throw "args.path cannot be null"; + } - if (Utilities.isString(args.path)) { - args.path = args.path.replace('"', '').split(','); - } + if (Utilities.isString(args.path)) { + args.path = args.path.replace('"', '').split(','); + } - //Filter the path for root node ids (we don't want to pass in -1 or 'init') + //Filter the path for root node ids (we don't want to pass in -1 or 'init') - args.path = _.filter(args.path, function (item) { return (item !== "init" && item !== "-1"); }); + args.path = _.filter(args.path, function (item) { return (item !== "init" && item !== "-1"); }); - var treeNode = loadActiveTree(args.tree); + var treeNode = loadActiveTree(args.tree); - return treeService.syncTree({ - node: treeNode, - path: args.path, - forceReload: args.forceReload - }).then(function (data) { + return treeService.syncTree({ + node: treeNode, + path: args.path, + forceReload: args.forceReload + }).then(function (data) { - if (args.activate === undefined || args.activate === true) { - $scope.currentNode = data; - } + if (args.activate === undefined || args.activate === true) { + $scope.currentNode = data; + } - emitEvent("treeSynced", { node: data, activate: args.activate }); + emitEvent("treeSynced", { node: data, activate: args.activate }); - return $q.when({ node: data, activate: args.activate }); - }, function (data) { - return $q.reject(data); - }, function (data) { - //on notification - if (data.type === "treeNodeExpanded") { - //raise the event - emitEvent("treeNodeExpanded", { tree: $scope.tree, node: data.node, children: data.children }); - } - }); + return $q.when({ node: data, activate: args.activate }); + }, function (data) { + return $q.reject(data); + }, function (data) { + //on notification + if (data.type === "treeNodeExpanded") { + //raise the event + emitEvent("treeNodeExpanded", { tree: $scope.tree, node: data.node, children: data.children }); + } + }); - } + } - /** This will check the section tree loaded and return all actual root nodes based on a tree type (non group nodes, non section groups) */ - function getTreeRootNodes() { - var roots; - if ($scope.tree.root.containsGroups) { - //all children in this case are group nodes, so we want the children of these children - roots = _.reduce( - //get the array of array of children - _.map($scope.tree.root.children, function (n) { - return n.children - }), function (m, p) { - //combine the arrays to one array - return m.concat(p) - }); - } - else { - roots = [$scope.tree.root].concat($scope.tree.root.children); - } - - return _.filter(roots, function (node) { - return node && node.metaData && node.metaData.treeAlias; - }); - } - - //given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node - function hasTree(treeAlias) { - - if (!$scope.tree) { - throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null"; - } - - if (!treeAlias) { - return false; - } - - var treeRoots = getTreeRootNodes(); - var foundTree = _.find(treeRoots, function (node) { - return node.metaData.treeAlias.toUpperCase() === treeAlias.toUpperCase(); - }); - - return foundTree !== undefined; - } - - //given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node - function loadActiveTree(treeAlias) { - - if (!$scope.tree) { - throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null"; - } - - //if its not specified, it should have been specified before - if (!treeAlias) { - if (!$scope.activeTree) { - throw "Err in umbtree.directive.loadActiveTree, $scope.activeTree is null"; - } - return $scope.activeTree; - } - - var treeRoots = getTreeRootNodes(); - $scope.activeTree = _.find(treeRoots, function (node) { - return node.metaData.treeAlias.toUpperCase() === treeAlias.toUpperCase(); - }); - - if (!$scope.activeTree) { - throw "Could not find the tree " + treeAlias; - } - - emitEvent("activeTreeLoaded", { tree: $scope.activeTree }); - - return $scope.activeTree; - } - - /** Method to load in the tree data */ - function loadTree() { - if ($scope.section) { - - //default args - var args = { section: $scope.section, tree: $scope.treealias, cacheKey: $scope.cachekey, isDialog: $scope.isdialog ? $scope.isdialog : false }; - - //add the extra query string params if specified - if ($scope.customtreeparams) { - args["queryString"] = $scope.customtreeparams; - } - - return treeService.getTree(args) - .then(function (data) { - //Only use the tree data, if we are still on the correct section - if(data.alias !== $scope.section){ - return $q.reject(); - } - - //set the data once we have it - $scope.tree = data; - - //set the root as the current active tree - $scope.activeTree = $scope.tree.root; - - emitEvent("treeLoaded", { tree: $scope.tree }); - emitEvent("treeNodeExpanded", { tree: $scope.tree, node: $scope.tree.root, children: $scope.tree.root.children }); - - return $q.when(data); - }, function (reason) { - notificationsService.error("Tree Error", reason); - return $q.reject(reason); - }); - } - else { - return $q.reject(); - } - } - - function loadChildren(node, forceReload) { - //emit treeNodeExpanding event, if a callback object is set on the tree - emitEvent("treeNodeExpanding", { tree: $scope.tree, node: node }); - - //standardising - if (!node.children) { - node.children = []; - } - - if (forceReload || (node.hasChildren && node.children.length === 0)) { - //get the children from the tree service - return treeService.loadNodeChildren({ node: node, section: $scope.section, isDialog: $scope.isdialog }) - .then(function (data) { - //emit expanded event - emitEvent("treeNodeExpanded", { tree: $scope.tree, node: node, children: data }); - - return $q.when(data); - }); - } - else { - emitEvent("treeNodeExpanded", { tree: $scope.tree, node: node, children: node.children }); - node.expanded = true; - - return $q.when(node.children); - } - } - - /** Returns the css classses assigned to the node (div element) */ - $scope.getNodeCssClass = function (node) { - if (!node) { - return ''; - } - - // TODO: This is called constantly because as a method in a template it's re-evaluated pretty much all the time - // it would be better if we could cache the processing. The problem is that some of these things are dynamic. - - var css = []; - if (node.cssClasses) { - node.cssClasses.forEach(c => css.push(c)); - } - - return css.join(" "); - }; - - $scope.selectEnabledNodeClass = node => - node && node.selected ? 'icon sprTree icon-check green temporary' : '-hidden'; - - /* helper to force reloading children of a tree node */ - $scope.loadChildren = (node, forceReload) => loadChildren(node, forceReload); - - /** - Method called when the options button next to the root node is called. - The tree doesnt know about this, so it raises an event to tell the parent controller - about it. - */ - $scope.options = function (n, ev) { - emitEvent("treeOptionsClick", { element: $element, node: n, event: ev }); - }; - - /** - Method called when an item is clicked in the tree, this passes the - DOM element, the tree node object and the original click - and emits it as a treeNodeSelect element if there is a callback object - defined on the tree - */ - $scope.select = function (n, ev) { - - if (n.metaData && n.metaData.noAccess === true) { - ev.preventDefault(); - return; - } - - //on tree select we need to remove the current node - - // whoever handles this will need to make sure the correct node is selected - //reset current node selection - $scope.currentNode = null; - - emitEvent("treeNodeSelect", { element: $element, node: n, event: ev }); - }; - - $scope.altSelect = function (n, ev) { - emitEvent("treeNodeAltSelect", { element: $element, tree: $scope.tree, node: n, event: ev }); - }; - - //call the onInit method, if the result is a promise then load the tree after that resolves (if it's not a promise this will just resolve automatically). - //NOTE: The promise cannot be rejected, else the tree won't be loaded and we'll get exceptions if some API calls syncTree or similar. - $q.when($scope.onInit(), function (args) { - - //the promise resolution can pass in parameters - if (args) { - if (args.section) { - $scope.section = args.section; - } - if (args.cacheKey) { - $scope.cachekey = args.cacheKey; - } - if (args.customTreeParams) { - $scope.customtreeparams = args.customTreeParams; - } - } - - //load the tree - loadTree().then(function () { - //because angular doesn't return a promise for the resolve method, we need to resort to some hackery, else - //like normal JS promises we could do resolve(...).then() - if (args && args.onLoaded && Utilities.isFunction(args.onLoaded)) { - args.onLoaded(); - } - }); + /** This will check the section tree loaded and return all actual root nodes based on a tree type (non group nodes, non section groups) */ + function getTreeRootNodes() { + var roots; + if ($scope.tree.root.containsGroups) { + //all children in this case are group nodes, so we want the children of these children + roots = _.reduce( + //get the array of array of children + _.map($scope.tree.root.children, function (n) { + return n.children + }), function (m, p) { + //combine the arrays to one array + return m.concat(p) }); } - }; + else { + roots = [$scope.tree.root].concat($scope.tree.root.children); + } + + return _.filter(roots, function (node) { + return node && node.metaData && node.metaData.treeAlias; + }); + } + + //given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node + function hasTree(treeAlias) { + + if (!$scope.tree) { + throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null"; + } + + if (!treeAlias) { + return false; + } + + var treeRoots = getTreeRootNodes(); + var foundTree = _.find(treeRoots, function (node) { + return node.metaData.treeAlias.toUpperCase() === treeAlias.toUpperCase(); + }); + + return foundTree !== undefined; + } + + //given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node + function loadActiveTree(treeAlias) { + + if (!$scope.tree) { + throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null"; + } + + //if its not specified, it should have been specified before + if (!treeAlias) { + if (!$scope.activeTree) { + throw "Err in umbtree.directive.loadActiveTree, $scope.activeTree is null"; + } + return $scope.activeTree; + } + + var treeRoots = getTreeRootNodes(); + $scope.activeTree = _.find(treeRoots, function (node) { + return node.metaData.treeAlias.toUpperCase() === treeAlias.toUpperCase(); + }); + + if (!$scope.activeTree) { + throw "Could not find the tree " + treeAlias; + } + + emitEvent("activeTreeLoaded", { tree: $scope.activeTree }); + + return $scope.activeTree; + } + + /** Method to load in the tree data */ + function loadTree() { + if ($scope.section) { + + //default args + var args = { section: $scope.section, tree: $scope.treealias, cacheKey: $scope.cachekey, isDialog: $scope.isdialog ? $scope.isdialog : false }; + + //add the extra query string params if specified + if ($scope.customtreeparams) { + args["queryString"] = $scope.customtreeparams; + } + + return treeService.getTree(args) + .then(function (data) { + //Only use the tree data, if we are still on the correct section + if (data.alias !== $scope.section) { + return $q.reject(); + } + + //set the data once we have it + $scope.tree = data; + + //set the root as the current active tree + $scope.activeTree = $scope.tree.root; + + emitEvent("treeLoaded", { tree: $scope.tree }); + emitEvent("treeNodeExpanded", { tree: $scope.tree, node: $scope.tree.root, children: $scope.tree.root.children }); + + return $q.when(data); + }, function (reason) { + notificationsService.error("Tree Error", reason); + return $q.reject(reason); + }); + } + else { + return $q.reject(); + } + } + + function loadChildren(node, forceReload) { + //emit treeNodeExpanding event, if a callback object is set on the tree + emitEvent("treeNodeExpanding", { tree: $scope.tree, node: node }); + + //standardising + if (!node.children) { + node.children = []; + } + + if (forceReload || (node.hasChildren && node.children.length === 0)) { + //get the children from the tree service + return treeService.loadNodeChildren({ node: node, section: $scope.section, isDialog: $scope.isdialog }) + .then(function (data) { + //emit expanded event + emitEvent("treeNodeExpanded", { tree: $scope.tree, node: node, children: data }); + + return $q.when(data); + }); + } + else { + emitEvent("treeNodeExpanded", { tree: $scope.tree, node: node, children: node.children }); + node.expanded = true; + + return $q.when(node.children); + } + } + + /** Returns the css classses assigned to the node (div element) */ + $scope.getNodeCssClass = function (node) { + if (!node) { + return ''; + } + + // TODO: This is called constantly because as a method in a template it's re-evaluated pretty much all the time + // it would be better if we could cache the processing. The problem is that some of these things are dynamic. + + var css = []; + if (node.cssClasses) { + node.cssClasses.forEach(c => css.push(c)); + } + + return css.join(" "); + }; + + $scope.selectEnabledNodeClass = node => + node && node.selected ? 'icon sprTree icon-check green temporary' : '-hidden'; + + /* helper to force reloading children of a tree node */ + $scope.loadChildren = (node, forceReload) => loadChildren(node, forceReload); + + /** + Method called when the options button next to the root node is called. + The tree doesnt know about this, so it raises an event to tell the parent controller + about it. + */ + $scope.options = function (n, ev) { + emitEvent("treeOptionsClick", { element: $element, node: n, event: ev }); + }; + + /** + Method called when an item is clicked in the tree, this passes the + DOM element, the tree node object and the original click + and emits it as a treeNodeSelect element if there is a callback object + defined on the tree + */ + $scope.select = function (n, ev) { + + if (n.metaData && n.metaData.noAccess === true) { + ev.preventDefault(); + return; + } + + //on tree select we need to remove the current node - + // whoever handles this will need to make sure the correct node is selected + //reset current node selection + $scope.currentNode = null; + + emitEvent("treeNodeSelect", { element: $element, node: n, event: ev }); + }; + + $scope.altSelect = function (n, ev) { + emitEvent("treeNodeAltSelect", { element: $element, tree: $scope.tree, node: n, event: ev }); + }; + + //call the onInit method, if the result is a promise then load the tree after that resolves (if it's not a promise this will just resolve automatically). + //NOTE: The promise cannot be rejected, else the tree won't be loaded and we'll get exceptions if some API calls syncTree or similar. + $q.when($scope.onInit(), function (args) { + + //the promise resolution can pass in parameters + if (args) { + if (args.section) { + $scope.section = args.section; + } + if (args.cacheKey) { + $scope.cachekey = args.cacheKey; + } + if (args.customTreeParams) { + $scope.customtreeparams = args.customTreeParams; + } + } + + //load the tree + loadTree().then(function () { + //because angular doesn't return a promise for the resolve method, we need to resort to some hackery, else + //like normal JS promises we could do resolve(...).then() + if (args && args.onLoaded && Utilities.isFunction(args.onLoaded)) { + args.onLoaded(); + } + }); + + localizationService.localize("visuallyHiddenTexts_openContextNode").then((value) => { + $scope.labels.openContextNode = value; + }); + + }); + } + }; } angular.module("umbraco.directives").directive('umbTree', umbTreeDirective); diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html index bb789d8c98..85cc5a4d46 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html @@ -1,32 +1,36 @@ -
  • -
    - +
  • +
    + - - - {{node.name}} + + + {{node.name}} - - - + + + - -
    + + - +
  • diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html index 0aa1be85b5..055bcfedc1 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html @@ -1,79 +1,57 @@