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 6e2c2ae328..79260ace69 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 @@ -395,6 +395,76 @@ function entityResource($q, $http, umbRequestHelper) { )), 'Failed to retrieve child data for id ' + parentId); }, + + /** + * @ngdoc method + * @name umbraco.resources.entityResource#getPagedDescendants + * @methodOf umbraco.resources.entityResource + * + * @description + * Gets paged descendants of a content item with a given id + * + * ##usage + *
+          * entityResource.getPagedDescendants(1234, "Content", {pageSize: 10, pageNumber: 2})
+          *    .then(function(contentArray) {
+          *        var children = contentArray; 
+          *        alert('they are here!');
+          *    });
+          * 
+ * + * @param {Int} parentid id of content item to return descendants of + * @param {string} type Object type name + * @param {Object} options optional options object + * @param {Int} options.pageSize if paging data, number of nodes per page, default = 0 + * @param {Int} options.pageNumber if paging data, current page index, default = 0 + * @param {String} options.filter if provided, query will only return those with names matching the filter + * @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending` + * @param {String} options.orderBy property to order items by, default: `SortOrder` + * @returns {Promise} resourcePromise object containing an array of content items. + * + */ + getPagedDescendants: function (parentId, type, options) { + + var defaults = { + pageSize: 0, + pageNumber: 0, + filter: '', + orderDirection: "Ascending", + orderBy: "SortOrder" + }; + if (options === undefined) { + options = {}; + } + //overwrite the defaults if there are any specified + angular.extend(defaults, options); + //now copy back to the options we will use + options = defaults; + //change asc/desct + if (options.orderDirection === "asc") { + options.orderDirection = "Ascending"; + } + else if (options.orderDirection === "desc") { + options.orderDirection = "Descending"; + } + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "entityApiBaseUrl", + "GetPagedDescendants", + { + id: parentId, + type: type, + pageNumber: options.pageNumber, + pageSize: options.pageSize, + orderBy: options.orderBy, + orderDirection: options.orderDirection, + filter: options.filter + } + )), + 'Failed to retrieve child data for id ' + parentId); + }, /** * @ngdoc method diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js index 5aa249290a..c21fdd8a00 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js @@ -37,7 +37,8 @@ angular.module("umbraco") pageNumber: 1, pageSize: 100, totalItems: 0, - totalPages: 0 + totalPages: 0, + filter: '', }; //preload selected item @@ -233,7 +234,7 @@ angular.module("umbraco") var debounceSearchMedia = _.debounce(function () { $scope.$apply(function () { - if ($scope.searchTerm) { + if ($scope.searchOptions.filter) { searchMedia(); } else { // reset pagination @@ -241,7 +242,8 @@ angular.module("umbraco") pageNumber: 1, pageSize: 100, totalItems: 0, - totalPages: 0 + totalPages: 0, + filter: '' }; getChildren($scope.currentFolder.id); } @@ -250,7 +252,7 @@ angular.module("umbraco") function searchMedia() { $scope.loading = true; - mediaResource.search($scope.searchTerm, $scope.searchOptions.pageNumber, $scope.searchOptions.pageSize, $scope.startNodeId) + entityResource.getPagedDescendants($scope.startNodeId, "Media", $scope.searchOptions) .then(function (data) { // update images $scope.images = data.items ? data.items : []; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html index c980ebd1d2..084559b9c9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.html @@ -18,7 +18,7 @@ GetPagedDescendants( + int id, + UmbracoEntityTypes type, + int pageNumber, + int pageSize, + string orderBy = "SortOrder", + Direction orderDirection = Direction.Ascending, + string filter = "") + { + if (pageNumber <= 0) + throw new HttpResponseException(HttpStatusCode.NotFound); + if (pageSize <= 0) + throw new HttpResponseException(HttpStatusCode.NotFound); + + var objectType = ConvertToObjectType(type); + if (objectType.HasValue) + { + long totalRecords; + var entities = Services.EntityService.GetPagedDescendants(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter); + + if (totalRecords == 0) + { + return new PagedResult(0, 0, 0); + } + + var pagedResult = new PagedResult(totalRecords, pageNumber, pageSize) + { + Items = entities.Select(Mapper.Map) + }; + + return pagedResult; + } + + //now we need to convert the unknown ones + switch (type) + { + case UmbracoEntityTypes.PropertyType: + case UmbracoEntityTypes.PropertyGroup: + case UmbracoEntityTypes.Domain: + case UmbracoEntityTypes.Language: + case UmbracoEntityTypes.User: + case UmbracoEntityTypes.Macro: + default: + throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + type); + } + } + public IEnumerable GetAncestors(int id, UmbracoEntityTypes type) { return GetResultForAncestors(id, type); diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 6efbac94ba..3db1656c34 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -315,31 +315,6 @@ namespace Umbraco.Web.Editors } #endregion - /// - /// Searches media and returns a paged result - /// - /// - /// - /// - /// - /// - [HttpGet] - [FilterAllowedOutgoingMedia(typeof(IEnumerable>), "Items")] - public PagedResult> Search(string query, int pageNumber = 0, - int pageSize = 0, string searchFrom = null) - { - if (string.IsNullOrEmpty(query)) - return new PagedResult>(0, 0, 0); - - var searchResult = ExamineSearch(query, searchFrom).ToArray(); - var items = searchResult.Skip(pageSize * (pageNumber - 1)).Take(pageSize); - var pagedResult = new PagedResult>(searchResult.Length, pageNumber, pageSize); - pagedResult.Items = Services.MediaService.GetByIds(items.Select(x => Convert.ToInt32(x.Id))) - .Select(Mapper.Map>); - - return pagedResult; - } - /// /// Moves an item to the recycle bin, if it is already there then it will permanently delete it /// @@ -858,144 +833,5 @@ namespace Umbraco.Web.Editors return hasPathAccess; } - - /// - /// 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, string searchFrom = null) - { - var sb = new StringBuilder(); - - string type; - var searcher = Constants.Examine.InternalSearcher; - var fields = new[] { "id", "__NodeId" }; - - type = "media"; - - var mediaSearchFrom = int.MinValue; - - if (Security.CurrentUser.StartMediaId > 0 || - //if searchFrom is specified and it is greater than 0 - (searchFrom != null && int.TryParse(searchFrom, out mediaSearchFrom) && mediaSearchFrom > 0)) - { - sb.Append("+__Path: \\-1*\\,"); - sb.Append(mediaSearchFrom > 0 - ? mediaSearchFrom.ToString(CultureInfo.InvariantCulture) - : Security.CurrentUser.StartMediaId.ToString(CultureInfo.InvariantCulture)); - sb.Append("\\,* "); - } - - var internalSearcher = ExamineManager.Instance.SearchProviderCollection[searcher]; - - //build a lucene query: - // the __nodeName will be boosted 10x without wildcards - // then __nodeName will be matched normally with wildcards - // the rest will be normal without wildcards - - - //check if text is surrounded by single or double quotes, if so, then exact match - var surroundedByQuotes = Regex.IsMatch(query, "^\".*?\"$") - || Regex.IsMatch(query, "^\'.*?\'$"); - - if (surroundedByQuotes) - { - //strip quotes, escape string, the replace again - query = query.Trim(new[] { '\"', '\'' }); - - query = Lucene.Net.QueryParsers.QueryParser.Escape(query); - - if (query.IsNullOrWhiteSpace()) - { - return new List(); - } - - //add back the surrounding quotes - query = string.Format("{0}{1}{0}", "\"", query); - - //node name exactly boost x 10 - sb.Append("+(__nodeName: ("); - sb.Append(query.ToLower()); - sb.Append(")^10.0 "); - - foreach (var f in fields) - { - //additional fields normally - sb.Append(f); - sb.Append(": ("); - sb.Append(query); - sb.Append(") "); - } - } - else - { - if (query.Trim(new[] { '\"', '\'' }).IsNullOrWhiteSpace()) - { - return new List(); - } - - query = Lucene.Net.QueryParsers.QueryParser.Escape(query); - - var querywords = query.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - - //node name exactly boost x 10 - sb.Append("+(__nodeName:"); - sb.Append("\""); - sb.Append(query.ToLower()); - sb.Append("\""); - sb.Append("^10.0 "); - - //node name normally with wildcards - sb.Append(" __nodeName:"); - sb.Append("("); - foreach (var w in querywords) - { - sb.Append(w.ToLower()); - sb.Append("* "); - } - sb.Append(") "); - - - foreach (var f in fields) - { - //additional fields normally - sb.Append(f); - sb.Append(":"); - sb.Append("("); - foreach (var w in querywords) - { - sb.Append(w.ToLower()); - sb.Append("* "); - } - sb.Append(")"); - sb.Append(" "); - } - } - - //must match index type - sb.Append(") +__IndexType:"); - sb.Append(type); - - var raw = internalSearcher.CreateSearchCriteria().RawQuery(sb.ToString()); - - //limit results to 200 to avoid huge over processing (CPU) - var result = internalSearcher.Search(raw, 200); - - var mapped = Mapper.Map>(result).ToArray(); - //add additional data - foreach (var m in mapped) - { - //if no icon could be mapped, it will be set to document, so change it to picture - if (m.Icon == "icon-document") - { - m.Icon = "icon-picture"; - } - } - return mapped; - } } }