From 9461e35028494fdcc2a80f87df2bb43824c1923b Mon Sep 17 00:00:00 2001 From: Emil Wangaa Date: Mon, 13 Feb 2017 09:54:50 +0100 Subject: [PATCH 1/9] Adds endpoint for searching media for the mediapicker --- src/Umbraco.Web/Editors/EntityController.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 104c451273..485512cefb 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -81,6 +81,26 @@ namespace Umbraco.Web.Editors return ExamineSearch(query, type, searchFrom); } + /// + /// Searches media and returns a list of ContentItemBasic based on the IMedia + /// + /// + /// + /// + [HttpGet] + public IEnumerable> SearchMedia(string query, string searchFrom = null) + { + if (string.IsNullOrEmpty(query)) + return Enumerable.Empty>(); + + // limiting the examine results to 50 to avoid killing the GetByIds lookup + var searchResult = ExamineSearch(query, UmbracoEntityTypes.Media, searchFrom).Take(50); + var mediaItems = Services.MediaService.GetByIds(searchResult.Select(x => Convert.ToInt32(x.Id))) + .Select(Mapper.Map>); + + return mediaItems; + } + /// /// Searches for all content that the user is allowed to see (based on their allowed sections) /// From 21f947efbd12c2957c1368c388c7374a32adbac8 Mon Sep 17 00:00:00 2001 From: Emil Wangaa Date: Mon, 13 Feb 2017 11:21:09 +0100 Subject: [PATCH 2/9] Moves media search to MediaController and implements paging for the endpoint --- src/Umbraco.Web/Editors/EntityController.cs | 20 --- src/Umbraco.Web/Editors/MediaController.cs | 166 ++++++++++++++++++++ 2 files changed, 166 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Web/Editors/EntityController.cs b/src/Umbraco.Web/Editors/EntityController.cs index 485512cefb..104c451273 100644 --- a/src/Umbraco.Web/Editors/EntityController.cs +++ b/src/Umbraco.Web/Editors/EntityController.cs @@ -81,26 +81,6 @@ namespace Umbraco.Web.Editors return ExamineSearch(query, type, searchFrom); } - /// - /// Searches media and returns a list of ContentItemBasic based on the IMedia - /// - /// - /// - /// - [HttpGet] - public IEnumerable> SearchMedia(string query, string searchFrom = null) - { - if (string.IsNullOrEmpty(query)) - return Enumerable.Empty>(); - - // limiting the examine results to 50 to avoid killing the GetByIds lookup - var searchResult = ExamineSearch(query, UmbracoEntityTypes.Media, searchFrom).Take(50); - var mediaItems = Services.MediaService.GetByIds(searchResult.Select(x => Convert.ToInt32(x.Id))) - .Select(Mapper.Map>); - - return mediaItems; - } - /// /// Searches for all content that the user is allowed to see (based on their allowed sections) /// diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 77ab9ff6e5..6021378b2d 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Globalization; using System.IO; using System.Net; using System.Net.Http; @@ -28,7 +29,9 @@ using Umbraco.Web.Mvc; using Umbraco.Web.WebApi; using System.Linq; using System.Runtime.Serialization; +using System.Text.RegularExpressions; using System.Web.Http.Controllers; +using Examine; using Umbraco.Web.WebApi.Binders; using Umbraco.Web.WebApi.Filters; using umbraco; @@ -277,6 +280,30 @@ namespace Umbraco.Web.Editors throw new HttpResponseException(HttpStatusCode.NotFound); } + /// + /// Searches media and returns a paged result + /// + /// + /// + /// + /// + /// + [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 /// @@ -795,5 +822,144 @@ 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; + } } } From 051b3f2e6a4637626f3a47083ca0875a523262de Mon Sep 17 00:00:00 2001 From: Emil Wangaa Date: Mon, 13 Feb 2017 11:23:21 +0100 Subject: [PATCH 3/9] Allows get for search media endpoint --- src/Umbraco.Web/Editors/MediaController.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Umbraco.Web/Editors/MediaController.cs b/src/Umbraco.Web/Editors/MediaController.cs index 6021378b2d..0f9c1384ed 100644 --- a/src/Umbraco.Web/Editors/MediaController.cs +++ b/src/Umbraco.Web/Editors/MediaController.cs @@ -288,6 +288,7 @@ namespace Umbraco.Web.Editors /// /// /// + [HttpGet] [FilterAllowedOutgoingMedia(typeof(IEnumerable>), "Items")] public PagedResult> Search(string query, int pageNumber = 0, int pageSize = 0, string searchFrom = null) From 7c049b55a8708e7a63488fdc16607f03494f0785 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 13 Feb 2017 14:36:39 +0100 Subject: [PATCH 4/9] media picker - search media library instead of filter current folder --- .../src/common/resources/media.resource.js | 42 +++++++ .../mediaPicker/mediapicker.controller.js | 114 +++++++++++++----- .../overlays/mediaPicker/mediapicker.html | 30 ++++- 3 files changed, 154 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js index 4b56e55801..bbb78cd616 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/media.resource.js @@ -482,7 +482,49 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) { "mediaApiBaseUrl", "EmptyRecycleBin")), 'Failed to empty the recycle bin'); + }, + + /** + * @ngdoc method + * @name umbraco.resources.mediaResource#search + * @methodOf umbraco.resources.mediaResource + * + * @description + * Empties the media recycle bin + * + * ##usage + *
+          * mediaResource.search("my search", 1, 100, -1)
+          *    .then(function(searchResult) {
+          *        alert('it's here!');
+          *    });
+          * 
+ * + * @param {string} query The search query + * @param {int} pageNumber The page number + * @param {int} pageSize The number of media items on a page + * @param {int} searchFrom Id to search from + * @returns {Promise} resourcePromise object. + * + */ + search: function (query, pageNumber, pageSize, searchFrom) { + + var args = [ + { "query": query }, + { "pageNumber": pageNumber }, + { "pageSize": pageSize }, + { "searchFrom": searchFrom } + ]; + + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "mediaApiBaseUrl", + "Search", + args)), + 'Failed to retrieve media items for search: ' + query); } + }; } 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 3b6c39e84a..5aa249290a 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 @@ -33,6 +33,13 @@ angular.module("umbraco") $scope.acceptedMediatypes = types; }); + $scope.searchOptions = { + pageNumber: 1, + pageSize: 100, + totalItems: 0, + totalPages: 0 + }; + //preload selected item $scope.target = undefined; if (dialogOptions.currentTarget) { @@ -106,35 +113,9 @@ angular.module("umbraco") $scope.path = []; } - //mediaResource.rootMedia() - mediaResource.getChildren(folder.id) - .then(function(data) { - $scope.searchTerm = ""; - $scope.images = data.items ? data.items : []; - - // set already selected images to selected - for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) { - var folderImage = $scope.images[folderImageIndex]; - var imageIsSelected = false; - - for (var selectedImageIndex = 0; - selectedImageIndex < $scope.model.selectedImages.length; - selectedImageIndex++) { - var selectedImage = $scope.model.selectedImages[selectedImageIndex]; - - if (folderImage.key === selectedImage.key) { - imageIsSelected = true; - } - } - if (imageIsSelected) { - folderImage.selected = true; - } - } - }); + getChildren(folder.id); $scope.currentFolder = folder; - localStorageService.set("umbLastOpenedMediaNodeId", folder.id); - }; $scope.clickHandler = function(image, event, index) { @@ -238,4 +219,83 @@ angular.module("umbraco") $scope.mediaPickerDetailsOverlay = null; }; }; + + $scope.changeSearch = function() { + $scope.loading = true; + debounceSearchMedia(); + }; + + $scope.changePagination = function(pageNumber) { + $scope.loading = true; + $scope.searchOptions.pageNumber = pageNumber; + searchMedia(); + }; + + var debounceSearchMedia = _.debounce(function () { + $scope.$apply(function () { + if ($scope.searchTerm) { + searchMedia(); + } else { + // reset pagination + $scope.searchOptions = { + pageNumber: 1, + pageSize: 100, + totalItems: 0, + totalPages: 0 + }; + getChildren($scope.currentFolder.id); + } + }); + }, 500); + + function searchMedia() { + $scope.loading = true; + mediaResource.search($scope.searchTerm, $scope.searchOptions.pageNumber, $scope.searchOptions.pageSize, $scope.startNodeId) + .then(function (data) { + // update images + $scope.images = data.items ? data.items : []; + // update pagination + $scope.searchOptions = { + pageNumber: data.pageNumber, + pageSize: data.pageSize, + totalItems: data.totalItems, + totalPages: data.totalPages + }; + // set already selected images to selected + preSelectImages(); + $scope.loading = false; + }); + } + + function getChildren(id) { + $scope.loading = true; + mediaResource.getChildren(id) + .then(function(data) { + $scope.searchTerm = ""; + $scope.images = data.items ? data.items : []; + // set already selected images to selected + preSelectImages(); + $scope.loading = false; + }); + } + + function preSelectImages() { + for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) { + var folderImage = $scope.images[folderImageIndex]; + var imageIsSelected = false; + + for (var selectedImageIndex = 0; + selectedImageIndex < $scope.model.selectedImages.length; + selectedImageIndex++) { + var selectedImage = $scope.model.selectedImages[selectedImageIndex]; + + if (folderImage.key === selectedImage.key) { + imageIsSelected = true; + } + } + if (imageIsSelected) { + folderImage.selected = true; + } + } + } }); 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 993ede9587..c980ebd1d2 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 @@ -10,13 +10,18 @@
+ + + @@ -32,7 +37,7 @@
-
+
  • Media @@ -63,20 +68,20 @@
+
+ + +
+ + + + +
Date: Thu, 16 Feb 2017 14:41:50 +0100 Subject: [PATCH 5/9] Adds GetPagedDescendants to EntityController Implements GetPagedDescendants in the mediapicker Search Removes duplicate ExamineSearch and Search endpoint code from MediaController --- .../src/common/resources/entity.resource.js | 70 ++++++++ .../mediaPicker/mediapicker.controller.js | 10 +- .../overlays/mediaPicker/mediapicker.html | 2 +- src/Umbraco.Web/Editors/EntityController.cs | 47 +++++ src/Umbraco.Web/Editors/MediaController.cs | 164 ------------------ 5 files changed, 124 insertions(+), 169 deletions(-) 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; - } } } From d5f66ebe02767850dc0f57afcd9f606d05f28039 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 16 Feb 2017 19:59:45 +0100 Subject: [PATCH 6/9] update image properties to match media grid component --- .../mediaPicker/mediapicker.controller.js | 29 ++++++++++++++----- .../overlays/mediaPicker/mediapicker.html | 8 ++--- 2 files changed, 26 insertions(+), 11 deletions(-) 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 c21fdd8a00..9cb78cdff2 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 @@ -254,15 +254,30 @@ angular.module("umbraco") $scope.loading = true; entityResource.getPagedDescendants($scope.startNodeId, "Media", $scope.searchOptions) .then(function (data) { + // update image data to work with image grid + angular.forEach(data.items, function(mediaItem){ + // set thumbnail and src + mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true); + mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false); + // set properties to match a media object + mediaItem.properties = [ + { + alias: "umbracoWidth", + value: mediaItem.metaData.umbracoWidth.Value + }, + { + alias: "umbracoHeight", + value: mediaItem.metaData.umbracoHeight.Value + } + ]; + }); // update images $scope.images = data.items ? data.items : []; // update pagination - $scope.searchOptions = { - pageNumber: data.pageNumber, - pageSize: data.pageSize, - totalItems: data.totalItems, - totalPages: data.totalPages - }; + $scope.searchOptions.pageNumber = data.pageNumber; + $scope.searchOptions.pageSize = data.pageSize; + $scope.searchOptions.totalItems = data.totalItems; + $scope.searchOptions.totalPages = data.totalPages; // set already selected images to selected preSelectImages(); $scope.loading = false; @@ -273,7 +288,7 @@ angular.module("umbraco") $scope.loading = true; mediaResource.getChildren(id) .then(function(data) { - $scope.searchTerm = ""; + $scope.searchOptions.filter = ""; $scope.images = data.items ? data.items : []; // set already selected images to selected preSelectImages(); 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 084559b9c9..01355dcf12 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 @@ -17,7 +17,7 @@