From c58a9429e133148de35f4bd3a18cf55d4b762a18 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 9 Oct 2014 11:08:09 +1100 Subject: [PATCH] Member picker now using standard treePicker and search is working --- src/Umbraco.Core/Constants-Conventions.cs | 2 + .../src/common/resources/entity.resource.js | 11 ++- .../src/common/services/dialog.service.js | 9 +- .../src/common/services/search.service.js | 6 +- .../common/dialogs/memberpicker.controller.js | 95 ------------------- .../views/common/dialogs/memberpicker.html | 68 ------------- .../common/dialogs/treepicker.controller.js | 20 ++-- .../src/views/common/dialogs/treepicker.html | 4 +- src/Umbraco.Web/Editors/EntityController.cs | 50 +++++++--- src/Umbraco.Web/Editors/MemberController.cs | 2 +- src/Umbraco.Web/Trees/MemberTreeController.cs | 4 +- 11 files changed, 73 insertions(+), 198 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js delete mode 100644 src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.html diff --git a/src/Umbraco.Core/Constants-Conventions.cs b/src/Umbraco.Core/Constants-Conventions.cs index 11255af8e2..59cec787f6 100644 --- a/src/Umbraco.Core/Constants-Conventions.cs +++ b/src/Umbraco.Core/Constants-Conventions.cs @@ -277,6 +277,8 @@ namespace Umbraco.Core public const string DefaultAlias = "Member"; public const string SystemDefaultProtectType = "_umbracoSystemDefaultProtectType"; + + public const string AllMembersListId = "all-members"; } /// diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js index e851f873b0..8e5ed0a9b6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/entity.resource.js @@ -263,14 +263,19 @@ function entityResource($q, $http, umbRequestHelper) { * @returns {Promise} resourcePromise object containing the entity array. * */ - search: function (query, type, startNodeId) { - + search: function (query, type, searchFrom) { + + var args = [{ query: query }, { type: type }]; + if (searchFrom) { + args.push({ searchFrom: searchFrom }); + } + return umbRequestHelper.resourcePromise( $http.get( umbRequestHelper.getApiUrl( "entityApiBaseUrl", "Search", - [{ query: query }, { type: type }, { startNodeId: startNodeId }])), + args)), 'Failed to retrieve entity data for query ' + query); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js b/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js index 802076acb9..5746fd022c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/dialog.service.js @@ -424,9 +424,11 @@ angular.module('umbraco.services') * @returns {Object} modal object */ memberPicker: function (options) { - options.template = 'views/common/dialogs/memberPicker.html'; - options.show = true; - return openDialog(options); + + options.treeAlias = "member"; + options.section = "member"; + + return this.treePicker(options); }, /** @@ -497,6 +499,7 @@ angular.module('umbraco.services') * @param {Object} value value sent to the property editor * @returns {Object} modal object */ + //TODO: Wtf does this do? I don't think anything! propertyDialog: function (options) { options.template = 'views/common/dialogs/property.html'; options.show = true; diff --git a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js index 0167e6b127..6aa1ac5838 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/search.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/search.service.js @@ -63,7 +63,7 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Member").then(function (data) { + return entityResource.search(args.term, "Member", args.searchFrom).then(function (data) { _.each(data, function(item) { configureMemberResult(item); }); @@ -88,7 +88,7 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Document", args.startNodeId).then(function (data) { + return entityResource.search(args.term, "Document", args.searchFrom).then(function (data) { _.each(data, function (item) { configureContentResult(item); }); @@ -113,7 +113,7 @@ angular.module('umbraco.services') throw "args.term is required"; } - return entityResource.search(args.term, "Media", args.startNodeId).then(function (data) { + return entityResource.search(args.term, "Media", args.searchFrom).then(function (data) { _.each(data, function (item) { configureMediaResult(item); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js deleted file mode 100644 index cddddd5f9f..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.controller.js +++ /dev/null @@ -1,95 +0,0 @@ -//used for the member picker dialog -angular.module("umbraco").controller("Umbraco.Dialogs.MemberPickerController", - function($scope, eventsService, entityResource, searchService, $log) { - var dialogOptions = $scope.dialogOptions; - $scope.dialogTreeEventHandler = $({}); - $scope.results = []; - - /** Method used for selecting a node */ - function select(text, key, entity) { - - $scope.showSearch = false; - $scope.results = []; - $scope.term = ""; - $scope.oldTerm = undefined; - - if (dialogOptions.multiPicker) { - $scope.select(key); - } - else { - //if an entity has been passed in, use it - if (entity) { - $scope.submit(entity); - } - else { - //otherwise we have to get it from the server - entityResource.getById(key, "Member").then(function (ent) { - $scope.submit(ent); - }); - } - } - } - - - //TODO: This needs debounce! - $scope.performSearch = function() { - if ($scope.term) { - if ($scope.oldTerm !== $scope.term) { - $scope.results = []; - searchService.searchMembers({ term: $scope.term }).then(function(data) { - $scope.results = data; - }); - $scope.showSearch = true; - $scope.oldTerm = $scope.term; - } - } - else { - $scope.oldTerm = ""; - $scope.showSearch = false; - $scope.results = []; - } - }; - - /** method to select a search result */ - $scope.selectResult = function(result) { - //since result = an entity, we'll pass it in so we don't have to go back to the server - select(result.name, result.id, result); - }; - - function nodeSelectHandler(ev, args) { - args.event.preventDefault(); - args.event.stopPropagation(); - - if (args.node.nodeType === "member-folder") { - return; - } - - eventsService.emit("dialogs.memberPickerController", args); - - //This is a tree node, so we don't have an entity to pass in, it will need to be looked up - //from the server in this method. - select(args.node.name, args.node.id); - - if (dialogOptions && dialogOptions.multipicker) { - - var c = $(args.event.target.parentElement); - if (!args.node.selected) { - args.node.selected = true; - c.find("i.umb-tree-icon").hide() - .after(""); - } - else { - args.node.selected = false; - c.find(".temporary").remove(); - c.find("i.umb-tree-icon").show(); - } - } - - } - - $scope.dialogTreeEventHandler.bind("treeNodeSelect", nodeSelectHandler); - - $scope.$on('$destroy', function () { - $scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler); - }); - }); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.html deleted file mode 100644 index e36f1bf724..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/memberpicker.html +++ /dev/null @@ -1,68 +0,0 @@ -
-
-
- -
-
- - - -
\ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js index f31125e5d5..6c1d9e4d4f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.controller.js @@ -13,8 +13,8 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController", }); $scope.searchInfo = { selectedSearchResults: [], - searchStartNodeId: null, - searchStartNodeName: null, + searchFrom: null, + searchFromName: null, showSearch: false, term: null, oldTerm: null, @@ -28,7 +28,7 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController", //search defaults var searcher = searchService.searchContent; var entityType = "Document"; - $scope.results = []; + //min / max values if (dialogOptions.minNumber) { @@ -41,7 +41,7 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController", //search if (dialogOptions.section === "member") { searcher = searchService.searchMembers; - entityType = "Member"; + entityType = "Member"; } else if (dialogOptions.section === "media") { searcher = searchService.searchMedia; @@ -68,8 +68,8 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController", function nodeSearchHandler(ev, args) { if (args.node.metaData.isContainer === true) { $scope.searchInfo.showSearch = true; - $scope.searchInfo.searchStartNodeName = args.node.name; - $scope.searchInfo.searchStartNodeId = args.node.id; + $scope.searchInfo.searchFromName = args.node.name; + $scope.searchInfo.searchFrom = args.node.id; } } @@ -213,8 +213,8 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController", $scope.hideSearch = function() { $scope.searchInfo.showSearch = false; - $scope.searchInfo.searchStartNodeName = null; - $scope.searchInfo.searchStartNodeId = null; + $scope.searchInfo.searchFromName = null; + $scope.searchInfo.searchFrom = null; $scope.searchInfo.term = null; $scope.searchInfo.oldTerm = null; $scope.searchInfo.results = []; @@ -231,8 +231,8 @@ angular.module("umbraco").controller("Umbraco.Dialogs.TreePickerController", term: $scope.searchInfo.term }; //append a start node id, whether it's a global one, or based on a selected list view - if ($scope.searchInfo.searchStartNodeId || dialogOptions.startNodeId) { - searchArgs["startNodeId"] = $scope.searchInfo.searchStartNodeId ? $scope.searchInfo.searchStartNodeId : dialogOptions.startNodeId; + if ($scope.searchInfo.searchFrom || dialogOptions.startNodeId) { + searchArgs["searchFrom"] = $scope.searchInfo.searchFrom ? $scope.searchInfo.searchFrom : dialogOptions.startNodeId; } searcher(searchArgs).then(function (data) { $scope.searchInfo.results = data; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.html index 6088c3de06..8775fc02cb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/treepicker.html @@ -10,9 +10,9 @@ placeholder="{{searchPlaceholderText}}" on-keyup="performSearch()" focus-when="{{searchInfo.showSearch}}"> -

+

Search - {{searchInfo.searchStartNodeName}} + {{searchInfo.searchFromName}}

diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 24cb4356a9..fc34f4cc00 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Net; using System.Text; using System.Web.Http; @@ -39,13 +40,25 @@ namespace Umbraco.Web.Editors [PluginController("UmbracoApi")] public class EntityController : UmbracoAuthorizedJsonController { + /// + /// Searches for results based on the entity type + /// + /// + /// + /// + /// A starting point for the search, generally a node id, but for members this is a member type alias + /// + /// [HttpGet] - public IEnumerable Search(string query, UmbracoEntityTypes type, int? startNodeId = null) + public IEnumerable Search(string query, UmbracoEntityTypes type, string searchFrom = null) { + //TODO: Should we restrict search results based on what app the user has access to? + // - Theoretically you shouldn't be able to see member data if you don't have access to members right? + if (string.IsNullOrEmpty(query)) return Enumerable.Empty(); - return ExamineSearch(query, type, startNodeId); + return ExamineSearch(query, type, searchFrom); } /// @@ -259,7 +272,16 @@ namespace Umbraco.Web.Editors return GetResultForAll(type, postFilter, postFilterParams); } - private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, int? startNodeId = null) + /// + /// Searches for results based on the entity type + /// + /// + /// + /// + /// A starting point for the search, generally a node id, but for members this is a member type alias + /// + /// + private IEnumerable ExamineSearch(string query, UmbracoEntityTypes entityType, string searchFrom = null) { var sb = new StringBuilder(); @@ -274,24 +296,30 @@ namespace Umbraco.Web.Editors searcher = Constants.Examine.InternalMemberSearcher; type = "member"; fields = new[] { "id", "__NodeId", "email", "loginName"}; + if (searchFrom != null && searchFrom != Constants.Conventions.MemberTypes.AllMembersListId) + { + sb.Append("+__NodeTypeAlias:"); + sb.Append(searchFrom); + sb.Append(" "); + } break; case UmbracoEntityTypes.Media: type = "media"; - if (Security.CurrentUser.StartMediaId > 0 || startNodeId.HasValue) + if (Security.CurrentUser.StartMediaId > 0 || searchFrom != null) { - sb.Append("+__Path: \\-1*\\," + - (startNodeId.HasValue ? startNodeId.Value : Security.CurrentUser.StartMediaId) + - "\\,* "); + sb.Append("+__Path: \\-1*\\,"); + sb.Append((searchFrom ?? Security.CurrentUser.StartMediaId.ToString(CultureInfo.InvariantCulture))); + sb.Append("\\,* "); } break; case UmbracoEntityTypes.Document: type = "content"; - if (Security.CurrentUser.StartMediaId > 0 || startNodeId.HasValue) + if (Security.CurrentUser.StartMediaId > 0 || searchFrom != null) { - sb.Append("+__Path: \\-1*\\," + - (startNodeId.HasValue ? startNodeId.Value : Security.CurrentUser.StartContentId) + - "\\,* "); + sb.Append("+__Path: \\-1*\\,"); + sb.Append((searchFrom ?? Security.CurrentUser.StartContentId.ToString(CultureInfo.InvariantCulture))); + sb.Append("\\,* "); } break; default: diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 80a6bf6781..a696ccf0b1 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -127,7 +127,7 @@ namespace Umbraco.Web.Editors ContentTypeName = listName, Id = listName, IsContainer = true, - Name = listName == "all-members" ? "All Members" : listName, + Name = listName == Constants.Conventions.MemberTypes.AllMembersListId ? "All Members" : listName, Path = "-1," + listName, ParentId = -1 }; diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index 7819dae8cc..d45d0608be 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -122,8 +122,8 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { nodes.Add( - CreateTreeNode("all-members", id, queryStrings, "All Members", "icon-users", false, - queryStrings.GetValue("application") + TreeAlias.EnsureStartsWith('/') + "/list/all-members")); + CreateTreeNode(Constants.Conventions.MemberTypes.AllMembersListId, id, queryStrings, "All Members", "icon-users", false, + queryStrings.GetValue("application") + TreeAlias.EnsureStartsWith('/') + "/list/" + Constants.Conventions.MemberTypes.AllMembersListId)); if (_isUmbracoProvider) {