From ed019a90e2b43208eb85a8e7b84fdd78f3c3116f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 30 Jan 2017 14:25:10 +0100 Subject: [PATCH 01/58] start on mini list view for pickers --- .../src/less/components/umb-table.less | 13 ++ .../treepicker/treepicker.controller.js | 100 ++++++++++++- .../overlays/treepicker/treepicker.html | 141 ++++++++++++++---- 3 files changed, 216 insertions(+), 38 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less index bc8e19cf2b..7f4afc3de7 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-table.less @@ -256,3 +256,16 @@ input.umb-table__input { flex: 1 1 25%; max-width: 25%; } + +.umb-table--condensed { + + .umb-table-cell:first-of-type:not(.not-fixed) { + padding-top: 10px; + padding-bottom: 10px; + } + + .umb-table-body__icon { + font-size: 20px; + } + +} diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js index e69b5ee3ce..8bcf427d7e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js @@ -1,6 +1,6 @@ //used for the media picker dialog angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", - function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService) { + function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService, contentResource) { var tree = null; var dialogOptions = $scope.model; @@ -106,13 +106,16 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", //iterate children _.each(args.children, function (child) { + console.log("child", child); + //check if any of the items are list views, if so we need to add some custom // children: A node to activate the search, any nodes that have already been // selected in the search if (child.metaData.isContainer) { child.hasChildren = true; child.children = [ - { + { + id: child.id, level: child.level + 1, hasChildren: false, parent: function () { @@ -177,13 +180,26 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", if (args.node.metaData.listViewNode) { //check if list view 'search' node was selected - $scope.searchInfo.showSearch = true; - $scope.searchInfo.searchFromId = args.node.metaData.listViewNode.id; - $scope.searchInfo.searchFromName = args.node.metaData.listViewNode.name; + //alert("list view"); + + $scope.showMiniListView = true; + + console.log(args); + + $scope.pagination = { + pageSize: 10, + pageNumber: 1, + filter: '', + orderDirection: "Ascending", + orderBy: "SortOrder", + orderBySystemField: true + }; + + getPagedChildren(args.node); + + $scope.miniListView.nodeName = args.node.metaData.listViewNode.name; + $scope.miniListView.nodeId = args.node.metaData.listViewNode.id; - //add transition classes - var listViewNode = args.node.parent(); - listViewNode.cssClasses.push('tree-node-slide-up-hide-active'); } else if (args.node.metaData.isSearchResult) { //check if the item selected was a search result from a list view @@ -504,4 +520,72 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", $scope.dialogTreeEventHandler.unbind("treeNodeExpanded", nodeExpandedHandler); $scope.dialogTreeEventHandler.unbind("treeNodeSelect", nodeSelectHandler); }); + + /* Mini List View */ + $scope.miniListView = {}; + + $scope.nextPage = function(pageNumber) { + $scope.pagination.pageNumber = pageNumber; + getPagedChildren($scope.miniListView.node); + }; + + $scope.prevPage = function(pageNumber) { + $scope.pagination.pageNumber = pageNumber; + getPagedChildren($scope.miniListView.node); + }; + + $scope.goToPage = function(pageNumber) { + $scope.pagination.pageNumber = pageNumber; + getPagedChildren($scope.miniListView.node); + }; + + $scope.selectListViewItem = function(item) { + select(item.name, item.id); + //toggle checked state + item.selected = item.selected === true ? false : true; + }; + + $scope.exitMiniListView = function() { + console.log($scope.miniListView); + $scope.showMiniListView = false; + }; + + $scope.searchMiniListView = function() { + searchMiniListView(); + }; + + function getPagedChildren(node) { + + // start load indicator + $scope.miniListView.loading = true; + + contentResource.getChildren(node.id, $scope.pagination) + .then(function (data) { + + // update children + $scope.miniListView.node = node; + $scope.miniListView.children = data.items; + + // update pagination + $scope.pagination.totalItems = data.totalItems; + $scope.pagination.totalPages = data.totalPages; + + // stop load indicator + $scope.miniListView.loading = false; + + }); + + } + + var searchMiniListView = _.debounce(function () { + + $scope.$apply(function () { + if ($scope.pagination.filter !== null && $scope.pagination.filter !== undefined) { + $scope.pagination.pageNumber = 1; + getPagedChildren($scope.miniListView.node, $scope.pagination); + } + }); + + }, 500); + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html index b009b4d45f..fe2c479e4e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html @@ -1,35 +1,116 @@
-
- - -
+
+
+ + +
- - + + -
- - -
+
+ + +
+
-
+
+ +
+
+ + + +

{{ miniListView.nodeName }}

+
+
+ +
+ + +
+
+
+ +
+ Name +
+
+ +
+
+
+ + +
+ + +
+
+ + +
+
{{ child.name }}
+
+ + +
+ +
+ +
+ +
+ +
+ + +
+ +
+ + \ No newline at end of file From 4336f5201d3f5efd3cd09a4d608f892e67fb50d5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 30 Jan 2017 22:34:04 +0100 Subject: [PATCH 02/58] show expand arrow for list views --- .../directives/components/tree/umbtreeitem.directive.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js index f4fe0db4e6..e519bb78b0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtreeitem.directive.js @@ -74,11 +74,14 @@ angular.module("umbraco.directives") //toggle visibility of last 'ins' depending on children //visibility still ensure the space is "reserved", so both nodes with and without children are aligned. - if (!node.hasChildren) { - element.find("ins").last().css("visibility", "hidden"); + + console.log(node); + + if (node.hasChildren || node.metaData.isContainer) { + element.find("ins").last().css("visibility", "visible"); } else { - element.find("ins").last().css("visibility", "visible"); + element.find("ins").last().css("visibility", "hidden"); } var icon = element.find("i:first"); From bf797bccc7ea09966cd2ad6c31e39206d2a12d1b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 30 Jan 2017 22:35:19 +0100 Subject: [PATCH 03/58] open list view on expand --- .../treepicker/treepicker.controller.js | 44 +++++++++++++++++-- .../overlays/treepicker/treepicker.html | 15 ++++--- 2 files changed, 50 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js index 8bcf427d7e..a1ee1f031f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js @@ -1,6 +1,6 @@ //used for the media picker dialog angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", - function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService, contentResource) { + function ($scope, entityResource, eventsService, $log, searchService, angularHelper, $timeout, localizationService, treeService, contentResource, mediaResource, memberResource) { var tree = null; var dialogOptions = $scope.model; @@ -101,6 +101,13 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", } function nodeExpandedHandler(ev, args) { + + console.log("args", args); + + if (args.node.metaData.isContainer) { + openMiniListView(args.node); + } + if (angular.isArray(args.children)) { //iterate children @@ -111,6 +118,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", //check if any of the items are list views, if so we need to add some custom // children: A node to activate the search, any nodes that have already been // selected in the search + /* if (child.metaData.isContainer) { child.hasChildren = true; child.children = [ @@ -151,6 +159,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", }); }); } + */ //now we need to look in the already selected search results and // toggle the check boxes for those ones that are listed @@ -554,16 +563,43 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", searchMiniListView(); }; + function openMiniListView(node) { + + $scope.showMiniListView = true; + + $scope.pagination = { + pageSize: 10, + pageNumber: 1, + filter: '', + orderDirection: "Ascending", + orderBy: "SortOrder", + orderBySystemField: true + }; + + getPagedChildren(node); + + } + function getPagedChildren(node) { // start load indicator + $scope.miniListView.node = node; $scope.miniListView.loading = true; + + var promise = ""; - contentResource.getChildren(node.id, $scope.pagination) + if(node.nodeType === "content") { + promise = contentResource.getChildren(node.id, $scope.pagination); + } else if( node.nodeType === "member") { + promise = memberResource.getPagedResults(node.id, $scope.pagination); + } else if(node.nodeType === "media") { + promise = mediaResource.getChildren(node.id, $scope.pagination); + } + + promise .then(function (data) { - + // update children - $scope.miniListView.node = node; $scope.miniListView.children = data.items; // update pagination diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html index fe2c479e4e..a37a63bb0f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html @@ -1,6 +1,7 @@
+
-
+
+
-
+
- - + + Back -

{{ miniListView.nodeName }}

+

+ + {{ miniListView.node.name }} +

From f192f241cfef14ca19f81ef7b772db8e98b7773f Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 31 Jan 2017 13:48:47 +1100 Subject: [PATCH 04/58] U4-9450 Paged data queries return all property data in the entire database, not just for the paged subset --- .../Repositories/ContentRepository.cs | 9 +++++---- .../Persistence/Repositories/MediaRepository.cs | 10 +++++----- .../Repositories/MemberRepository.cs | 10 +++++----- .../Repositories/VersionableRepositoryBase.cs | 17 +++++++++++------ 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index b02f5304e6..f7b88ef46b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -859,7 +859,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsDocument", "nodeId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds), orderBy, orderDirection, orderBySystemField, + (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds, isPaged:true), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -899,9 +899,10 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", /// /// The Id SQL without the outer join to just return all document ids - used to process the properties for the content item /// + /// True if this is a paged query /// /// - private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false) + private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false, bool isPaged = false) { // fetch returns a list so it's ok to iterate it in this method var dtos = Database.Fetch(sqlFull); @@ -967,7 +968,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", .ToDictionary(x => x.Id, x => x); // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sqlIds, defs); + var propertyData = GetPropertyCollection(sqlIds, defs, isPaged); // assign var dtoIndex = 0; @@ -1014,7 +1015,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", var docDef = new DocumentDefinition(dto.NodeId, versionId, content.UpdateDate, content.CreateDate, contentType); - var properties = GetPropertyCollection(docSql, new[] { docDef }); + var properties = GetPropertyCollection(docSql, new[] { docDef }, false); content.Properties = properties[dto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 8cfb037c6c..8bcfc3558b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -146,7 +146,7 @@ namespace Umbraco.Core.Persistence.Repositories return ProcessQuery(sql, true); } - private IEnumerable ProcessQuery(Sql sql, bool withCache = false) + private IEnumerable ProcessQuery(Sql sql, bool withCache = false, bool isPaged = false) { // fetch returns a list so it's ok to iterate it in this method var dtos = Database.Fetch(sql); @@ -200,7 +200,7 @@ namespace Umbraco.Core.Persistence.Repositories } // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sql, defs); + var propertyData = GetPropertyCollection(sql, defs, isPaged); // assign var dtoIndex = 0; @@ -507,7 +507,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsContentVersion", "contentId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull), orderBy, orderDirection, orderBySystemField, + (sqlFull, sqlIds) => ProcessQuery(sqlFull, isPaged:true), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -515,7 +515,7 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Private method to create a media object from a ContentDto /// - /// + /// /// /// /// @@ -527,7 +527,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.NodeId, versionId, media.UpdateDate, media.CreateDate, contentType); - var properties = GetPropertyCollection(docSql, new[] { docDef }); + var properties = GetPropertyCollection(docSql, new[] { docDef }, false); media.Properties = properties[dto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index 8b3bf4a471..f83fdcef51 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -449,7 +449,7 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new MemberFactory(memberType, NodeObjectTypeId, dto.NodeId); var media = factory.BuildEntity(dto); - var properties = GetPropertyCollection(sql, new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) }); + var properties = GetPropertyCollection(sql, new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) }, false); media.Properties = properties[dto.NodeId]; @@ -624,7 +624,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsMember", "nodeId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull), orderBy, orderDirection, orderBySystemField, + (sqlFull, sqlIds) => ProcessQuery(sqlFull, isPaged:true), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -664,7 +664,7 @@ namespace Umbraco.Core.Persistence.Repositories return base.GetEntityPropertyNameForOrderBy(orderBy); } - private IEnumerable ProcessQuery(Sql sql, bool withCache = false) + private IEnumerable ProcessQuery(Sql sql, bool withCache = false, bool isPaged = false) { // fetch returns a list so it's ok to iterate it in this method var dtos = Database.Fetch(sql); @@ -704,7 +704,7 @@ namespace Umbraco.Core.Persistence.Repositories } // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sql, defs); + var propertyData = GetPropertyCollection(sql, defs, isPaged); // assign var dtoIndex = 0; @@ -741,7 +741,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.ContentVersionDto.NodeId, versionId, member.UpdateDate, member.CreateDate, memberType); - var properties = GetPropertyCollection(docSql, new[] { docDef }); + var properties = GetPropertyCollection(docSql, new[] { docDef }, false); member.Properties = properties[dto.ContentVersionDto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 31fc4a3f68..26c53a091f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -465,7 +465,7 @@ namespace Umbraco.Core.Persistence.Repositories // the pageResult, then the GetAll will actually return ALL records in the db. if (pagedResult.Items.Any()) { - //Crete the inner paged query that was used above to get the paged result, we'll use that as the inner sub query + //Create the inner paged query that was used above to get the paged result, we'll use that as the inner sub query var args = sqlNodeIdsWithSort.Arguments; string sqlStringCount, sqlStringPage; Database.BuildPageQueries(pageIndex * pageSize, pageSize, sqlNodeIdsWithSort.SQL, ref args, out sqlStringCount, out sqlStringPage); @@ -486,7 +486,10 @@ namespace Umbraco.Core.Persistence.Repositories GetFilteredSqlForPagedResults(fullQueryWithPagedInnerJoin, defaultFilter), orderDirection, orderBy, orderBySystemField, nodeIdSelect); - return processQuery(fullQuery, sqlNodeIdsWithSort); + //get the id query in the paged format + var idPagedQuery = new Sql(sqlStringPage, args); + + return processQuery(fullQuery, idPagedQuery); } else { @@ -498,15 +501,17 @@ namespace Umbraco.Core.Persistence.Repositories protected IDictionary GetPropertyCollection( Sql docSql, - IReadOnlyCollection documentDefs) + IReadOnlyCollection documentDefs, + bool isPaged) { if (documentDefs.Count == 0) return new Dictionary(); //we need to parse the original SQL statement and reduce the columns to just cmsContent.nodeId, cmsContentVersion.VersionId so that we can use // the statement to go get the property data for all of the items by using an inner join var parsedOriginalSql = "SELECT {0} " + docSql.SQL.Substring(docSql.SQL.IndexOf("FROM", StringComparison.Ordinal)); - //now remove everything from an Orderby clause and beyond - if (parsedOriginalSql.InvariantContains("ORDER BY ")) + + //now remove everything from an Orderby clause and beyond if this is unpaged data + if (isPaged == false && parsedOriginalSql.InvariantContains("ORDER BY ")) { parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal)); } @@ -524,7 +529,7 @@ WHERE EXISTS( INNER JOIN cmsPropertyType ON b.datatypeNodeId = cmsPropertyType.dataTypeId INNER JOIN - (" + string.Format(parsedOriginalSql, "DISTINCT cmsContent.contentType") + @") as docData + (" + string.Format(parsedOriginalSql, "cmsContent.contentType") + @") as docData ON cmsPropertyType.contentTypeId = docData.contentType WHERE a.id = b.id)", docSql.Arguments); From 2f67a485aaa2712932af5bba321c93f7508a27dd Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 31 Jan 2017 14:52:48 +1100 Subject: [PATCH 05/58] Ensures that the sqlIds query is used for paging when processing members/media --- .../Repositories/MediaRepository.cs | 29 +++++++++++----- .../Repositories/MemberRepository.cs | 33 +++++++++++++------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index 8bcfc3558b..c4957ca9fe 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -68,7 +68,7 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("umbracoNode.id in (@ids)", new { ids = ids }); } - return ProcessQuery(sql); + return ProcessQuery(sql, sql); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -78,7 +78,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate() .OrderBy(x => x.SortOrder, SqlSyntax); - return ProcessQuery(sql); + return ProcessQuery(sql, sql); } #endregion @@ -143,13 +143,25 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) .OrderByDescending(x => x.VersionDate, SqlSyntax); - return ProcessQuery(sql, true); + return ProcessQuery(sql, sql, true); } - private IEnumerable ProcessQuery(Sql sql, bool withCache = false, bool isPaged = false) + /// + /// This is the underlying method that processes most queries for this repository + /// + /// + /// The full SQL to select all media data + /// + /// + /// The Id SQL to just return all media ids - used to process the properties for the media item + /// + /// True if this is a paged query + /// + /// + private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false, bool isPaged = false) { // fetch returns a list so it's ok to iterate it in this method - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sqlFull); var content = new IMedia[dtos.Count]; var defs = new List(); @@ -200,7 +212,7 @@ namespace Umbraco.Core.Persistence.Repositories } // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sql, defs, isPaged); + var propertyData = GetPropertyCollection(sqlIds, defs, isPaged); // assign var dtoIndex = 0; @@ -257,7 +269,8 @@ namespace Umbraco.Core.Persistence.Repositories query = query .Where(x => x.NodeId > baseId, SqlSyntax) .OrderBy(x => x.NodeId, SqlSyntax); - var xmlItems = ProcessQuery(SqlSyntax.SelectTop(query, groupSize)) + var sql = SqlSyntax.SelectTop(query, groupSize); + var xmlItems = ProcessQuery(sql, sql) .Select(x => new ContentXmlDto { NodeId = x.Id, Xml = serializer(x).ToString() }) .ToList(); @@ -507,7 +520,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsContentVersion", "contentId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull, isPaged:true), orderBy, orderDirection, orderBySystemField, + (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds, isPaged: true), orderBy, orderDirection, orderBySystemField, filterCallback); } diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index f83fdcef51..0cb5be4ce0 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -68,7 +68,7 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("umbracoNode.id in (@ids)", new { ids = ids }); } - return ProcessQuery(sql); + return ProcessQuery(sql, sql); } @@ -90,7 +90,7 @@ namespace Umbraco.Core.Persistence.Repositories baseQuery.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments)) .OrderBy(x => x.SortOrder); - return ProcessQuery(baseQuery); + return ProcessQuery(baseQuery, baseQuery); } else { @@ -98,7 +98,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate() .OrderBy(x => x.SortOrder); - return ProcessQuery(sql); + return ProcessQuery(sql, sql); } } @@ -385,7 +385,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) .OrderByDescending(x => x.VersionDate, SqlSyntax); - return ProcessQuery(sql, true); + return ProcessQuery(sql, sql, true); } public void RebuildXmlStructures(Func serializer, int groupSize = 200, IEnumerable contentTypeIds = null) @@ -408,7 +408,8 @@ namespace Umbraco.Core.Persistence.Repositories query = query .Where(x => x.NodeId > baseId) .OrderBy(x => x.NodeId, SqlSyntax); - var xmlItems = ProcessQuery(SqlSyntax.SelectTop(query, groupSize)) + var sql = SqlSyntax.SelectTop(query, groupSize); + var xmlItems = ProcessQuery(sql, sql) .Select(x => new ContentXmlDto { NodeId = x.Id, Xml = serializer(x).ToString() }) .ToList(); @@ -540,7 +541,7 @@ namespace Umbraco.Core.Persistence.Repositories .OrderByDescending(x => x.VersionDate) .OrderBy(x => x.SortOrder); - return ProcessQuery(sql); + return ProcessQuery(sql, sql); } @@ -624,7 +625,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsMember", "nodeId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull, isPaged:true), orderBy, orderDirection, orderBySystemField, + (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds, isPaged:true), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -664,10 +665,22 @@ namespace Umbraco.Core.Persistence.Repositories return base.GetEntityPropertyNameForOrderBy(orderBy); } - private IEnumerable ProcessQuery(Sql sql, bool withCache = false, bool isPaged = false) + /// + /// This is the underlying method that processes most queries for this repository + /// + /// + /// The full SQL to select all member data + /// + /// + /// The Id SQL to just return all member ids - used to process the properties for the member item + /// + /// True if this is a paged query + /// + /// + private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false, bool isPaged = false) { // fetch returns a list so it's ok to iterate it in this method - var dtos = Database.Fetch(sql); + var dtos = Database.Fetch(sqlFull); var content = new IMember[dtos.Count]; var defs = new List(); @@ -704,7 +717,7 @@ namespace Umbraco.Core.Persistence.Repositories } // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sql, defs, isPaged); + var propertyData = GetPropertyCollection(sqlIds, defs, isPaged); // assign var dtoIndex = 0; From 86b2dac231e771c1e0639ae2d2d9fff0d7121c35 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 31 Jan 2017 17:20:44 +1100 Subject: [PATCH 06/58] Needed to change the 2nd query to use a new PagingSqlQuery object due to the way that < SQL 2012 formats it's paging query which is just not compatible with how we were parsing the queries for properties... i don't actually think it was working for a long tme. --- .../Repositories/ContentRepository.cs | 21 ++- .../Repositories/MediaRepository.cs | 19 +-- .../Repositories/MemberRepository.cs | 25 ++- .../Repositories/VersionableRepositoryBase.cs | 159 ++++++++++++++---- 4 files changed, 156 insertions(+), 68 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs index f7b88ef46b..aedf701524 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentRepository.cs @@ -84,7 +84,7 @@ namespace Umbraco.Core.Persistence.Repositories var sqlBaseFull = GetBaseQuery(BaseQueryType.Full); var sqlBaseIds = GetBaseQuery(BaseQueryType.Ids); - return ProcessQuery(translate(sqlBaseFull), translate(sqlBaseIds)); + return ProcessQuery(translate(sqlBaseFull), new PagingSqlQuery(translate(sqlBaseIds))); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -103,7 +103,7 @@ namespace Umbraco.Core.Persistence.Repositories var translatorFull = new SqlTranslator(sqlBaseFull, query); var translatorIds = new SqlTranslator(sqlBaseIds, query); - return ProcessQuery(translate(translatorFull), translate(translatorIds)); + return ProcessQuery(translate(translatorFull), new PagingSqlQuery(translate(translatorIds))); } #endregion @@ -225,7 +225,7 @@ namespace Umbraco.Core.Persistence.Repositories var sqlFull = translate(baseId, GetBaseQuery(BaseQueryType.Full)); var sqlIds = translate(baseId, GetBaseQuery(BaseQueryType.Ids)); - var xmlItems = ProcessQuery(SqlSyntax.SelectTop(sqlFull, groupSize), SqlSyntax.SelectTop(sqlIds, groupSize)) + var xmlItems = ProcessQuery(SqlSyntax.SelectTop(sqlFull, groupSize), new PagingSqlQuery(SqlSyntax.SelectTop(sqlIds, groupSize))) .Select(x => new ContentXmlDto { NodeId = x.Id, Xml = serializer(x).ToString() }) .ToList(); @@ -260,7 +260,7 @@ namespace Umbraco.Core.Persistence.Repositories var sqlFull = translate(GetBaseQuery(BaseQueryType.Full)); var sqlIds = translate(GetBaseQuery(BaseQueryType.Ids)); - return ProcessQuery(sqlFull, sqlIds, true); + return ProcessQuery(sqlFull, new PagingSqlQuery(sqlIds), true); } public override IContent GetByVersion(Guid versionId) @@ -679,7 +679,7 @@ namespace Umbraco.Core.Persistence.Repositories var sqlIds = GetBaseQuery(BaseQueryType.Ids); var translatorIds = new SqlTranslator(sqlIds, query); - return ProcessQuery(translate(translatorFull), translate(translatorIds), true); + return ProcessQuery(translate(translatorFull), new PagingSqlQuery(translate(translatorIds)), true); } /// @@ -859,7 +859,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsDocument", "nodeId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds, isPaged:true), orderBy, orderDirection, orderBySystemField, + (sqlFull, pagingSqlQuery) => ProcessQuery(sqlFull, pagingSqlQuery), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -896,13 +896,12 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", /// /// The full SQL with the outer join to return all data required to create an IContent /// - /// + /// /// The Id SQL without the outer join to just return all document ids - used to process the properties for the content item /// - /// True if this is a paged query /// /// - private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false, bool isPaged = false) + private IEnumerable ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false) { // fetch returns a list so it's ok to iterate it in this method var dtos = Database.Fetch(sqlFull); @@ -968,7 +967,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", .ToDictionary(x => x.Id, x => x); // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sqlIds, defs, isPaged); + var propertyData = GetPropertyCollection(pagingSqlQuery, defs); // assign var dtoIndex = 0; @@ -1015,7 +1014,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder", var docDef = new DocumentDefinition(dto.NodeId, versionId, content.UpdateDate, content.CreateDate, contentType); - var properties = GetPropertyCollection(docSql, new[] { docDef }, false); + var properties = GetPropertyCollection(docSql, new[] { docDef }); content.Properties = properties[dto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs index c4957ca9fe..56b5e2ed9d 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MediaRepository.cs @@ -68,7 +68,7 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("umbracoNode.id in (@ids)", new { ids = ids }); } - return ProcessQuery(sql, sql); + return ProcessQuery(sql, new PagingSqlQuery(sql)); } protected override IEnumerable PerformGetByQuery(IQuery query) @@ -78,7 +78,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate() .OrderBy(x => x.SortOrder, SqlSyntax); - return ProcessQuery(sql, sql); + return ProcessQuery(sql, new PagingSqlQuery(sql)); } #endregion @@ -143,7 +143,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) .OrderByDescending(x => x.VersionDate, SqlSyntax); - return ProcessQuery(sql, sql, true); + return ProcessQuery(sql, new PagingSqlQuery(sql), true); } /// @@ -152,13 +152,12 @@ namespace Umbraco.Core.Persistence.Repositories /// /// The full SQL to select all media data /// - /// + /// /// The Id SQL to just return all media ids - used to process the properties for the media item /// - /// True if this is a paged query /// /// - private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false, bool isPaged = false) + private IEnumerable ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false) { // fetch returns a list so it's ok to iterate it in this method var dtos = Database.Fetch(sqlFull); @@ -212,7 +211,7 @@ namespace Umbraco.Core.Persistence.Repositories } // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sqlIds, defs, isPaged); + var propertyData = GetPropertyCollection(pagingSqlQuery, defs); // assign var dtoIndex = 0; @@ -270,7 +269,7 @@ namespace Umbraco.Core.Persistence.Repositories .Where(x => x.NodeId > baseId, SqlSyntax) .OrderBy(x => x.NodeId, SqlSyntax); var sql = SqlSyntax.SelectTop(query, groupSize); - var xmlItems = ProcessQuery(sql, sql) + var xmlItems = ProcessQuery(sql, new PagingSqlQuery(sql)) .Select(x => new ContentXmlDto { NodeId = x.Id, Xml = serializer(x).ToString() }) .ToList(); @@ -520,7 +519,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsContentVersion", "contentId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds, isPaged: true), orderBy, orderDirection, orderBySystemField, + (sqlFull, pagingSqlQuery) => ProcessQuery(sqlFull, pagingSqlQuery), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -540,7 +539,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.NodeId, versionId, media.UpdateDate, media.CreateDate, contentType); - var properties = GetPropertyCollection(docSql, new[] { docDef }, false); + var properties = GetPropertyCollection(new PagingSqlQuery(docSql), new[] { docDef }); media.Properties = properties[dto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs index 0cb5be4ce0..9fdee650b3 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberRepository.cs @@ -68,7 +68,7 @@ namespace Umbraco.Core.Persistence.Repositories sql.Where("umbracoNode.id in (@ids)", new { ids = ids }); } - return ProcessQuery(sql, sql); + return ProcessQuery(sql, new PagingSqlQuery(sql)); } @@ -90,7 +90,7 @@ namespace Umbraco.Core.Persistence.Repositories baseQuery.Append(new Sql("WHERE umbracoNode.id IN (" + sql.SQL + ")", sql.Arguments)) .OrderBy(x => x.SortOrder); - return ProcessQuery(baseQuery, baseQuery); + return ProcessQuery(baseQuery, new PagingSqlQuery(baseQuery)); } else { @@ -98,7 +98,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = translator.Translate() .OrderBy(x => x.SortOrder); - return ProcessQuery(sql, sql); + return ProcessQuery(sql, new PagingSqlQuery(sql)); } } @@ -385,7 +385,7 @@ namespace Umbraco.Core.Persistence.Repositories var sql = GetBaseQuery(false) .Where(GetBaseWhereClause(), new { Id = id }) .OrderByDescending(x => x.VersionDate, SqlSyntax); - return ProcessQuery(sql, sql, true); + return ProcessQuery(sql, new PagingSqlQuery(sql), true); } public void RebuildXmlStructures(Func serializer, int groupSize = 200, IEnumerable contentTypeIds = null) @@ -409,7 +409,7 @@ namespace Umbraco.Core.Persistence.Repositories .Where(x => x.NodeId > baseId) .OrderBy(x => x.NodeId, SqlSyntax); var sql = SqlSyntax.SelectTop(query, groupSize); - var xmlItems = ProcessQuery(sql, sql) + var xmlItems = ProcessQuery(sql, new PagingSqlQuery(sql)) .Select(x => new ContentXmlDto { NodeId = x.Id, Xml = serializer(x).ToString() }) .ToList(); @@ -450,7 +450,7 @@ namespace Umbraco.Core.Persistence.Repositories var factory = new MemberFactory(memberType, NodeObjectTypeId, dto.NodeId); var media = factory.BuildEntity(dto); - var properties = GetPropertyCollection(sql, new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) }, false); + var properties = GetPropertyCollection(new PagingSqlQuery(sql), new[] { new DocumentDefinition(dto.NodeId, dto.ContentVersionDto.VersionId, media.UpdateDate, media.CreateDate, memberType) }); media.Properties = properties[dto.NodeId]; @@ -541,7 +541,7 @@ namespace Umbraco.Core.Persistence.Repositories .OrderByDescending(x => x.VersionDate) .OrderBy(x => x.SortOrder); - return ProcessQuery(sql, sql); + return ProcessQuery(sql, new PagingSqlQuery(sql)); } @@ -625,7 +625,7 @@ namespace Umbraco.Core.Persistence.Repositories return GetPagedResultsByQuery(query, pageIndex, pageSize, out totalRecords, new Tuple("cmsMember", "nodeId"), - (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds, isPaged:true), orderBy, orderDirection, orderBySystemField, + (sqlFull, sqlIds) => ProcessQuery(sqlFull, sqlIds), orderBy, orderDirection, orderBySystemField, filterCallback); } @@ -671,13 +671,12 @@ namespace Umbraco.Core.Persistence.Repositories /// /// The full SQL to select all member data /// - /// + /// /// The Id SQL to just return all member ids - used to process the properties for the member item /// - /// True if this is a paged query /// /// - private IEnumerable ProcessQuery(Sql sqlFull, Sql sqlIds, bool withCache = false, bool isPaged = false) + private IEnumerable ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false) { // fetch returns a list so it's ok to iterate it in this method var dtos = Database.Fetch(sqlFull); @@ -717,7 +716,7 @@ namespace Umbraco.Core.Persistence.Repositories } // load all properties for all documents from database in 1 query - var propertyData = GetPropertyCollection(sqlIds, defs, isPaged); + var propertyData = GetPropertyCollection(pagingSqlQuery, defs); // assign var dtoIndex = 0; @@ -754,7 +753,7 @@ namespace Umbraco.Core.Persistence.Repositories var docDef = new DocumentDefinition(dto.ContentVersionDto.NodeId, versionId, member.UpdateDate, member.CreateDate, memberType); - var properties = GetPropertyCollection(docSql, new[] { docDef }, false); + var properties = GetPropertyCollection(docSql, new[] { docDef }); member.Properties = properties[dto.ContentVersionDto.NodeId]; diff --git a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs index 26c53a091f..6b18fc70b4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/VersionableRepositoryBase.cs @@ -431,7 +431,7 @@ namespace Umbraco.Core.Persistence.Repositories /// orderBy protected IEnumerable GetPagedResultsByQuery(IQuery query, long pageIndex, int pageSize, out long totalRecords, Tuple nodeIdSelect, - Func> processQuery, + Func, IEnumerable> processQuery, string orderBy, Direction orderDirection, bool orderBySystemField, @@ -485,11 +485,8 @@ namespace Umbraco.Core.Persistence.Repositories var fullQuery = GetSortedSqlForPagedResults( GetFilteredSqlForPagedResults(fullQueryWithPagedInnerJoin, defaultFilter), orderDirection, orderBy, orderBySystemField, nodeIdSelect); - - //get the id query in the paged format - var idPagedQuery = new Sql(sqlStringPage, args); - - return processQuery(fullQuery, idPagedQuery); + + return processQuery(fullQuery, new PagingSqlQuery(Database, sqlNodeIdsWithSort, pageIndex, pageSize)); } else { @@ -499,20 +496,47 @@ namespace Umbraco.Core.Persistence.Repositories return result; } + /// + /// Gets the property collection for a non-paged query + /// + /// + /// + /// protected IDictionary GetPropertyCollection( - Sql docSql, - IReadOnlyCollection documentDefs, - bool isPaged) + Sql sql, + IReadOnlyCollection documentDefs) + { + return GetPropertyCollection(new PagingSqlQuery(sql), documentDefs); + } + + /// + /// Gets the property collection for a query + /// + /// + /// + /// + protected IDictionary GetPropertyCollection( + PagingSqlQuery pagingSqlQuery, + IReadOnlyCollection documentDefs) { if (documentDefs.Count == 0) return new Dictionary(); + //initialize to the query passed in + var docSql = pagingSqlQuery.PrePagedSql; + //we need to parse the original SQL statement and reduce the columns to just cmsContent.nodeId, cmsContentVersion.VersionId so that we can use // the statement to go get the property data for all of the items by using an inner join var parsedOriginalSql = "SELECT {0} " + docSql.SQL.Substring(docSql.SQL.IndexOf("FROM", StringComparison.Ordinal)); - - //now remove everything from an Orderby clause and beyond if this is unpaged data - if (isPaged == false && parsedOriginalSql.InvariantContains("ORDER BY ")) + + if (pagingSqlQuery.HasPaging) { + //if this is a paged query, build the paged query with the custom column substitution, then re-assign + docSql = pagingSqlQuery.BuildPagedQuery("{0}"); + parsedOriginalSql = docSql.SQL; + } + else if (parsedOriginalSql.InvariantContains("ORDER BY ")) + { + //now remove everything from an Orderby clause and beyond if this is unpaged data parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal)); } @@ -652,28 +676,7 @@ ORDER BY contentNodeId, propertytypeid return result; } - - public class DocumentDefinition - { - /// - /// Initializes a new instance of the class. - /// - public DocumentDefinition(int id, Guid version, DateTime versionDate, DateTime createDate, IContentTypeComposition composition) - { - Id = id; - Version = version; - VersionDate = versionDate; - CreateDate = createDate; - Composition = composition; - } - - public int Id { get; set; } - public Guid Version { get; set; } - public DateTime VersionDate { get; set; } - public DateTime CreateDate { get; set; } - public IContentTypeComposition Composition { get; set; } - } - + protected virtual string GetDatabaseFieldNameForOrderBy(string orderBy) { // Translate the passed order by field (which were originally defined for in-memory object sorting @@ -769,5 +772,93 @@ ORDER BY contentNodeId, propertytypeid /// /// protected abstract Sql GetBaseQuery(BaseQueryType queryType); + + + internal class DocumentDefinition + { + /// + /// Initializes a new instance of the class. + /// + public DocumentDefinition(int id, Guid version, DateTime versionDate, DateTime createDate, IContentTypeComposition composition) + { + Id = id; + Version = version; + VersionDate = versionDate; + CreateDate = createDate; + Composition = composition; + } + + public int Id { get; set; } + public Guid Version { get; set; } + public DateTime VersionDate { get; set; } + public DateTime CreateDate { get; set; } + public IContentTypeComposition Composition { get; set; } + } + + /// + /// An object representing a query that may contain paging information + /// + internal class PagingSqlQuery + { + public Sql PrePagedSql { get; private set; } + + public PagingSqlQuery(Sql prePagedSql) + { + PrePagedSql = prePagedSql; + } + + public virtual bool HasPaging + { + get { return false; } + } + + public virtual Sql BuildPagedQuery(string selectColumns) + { + throw new InvalidOperationException("This query has no paging information"); + } + } + + /// + /// An object representing a query that contains paging information + /// + /// + internal class PagingSqlQuery : PagingSqlQuery + { + private readonly Database _db; + private readonly long _pageIndex; + private readonly int _pageSize; + + public PagingSqlQuery(Database db, Sql prePagedSql, long pageIndex, int pageSize) : base(prePagedSql) + { + _db = db; + _pageIndex = pageIndex; + _pageSize = pageSize; + } + + public override bool HasPaging + { + get { return _pageSize > 0; } + } + + /// + /// Creates a paged query based on the original query and subtitutes the selectColumns specified + /// + /// + /// + public override Sql BuildPagedQuery(string selectColumns) + { + if (HasPaging == false) throw new InvalidOperationException("This query has no paging information"); + + var resultSql = string.Format("SELECT {0} {1}", selectColumns, PrePagedSql.SQL.Substring(PrePagedSql.SQL.IndexOf("FROM", StringComparison.Ordinal))); + + //this query is meant to be paged so we need to generate the paging syntax + //Create the inner paged query that was used above to get the paged result, we'll use that as the inner sub query + var args = PrePagedSql.Arguments; + string sqlStringCount, sqlStringPage; + _db.BuildPageQueries(_pageIndex * _pageSize, _pageSize, resultSql, ref args, out sqlStringCount, out sqlStringPage); + + return new Sql(sqlStringPage, args); + } + } } } \ No newline at end of file From 77b04d74d4dd8c4b464984480bd0cb16c64a51e2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 31 Jan 2017 10:00:44 +0100 Subject: [PATCH 07/58] load mini list view for pickers with a start node --- src/Umbraco.Web.UI.Client/src/less/belle.less | 1 + .../src/less/components/umb-pagination.less | 3 ++ .../treepicker/treepicker.controller.js | 28 +++++++++++----- .../overlays/treepicker/treepicker.html | 32 +++++++++---------- .../src/views/components/umb-pagination.html | 2 +- 5 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less diff --git a/src/Umbraco.Web.UI.Client/src/less/belle.less b/src/Umbraco.Web.UI.Client/src/less/belle.less index 6fbf12e815..c6c63f1057 100644 --- a/src/Umbraco.Web.UI.Client/src/less/belle.less +++ b/src/Umbraco.Web.UI.Client/src/less/belle.less @@ -118,6 +118,7 @@ @import "components/umb-avatar.less"; @import "components/umb-progress-bar.less"; @import "components/umb-querybuilder.less"; +@import "components/umb-pagination.less"; @import "components/buttons/umb-button.less"; @import "components/buttons/umb-button-group.less"; diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less new file mode 100644 index 0000000000..8d3d563cab --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-pagination.less @@ -0,0 +1,3 @@ +.umb-pagination ul { + box-shadow: none; +} \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js index a1ee1f031f..8127cd8de6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js @@ -38,11 +38,6 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", } } } - - // Search is only working for content, media and member section so we will remove it from everything else - if($scope.section === "content" || $scope.section === "media" || $scope.section === "member" ) { - $scope.enableSearh = true; - } //create the custom query string param for this tree $scope.customTreeParams = dialogOptions.startNodeId ? "startNodeId=" + dialogOptions.startNodeId : ""; @@ -72,6 +67,21 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", entityType = "Media"; } + // Search and listviews is only working for content, media and member section so we will remove it from everything else + if ($scope.section === "content" || $scope.section === "media" || $scope.section === "member") { + $scope.enableSearh = true; + + //if a alternative startnode is used, we need to check if it is a container + if (dialogOptions.startNodeId) { + + entityResource.getById(dialogOptions.startNodeId, entityType).then(function (node) { + if (node.metaData.IsContainer) { + openMiniListView(node); + } + }); + } + } + //Configures filtering if (dialogOptions.filter) { @@ -588,11 +598,13 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", var promise = ""; - if(node.nodeType === "content") { + console.log(entityType); + + if (entityType === "Document") { promise = contentResource.getChildren(node.id, $scope.pagination); - } else if( node.nodeType === "member") { + } else if (entityType === "Member") { promise = memberResource.getPagedResults(node.id, $scope.pagination); - } else if(node.nodeType === "media") { + } else if (entityType === "Media") { promise = mediaResource.getChildren(node.id, $scope.pagination); } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html index a37a63bb0f..e2a0554b47 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html @@ -38,33 +38,31 @@
-
-
- - Back - -

- - {{ miniListView.node.name }} -

+
+ +
+ Back
+ +
+ +

{{ miniListView.node.name }}

+
+
- +
-
- -
- Name -
-
-
/// The version comment. - public static string CurrentComment { get { return "alpha061"; } } + public static string CurrentComment { get { return "alpha062"; } } // Get the version of the umbraco.dll by looking at a class in that dll // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx