slowly getting the tree node model decoupled from being passed in to menu actions, updated more of the appState and clarified a few things, created a new umboptionsmenu directive to be used for the options drop down on editors
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbContextMenu', function ($injector, navigationService) {
|
||||
.directive('umbContextMenu', function ($injector, umbModelMapper, treeService) {
|
||||
return {
|
||||
scope: {
|
||||
menuDialogTitle: "@",
|
||||
currentSection: "@",
|
||||
currentEntity: "=",
|
||||
currentNode: "=",
|
||||
menuActions: "="
|
||||
},
|
||||
restrict: 'E',
|
||||
@@ -14,7 +14,7 @@ angular.module("umbraco.directives")
|
||||
|
||||
//adds a handler to the context menu item click, we need to handle this differently
|
||||
//depending on what the menu item is supposed to do.
|
||||
scope.executeMenuItem = function (currentNode, action, currentSection) {
|
||||
scope.executeMenuItem = function (action) {
|
||||
|
||||
if (action.metaData && action.metaData["jsAction"] && angular.isString(action.metaData["jsAction"])) {
|
||||
|
||||
@@ -41,9 +41,13 @@ angular.module("umbraco.directives")
|
||||
}
|
||||
|
||||
method.apply(this, [{
|
||||
treeNode: currentNode,
|
||||
//map our content object to a basic entity to pass in to the menu handlers,
|
||||
//this is required for consistency since a menu item needs to be decoupled from a tree node since the menu can
|
||||
//exist standalone in the editor for which it can only pass in an entity (not tree node).
|
||||
entity: umbModelMapper.convertToEntityBasic(scope.currentNode),
|
||||
action: action,
|
||||
section: currentSection
|
||||
section: scope.currentSection,
|
||||
treeAlias: treeService.getTreeAlias(scope.currentNode)
|
||||
}]);
|
||||
}
|
||||
}
|
||||
@@ -54,7 +58,7 @@ angular.module("umbraco.directives")
|
||||
// the problem with all these dialogs is were passing other object's scopes around which isn't nice at all.
|
||||
// Each of these passed scopes expects a .nav property assigned to it which is a reference to the navigationService,
|
||||
// which should not be happenning... should simply be using the navigation service, no ?!
|
||||
scope.$parent.openDialog(currentNode, action, currentSection);
|
||||
scope.$parent.openDialog(scope.currentNode, action, scope.currentSection);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
angular.module("umbraco.directives")
|
||||
.directive('umbOptionsMenu', function ($injector, treeService, navigationService, umbModelMapper) {
|
||||
return {
|
||||
scope: {
|
||||
content: "=",
|
||||
currentSection: "@",
|
||||
treeAlias: "@"
|
||||
},
|
||||
restrict: 'E',
|
||||
replace: true,
|
||||
templateUrl: 'views/directives/umb-optionsmenu.html',
|
||||
link: function (scope, element, attrs, ctrl) {
|
||||
|
||||
//adds a handler to the context menu item click, we need to handle this differently
|
||||
//depending on what the menu item is supposed to do.
|
||||
scope.executeMenuItem = function (action) {
|
||||
|
||||
//map our content object to a basic entity to pass in to the handlers
|
||||
var currentEntity = umbModelMapper.convertToEntityBasic(scope.content);
|
||||
|
||||
if (action.metaData && action.metaData["jsAction"] && angular.isString(action.metaData["jsAction"])) {
|
||||
|
||||
//we'll try to get the jsAction from the injector
|
||||
var menuAction = action.metaData["jsAction"].split('.');
|
||||
if (menuAction.length !== 2) {
|
||||
|
||||
//if it is not two parts long then this most likely means that it's a legacy action
|
||||
var js = action.metaData["jsAction"].replace("javascript:", "");
|
||||
//there's not really a different way to acheive this except for eval
|
||||
eval(js);
|
||||
|
||||
}
|
||||
else {
|
||||
var service = $injector.get(menuAction[0]);
|
||||
if (!service) {
|
||||
throw "The angular service " + menuAction[0] + " could not be found";
|
||||
}
|
||||
|
||||
var method = service[menuAction[1]];
|
||||
|
||||
if (!method) {
|
||||
throw "The method " + menuAction[1] + " on the angular service " + menuAction[0] + " could not be found";
|
||||
}
|
||||
|
||||
method.apply(this, [{
|
||||
entity: currentEntity,
|
||||
action: action,
|
||||
section: scope.currentSection,
|
||||
treeAlias: scope.treeAlias
|
||||
}]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//by default we launch the dialog
|
||||
|
||||
//TODO: This is temporary using $parent, now that this is an isolated scope
|
||||
// the problem with all these dialogs is were passing other object's scopes around which isn't nice at all.
|
||||
// Each of these passed scopes expects a .nav property assigned to it which is a reference to the navigationService,
|
||||
// which should not be happenning... should simply be using the navigation service, no ?!
|
||||
scope.$parent.openDialog(currentEntity, action, scope.currentSection);
|
||||
}
|
||||
};
|
||||
|
||||
//callback method to go and get the options async
|
||||
scope.getOptions = function () {
|
||||
if (!scope.content.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scope.actions) {
|
||||
treeService.getMenu({ treeNode: navigationService.ui.currentNode })
|
||||
.then(function (data) {
|
||||
scope.actions = data.menuItems;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -25,8 +25,11 @@ function appState($rootScope) {
|
||||
};
|
||||
|
||||
var treeState = {
|
||||
//The currently selected/edited entity
|
||||
currentEntity: null
|
||||
//The currently selected node
|
||||
selectedNode: null,
|
||||
//The currently loaded root node reference - depending on the section loaded this could be a section root or a normal root.
|
||||
//We keep this reference so we can lookup nodes to interact with in the UI via the tree service
|
||||
currentRootNode: null
|
||||
};
|
||||
|
||||
var menuState = {
|
||||
@@ -34,8 +37,8 @@ function appState($rootScope) {
|
||||
menuActions: null,
|
||||
//the title to display in the context menu dialog
|
||||
dialogTitle: null,
|
||||
//The basic entity that is having an action performed on it
|
||||
currentEntity: null,
|
||||
//The tree node that the ctx menu is launched for
|
||||
currentNode: null,
|
||||
//Whether the menu's dialog is being shown or not
|
||||
showMenuDialog: null,
|
||||
//Whether the context menu is being shown or not
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* @description
|
||||
* Defines the methods that are called when menu items declare only an action to execute
|
||||
*/
|
||||
function umbracoMenuActions($q, treeService, $location, navigationService) {
|
||||
function umbracoMenuActions($q, treeService, $location, navigationService, appState) {
|
||||
|
||||
return {
|
||||
|
||||
@@ -21,11 +21,32 @@ function umbracoMenuActions($q, treeService, $location, navigationService) {
|
||||
* @description
|
||||
* Clears all node children and then gets it's up-to-date children from the server and re-assigns them
|
||||
* @param {object} args An arguments object
|
||||
* @param {object} args.treeNode The tree node
|
||||
* @param {object} args.entity The basic entity being acted upon
|
||||
* @param {object} args.treeAlias The tree alias associated with this entity
|
||||
* @param {object} args.section The current section
|
||||
*/
|
||||
"RefreshNode": function (args) {
|
||||
treeService.loadNodeChildren({ node: args.treeNode, section: args.section });
|
||||
|
||||
//just in case clear any tree cache for this node/section
|
||||
treeService.clearCache({
|
||||
cacheKey: "__" + args.section, //each item in the tree cache is cached by the section name
|
||||
childrenOf: args.entity.parentId //clear the children of the parent
|
||||
});
|
||||
|
||||
//since we're dealing with an entity, we need to attempt to find it's tree node, in the main tree
|
||||
// this action is purely a UI thing so if for whatever reason there is no loaded tree node in the UI
|
||||
// we can safely ignore this process.
|
||||
|
||||
//to find a visible tree node, we'll go get the currently loaded root node from appState
|
||||
var treeRoot = appState.getTreeState("currentRootNode");
|
||||
if (treeRoot) {
|
||||
var treeNode = treeService.getDescendantNode(treeRoot, args.entity.id, args.treeAlias);
|
||||
if (treeNode) {
|
||||
treeService.loadNodeChildren({ node: treeNode, section: args.section });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -37,14 +58,15 @@ function umbracoMenuActions($q, treeService, $location, navigationService) {
|
||||
* @description
|
||||
* This will re-route to a route for creating a new entity as a child of the current node
|
||||
* @param {object} args An arguments object
|
||||
* @param {object} args.treeNode The tree node
|
||||
* @param {object} args.entity The basic entity being acted upon
|
||||
* @param {object} args.treeAlias The tree alias associated with this entity
|
||||
* @param {object} args.section The current section
|
||||
*/
|
||||
"CreateChildEntity": function (args) {
|
||||
|
||||
navigationService.hideNavigation();
|
||||
|
||||
var route = "/" + args.section + "/" + treeService.getTreeAlias(args.treeNode) + "/edit/" + args.treeNode.id;
|
||||
var route = "/" + args.section + "/" + args.treeAlias + "/edit/" + args.entity.id;
|
||||
//change to new path
|
||||
$location.path(route).search({ create: true });
|
||||
|
||||
|
||||
@@ -198,6 +198,11 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
setupTreeEvents: function(treeEventHandler, scope) {
|
||||
mainTreeEventHandler = treeEventHandler;
|
||||
|
||||
//when a tree is loaded into a section, we need to put it into appState
|
||||
mainTreeEventHandler.bind("treeLoaded", function(ev, args) {
|
||||
appState.setTreeState("currentRootNode", args.tree);
|
||||
});
|
||||
|
||||
//when a tree node is synced this event will fire, this allows us to set the currentNode
|
||||
mainTreeEventHandler.bind("treeSynced", function (ev, args) {
|
||||
|
||||
@@ -218,8 +223,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
ev.preventDefault();
|
||||
|
||||
//Set the current action node (this is not the same as the current selected node!)
|
||||
//TODO: Convert this to basic entity , not tree node
|
||||
appState.setMenuState("currentEntity", args.node);
|
||||
appState.setMenuState("currentNode", args.node);
|
||||
|
||||
args.scope = scope;
|
||||
|
||||
@@ -248,6 +252,8 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
|
||||
//put this into the app state
|
||||
appState.setTreeState("selectedNode", args.node);
|
||||
|
||||
if (n.metaData && n.metaData["jsClickCallback"] && angular.isString(n.metaData["jsClickCallback"]) && n.metaData["jsClickCallback"] !== "") {
|
||||
//this is a legacy tree node!
|
||||
@@ -439,8 +445,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
if (found) {
|
||||
|
||||
//NOTE: This is assigning the current action node - this is not the same as the currently selected node!
|
||||
//TODO: Change this to an entity instead of a node!
|
||||
appState.setMenuState("currentEntity", args.node);
|
||||
appState.setMenuState("currentNode", args.node);
|
||||
|
||||
//ensure the current dialog is cleared before creating another!
|
||||
if (currentDialog) {
|
||||
@@ -464,8 +469,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
|
||||
setMode("menu");
|
||||
|
||||
//TODO: Change this to an entity instead of a node!
|
||||
appState.setMenuState("currentEntity", args.node);
|
||||
appState.setMenuState("currentNode", args.node);
|
||||
appState.setMenuState("menuActions", data.menuItems);
|
||||
appState.setMenuState("dialogTitle", args.node.name);
|
||||
|
||||
@@ -486,7 +490,7 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
*/
|
||||
hideMenu: function() {
|
||||
//SD: Would we ever want to access the last action'd node instead of clearing it here?
|
||||
appState.setMenuState("currentEntity", null);
|
||||
appState.setMenuState("currentNode", null);
|
||||
appState.setMenuState("menuActions", []);
|
||||
setMode("tree");
|
||||
},
|
||||
@@ -666,8 +670,8 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo
|
||||
* @description
|
||||
* hides the currently open dialog
|
||||
*/
|
||||
hideDialog: function() {
|
||||
this.showMenu(undefined, { skipDefault: true, node: appState.getMenuState("currentEntity") });
|
||||
hideDialog: function () {
|
||||
this.showMenu(undefined, { skipDefault: true, node: appState.getMenuState("currentNode") });
|
||||
},
|
||||
/**
|
||||
* @ngdoc method
|
||||
|
||||
@@ -147,10 +147,12 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc
|
||||
cacheKey: args.cacheKey,
|
||||
filter: function(cc) {
|
||||
//get the new parent node from the tree cache
|
||||
var parent = self.getDescendantNode(cc.root, args.childrenOf);
|
||||
//clear it's children and set to not expanded
|
||||
parent.children = null;
|
||||
parent.expanded = false;
|
||||
var parent = self.getDescendantNode(cc.root, args.childrenOf);
|
||||
if (parent) {
|
||||
//clear it's children and set to not expanded
|
||||
parent.children = null;
|
||||
parent.expanded = false;
|
||||
}
|
||||
//return the cache to be saved
|
||||
return cc;
|
||||
}
|
||||
@@ -277,7 +279,33 @@ function treeService($q, treeResource, iconHelper, notificationsService, $rootSc
|
||||
},
|
||||
|
||||
/** Gets a descendant node by id */
|
||||
getDescendantNode: function(treeNode, id) {
|
||||
getDescendantNode: function(treeNode, id, treeAlias) {
|
||||
|
||||
//validate if it is a section container since we'll need a treeAlias if it is one
|
||||
if (treeNode.isContainer === true && !treeAlias) {
|
||||
throw "Cannot get a descendant node from a section container node without a treeAlias specified";
|
||||
}
|
||||
|
||||
//if it is a section container, we need to find the tree to be searched
|
||||
if (treeNode.isContainer) {
|
||||
var foundRoot = null;
|
||||
for (var c = 0; c < treeNode.children.length; c++) {
|
||||
if (this.getTreeAlias(treeNode.children[c]) === treeAlias) {
|
||||
foundRoot = treeNode.children[c];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundRoot) {
|
||||
throw "Could not find a tree in the current section with alias " + treeAlias;
|
||||
}
|
||||
treeNode = foundRoot;
|
||||
}
|
||||
|
||||
//check this node
|
||||
if (treeNode.id === id) {
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
//check the first level
|
||||
var found = this.getChildNode(treeNode, id);
|
||||
if (found) {
|
||||
|
||||
@@ -1,5 +1,35 @@
|
||||
/*Contains multiple services for various helper tasks */
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.umbModelMapper
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* Utility class to map/convert models
|
||||
*/
|
||||
function umbModelMapper() {
|
||||
|
||||
return {
|
||||
|
||||
/** This converts the source model to a basic entity model, it will throw an exception if there isn't enough data to create the model */
|
||||
convertToEntityBasic: function (source) {
|
||||
var required = ["id", "name", "icon", "parentId", "path"];
|
||||
_.each(required, function (k) {
|
||||
if (!_.has(source, k)) {
|
||||
throw "The source object does not contain the property " + k;
|
||||
}
|
||||
});
|
||||
var optional = ["metaData", "key", "alias"];
|
||||
//now get the basic object
|
||||
var result = _.pick(source, required.concat(optional));
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
angular.module('umbraco.services').factory('umbModelMapper', umbModelMapper);
|
||||
|
||||
/**
|
||||
* @ngdoc function
|
||||
* @name umbraco.services.umbSessionStorage
|
||||
|
||||
@@ -27,7 +27,7 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
|
||||
$scope.showSearchResults = false;
|
||||
$scope.menuDialogTitle = null;
|
||||
$scope.menuActions = [];
|
||||
$scope.menuEntity = null;
|
||||
$scope.menuNode = null;
|
||||
$scope.currentSection = appState.getSectionState("currentSection");
|
||||
$scope.showNavigation = appState.getGlobalState("showNavigation");
|
||||
|
||||
@@ -66,8 +66,8 @@ function NavigationController($scope, $rootScope, $location, $log, $routeParams,
|
||||
if (args.key === "menuActions") {
|
||||
$scope.menuActions = args.value;
|
||||
}
|
||||
if (args.key === "currentEntity") {
|
||||
$scope.menuEntity = args.value;
|
||||
if (args.key === "currentNode") {
|
||||
$scope.menuNode = args.value;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -221,19 +221,6 @@ function ContentEditController($scope, $routeParams, $q, $timeout, $window, appS
|
||||
}
|
||||
};
|
||||
|
||||
$scope.options = function(content){
|
||||
if(!content.id){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$scope.actions){
|
||||
treeService.getMenu({ treeNode: $scope.nav.ui.currentNode })
|
||||
.then(function(data) {
|
||||
$scope.actions = data.menuItems;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/** this method is called for all action buttons and then we proxy based on the btn definition */
|
||||
$scope.performAction = function(btn) {
|
||||
if (!btn || !angular.isFunction(btn.handler)) {
|
||||
|
||||
@@ -21,27 +21,9 @@
|
||||
<div class="btn-group" ng-animate="'fade'" ng-show="formStatus">
|
||||
<p class="btn btn-link umb-status-label">{{formStatus}}</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" ng-class="{dimmed: content.id === 0}">
|
||||
<!-- options button -->
|
||||
<a class="btn" href="#" ng-click="options(content)" prevent-default data-toggle="dropdown">
|
||||
<localize key="general_actions">Actions</localize> <span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- actions -->
|
||||
<ul class="dropdown-menu umb-actions" role="menu" aria-labelledby="dLabel">
|
||||
<li class="action" ng-class="{sep:action.seperator}" ng-repeat="action in actions">
|
||||
|
||||
<!-- How does this reference executeMenuItem() i really don't think that this is very clear -->
|
||||
<a prevent-default
|
||||
ng-click="executeMenuItem(nav.ui.currentNode,action,currentSection)">
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<umb-options-menu content="content" current-section="{{currentSection}}"></umb-options-menu>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</umb-header>
|
||||
|
||||
@@ -87,19 +87,6 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig
|
||||
}
|
||||
});
|
||||
|
||||
$scope.options = function(content){
|
||||
if(!content.id){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$scope.actions){
|
||||
treeService.getMenu({ treeNode: $scope.nav.ui.currentNode })
|
||||
.then(function(data) {
|
||||
$scope.actions = data.menuItems;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.save = function() {
|
||||
|
||||
if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) {
|
||||
|
||||
@@ -17,30 +17,9 @@
|
||||
|
||||
<div class="span8">
|
||||
<div class="btn-toolbar pull-right umb-btn-toolbar">
|
||||
<div class="btn-group" ng-class="{dimmed: content.id === 0}">
|
||||
<!-- options button -->
|
||||
<a class="btn" href="#" ng-click="options(content)" prevent-default data-toggle="dropdown">
|
||||
<i class="icon-settings" style="line-height: 14px"></i>
|
||||
<localize key="general_actions">Actions</localize>
|
||||
</a>
|
||||
|
||||
<a class="btn dropdown-toggle" ng-click="options(content)" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- actions -->
|
||||
<ul class="dropdown-menu umb-actions" role="menu" aria-labelledby="dLabel">
|
||||
<li class="action" ng-class="{sep:action.seperator}" ng-repeat="action in actions">
|
||||
|
||||
<!-- How does this reference executeMenuItem() i really don't think that this is very clear -->
|
||||
<a prevent-default
|
||||
ng-click="executeMenuItem(nav.ui.currentNode,action,currentSection)">
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<umb-options-menu content="content" current-section="{{currentSection}}"></umb-options-menu>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</umb-header>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<ul class="umb-actions">
|
||||
<li class="action" ng-class="{sep:action.seperator}" ng-repeat="action in menuActions">
|
||||
<a prevent-default
|
||||
ng-click="executeMenuItem(currentEntity,action,currentSection)">
|
||||
ng-click="executeMenuItem(action)">
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
<umb-context-menu
|
||||
menu-dialog-title="{{menuDialogTitle}}"
|
||||
current-section="{{currentSection}}"
|
||||
current-entity="menuEntity"
|
||||
current-node="menuNode"
|
||||
menu-actions="menuActions">
|
||||
</umb-context-menu>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
<div class="btn-group" ng-class="{dimmed: content.id === 0}">
|
||||
|
||||
<!-- options button -->
|
||||
<a class="btn" href="#" ng-click="getOptions()" prevent-default data-toggle="dropdown">
|
||||
<localize key="general_actions">Actions</localize>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- actions -->
|
||||
<ul class="dropdown-menu umb-actions" role="menu" aria-labelledby="dLabel">
|
||||
<li class="action" ng-class="{sep:action.seperator}" ng-repeat="action in actions">
|
||||
|
||||
<!-- How does this reference executeMenuItem() i really don't think that this is very clear -->
|
||||
<a prevent-default
|
||||
ng-click="executeMenuItem(action)">
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -20,30 +20,8 @@
|
||||
<p class="btn btn-link umb-status-label">{{formStatus}}</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" ng-class="{dimmed: content.id === 0}">
|
||||
<!-- options button -->
|
||||
<a class="btn" href="#" ng-click="options(content)" prevent-default data-toggle="dropdown">
|
||||
<i class="icon-settings" style="line-height: 14px"></i>
|
||||
<localize key="general_actions">Actions</localize>
|
||||
</a>
|
||||
|
||||
<a class="btn dropdown-toggle" ng-click="options(content)" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- actions -->
|
||||
<ul class="dropdown-menu umb-actions" role="menu" aria-labelledby="dLabel">
|
||||
<li class="action" ng-class="{sep:action.seperator}" ng-repeat="action in actions">
|
||||
|
||||
<!-- How does this reference executeMenuItem() i really don't think that this is very clear -->
|
||||
<a prevent-default
|
||||
ng-click="executeMenuItem(nav.ui.currentNode,action,currentSection)">
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<umb-options-menu content="content" current-section="{{currentSection}}"></umb-options-menu>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</umb-header>
|
||||
|
||||
@@ -38,19 +38,6 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, navi
|
||||
});
|
||||
}
|
||||
|
||||
$scope.options = function(content){
|
||||
if(!content.id){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$scope.actions){
|
||||
treeService.getMenu({ treeNode: $scope.nav.ui.currentNode })
|
||||
.then(function(data) {
|
||||
$scope.actions = data.menuItems;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
$scope.save = function () {
|
||||
|
||||
if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) {
|
||||
|
||||
@@ -20,30 +20,8 @@
|
||||
<p class="btn btn-link umb-status-label">{{formStatus}}</p>
|
||||
</div>
|
||||
|
||||
<div class="btn-group" ng-class="{dimmed: content.id === 0}">
|
||||
<!-- options button -->
|
||||
<a class="btn" href="#" ng-click="options(content)" prevent-default data-toggle="dropdown">
|
||||
<i class="icon-settings" style="line-height: 14px"></i>
|
||||
<localize key="general_actions">Actions</localize>
|
||||
</a>
|
||||
|
||||
<a class="btn dropdown-toggle" ng-click="options(content)" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- actions -->
|
||||
<ul class="dropdown-menu umb-actions" role="menu" aria-labelledby="dLabel">
|
||||
<li class="action" ng-class="{sep:action.seperator}" ng-repeat="action in actions">
|
||||
|
||||
<!-- How does this reference executeMenuItem() i really don't think that this is very clear -->
|
||||
<a prevent-default
|
||||
ng-click="executeMenuItem(nav.ui.currentNode,action,currentSection)">
|
||||
<i class="icon icon-{{action.cssclass}}"></i>
|
||||
<span class="menu-label">{{action.name}}</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<umb-options-menu content="content" current-section="{{currentSection}}"></umb-options-menu>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</umb-header>
|
||||
|
||||
@@ -54,22 +54,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
$scope.options = function(content){
|
||||
if(!content.id){
|
||||
return;
|
||||
}
|
||||
|
||||
if(!$scope.actions){
|
||||
treeService.getMenu({ treeNode: $scope.nav.ui.currentNode })
|
||||
.then(function(data) {
|
||||
$scope.actions = data.menuItems;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
$scope.save = function() {
|
||||
|
||||
if (formHelper.submitForm({ scope: $scope, statusMessage: "Saving..." })) {
|
||||
|
||||
@@ -44,8 +44,8 @@ describe('appState tests', function () {
|
||||
|
||||
describe('Tree state', function () {
|
||||
it('Can get/set state', function () {
|
||||
appState.setTreeState("currentEntity", true);
|
||||
expect(appState.getTreeState("currentEntity")).toBe(true);
|
||||
appState.setTreeState("selectedNode", true);
|
||||
expect(appState.getTreeState("selectedNode")).toBe(true);
|
||||
});
|
||||
it('Throws when invalid key', function () {
|
||||
function setInvalidKey() {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
describe('model mapper tests', function () {
|
||||
var umbModelMapper;
|
||||
|
||||
beforeEach(module('umbraco.services'));
|
||||
|
||||
beforeEach(inject(function ($injector) {
|
||||
umbModelMapper = $injector.get('umbModelMapper');
|
||||
}));
|
||||
|
||||
describe('maps basic entity', function () {
|
||||
|
||||
it('can map content object', function () {
|
||||
var content = {
|
||||
id: "1",
|
||||
name: "test",
|
||||
icon: "icon",
|
||||
key: "some key",
|
||||
parentId: "-1",
|
||||
alias: "test alias",
|
||||
path: "-1,1",
|
||||
metaData: {hello:"world"},
|
||||
publishDate: null,
|
||||
releaseDate: null,
|
||||
removeDate: false,
|
||||
template: "test",
|
||||
urls: [],
|
||||
allowedActions: [],
|
||||
contentTypeName: null,
|
||||
notifications: [],
|
||||
ModelState: {},
|
||||
tabs: [],
|
||||
properties: [],
|
||||
};
|
||||
|
||||
var mapped = umbModelMapper.convertToEntityBasic(content);
|
||||
var keys = _.keys(mapped);
|
||||
|
||||
expect(keys.length).toBe(8);
|
||||
expect(mapped.id).toBe("1");
|
||||
expect(mapped.name).toBe("test");
|
||||
expect(mapped.icon).toBe("icon");
|
||||
expect(mapped.key).toBe("some key");
|
||||
expect(mapped.parentId).toBe("-1");
|
||||
expect(mapped.alias).toBe("test alias");
|
||||
expect(mapped.metaData.hello).toBe("world");
|
||||
});
|
||||
|
||||
it('throws when info is missing', function () {
|
||||
var content = {
|
||||
id: "1",
|
||||
//name: "test", //removed
|
||||
icon: "icon",
|
||||
key: "some key",
|
||||
parentId: "-1",
|
||||
alias: "test alias",
|
||||
path: "-1,1",
|
||||
metaData: { hello: "world" },
|
||||
publishDate: null,
|
||||
releaseDate: null,
|
||||
removeDate: false,
|
||||
template: "test",
|
||||
urls: [],
|
||||
allowedActions: [],
|
||||
contentTypeName: null,
|
||||
notifications: [],
|
||||
ModelState: {},
|
||||
tabs: [],
|
||||
properties: [],
|
||||
};
|
||||
|
||||
function doMap() {
|
||||
umbModelMapper.convertToEntityBasic(content);
|
||||
}
|
||||
|
||||
expect(doMap).toThrow();
|
||||
});
|
||||
|
||||
it('can map the minimum props', function () {
|
||||
var content = {
|
||||
id: "1",
|
||||
name: "test",
|
||||
icon: "icon",
|
||||
parentId: "-1",
|
||||
path: "-1,1"
|
||||
};
|
||||
|
||||
var mapped = umbModelMapper.convertToEntityBasic(content);
|
||||
var keys = _.keys(mapped);
|
||||
|
||||
expect(keys.length).toBe(5);
|
||||
expect(mapped.id).toBe("1");
|
||||
expect(mapped.name).toBe("test");
|
||||
expect(mapped.icon).toBe("icon");
|
||||
expect(mapped.parentId).toBe("-1");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
Reference in New Issue
Block a user