Gets the content tree controller to return the names for items per language (with mock data), wires up the navigation.controller to re-build the tree for the new language

This commit is contained in:
Shannon
2018-04-17 01:37:35 +10:00
parent f7719773f2
commit d45112f2ab
6 changed files with 186 additions and 82 deletions

View File

@@ -35,7 +35,42 @@ function treeService($q, treeResource, iconHelper, notificationsService, eventsS
_getTreeCache: function() {
return treeCache;
},
/** Internal method to track expanded paths on a tree */
_trackExpandedPaths: function (node, expandedPaths) {
if (!node.children || !angular.isArray(node.children) || node.children.length == 0) {
return;
}
//take the last child
var childPath = this.getPath(node.children[node.children.length - 1]).join(",");
//check if this already exists, if so exit
if (expandedPaths.indexOf(childPath) !== -1) {
return;
}
if (expandedPaths.length === 0) {
expandedPaths.push(childPath); //track it
return;
}
var clonedPaths = expandedPaths.slice(0); //make a copy to iterate over so we can modify the original in the iteration
_.each(clonedPaths, function (p) {
if (childPath.startsWith(p + ",")) {
//this means that the node's path supercedes this path stored so we can remove the current 'p' and replace it with node.path
expandedPaths.splice(expandedPaths.indexOf(p), 1); //remove it
expandedPaths.push(childPath); //replace it
}
else if (p.startsWith(childPath + ",")) {
//this means we've already tracked a deeper node so we shouldn't track this one
}
else {
expandedPaths.push(childPath); //track it
}
});
},
/** Internal method that ensures there's a routePath, parent and level property on each tree node and adds some icon specific properties so that the nodes display properly */
_formatNodeDataForUseInUI: function (parentNode, treeNodes, section, level) {
//if no level is set, then we make it 1

View File

@@ -9,12 +9,15 @@
*
* @param {navigationService} navigationService A reference to the navigationService
*/
function NavigationController($scope, $rootScope, $location, $log, $routeParams, $timeout, appState, navigationService, keyboardService, dialogService, historyService, eventsService, sectionResource, angularHelper, languageResource) {
function NavigationController($scope, $rootScope, $location, $log, $q, $routeParams, $timeout, treeService, appState, navigationService, keyboardService, dialogService, historyService, eventsService, sectionResource, angularHelper, languageResource) {
$scope.treeApi = {};
//Bind to the main tree events
$scope.onTreeInit = function () {
$scope.treeApi.callbacks.treeNodeExpanded(nodeExpandedHandler);
//when a tree is loaded into a section, we need to put it into appState
$scope.treeApi.callbacks.treeLoaded(function (args) {
appState.setTreeState("currentRootNode", args.tree);
@@ -106,11 +109,13 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
eventsService.emit("app.navigationReady", { treeApi: $scope.treeApi});
}
//Put the navigation service on this scope so we can use it's methods/properties in the view.
//TODO: Remove this, this is not healthy
// Put the navigation service on this scope so we can use it's methods/properties in the view.
// IMPORTANT: all properties assigned to this scope are generally available on the scope object on dialogs since
// when we create a dialog we pass in this scope to be used for the dialog's scope instead of creating a new one.
$scope.nav = navigationService;
// TODO: Lets fix this, it is less than ideal to be passing in the navigationController scope to something else to be used as it's scope,
// TODO: Remove this, this is not healthy
// it is less than ideal to be passing in the navigationController scope to something else to be used as it's scope,
// this is going to lead to problems/confusion. I really don't think passing scope's around is very good practice.
$rootScope.nav = navigationService;
@@ -127,7 +132,11 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
$scope.page.languageSelectorIsOpen = false;
$scope.currentSection = appState.getSectionState("currentSection");
$scope.customTreeParams = null;
$scope.treeCacheKey = "_";
$scope.showNavigation = appState.getGlobalState("showNavigation");
// tracks all expanded paths so when the language is switched we can resync it with the already loaded paths
var expandedPaths = [];
//trigger search with a hotkey:
keyboardService.bind("ctrl+shift+s", function () {
@@ -238,10 +247,77 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
}));
/**
* Updates the tree's query parameters
*/
function initTree() {
//create the custom query string param for this tree
var queryParams = {};
if ($scope.selectedLanguage && $scope.selectedLanguage.id) {
queryParams["languageId"] = $scope.selectedLanguage.id;
}
var queryString = $.param(queryParams); //create the query string from the params object
if (queryString) {
$scope.customTreeParams = queryString;
$scope.treeCacheKey = queryString; // this tree uses caching but we need to change it's cache key per lang
}
else {
$scope.treeCacheKey = "_"; // this tree uses caching, there's no lang selected so use the default
}
}
function nodeExpandedHandler(args) {
//store the reference to the expanded node path
if (args.node) {
treeService._trackExpandedPaths(args.node, expandedPaths);
}
}
$scope.selectLanguage = function(language, languages) {
$scope.selectedLanguage = language;
// close the language selector
$scope.page.languageSelectorIsOpen = false;
initTree(); //this will reset the tree params and the tree directive will pick up the changes in a $watch
//reload the tree with it's updated querystring args
$scope.treeApi.load($scope.currentSection).then(function () {
//this is sequential promise chaining, it's not pretty but we need to do it this way. $q.all doesn't execute promises in
//sequence but that's what we need to do here
//re-sync to currently edited node
var currNode = appState.getTreeState("selectedNode");
//create the list of promises
var promises = [];
//starting with syncing to the currently selected node if there is one
if (currNode) {
var path = treeService.getPath(currNode);
promises.push($scope.treeApi.syncTree({ path: path, activate: true }));
}
for (var i = 0; i < expandedPaths.length; i++) {
promises.push($scope.treeApi.syncTree({ path: expandedPaths[i], activate: false, forceReload: true }));
}
//now execute them in sequence... sorry there's no other good way to do it with angular promises
var j = 0;
function pExec(promise) {
j++;
promise.then(function (data) {
if (j === promises.length) {
return $q.when(data); //exit
}
else {
return pExec(promises[j]); //recurse
}
});
}
if (promises.length > 0) {
pExec(promises[0]); //start the promise chain
}
});
};
//this reacts to the options item in the tree

View File

@@ -194,82 +194,46 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController",
initTree(); //this will reset the tree params and the tree directive will pick up the changes in a $watch
$timeout(function () { //execute in the next digest since the $watch needs to update first
//reload the tree with it's updated querystring args
vm.dialogTreeApi.load(vm.section).then(function () {
//reload the tree with it's updated querystring args
vm.dialogTreeApi.load(vm.section).then(function () {
//this is sequential promise chaining, it's not pretty but we need to do it this way. $q.all doesn't execute promises in
//sequence but that's what we need to do here
//this is sequential promise chaining, it's not pretty but we need to do it this way. $q.all doesn't execute promises in
//sequence but that's what we need to do here
//create the list of promises
var promises = [];
for (var i = 0; i < expandedPaths.length; i++) {
promises.push(vm.dialogTreeApi.syncTree({ path: expandedPaths[i], activate: false, forceReload: true }));
}
//create the list of promises
var promises = [];
for (var i = 0; i < expandedPaths.length; i++) {
promises.push(vm.dialogTreeApi.syncTree({ path: expandedPaths[i], activate: false, forceReload: true }));
}
//now execute them in sequence... sorry there's no other good way to do it with angular promises
var j = 0;
function pExec(promise) {
j++;
promise.then(function (data) {
if (j === promises.length) {
return $q.when(data); //exit
}
else {
return pExec(promises[j]); //recurse
}
});
}
//now execute them in sequence... sorry there's no other good way to do it with angular promises
var j = 0;
function pExec(promise) {
j++;
promise.then(function (data) {
if (j === promises.length) {
return $q.when(data); //exit
}
else {
return pExec(promises[j]); //recurse
}
});
}
if (promises.length > 0) {
pExec(promises[0]); //start the promise chain
});
}
});
};
function toggleLanguageSelector() {
vm.languageSelectorIsOpen = !vm.languageSelectorIsOpen;
};
function trackExpandedPaths(node) {
if (!node.children || !angular.isArray(node.children) || node.children.length == 0) {
return;
}
//take the last child
var childPath = treeService.getPath(node.children[node.children.length - 1]).join(",");
//check if this already exists, if so exit
if (expandedPaths.indexOf(childPath) !== -1) {
return;
}
if (expandedPaths.length === 0) {
expandedPaths.push(childPath); //track it
return;
}
var clonedPaths = expandedPaths.slice(0); //make a copy to iterate over so we can modify the original in the iteration
_.each(clonedPaths, function (p) {
if (childPath.startsWith(p + ",")) {
//this means that the node's path supercedes this path stored so we can remove the current 'p' and replace it with node.path
expandedPaths.splice(expandedPaths.indexOf(p), 1); //remove it
expandedPaths.push(childPath); //replace it
}
else if (p.startsWith(childPath + ",")) {
//this means we've already tracked a deeper node so we shouldn't track this one
}
else {
expandedPaths.push(childPath); //track it
}
});
}
function nodeExpandedHandler(args) {
//store the reference to the expanded node path
if (args.node) {
trackExpandedPaths(args.node);
treeService._trackExpandedPaths(args.node, expandedPaths);
}
// open mini list view for list views

View File

@@ -18,10 +18,11 @@
<!-- the tree -->
<div id="tree" ng-if="authenticated">
<umb-tree
cachekey="_"
cachekey="{{treeCacheKey}}"
api="treeApi"
on-init="onTreeInit()"
section="{{currentSection}}">
section="{{currentSection}}"
customtreeparams="{{customTreeParams}}">
</umb-tree>
</div>
</div>