Merge branch 'temp8' into temp8-macros-dont-render-and-other-macro-bugs

# Conflicts:
#	src/Umbraco.Tests/Testing/TestingTests/MockTests.cs
#	src/Umbraco.Tests/Web/Mvc/SurfaceControllerTests.cs
#	src/Umbraco.Web/Templates/TemplateRenderer.cs
This commit is contained in:
Shannon
2019-02-01 11:33:13 +11:00
40 changed files with 491 additions and 224 deletions

View File

@@ -150,7 +150,7 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
urlHelper.Setup(provider => provider.GetUrl(It.IsAny<UmbracoContext>(), It.IsAny<IPublishedContent>(), It.IsAny<UrlProviderMode>(), It.IsAny<string>(), It.IsAny<Uri>()))
.Returns(UrlInfo.Url("/hello/world/1234"));
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), null, Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var membershipHelper = new MembershipHelper(new TestUmbracoContextAccessor(umbCtx), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var umbHelper = new UmbracoHelper(umbCtx,
Mock.Of<ITagQuery>(),

View File

@@ -65,7 +65,7 @@ namespace Umbraco.Tests.Testing.TestingTests
Mock.Of<ICultureDictionaryFactory>(),
Mock.Of<IUmbracoComponentRenderer>(),
Mock.Of<IPublishedContentQuery>(),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), null, Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
Assert.Pass();
}

View File

@@ -213,7 +213,7 @@ namespace Umbraco.Tests.Testing
// web
Composition.RegisterUnique(_ => Umbraco.Web.Composing.Current.UmbracoContextAccessor);
Composition.RegisterUnique<PublishedRouter>();
Composition.RegisterUnique<IPublishedRouter, PublishedRouter>();
Composition.WithCollectionBuilder<ContentFinderCollectionBuilder>();
Composition.RegisterUnique<IContentLastChanceFinder, TestLastChanceFinder>();
Composition.RegisterUnique<IVariationContextAccessor, TestVariationContextAccessor>();

View File

@@ -132,7 +132,7 @@ namespace Umbraco.Tests.Web.Mvc
Mock.Of<ICultureDictionaryFactory>(),
Mock.Of<IUmbracoComponentRenderer>(),
Mock.Of<IPublishedContentQuery>(),
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), null, Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
new MembershipHelper(new TestUmbracoContextAccessor(umbracoContext), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>()));
var ctrl = new TestSurfaceController(umbracoContext, helper);
var result = ctrl.GetContent(2) as PublishedContentResult;

View File

@@ -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);
@@ -340,7 +363,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 });
@@ -414,7 +437,7 @@
$scope.content = data;
init($scope.content);
init();
resetLastListPageNumber($scope.content);
@@ -454,7 +477,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 });
@@ -845,8 +868,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

View File

@@ -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) {

View File

@@ -52,7 +52,8 @@
vm.isLoading = false;
configureViewModel();
//ensure that the models are formatted correctly
configureViewModel(true);
// Set the visible prompt to -1 to ensure it will not be visible
vm.promptIsVisible = "-1";
@@ -123,9 +124,13 @@
});
}
/**
* Watch for value changes
* @param {any} changes
*/
function onChanges(changes) {
// watch for value changes externally
//when the model 'value' changes, sync the viewModel object
if (changes.value) {
if (!changes.value.isFirstChange() && changes.value.currentValue !== changes.value.previousValue) {
@@ -145,13 +150,15 @@
$element.find('.tags-' + vm.htmlId).typeahead('destroy');
}
function configureViewModel() {
function configureViewModel(isInitLoad) {
if (vm.value) {
if (angular.isString(vm.value) && vm.value.length > 0) {
if (vm.config.storageType === "Json") {
//json storage
vm.viewModel = JSON.parse(vm.value);
updateModelValue(vm.viewModel);
if (!isInitLoad) {
updateModelValue(vm.viewModel);
}
}
else {
//csv storage
@@ -165,7 +172,10 @@
return self.indexOf(v) === i;
});
updateModelValue(vm.viewModel);
if (!isInitLoad) {
updateModelValue(vm.viewModel);
}
}
}
else if (angular.isArray(vm.value)) {
@@ -175,13 +185,18 @@
}
function updateModelValue(val) {
if (val) {
vm.onValueChanged({ value: val });
//need to format the underlying model value for persistence based on the storage type
if (vm.config.storageType === "Json") {
val = val ? val : [];
}
else {
vm.onValueChanged({ value: [] });
//then it is csv and we need to format it like that
val = val ? val.join() : "";
}
vm.onValueChanged({ value: val });
reValidate();
}
@@ -273,8 +288,10 @@
}
function reValidate() {
//this is required to re-validate
vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length);
//this is required to re-validate for the mandatory validation
if (vm.tagEditorForm && vm.tagEditorForm.tagCount) {
vm.tagEditorForm.tagCount.$setViewValue(vm.viewModel.length);
}
}
}

View File

@@ -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");
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -197,7 +197,12 @@ 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 {
@btnSelectionBackgroundHover: darken(@pinkLight, 10%);
.buttonBackground(@pinkLight, @btnSelectionBackgroundHover, @blueExtraDark, @blueDark);
}
// Made for Umbraco, 2019, used for buttons that has to stand back.
.btn-white {

View File

@@ -45,7 +45,6 @@ h4 {
h5 {
margin: 0 0 6px 0;
color: #535353;
font-size: 12px;
}

View File

@@ -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;
}

View File

@@ -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 {

View File

@@ -14,10 +14,32 @@
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);
pointer-events: none;
}
}
.umb-content-grid__icon-container {
@@ -31,12 +53,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 +70,7 @@
.umb-content-grid__item-name {
font-weight: bold;
margin-bottom: 15px;
color: @black;
//color: @black;
line-height: 1.4em;
display: inline-flex;
}

View File

@@ -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,29 @@
}
.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);
pointer-events: none;
}
&:hover {
color:@ui-selected-type-hover;
border-color:@ui-selected-border-hover;
//border-color:@ui-selected-border-hover;
}
}
@@ -59,12 +73,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;
}

View File

@@ -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 {

View File

@@ -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,31 @@
}
.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);
pointer-events: none;
}
.umb-media-grid__item-overlay {
color: @ui-selected-type;
//background: @ui-selected-border;
}
}
.umb-media-grid__item-file-icon > span {
@@ -64,16 +82,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 +119,22 @@
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;
&:hover {
text-decoration: underline;
}
}
/*
.umb-media-grid__item.-file .umb-media-grid__item-overlay {
opacity: 1;
@@ -180,6 +209,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 {

View File

@@ -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

View File

@@ -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;

View File

@@ -1,21 +1,19 @@
<li class="umb-tree-item" data-element="tree-item-{{::node.dataElement}}" ng-class="{'current': (node == currentNode), 'has-children': node.hasChildren, 'umb-tree-item--deleted': node.deleteAnimations}" on-right-click="altSelect(node, $event)">
<div class="umb-tree-item__inner" ng-class="getNodeCssClass(node)" ng-swipe-right="options(node, $event)" ng-dblclick="load(node)" >
<ins data-element="tree-item-expand"
ng-class="{'icon-navigation-right': !node.expanded || node.metaData.isContainer, 'icon-navigation-down': node.expanded && !node.metaData.isContainer}"
<li class="umb-tree-item" data-element="tree-item-{{::node.dataElement}}" ng-class="getNodeCssClass(node)" on-right-click="altSelect(node, $event)">
<div class="umb-tree-item__inner" ng-swipe-right="options(node, $event)" ng-dblclick="load(node)" >
<ins data-element="tree-item-expand"
ng-class="{'icon-navigation-right': !node.expanded || node.metaData.isContainer, 'icon-navigation-down': node.expanded && !node.metaData.isContainer}"
ng-style="{'visibility': (scope.enablelistviewexpand === 'true' || node.hasChildren && (!node.metaData.isContainer || isDialog)) ? 'visible' : 'hidden'}"
ng-click="load(node)">&nbsp;</ins>
<i class="icon umb-tree-icon sprTree" ng-class="::node.cssClass" title="{{::node.routePath}}" ng-click="select(node, $event)" ng-style="::node.style"></i>
<a class="umb-tree-item__label" ng-href="#/{{::node.routePath}}" ng-click="select(node, $event)">{{node.name}}</a>
<!-- NOTE: These are the 'option' elipses -->
<a data-element="tree-item-options" class="umb-options" ng-click="options(node, $event)" ng-if="::node.menuUrl"><i></i><i></i><i></i></a>
<div ng-show="node.loading" class="l"><div></div></div>
</div>
<ul ng-class="{collapsed: !node.expanded}">
<umb-tree-item class="umb-animated" ng-repeat="child in node.children track by child.id" enablelistviewexpand="{{enablelistviewexpand}}" tree="tree" current-node="currentNode" node="child" is-dialog="isDialog" section="{{section}}"></umb-tree-item>
</ul>
</li>

View File

@@ -5,8 +5,8 @@
ng-repeat="item in content"
ng-class="{'-selected': item.selected}"
ng-click="clickItem(item, $event, $index)">
<i ng-if="item.selected" class="icon-check umb-content-grid__checkmark"></i>
<!--<i ng-if="item.selected" class="icon-check umb-content-grid__checkmark"></i>-->
<div class="umb-content-grid__content">

View File

@@ -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)">
</umb-editor-header>
<umb-editor-container>

View File

@@ -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,91 @@ function mediaEditController($scope, $routeParams, $q, appState, mediaResource,
$scope.page.listViewPath = null;
$scope.page.saveButtonState = "init";
$scope.page.submitButtonLabelKey = "buttons_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;
});
}
}));
}
$scope.page.submitButtonLabelKey = "buttons_save";
/** Syncs the content item to it's tree node - this occurs on first load and after saving */
function syncTreeNode(content, path, initialLoad) {
@@ -68,45 +155,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.submitButtonLabelKey = "buttons_saveAndClose";
}
}
$scope.save = function () {
@@ -212,14 +260,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.submitButtonLabelKey = "buttons_saveAndClose";
}
}));
}
//ensure to unregister from all events!
$scope.$on('$destroy', function () {

View File

@@ -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 = [];

View File

@@ -65,8 +65,8 @@
<p><span>{{item.alias}}</span> <small>({{item.width}}px &times; {{item.height}}px)</small></p>
</div>
<div class="umb-prevalues-multivalues__right">
<a href="#" prevent-default class="umb-node-preview__action umb-node-preview__action--red" ng-click="edit(item, $event)" class="umb-prevalues-multivalues__action">Edit</a>
<a class="umb-node-preview__action umb-node-preview__action--red" ng-click="remove(item, $event)"><localize key="general_remove">Remove</localize></a>
<a href="#" prevent-default class="umb-node-preview__action" ng-click="edit(item, $event)"><localize key="general_edit">Edit</localize></a>
<a href="#" prevent-default class="umb-node-preview__action umb-node-preview__action--red" ng-click="remove(item, $event)"><localize key="general_remove">Remove</localize></a>
</div>
</div>
</div>

View File

@@ -13,13 +13,13 @@
<umb-editor-sub-header-section ng-if="(listViewAllowedTypes && listViewAllowedTypes.length > 0 && (selection.length == 0)) && (currentNodePermissions == null || currentNodePermissions.canCreate)">
<div class="btn-group" ng-show="createAllowedButtonSingle">
<a class="btn btn-success" ng-click="createBlank(entityType,listViewAllowedTypes[0].alias)">
<a class="btn btn-white" ng-click="createBlank(entityType,listViewAllowedTypes[0].alias)">
<localize key="actions_create">Create</localize> {{listViewAllowedTypes[0].name}}
</a>
</div>
<div class="btn-group" ng-show="createAllowedButtonSingleWithBlueprints">
<a class="btn btn-success dropdown-toggle" data-toggle="dropdown" ng-href="">
<a class="btn btn-white dropdown-toggle" data-toggle="dropdown" ng-href="">
<span ng-click="createBlank(entityType,listViewAllowedTypes[0].alias)">
<localize key="actions_create">Create</localize> {{listViewAllowedTypes[0].name}}
</span>
@@ -85,6 +85,7 @@
type="button"
label="Clear selection"
label-key="buttons_clearSelection"
button-style="selection"
action="clearSelection()"
disabled="actionInProgress">
</umb-button>
@@ -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 @@
<umb-button
ng-if="options.allowBulkDelete && (buttonPermissions == null || buttonPermissions.canDelete)"
type="button"
button-style="outline"
button-style="selection"
label-key="actions_delete"
icon="icon-trash"
action="delete()"

View File

@@ -1,12 +1,9 @@
angular.module("umbraco")
.controller("Umbraco.PropertyEditors.TagsController",
function ($scope, angularHelper) {
function ($scope) {
$scope.valueChanged = function(value) {
$scope.model.value = value;
// the model value seems to be a reference to the same array, so we need
// to set the form as dirty explicitly when the content of the array changes
angularHelper.getCurrentForm($scope).$setDirty();
}
}

View File

@@ -11,7 +11,7 @@ namespace Umbraco.Web.Models.Mapping
internal class ContentUrlResolver : IValueResolver<IContent, ContentItemDisplay, UrlInfo[]>
{
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,

View File

@@ -33,8 +33,7 @@ namespace Umbraco.Web.Mvc
/// <param name="contentId"></param>
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
/// <param name="dataTokenName"></param>
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<PublishedRouter>();
private IPublishedRouter PublishedRouter => Core.Composing.Current.Factory.GetInstance<IPublishedRouter>();
/// <summary>
/// Exposes an UmbracoHelper

View File

@@ -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.

View File

@@ -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<PublishedRouter>();
private IPublishedRouter PublishedRouter => Current.Factory.GetInstance<IPublishedRouter>();
/// <summary>
/// Returns the UmbracoContext for this route handler

View File

@@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using Umbraco.Core.Models;
namespace Umbraco.Web.Routing
{
/// <summary>
/// Routes requests.
/// </summary>
public interface IPublishedRouter
{
// TODO: consider this and RenderRouteHandler - move some code around?
/// <summary>
/// Creates a published request.
/// </summary>
/// <param name="umbracoContext">The current Umbraco context.</param>
/// <param name="uri">The (optional) request Uri.</param>
/// <returns>A published request.</returns>
PublishedRequest CreateRequest(UmbracoContext umbracoContext, Uri uri = null);
/// <summary>
/// Prepares a request for rendering.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>A value indicating whether the request was successfully prepared and can be rendered.</returns>
bool PrepareRequest(PublishedRequest request);
/// <summary>
/// Tries to route a request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns>A value indicating whether the request can be routed to a document.</returns>
bool TryRouteRequest(PublishedRequest request);
/// <summary>
/// Gets a template.
/// </summary>
/// <param name="alias">The template alias</param>
/// <returns>The template.</returns>
ITemplate GetTemplate(string alias);
/// <summary>
/// Updates the request to "not found".
/// </summary>
/// <param name="request">The request.</param>
/// <remarks>
/// <para>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).</para>
/// </remarks>
void UpdateRequestToNotFound(PublishedRequest request);
}
}

View File

@@ -17,7 +17,7 @@ namespace Umbraco.Web.Routing
/// </summary>
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
/// <param name="publishedRouter">The published router.</param>
/// <param name="umbracoContext">The Umbraco context.</param>
/// <param name="uri">The request <c>Uri</c>.</param>
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));
@@ -290,11 +290,11 @@ namespace Umbraco.Web.Routing
/// </summary>
public bool HasTemplate => TemplateModel != null;
internal void UpdateOnMissingTemplate()
internal void UpdateToNotFound()
{
var __readonly = _readonly;
_readonly = false;
_publishedRouter.UpdateRequestOnMissingTemplate(this);
_publishedRouter.UpdateRequestToNotFound(this);
_readonly = __readonly;
}

View File

@@ -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
/// <summary>
/// Provides the default <see cref="IPublishedRouter"/> implementation.
/// </summary>
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<string, IEnumerable<string>> GetRolesForLogin { get; }
/// <inheritdoc />
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
/// <summary>
/// Tries to route the request.
/// </summary>
internal bool TryRouteRequest(PublishedRequest request)
/// <inheritdoc />
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);
}
/// <summary>
/// Prepares the request.
/// </summary>
/// <returns>
/// Returns false if the request was not successfully prepared
/// </returns>
/// <inheritdoc />
public bool PrepareRequest(PublishedRequest request)
{
// note - at that point the original legacy module did something do handle IIS custom 404 errors
@@ -210,11 +200,8 @@ namespace Umbraco.Web.Routing
return true;
}
/// <summary>
/// Updates the request when there is no template to render the content.
/// </summary>
/// <remarks>This is called from Mvc when there's a document to render but no template.</remarks>
public void UpdateRequestOnMissingTemplate(PublishedRequest request)
/// <inheritdoc />
public void UpdateRequestToNotFound(PublishedRequest request)
{
// clear content
var content = request.PublishedContent;
@@ -381,11 +368,7 @@ namespace Umbraco.Web.Routing
#region Document and template
/// <summary>
/// Gets a template.
/// </summary>
/// <param name="alias">The template alias</param>
/// <returns>The template.</returns>
/// <inheritdoc />
public ITemplate GetTemplate(string alias)
{
return _services.FileService.GetTemplate(alias);
@@ -602,7 +585,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<PublishedRouter>("EnsurePublishedContentAccess: Current member has not access, redirect to error page");
var errorPageId = publicAccessAttempt.Result.NoAccessNodeId;

View File

@@ -18,7 +18,7 @@ namespace Umbraco.Web.Routing
/// <para>Contains all the Urls that we can figure out (based upon domains, etc).</para>
/// </remarks>
public static IEnumerable<UrlInfo> GetContentUrls(this IContent content,
PublishedRouter publishedRouter,
IPublishedRouter publishedRouter,
UmbracoContext umbracoContext,
ILocalizationService localizationService,
ILocalizedTextService textService,
@@ -92,7 +92,7 @@ namespace Umbraco.Web.Routing
/// <returns></returns>
private static IEnumerable<UrlInfo> GetContentUrlsByCulture(IContent content,
IEnumerable<string> 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);

View File

@@ -191,7 +191,7 @@ namespace Umbraco.Web.Runtime
composition.RegisterAuto(typeof(UmbracoViewPage<>));
// register published router
composition.RegisterUnique<PublishedRouter>();
composition.RegisterUnique<IPublishedRouter, PublishedRouter>();
composition.Register(_ => Current.Configs.Settings().WebRouting);
// register preview SignalR hub

View File

@@ -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);
}
/// <summary>
@@ -514,6 +511,24 @@ namespace Umbraco.Web.Security
}
#endregion
/// <summary>
/// Gets the current user's roles.
/// </summary>
/// <remarks>Roles are cached per user name, at request level.</remarks>
public IEnumerable<string> GetCurrentUserRoles()
=> GetUserRoles(CurrentUserName);
/// <summary>
/// Gets a user's roles.
/// </summary>
/// <remarks>Roles are cached per user name, at request level.</remarks>
public IEnumerable<string> 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));
}
/// <summary>
/// Returns the login status model of the currently logged in member, if no member is logged in it returns null;
/// </summary>
@@ -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<string> ?? allowTypes.ToList();
if (allowTypesList.Any(allowType => allowType != string.Empty))

View File

@@ -184,6 +184,7 @@
<Compile Include="Models\ContentEditing\MacroDisplay.cs" />
<Compile Include="Models\ContentEditing\MacroParameterDisplay.cs" />
<Compile Include="Models\TemplateQuery\QueryConditionExtensions.cs" />
<Compile Include="Routing\IPublishedRouter.cs" />
<Compile Include="Services\DashboardService.cs" />
<Compile Include="Services\IDashboardService.cs" />
<Compile Include="Models\Link.cs" />

View File

@@ -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<RouteCollection>(CreateRouteCollection);