From e651d5917a69ec874c9242026203d169eca6c9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Tue, 22 Jan 2019 14:38:10 +0100 Subject: [PATCH 1/9] Finds and set the active ContentApp when running init, fixing the issue of retuning to a node after editing the DocType in infinity editing. Fixes #4185 --- .../components/content/edit.controller.js | 63 +++++--- .../src/views/media/edit.html | 2 +- .../src/views/media/media.edit.controller.js | 139 ++++++++++++------ .../src/views/mediatypes/edit.controller.js | 5 +- 4 files changed, 143 insertions(+), 66 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 89c8b541d1..ecaf8b3ad3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -26,20 +26,43 @@ $scope.allowOpen = true; $scope.app = null; - function init(content) { - if (!$scope.app) { - // set first app to active + function init() { + + var content = $scope.content; + + // we need to check wether an app is present in the current data, if not we will present the default app. + var isAppPresent = false; + + // on first init, we dont have any apps. but if we are re-initializing, we do, but ... + if ($scope.app) { + + // lets check if it still exists as part of our apps array. (if not we have made a change to our docType, even just a re-save of the docType it will turn into new Apps.) + _.forEach(content.apps, function(app) { + if (app === $scope.app) { + isAppPresent = true; + } + }); + + // if we did reload our DocType, but still have the same app we will try to find it by the alias. + if (isAppPresent === false) { + _.forEach(content.apps, function(app) { + if (app.alias === $scope.app.alias) { + isAppPresent = true; + app.active = true; + $scope.appChanged(app); + } + }); + } + + } + + // if we still dont have a app, lets show the first one: + if (isAppPresent === false) { content.apps[0].active = true; - $scope.app = content.apps[0]; + $scope.appChanged(content.apps[0]); } - - if (infiniteMode) { - createInfiniteModeButtons(content); - } else { - createButtons(content); - } - - editorState.set($scope.content); + + editorState.set(content); //We fetch all ancestors of the node to generate the footer breadcrumb navigation if (!$scope.page.isNew) { @@ -129,7 +152,7 @@ "/content/content/edit/" + data.parentId; } - init($scope.content); + init(); syncTreeNode($scope.content, $scope.content.path, true); @@ -337,7 +360,7 @@ showNotifications: args.showNotifications }).then(function (data) { //success - init($scope.content); + init(); syncTreeNode($scope.content, data.path); eventsService.emit("content.saved", { content: $scope.content, action: args.action }); @@ -439,7 +462,7 @@ $scope.content = data; - init($scope.content); + init(); resetLastListPageNumber($scope.content); @@ -478,7 +501,7 @@ .then(function (data) { formHelper.resetForm({ scope: $scope }); contentEditingHelper.reBindChangedProperties($scope.content, data); - init($scope.content); + init(); syncTreeNode($scope.content, data.path); $scope.page.buttonGroupState = "success"; eventsService.emit("content.unpublished", { content: $scope.content }); @@ -915,8 +938,14 @@ * @param {any} app */ $scope.appChanged = function (app) { + $scope.app = app; - createButtons($scope.content); + + if (infiniteMode) { + createInfiniteModeButtons($scope.content); + } else { + createButtons($scope.content); + } }; // methods for infinite editing diff --git a/src/Umbraco.Web.UI.Client/src/views/media/edit.html b/src/Umbraco.Web.UI.Client/src/views/media/edit.html index be1219f052..35f9a6f7ff 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/edit.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/edit.html @@ -14,7 +14,7 @@ hide-description="true" hide-alias="true" navigation="content.apps" - on-select-navigation-item="appChanged(app)"> + on-select-navigation-item="appChanged(item)"> diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js index 19932887fd..af7184c82f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js @@ -6,7 +6,10 @@ * @description * The controller for the media editor */ -function mediaEditController($scope, $routeParams, $q, appState, mediaResource, entityResource, navigationService, notificationsService, angularHelper, serverValidationManager, contentEditingHelper, fileManager, formHelper, editorState, umbRequestHelper, $http, eventsService) { +function mediaEditController($scope, $routeParams, $q, appState, mediaResource, + entityResource, navigationService, notificationsService, angularHelper, + serverValidationManager, contentEditingHelper, fileManager, formHelper, + editorState, umbRequestHelper, $http, eventsService) { var evts = []; var nodeId = null; @@ -41,7 +44,90 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, $scope.page.listViewPath = null; $scope.page.saveButtonState = "init"; $scope.page.submitButtonLabel = "Save"; + $scope.app = null; + if (create) { + + $scope.page.loading = true; + + mediaResource.getScaffold(nodeId, $routeParams.doctype) + .then(function (data) { + $scope.content = data; + + init(); + + $scope.page.loading = false; + + }); + } + else { + $scope.page.loading = true; + loadMedia() + .then(function(){ + $scope.page.loading = false; + }); + } + + function init() { + + var content = $scope.content; + + // we need to check wether an app is present in the current data, if not we will present the default app. + var isAppPresent = false; + + // on first init, we dont have any apps. but if we are re-initializing, we do, but ... + if ($scope.app) { + + // lets check if it still exists as part of our apps array. (if not we have made a change to our docType, even just a re-save of the docType it will turn into new Apps.) + _.forEach(content.apps, function(app) { + if (app === $scope.app) { + isAppPresent = true; + } + }); + + // if we did reload our DocType, but still have the same app we will try to find it by the alias. + if (isAppPresent === false) { + _.forEach(content.apps, function(app) { + if (app.alias === $scope.app.alias) { + isAppPresent = true; + app.active = true; + $scope.appChanged(app); + } + }); + } + + } + + // if we still dont have a app, lets show the first one: + if (isAppPresent === false) { + content.apps[0].active = true; + $scope.appChanged(content.apps[0]); + } + + + editorState.set($scope.content); + + bindEvents(); + + } + + function bindEvents() { + //bindEvents can be called more than once and we don't want to have multiple bound events + for (var e in evts) { + eventsService.unsubscribe(evts[e]); + } + + evts.push(eventsService.on("editors.mediaType.saved", function(name, args) { + // if this media item uses the updated media type we need to reload the media item + if(args && args.mediaType && args.mediaType.key === $scope.content.contentType.key) { + $scope.page.loading = true; + loadMedia().then(function() { + $scope.page.loading = false; + }); + } + })); + } + /** Syncs the content item to it's tree node - this occurs on first load and after saving */ function syncTreeNode(content, path, initialLoad) { @@ -68,45 +154,6 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, }); } } - - if (create) { - - $scope.page.loading = true; - - mediaResource.getScaffold(nodeId, $routeParams.doctype) - .then(function (data) { - $scope.content = data; - - editorState.set($scope.content); - - init(); - - $scope.page.loading = false; - - }); - } - else { - $scope.page.loading = true; - loadMedia() - .then(function(){ - $scope.page.loading = false; - }); - } - - function init() { - - if (!$scope.app) { - // set first app to active - $scope.content.apps[0].active = true; - $scope.app = $scope.content.apps[0]; - } - - // setup infinite mode - if(infiniteMode) { - $scope.page.submitButtonLabel = "Save and Close"; - } - - } $scope.save = function () { @@ -212,14 +259,12 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource, $scope.appChanged = function (app) { $scope.app = app; - } - - evts.push(eventsService.on("editors.mediaType.saved", function(name, args) { - // if this media item uses the updated media type we need to reload the media item - if(args && args.mediaType && args.mediaType.key === $scope.content.contentType.key) { - loadMedia(); + + // setup infinite mode + if(infiniteMode) { + $scope.page.submitButtonLabel = "Save and Close"; } - })); + } //ensure to unregister from all events! $scope.$on('$destroy', function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index c8aba53cf5..0740f7866f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -9,7 +9,10 @@ (function () { "use strict"; - function MediaTypesEditController($scope, $routeParams, mediaTypeResource, dataTypeResource, editorState, contentEditingHelper, formHelper, navigationService, iconHelper, contentTypeHelper, notificationsService, $filter, $q, localizationService, overlayHelper, eventsService) { + function MediaTypesEditController($scope, $routeParams, mediaTypeResource, + dataTypeResource, editorState, contentEditingHelper, formHelper, + navigationService, iconHelper, contentTypeHelper, notificationsService, + $filter, $q, localizationService, overlayHelper, eventsService) { var vm = this; var evts = []; From 7b3623a9d9c9fe8d07121a7e38c95d4d4876bace Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 30 Jan 2019 23:29:09 +0100 Subject: [PATCH 2/9] Localize edit link, remove duplicate class attributes and only make remove link red --- .../propertyeditors/imagecropper/imagecropper.prevalues.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html index d11e176c2b..757978d32f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html @@ -65,8 +65,8 @@

{{item.alias}} ({{item.width}}px × {{item.height}}px)

From d55262b322f4884e211e709f5c2df6350836d48c Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 30 Jan 2019 23:29:50 +0100 Subject: [PATCH 3/9] Revert "Localize edit link, remove duplicate class attributes and only make remove link red" This reverts commit 63cc250c0f929b1f7e6f9f05fae2fd302682d418. --- .../propertyeditors/imagecropper/imagecropper.prevalues.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html index 757978d32f..d11e176c2b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html @@ -65,8 +65,8 @@

{{item.alias}} ({{item.width}}px × {{item.height}}px)

From 3ba32dafa5f67061d15ca7d5da803be74388c172 Mon Sep 17 00:00:00 2001 From: Bjarne Fyrstenborg Date: Wed, 30 Jan 2019 23:33:19 +0100 Subject: [PATCH 4/9] Localize edit link, remove duplicate class attributes and only make remove link red --- .../propertyeditors/imagecropper/imagecropper.prevalues.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html index d11e176c2b..757978d32f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html @@ -65,8 +65,8 @@

{{item.alias}} ({{item.width}}px × {{item.height}}px)

From a1f72826c777c130b2765b7159d080c8217ccb97 Mon Sep 17 00:00:00 2001 From: Sebastiaan Janssen Date: Thu, 31 Jan 2019 08:39:59 +0100 Subject: [PATCH 5/9] Remove duplicate css class --- .../propertyeditors/imagecropper/imagecropper.prevalues.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html index 757978d32f..0aa4b5e561 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/imagecropper/imagecropper.prevalues.html @@ -65,7 +65,7 @@

{{item.alias}} ({{item.width}}px × {{item.height}}px)

From 2ab391eb69abc7fc5d243e4930ce21386a81a870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 31 Jan 2019 09:37:04 +0100 Subject: [PATCH 6/9] V8: UI select colors --- .../editor/umbeditormenu.directive.js | 5 +- .../components/tree/umbtreeitem.directive.js | 25 +++++++-- .../components/umbmediagrid.directive.js | 10 ++-- .../src/controllers/navigation.controller.js | 6 +- .../src/less/buttons.less | 6 +- .../less/components/tree/umb-tree-item.less | 40 +++++++++++++ .../src/less/components/tree/umb-tree.less | 19 +------ .../src/less/components/umb-content-grid.less | 29 ++++++++-- .../src/less/components/umb-folder-grid.less | 25 +++++++-- .../src/less/components/umb-media-grid.less | 56 ++++++++++++++----- .../src/less/variables.less | 5 +- .../views/components/tree/umb-tree-item.html | 14 ++--- .../views/components/umb-content-grid.html | 4 +- .../propertyeditors/listview/listview.html | 15 ++--- 14 files changed, 181 insertions(+), 78 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js index 22939c7f2c..9dff712ef6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/editor/umbeditormenu.directive.js @@ -30,8 +30,9 @@ } //when the options item is selected, we need to set the current menu item in appState (since this is synonymous with a menu) - appState.setMenuState("currentNode", scope.currentNode); - + // Niels: No i think we are wrong, we should not set the currentNode, cause it represents the currentNode of interaction. + //appState.setMenuState("currentNode", scope.currentNode); + if (!scope.actions) { treeService.getMenu({ treeNode: scope.currentNode }) .then(function (data) { 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 0f9a14d71a..51eb8ca285 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 @@ -60,10 +60,13 @@ angular.module("umbraco.directives") if (!node) { return ''; } - + // TODO: This is called constantly because as a method in a template it's re-evaluated pretty much all the time // it would be better if we could cache the processing. The problem is that some of these things are dynamic. + //is this the current action node (this is not the same as the current selected node!) + var actionNode = appState.getMenuState("currentNode"); + var css = []; if (node.cssClasses) { _.each(node.cssClasses, function(c) { @@ -73,17 +76,27 @@ angular.module("umbraco.directives") if (node.selected) { css.push("umb-tree-node-checked"); } + if (node == scope.currentNode) { + css.push("current"); + if (actionNode && actionNode.id !== node.id) { + css.push("current-not-active");// when its the current node, but its not the active(current node for the given action) + } + } + if (node.hasChildren) { + css.push("has-children"); + } + if (node.deleteAnimations) { + css.push("umb-tree-item--deleted"); + } - //is this the current action node (this is not the same as the current selected node!) - var actionNode = appState.getMenuState("currentNode"); if (actionNode) { - if (actionNode.id === node.id && String(actionNode.id) !== "-1") { + if (actionNode.id === node.id && String(node.id) !== "-1") { css.push("active"); } - + // special handling of root nodes with id -1 // as there can be many nodes with id -1 in a tree we need to check the treeAlias instead - if (String(actionNode.id) === "-1" && actionNode.metaData.treeAlias === node.metaData.treeAlias) { + if (String(node.id) === "-1" && actionNode.metaData.treeAlias === node.metaData.treeAlias) { css.push("active"); } } diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js index 308ffbf00f..29335f276e 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbmediagrid.directive.js @@ -140,11 +140,11 @@ Use this directive to generate a thumbnail grid of media items. } } - + if (scope.items.length > 0) { setFlexValues(scope.items); } - + } function setItemData(item) { @@ -235,7 +235,7 @@ Use this directive to generate a thumbnail grid of media items. } } - + function setFlexValues(mediaItems) { var flexSortArray = mediaItems; @@ -269,12 +269,12 @@ Use this directive to generate a thumbnail grid of media items. "min-height": itemMinHeight + "px" }; - mediaItem.flexStyle = flexStyle; + mediaItem.flexStyle = flexStyle; } } - + scope.clickItem = function(item, $event, $index) { if (scope.onClick) { scope.onClick(item, $event, $index); diff --git a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js index 96f3115185..071d984c6a 100644 --- a/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js +++ b/src/Umbraco.Web.UI.Client/src/controllers/navigation.controller.js @@ -34,7 +34,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar appState.setTreeState("selectedNode", args.node); //when a node is activated, this is the same as clicking it and we need to set the //current menu item to be this node as well. - appState.setMenuState("currentNode", args.node); + //appState.setMenuState("currentNode", args.node);// Niels: No, we are setting it from the dialog. } }); @@ -44,7 +44,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar args.event.preventDefault(); //Set the current action node (this is not the same as the current selected node!) - appState.setMenuState("currentNode", args.node); + //appState.setMenuState("currentNode", args.node);// Niels: No, we are setting it from the dialog. if (args.event && args.event.altKey) { args.skipDefault = true; @@ -96,7 +96,7 @@ function NavigationController($scope, $rootScope, $location, $log, $q, $routePar //put this node into the tree state appState.setTreeState("selectedNode", args.node); //when a node is clicked we also need to set the active menu node to this node - appState.setMenuState("currentNode", args.node); + //appState.setMenuState("currentNode", args.node); //not legacy, lets just set the route value and clear the query string if there is one. $location.path(n.routePath); diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index 51dcce7b92..a246ef585e 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -197,7 +197,11 @@ input[type="button"] { } // Made for Umbraco, 2019 .btn-action { - .buttonBackground(@pinkLight, @blueDark, @blueExtraDark, @u-white); + .buttonBackground(@blueExtraDark, @blueDark, @pinkLight, @u-white); +} +// Made for Umbraco, 2019 +.btn-selection { + .buttonBackground(@pinkLight, ligthen(@pinkLight, 20%), @blueExtraDark, @blueDark); } // Made for Umbraco, 2019, used for buttons that has to stand back. .btn-white { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less index 097665bdd4..53e724cf54 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree-item.less @@ -2,6 +2,7 @@ display: block; min-width: 100%; width: auto; + margin-top:1px; .umb-tree-item__label { user-select: none; @@ -44,6 +45,38 @@ } } +// active is equivilant to selected, its the item that is begin affected by the actions performed in the right-click-dialog. +.umb-tree-item.active { + +} +.umb-tree-item.active > .umb-tree-item__inner { + //background: @ui-selected; + color: @ui-selected-type; + a { + color: @ui-selected-type; + } + + border-color: @ui-selected-border; + box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%); + &::before { + content: ""; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + border: 2px solid fade(white, 80%); + } + &:hover { + //background: @ui-selected-hover; + //border-color: @ui-selected-border-hover;// dont hover border, cause its cant be deselected in current code. + color: @ui-selected-type-hover; + a { + color: @ui-selected-type-hover; + } + } +} + .umb-tree-item.current > .umb-tree-item__inner { background: @ui-active; @@ -75,3 +108,10 @@ //border-color: @ui-active; } } + +.umb-tree-item.current-not-active > .umb-tree-item__inner { + + background: @ui-active-blur; + color:@ui-active-type; + +} diff --git a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less index 13e2a55089..698a4211f5 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/tree/umb-tree.less @@ -87,23 +87,6 @@ body.touch .umb-tree { } } -// active is equivilant to selected, its the item that is begin affected by the actions performed in the right-click-dialog. -.umb-tree-item > .umb-tree-item__inner.active { - //background: @ui-selected; - border-color: @ui-selected-border; - color: @ui-selected-type; - a { - color: @ui-selected-type; - } - &:hover { - //background: @ui-selected-hover; - border-color: @ui-selected-border-hover; - color: @ui-selected-type-hover; - a { - color: @ui-selected-type-hover; - } - } -} .umb-tree-root, .umb-tree-item__inner { padding: 0; position: relative; @@ -112,7 +95,7 @@ body.touch .umb-tree { flex-wrap: nowrap; align-items: center; - border:2px dashed transparent; + border:2px solid transparent; color: @ui-option-type; a { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less index 399a367dc5..b55a511f4b 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less @@ -14,10 +14,31 @@ user-select: none; box-shadow: 0 1px 1px 0 rgba(0,0,0,0.16); border-radius: 3px; + + color: @ui-option-type; + &:hover { + color:@ui-option-type-hover; + } } .umb-content-grid__item.-selected { - box-shadow: 0 2px 8px 0 rgba(0,0,0,0.35); + //box-shadow: 0 2px 8px 0 rgba(0,0,0,0.35); + + //color:@ui-selected-type; + + &::before { + content: ""; + position: absolute; + z-index:2; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid @ui-selected-border; + border-radius: 5px; + box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); + } + } .umb-content-grid__icon-container { @@ -31,12 +52,12 @@ .umb-content-grid__icon[class^="icon-"], .umb-content-grid__icon[class*=" icon-"] { font-size: 20px; - color: @gray-8; +//color: @gray-8; margin-right: 5px; } .umb-content-grid__icon.-light { - color: @gray-5; + //color: @gray-5; } @@ -48,7 +69,7 @@ .umb-content-grid__item-name { font-weight: bold; margin-bottom: 15px; - color: @black; + //color: @black; line-height: 1.4em; display: inline-flex; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less index f5ca1f8438..d2f86affab 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less @@ -14,7 +14,7 @@ padding: 10px 20px; box-sizing: border-box; flex: 1 1 200px; - border: 2px dashed transparent; + //border: 2px solid transparent; transition: border 0.2s; position: relative; justify-content: space-between; @@ -27,15 +27,28 @@ } .umb-folder-grid__folder.-selected { - box-shadow: 0 2px 8px 0 darken(@ui-selected-border, 20); + //box-shadow: 0 2px 8px 0 darken(@ui-selected-border, 20); //background: @ui-selected; color:@ui-selected-type; - border-color:@ui-selected-border; + //border-color:@ui-selected-border; + + &::before { + content: ""; + position: absolute; + z-index:2; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid @ui-selected-border; + border-radius: 5px; + box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); + } &:hover { color:@ui-selected-type-hover; - border-color:@ui-selected-border-hover; + //border-color:@ui-selected-border-hover; } } @@ -59,12 +72,12 @@ .umb-folder-grid__folder-icon[class*=" icon-"] { font-size: 20px; margin-right: 15px; - color: @black; + //color: @black; } .umb-folder-grid__folder-name { font-size: 13px; - color: @black; + //color: @black; font-weight: bold; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less index 8185040f23..017313af80 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less @@ -21,11 +21,14 @@ margin: 10px; position: relative; - overflow: hidden; + //overflow: hidden; + + user-select: none; + cursor: pointer; - border: 2px dashed transparent; box-shadow: 0 1px 1px 0 rgba(0,0,0,.2); + //border: 2px solid transparent; transition: box-shadow 150ms ease-in-out; } @@ -35,16 +38,30 @@ } .umb-media-grid__item.-selected { - box-shadow: 0 2px 8px 0 darken(@ui-selected-border, 20); //background: @ui-selected; color:@ui-selected-type; - border-color:@ui-selected-border; + //border-color: @ui-selected-border; + //box-shadow: 0 2px 8px 0 darken(@ui-selected-border, 20); - &:hover { - color:@ui-selected-type-hover; - border-color:@ui-selected-border-hover; + &::before { + content: ""; + position: absolute; + z-index:2; + top: -2px; + left: -2px; + right: -2px; + bottom: -2px; + border: 2px solid @ui-selected-border; + border-radius: 5px; + box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); } + + .umb-media-grid__item-overlay { + color: @ui-selected-type; + //background: @ui-selected-border; + } + } .umb-media-grid__item-file-icon > span { @@ -64,16 +81,22 @@ } .umb-media-grid__item-image { - max-width: 100% !important; - height: auto; + //max-width: 100% !important; + //height: auto; position: relative; + + object-fit: contain; + height: 100%; } .umb-media-grid__item-image-placeholder { width: 100%; - max-width: 100%; - height: auto; + //max-width: 100%; + //height: auto; position: relative; + + object-fit: contain; + height: 100%; } .umb-media-grid__image-background { @@ -95,17 +118,18 @@ right: 0; bottom: 0; left: 0; - z-index: 100; + z-index: 1; padding: 5px 10px; box-sizing: border-box; font-size: 12px; overflow: hidden; color: @black; white-space: nowrap; - border-top:1px solid @gray-9; - background: @white; + border-top:1px solid fade(black, 4%); + background: fade(@white, 92%); transition: opacity 150ms; } + /* .umb-media-grid__item.-file .umb-media-grid__item-overlay { opacity: 1; @@ -180,6 +204,10 @@ align-items: center; color: @black; transition: opacity 150ms; + + &:hover { + color: @ui-action-disgrete-type-hover; + } } .umb-media-grid__item:hover .umb-media-grid__edit { diff --git a/src/Umbraco.Web.UI.Client/src/less/variables.less b/src/Umbraco.Web.UI.Client/src/less/variables.less index e66c3de597..80665e4c64 100644 --- a/src/Umbraco.Web.UI.Client/src/less/variables.less +++ b/src/Umbraco.Web.UI.Client/src/less/variables.less @@ -117,7 +117,7 @@ @pinkRedLight: #ff8a89;// added 2019 @brown: #9d8057;// added 2019 @brownLight: #e4e0dd;// added 2019 -@brownGrayLight: #f3f2f1;// added 2019 +@brownGrayLight: #f6f4f4;// added 2019 @orange: #ff9412;// added 2019 //@u-greyLight: #f2ebe6;// added 2019 @@ -134,6 +134,7 @@ //@ui-active: #346ab3; @ui-active: @pinkLight; +@ui-active-blur: @brownLight; @ui-active-type: @blueExtraDark; @ui-active-type-hover: @blueMid; @@ -142,7 +143,7 @@ @ui-selected-type: @blueExtraDark; @ui-selected-type-hover: @blueMid; @ui-selected-border: @pinkLight; -@ui-selected-border-hover: @pinkLight; +@ui-selected-border-hover: darken(@pinkLight, 10); @ui-light-border: @pinkLight; @ui-light-type: @gray-4; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html index d3854683c8..9474e98350 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree-item.html @@ -1,21 +1,19 @@ -
  • -
    - +
    +   {{node.name}} - +
    - +
  • - - diff --git a/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html b/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html index 490c94a79d..487be4af87 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/umb-content-grid.html @@ -5,8 +5,8 @@ ng-repeat="item in content" ng-class="{'-selected': item.selected}" ng-click="clickItem(item, $event, $index)"> - - + +
    diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index dba6a41a7c..9a638d91fa 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -13,13 +13,13 @@
    - + Create {{listViewAllowedTypes[0].name}} @@ -85,6 +85,7 @@ type="button" label="Clear selection" label-key="buttons_clearSelection" + button-style="selection" action="clearSelection()" disabled="actionInProgress"> @@ -139,7 +140,7 @@ ng-if="options.allowBulkPublish && (buttonPermissions == null || buttonPermissions.canPublish)" style="margin-right: 5px;" type="button" - button-style="outline" + button-style="selection" label-key="actions_publish" icon="icon-globe" action="publish()" @@ -152,7 +153,7 @@ ng-if="options.allowBulkUnpublish && (buttonPermissions == null || buttonPermissions.canUnpublish)" style="margin-right: 5px;" type="button" - button-style="outline" + button-style="selection" label-key="actions_unpublish" icon="icon-block" action="unpublish()" @@ -165,7 +166,7 @@ ng-if="options.allowBulkCopy && (buttonPermissions == null || buttonPermissions.canCopy)" style="margin-right: 5px;" type="button" - button-style="outline" + button-style="selection" label-key="actions_copy" icon="icon-documents" action="copy()" @@ -178,7 +179,7 @@ ng-if="options.allowBulkMove && (buttonPermissions == null || buttonPermissions.canMove)" style="margin-right: 5px;" type="button" - button-style="outline" + button-style="selection" label-key="actions_move" icon="icon-enter" action="move()" @@ -190,7 +191,7 @@ Date: Thu, 31 Jan 2019 10:13:07 +0100 Subject: [PATCH 7/9] V8: UI interact vs. select --- src/Umbraco.Web.UI.Client/src/less/canvas-designer.less | 1 - .../src/less/components/umb-content-grid.less | 1 + .../src/less/components/umb-folder-grid.less | 1 + .../src/less/components/umb-media-grid.less | 5 +++++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less index a144336a54..146f9b8a67 100644 --- a/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less +++ b/src/Umbraco.Web.UI.Client/src/less/canvas-designer.less @@ -45,7 +45,6 @@ h4 { h5 { margin: 0 0 6px 0; - color: #535353; font-size: 12px; } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less index b55a511f4b..5a2821eb9e 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-content-grid.less @@ -37,6 +37,7 @@ border: 2px solid @ui-selected-border; border-radius: 5px; box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); + pointer-events: none; } } diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less index d2f86affab..32100247a0 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-folder-grid.less @@ -44,6 +44,7 @@ border: 2px solid @ui-selected-border; border-radius: 5px; box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); + pointer-events: none; } &:hover { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less index 017313af80..fc6de2bf75 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-media-grid.less @@ -55,6 +55,7 @@ border: 2px solid @ui-selected-border; border-radius: 5px; box-shadow: 0 0 4px 0 darken(@ui-selected-border, 20), inset 0 0 2px 0 darken(@ui-selected-border, 20); + pointer-events: none; } .umb-media-grid__item-overlay { @@ -128,6 +129,10 @@ border-top:1px solid fade(black, 4%); background: fade(@white, 92%); transition: opacity 150ms; + + &:hover { + text-decoration: underline; + } } /* From a6f9598a23e41687d2d6b0f6b0e518cf830ab825 Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 31 Jan 2019 09:08:51 +0100 Subject: [PATCH 8/9] Introduce IPublishedRouter --- .../TestControllerActivatorBase.cs | 2 +- .../Testing/TestingTests/MockTests.cs | 2 +- src/Umbraco.Tests/Testing/UmbracoTestBase.cs | 2 +- .../Web/Mvc/SurfaceControllerTests.cs | 2 +- .../Models/Mapping/ContentUrlResolver.cs | 4 +- .../EnsurePublishedContentRequestAttribute.cs | 8 ++- src/Umbraco.Web/Mvc/RenderRouteHandler.cs | 2 +- .../Mvc/UmbracoVirtualNodeRouteHandler.cs | 2 +- src/Umbraco.Web/Routing/IPublishedRouter.cs | 54 +++++++++++++++++++ src/Umbraco.Web/Routing/PublishedRequest.cs | 8 +-- src/Umbraco.Web/Routing/PublishedRouter.cs | 43 +++++---------- .../Routing/UrlProviderExtensions.cs | 6 +-- src/Umbraco.Web/Runtime/WebRuntimeComposer.cs | 2 +- src/Umbraco.Web/Security/MembershipHelper.cs | 27 +++++++--- src/Umbraco.Web/Templates/TemplateRenderer.cs | 2 +- src/Umbraco.Web/Umbraco.Web.csproj | 1 + src/Umbraco.Web/UmbracoInjectedModule.cs | 4 +- 17 files changed, 111 insertions(+), 60 deletions(-) create mode 100644 src/Umbraco.Web/Routing/IPublishedRouter.cs diff --git a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs index 602b5907d8..6414ea469d 100644 --- a/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs +++ b/src/Umbraco.Tests/TestHelpers/ControllerTesting/TestControllerActivatorBase.cs @@ -150,7 +150,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting urlHelper.Setup(provider => provider.GetUrl(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(UrlInfo.Url("/hello/world/1234")); - var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()); + var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()); var umbHelper = new UmbracoHelper(umbCtx, Mock.Of(), diff --git a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs index 575f14e818..622186a547 100644 --- a/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs +++ b/src/Umbraco.Tests/Testing/TestingTests/MockTests.cs @@ -65,7 +65,7 @@ namespace Umbraco.Tests.Testing.TestingTests Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), ServiceContext.CreatePartial()); Assert.Pass(); } diff --git a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs index 9616a26891..7c8d1100f8 100644 --- a/src/Umbraco.Tests/Testing/UmbracoTestBase.cs +++ b/src/Umbraco.Tests/Testing/UmbracoTestBase.cs @@ -213,7 +213,7 @@ namespace Umbraco.Tests.Testing // web Composition.RegisterUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor); - Composition.RegisterUnique(); + Composition.RegisterUnique(); Composition.WithCollectionBuilder(); Composition.RegisterUnique(); Composition.RegisterUnique(); diff --git a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs index 69f6c5d13e..ec37793c10 100644 --- a/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs @@ -132,7 +132,7 @@ namespace Umbraco.Tests.Web.Mvc Mock.Of(), Mock.Of(), Mock.Of(), - new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), null, Mock.Of(), Mock.Of()), + new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of(), Mock.Of()), ServiceContext.CreatePartial()); var ctrl = new TestSurfaceController(umbracoContext, helper); diff --git a/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs b/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs index f09638330b..42c4997d86 100644 --- a/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs +++ b/src/Umbraco.Web/Models/Mapping/ContentUrlResolver.cs @@ -11,7 +11,7 @@ namespace Umbraco.Web.Models.Mapping internal class ContentUrlResolver : IValueResolver { private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly PublishedRouter _publishedRouter; + private readonly IPublishedRouter _publishedRouter; private readonly ILocalizationService _localizationService; private readonly ILocalizedTextService _textService; private readonly IContentService _contentService; @@ -19,7 +19,7 @@ namespace Umbraco.Web.Models.Mapping public ContentUrlResolver( IUmbracoContextAccessor umbracoContextAccessor, - PublishedRouter publishedRouter, + IPublishedRouter publishedRouter, ILocalizationService localizationService, ILocalizedTextService textService, IContentService contentService, diff --git a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs index 62a7c48d2b..471cec6db7 100644 --- a/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs +++ b/src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs @@ -33,8 +33,7 @@ namespace Umbraco.Web.Mvc /// public EnsurePublishedContentRequestAttribute(UmbracoContext umbracoContext, int contentId) { - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - _umbracoContext = umbracoContext; + _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _contentId = contentId; } @@ -63,8 +62,7 @@ namespace Umbraco.Web.Mvc /// public EnsurePublishedContentRequestAttribute(UmbracoContext umbracoContext, string dataTokenName) { - if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext)); - _umbracoContext = umbracoContext; + _umbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _dataTokenName = dataTokenName; } @@ -74,7 +72,7 @@ namespace Umbraco.Web.Mvc protected UmbracoContext UmbracoContext => _umbracoContext ?? (_umbracoContext = UmbracoContext.Current); // TODO: try lazy property injection? - private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); + private IPublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); /// /// Exposes an UmbracoHelper diff --git a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs index 215eb39573..2c550effc4 100644 --- a/src/Umbraco.Web/Mvc/RenderRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/RenderRouteHandler.cs @@ -377,7 +377,7 @@ namespace Umbraco.Web.Mvc if ((request.HasTemplate == false && Features.Disabled.DisableTemplates == false) && routeDef.HasHijackedRoute == false) { - request.UpdateOnMissingTemplate(); // request will go 404 + request.UpdateToNotFound(); // request will go 404 // HandleHttpResponseStatus returns a value indicating that the request should // not be processed any further, eg because it has been redirect. then, exit. diff --git a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs index 48e16b48d7..1af434e94e 100644 --- a/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs +++ b/src/Umbraco.Web/Mvc/UmbracoVirtualNodeRouteHandler.cs @@ -12,7 +12,7 @@ namespace Umbraco.Web.Mvc public abstract class UmbracoVirtualNodeRouteHandler : IRouteHandler { // TODO: try lazy property injection? - private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); + private IPublishedRouter PublishedRouter => Current.Factory.GetInstance(); /// /// Returns the UmbracoContext for this route handler diff --git a/src/Umbraco.Web/Routing/IPublishedRouter.cs b/src/Umbraco.Web/Routing/IPublishedRouter.cs new file mode 100644 index 0000000000..df06e42e55 --- /dev/null +++ b/src/Umbraco.Web/Routing/IPublishedRouter.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using Umbraco.Core.Models; + +namespace Umbraco.Web.Routing +{ + /// + /// Routes requests. + /// + public interface IPublishedRouter + { + // TODO: consider this and RenderRouteHandler - move some code around? + + /// + /// Creates a published request. + /// + /// The current Umbraco context. + /// The (optional) request Uri. + /// A published request. + PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null); + + /// + /// Prepares a request for rendering. + /// + /// The request. + /// A value indicating whether the request was successfully prepared and can be rendered. + bool PrepareRequest(PublishedRequest request); + + /// + /// Tries to route a request. + /// + /// The request. + /// A value indicating whether the request can be routed to a document. + bool TryRouteRequest(PublishedRequest request); + + /// + /// Gets a template. + /// + /// The template alias + /// The template. + ITemplate GetTemplate(string alias); + + /// + /// Updates the request to "not found". + /// + /// The request. + /// + /// This method is invoked when the pipeline decides it cannot render + /// the request, for whatever reason, and wants to force it to be re-routed + /// and rendered as if no document were found (404). + /// + void UpdateRequestToNotFound(PublishedRequest request); + } +} diff --git a/src/Umbraco.Web/Routing/PublishedRequest.cs b/src/Umbraco.Web/Routing/PublishedRequest.cs index c5475f8b73..52f5820744 100644 --- a/src/Umbraco.Web/Routing/PublishedRequest.cs +++ b/src/Umbraco.Web/Routing/PublishedRequest.cs @@ -17,7 +17,7 @@ namespace Umbraco.Web.Routing /// public class PublishedRequest { - private readonly PublishedRouter _publishedRouter; + private readonly IPublishedRouter _publishedRouter; private bool _readonly; // after prepared private bool _readonlyUri; // after preparing @@ -35,7 +35,7 @@ namespace Umbraco.Web.Routing /// The published router. /// The Umbraco context. /// The request Uri. - internal PublishedRequest(PublishedRouter publishedRouter, UmbracoContext umbracoContext, Uri uri = null) + internal PublishedRequest(IPublishedRouter publishedRouter, UmbracoContext umbracoContext, Uri uri = null) { UmbracoContext = umbracoContext ?? throw new ArgumentNullException(nameof(umbracoContext)); _publishedRouter = publishedRouter ?? throw new ArgumentNullException(nameof(publishedRouter)); @@ -291,11 +291,11 @@ namespace Umbraco.Web.Routing /// public bool HasTemplate => TemplateModel != null; - internal void UpdateOnMissingTemplate() + internal void UpdateToNotFound() { var __readonly = _readonly; _readonly = false; - _publishedRouter.UpdateRequestOnMissingTemplate(this); + _publishedRouter.UpdateRequestToNotFound(this); _readonly = __readonly; } diff --git a/src/Umbraco.Web/Routing/PublishedRouter.cs b/src/Umbraco.Web/Routing/PublishedRouter.cs index 14c36198d8..7dd1ec9f1a 100644 --- a/src/Umbraco.Web/Routing/PublishedRouter.cs +++ b/src/Umbraco.Web/Routing/PublishedRouter.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.IO; using System.Web.Security; using Umbraco.Core; +using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.IO; @@ -18,8 +19,10 @@ using Umbraco.Web.Security; namespace Umbraco.Web.Routing { - // TODO: making sense to have an interface? - public class PublishedRouter + /// + /// Provides the default implementation. + /// + public class PublishedRouter : IPublishedRouter { private readonly IWebRoutingSection _webRoutingSection; private readonly ContentFinderCollection _contentFinders; @@ -47,15 +50,9 @@ namespace Umbraco.Web.Routing _profilingLogger = proflog ?? throw new ArgumentNullException(nameof(proflog)); _variationContextAccessor = variationContextAccessor ?? throw new ArgumentNullException(nameof(variationContextAccessor)); _logger = proflog; - - GetRolesForLogin = s => Roles.Provider.GetRolesForUser(s); } - // TODO: in 7.7 this is cached in the PublishedContentRequest, which ... makes little sense - // killing it entirely, if we need cache, just implement it properly !! - // this is all so weird - public Func> GetRolesForLogin { get; } - + /// public PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null) { return new PublishedRequest(this, umbracoContext, uri ?? umbracoContext.CleanedUmbracoUrl); @@ -63,10 +60,8 @@ namespace Umbraco.Web.Routing #region Request - /// - /// Tries to route the request. - /// - internal bool TryRouteRequest(PublishedRequest request) + /// + public bool TryRouteRequest(PublishedRequest request) { // disabled - is it going to change the routing? //_pcr.OnPreparing(); @@ -96,12 +91,7 @@ namespace Umbraco.Web.Routing _variationContextAccessor.VariationContext = new VariationContext(culture); } - /// - /// Prepares the request. - /// - /// - /// Returns false if the request was not successfully prepared - /// + /// public bool PrepareRequest(PublishedRequest request) { // note - at that point the original legacy module did something do handle IIS custom 404 errors @@ -213,11 +203,8 @@ namespace Umbraco.Web.Routing return true; } - /// - /// Updates the request when there is no template to render the content. - /// - /// This is called from Mvc when there's a document to render but no template. - public void UpdateRequestOnMissingTemplate(PublishedRequest request) + /// + public void UpdateRequestToNotFound(PublishedRequest request) { // clear content var content = request.PublishedContent; @@ -386,11 +373,7 @@ namespace Umbraco.Web.Routing #region Document and template - /// - /// Gets a template. - /// - /// The template alias - /// The template. + /// public ITemplate GetTemplate(string alias) { return _services.FileService.GetTemplate(alias); @@ -607,7 +590,7 @@ namespace Umbraco.Web.Routing if (loginPageId != request.PublishedContent.Id) request.PublishedContent = request.UmbracoContext.PublishedSnapshot.Content.GetById(loginPageId); } - else if (_services.PublicAccessService.HasAccess(request.PublishedContent.Id, _services.ContentService, membershipHelper.CurrentUserName, GetRolesForLogin(membershipHelper.CurrentUserName)) == false) + else if (_services.PublicAccessService.HasAccess(request.PublishedContent.Id, _services.ContentService, membershipHelper.CurrentUserName, membershipHelper.GetCurrentUserRoles()) == false) { _logger.Debug("EnsurePublishedContentAccess: Current member has not access, redirect to error page"); var errorPageId = publicAccessAttempt.Result.NoAccessNodeId; diff --git a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs index 8db657ed30..2a840828b6 100644 --- a/src/Umbraco.Web/Routing/UrlProviderExtensions.cs +++ b/src/Umbraco.Web/Routing/UrlProviderExtensions.cs @@ -18,7 +18,7 @@ namespace Umbraco.Web.Routing /// Contains all the Urls that we can figure out (based upon domains, etc). /// public static IEnumerable GetContentUrls(this IContent content, - PublishedRouter publishedRouter, + IPublishedRouter publishedRouter, UmbracoContext umbracoContext, ILocalizationService localizationService, ILocalizedTextService textService, @@ -92,7 +92,7 @@ namespace Umbraco.Web.Routing /// private static IEnumerable GetContentUrlsByCulture(IContent content, IEnumerable cultures, - PublishedRouter publishedRouter, + IPublishedRouter publishedRouter, UmbracoContext umbracoContext, IContentService contentService, ILocalizedTextService textService, @@ -161,7 +161,7 @@ namespace Umbraco.Web.Routing return UrlInfo.Message(textService.Localize("content/parentCultureNotPublished", new[] {parent.Name}), culture); } - private static bool DetectCollision(IContent content, string url, string culture, UmbracoContext umbracoContext, PublishedRouter publishedRouter, ILocalizedTextService textService, out UrlInfo urlInfo) + private static bool DetectCollision(IContent content, string url, string culture, UmbracoContext umbracoContext, IPublishedRouter publishedRouter, ILocalizedTextService textService, out UrlInfo urlInfo) { // test for collisions on the 'main' url var uri = new Uri(url.TrimEnd('/'), UriKind.RelativeOrAbsolute); diff --git a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs index de3ca47b38..4070ee9ece 100644 --- a/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs +++ b/src/Umbraco.Web/Runtime/WebRuntimeComposer.cs @@ -178,7 +178,7 @@ namespace Umbraco.Web.Runtime composition.RegisterAuto(typeof(UmbracoViewPage<>)); // register published router - composition.RegisterUnique(); + composition.RegisterUnique(); composition.Register(_ => Current.Configs.Settings().WebRouting); // register preview SignalR hub diff --git a/src/Umbraco.Web/Security/MembershipHelper.cs b/src/Umbraco.Web/Security/MembershipHelper.cs index e053617806..daec4bb1f7 100644 --- a/src/Umbraco.Web/Security/MembershipHelper.cs +++ b/src/Umbraco.Web/Security/MembershipHelper.cs @@ -31,7 +31,6 @@ namespace Umbraco.Web.Security private readonly IMemberTypeService _memberTypeService; private readonly IUserService _userService; private readonly IPublicAccessService _publicAccessService; - private readonly PublishedRouter _publishedRouter; private readonly AppCaches _appCaches; private readonly ILogger _logger; @@ -46,7 +45,6 @@ namespace Umbraco.Web.Security IMemberTypeService memberTypeService, IUserService userService, IPublicAccessService publicAccessService, - PublishedRouter publishedRouter, AppCaches appCaches, ILogger logger ) @@ -57,7 +55,6 @@ namespace Umbraco.Web.Security _memberTypeService = memberTypeService; _userService = userService; _publicAccessService = publicAccessService; - _publishedRouter = publishedRouter; _appCaches = appCaches; _logger = logger; @@ -116,7 +113,7 @@ namespace Umbraco.Web.Security { return UmbracoContext.PublishedRequest == null ? _publicAccessService.HasAccess(path, CurrentUserName, roleProvider.GetRolesForUser) - : _publicAccessService.HasAccess(path, CurrentUserName, _publishedRouter.GetRolesForLogin); + : _publicAccessService.HasAccess(path, CurrentUserName, GetUserRoles); } /// @@ -514,6 +511,24 @@ namespace Umbraco.Web.Security } #endregion + /// + /// Gets the current user's roles. + /// + /// Roles are cached per user name, at request level. + public IEnumerable GetCurrentUserRoles() + => GetUserRoles(CurrentUserName); + + /// + /// Gets a user's roles. + /// + /// Roles are cached per user name, at request level. + public IEnumerable GetUserRoles(string userName) + { + // optimize by caching per-request (v7 cached per PublishedRequest, in PublishedRouter) + var key = "Umbraco.Web.Security.MembershipHelper__Roles__" + userName; + return _appCaches.RequestCache.GetCacheItem(key, () => Roles.Provider.GetRolesForUser(userName)); + } + /// /// Returns the login status model of the currently logged in member, if no member is logged in it returns null; /// @@ -618,7 +633,7 @@ namespace Umbraco.Web.Security var provider = _membershipProvider; string username; - + if (provider.IsUmbracoMembershipProvider()) { var member = GetCurrentPersistedMember(); @@ -626,7 +641,7 @@ namespace Umbraco.Web.Security if (member == null) return false; username = member.Username; - + // If types defined, check member is of one of those types var allowTypesList = allowTypes as IList ?? allowTypes.ToList(); if (allowTypesList.Any(allowType => allowType != string.Empty)) diff --git a/src/Umbraco.Web/Templates/TemplateRenderer.cs b/src/Umbraco.Web/Templates/TemplateRenderer.cs index 9279eea124..7d678b93ca 100644 --- a/src/Umbraco.Web/Templates/TemplateRenderer.cs +++ b/src/Umbraco.Web/Templates/TemplateRenderer.cs @@ -36,7 +36,7 @@ namespace Umbraco.Web.Templates } private IFileService FileService => Current.Services.FileService; // TODO: inject - private PublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); // TODO: inject + private IPublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance(); // TODO: inject /// diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index f078e9d79f..709d938ba4 100755 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -183,6 +183,7 @@ + diff --git a/src/Umbraco.Web/UmbracoInjectedModule.cs b/src/Umbraco.Web/UmbracoInjectedModule.cs index 95819e79d7..ba1a384484 100644 --- a/src/Umbraco.Web/UmbracoInjectedModule.cs +++ b/src/Umbraco.Web/UmbracoInjectedModule.cs @@ -45,7 +45,7 @@ namespace Umbraco.Web private readonly UrlProviderCollection _urlProviders; private readonly IRuntimeState _runtime; private readonly ILogger _logger; - private readonly PublishedRouter _publishedRouter; + private readonly IPublishedRouter _publishedRouter; private readonly IVariationContextAccessor _variationContextAccessor; public UmbracoInjectedModule( @@ -56,7 +56,7 @@ namespace Umbraco.Web UrlProviderCollection urlProviders, IRuntimeState runtime, ILogger logger, - PublishedRouter publishedRouter, + IPublishedRouter publishedRouter, IVariationContextAccessor variationContextAccessor) { _combinedRouteCollection = new Lazy(CreateRouteCollection); From d45d0a816ef23346a9b52bc912b9162be5e8de74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niels=20Lyngs=C3=B8?= Date: Thu, 31 Jan 2019 12:58:17 +0100 Subject: [PATCH 9/9] =?UTF-8?q?V8:=20UI=20=E2=80=94=20changed=20colors=20f?= =?UTF-8?q?or=20selection=20state=20for=20rows=20in=20list-view?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/less/buttons.less | 3 ++- .../less/components/umb-layout-selector.less | 4 ++-- .../src/less/components/umb-table.less | 18 ++++++++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/buttons.less b/src/Umbraco.Web.UI.Client/src/less/buttons.less index a246ef585e..c6a8447342 100644 --- a/src/Umbraco.Web.UI.Client/src/less/buttons.less +++ b/src/Umbraco.Web.UI.Client/src/less/buttons.less @@ -201,7 +201,8 @@ input[type="button"] { } // Made for Umbraco, 2019 .btn-selection { - .buttonBackground(@pinkLight, ligthen(@pinkLight, 20%), @blueExtraDark, @blueDark); + @btnSelectionBackgroundHover: darken(@pinkLight, 10%); + .buttonBackground(@pinkLight, @btnSelectionBackgroundHover, @blueExtraDark, @blueDark); } // Made for Umbraco, 2019, used for buttons that has to stand back. .btn-white { diff --git a/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less b/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less index adaf45b4b0..cf407b667f 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/umb-layout-selector.less @@ -5,7 +5,7 @@ .umb-layout-selector__active-layout { box-sizing: border-box; - border: 1px solid transparent; + border: 1px solid @inputBorder; cursor: pointer; height: 30px; width: 30px; @@ -16,7 +16,7 @@ } .umb-layout-selector__active-layout:hover { - border-color: @gray-8; + border-color: @inputBorderFocus; } .umb-layout-selector__dropdown { 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 c1687636d3..291eef43e0 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 @@ -90,13 +90,13 @@ input.umb-table__input { .umb-table-body .umb-table-row { color: @gray-5; - border-top: 1px solid @gray-8; + border-top: 1px solid @gray-9; cursor: pointer; font-size: 14px; position: relative; min-height: 52px; &:hover { - background-color: @gray-10; + background-color: @ui-option-hover; } } @@ -151,12 +151,26 @@ input.umb-table__input { // Show checkmark when checked, hide file icon .umb-table-row--selected { + /* .umb-table-body__fileicon { display: none; } .umb-table-body__checkicon { display: inline-block; } + */ + &::before { + content: ""; + position: absolute; + z-index:1; + top: 1px; + left: 1px; + right: 1px; + bottom: 1px; + border: 2px solid @ui-selected-border; + box-shadow: 0 0 2px 0 fade(@ui-selected-border, 80%); + pointer-events: none; + } } // Table Row Styles