diff --git a/src/Umbraco.Core/Services/MemberService.cs b/src/Umbraco.Core/Services/MemberService.cs index f3c570e8ea..379cbc9d16 100644 --- a/src/Umbraco.Core/Services/MemberService.cs +++ b/src/Umbraco.Core/Services/MemberService.cs @@ -396,5 +396,80 @@ namespace Umbraco.Core.Services public static event TypedEventHandler> Saved; #endregion + + /// + /// A helper method that will create a basic/generic member for use with a generic membership provider + /// + /// + internal static IMember CreateGenericMembershipProviderMember() + { + var identity = int.MaxValue; + + var memType = new MemberType(-1); + var propGroup = new PropertyGroup + { + Name = "Membership", + Id = --identity + }; + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TextboxAlias, DataTypeDatabaseType.Ntext) + { + Alias = Constants.Conventions.Member.Comments, + Name = Constants.Conventions.Member.CommentsLabel, + SortOrder = 0, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar) + { + Alias = Constants.Conventions.Member.FailedPasswordAttempts, + Name = Constants.Conventions.Member.FailedPasswordAttemptsLabel, + SortOrder = 1, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Nvarchar) + { + Alias = Constants.Conventions.Member.IsApproved, + Name = Constants.Conventions.Member.IsApprovedLabel, + SortOrder = 2, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer) + { + Alias = Constants.Conventions.Member.IsApproved, + Name = Constants.Conventions.Member.IsApprovedLabel, + SortOrder = 3, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer) + { + Alias = Constants.Conventions.Member.IsLockedOut, + Name = Constants.Conventions.Member.IsLockedOutLabel, + SortOrder = 4, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date) + { + Alias = Constants.Conventions.Member.LastLockoutDate, + Name = Constants.Conventions.Member.LastLockoutDateLabel, + SortOrder = 5, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date) + { + Alias = Constants.Conventions.Member.LastLoginDate, + Name = Constants.Conventions.Member.LastLoginDateLabel, + SortOrder = 6, + Id = --identity + }); + propGroup.PropertyTypes.Add(new PropertyType(Constants.PropertyEditors.NoEditAlias, DataTypeDatabaseType.Date) + { + Alias = Constants.Conventions.Member.LastPasswordChangeDate, + Name = Constants.Conventions.Member.LastPasswordChangeDateLabel, + SortOrder = 7, + Id = --identity + }); + memType.PropertyGroups.Add(propGroup); + + return new Member("", memType); + } } } \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js index 37d5cdace6..cf03f7fcca 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js @@ -118,13 +118,23 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { */ getScaffold: function (alias) { - return umbRequestHelper.resourcePromise( - $http.get( - umbRequestHelper.getApiUrl( - "memberApiBaseUrl", - "GetEmpty", - [{ contentTypeAlias: alias }])), - 'Failed to retreive data for empty member item type ' + alias); + if (alias) { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetEmpty", + [{ contentTypeAlias: alias }])), + 'Failed to retreive data for empty member item type ' + alias); + } + else { + return umbRequestHelper.resourcePromise( + $http.get( + umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "GetEmpty")), + 'Failed to retreive data for empty member item type ' + alias); + } }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js index 79cf1a75b7..e346972706 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/navigation.service.js @@ -450,7 +450,14 @@ function navigationService($rootScope, $routeParams, $log, $location, $q, $timeo throw "section cannot be null"; } - if (action.metaData && action.metaData["jsAction"] && angular.isString(action.metaData["jsAction"])) { + if (action.metaData && action.metaData["actionRoute"] && angular.isString(action.metaData["actionRoute"])) { + //first check if the menu item simply navigates to a route + var parts = action.metaData["actionRoute"].split("?"); + $location.path(parts[0]).search(parts.length > 1 ? parts[1] : ""); + this.hideNavigation(); + return; + } + else if (action.metaData && action.metaData["jsAction"] && angular.isString(action.metaData["jsAction"])) { //we'll try to get the jsAction from the injector var menuAction = action.metaData["jsAction"].split('.'); diff --git a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js index 4a20db9c43..3218d64af7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js @@ -22,14 +22,29 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS } if ($routeParams.create) { - //we are creating so get an empty member item - memberResource.getScaffold($routeParams.doctype) - .then(function(data) { - $scope.loaded = true; - $scope.content = data; - //put this into appState - appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); - }); + + //if there is no doc type specified then we are going to assume that + // we are not using the umbraco membership provider + if ($routeParams.doctype) { + //we are creating so get an empty member item + memberResource.getScaffold($routeParams.doctype) + .then(function(data) { + $scope.loaded = true; + $scope.content = data; + //put this into appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + }); + } + else { + memberResource.getScaffold() + .then(function (data) { + $scope.loaded = true; + $scope.content = data; + //put this into appState + appState.setGlobalState("editingEntity", umbModelMapper.convertToEntityBasic($scope.content)); + }); + } + } else { //so, we usually refernce all editors with the Int ID, but with members we have diff --git a/src/Umbraco.Web/Editors/MemberController.cs b/src/Umbraco.Web/Editors/MemberController.cs index 0f37bc7ac4..8198e5aa21 100644 --- a/src/Umbraco.Web/Editors/MemberController.cs +++ b/src/Umbraco.Web/Editors/MemberController.cs @@ -16,6 +16,7 @@ using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Models.EntityBase; +using Umbraco.Core.Services; using Umbraco.Web.WebApi; using Umbraco.Web.Models.ContentEditing; using Umbraco.Web.Mvc; @@ -81,17 +82,34 @@ namespace Umbraco.Web.Editors /// /// /// - public MemberDisplay GetEmpty(string contentTypeAlias) + public MemberDisplay GetEmpty(string contentTypeAlias = null) { - var contentType = Services.MemberTypeService.GetMemberType(contentTypeAlias); - if (contentType == null) + //if this is null and we are in umbraco member mode we cannot continue, return not found + if (global::umbraco.cms.businesslogic.member.Member.InUmbracoMemberMode()) { - throw new HttpResponseException(HttpStatusCode.NotFound); - } + if (contentTypeAlias == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } - IMember emptyContent = new Member("", contentType); - emptyContent.AdditionalData["NewPassword"] = Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters); - return Mapper.Map(emptyContent); + var contentType = Services.MemberTypeService.GetMemberType(contentTypeAlias); + if (contentType == null) + { + throw new HttpResponseException(HttpStatusCode.NotFound); + } + + IMember emptyContent = new Member("", contentType); + emptyContent.AdditionalData["NewPassword"] = Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters); + return Mapper.Map(emptyContent); + + } + else + { + //we need to return a scaffold of a 'simple' member - basically just what a membership provider can edit + IMember emptyContent = MemberService.CreateGenericMembershipProviderMember(); + emptyContent.AdditionalData["NewPassword"] = Membership.GeneratePassword(Membership.MinRequiredPasswordLength, Membership.MinRequiredNonAlphanumericCharacters); + return Mapper.Map(emptyContent); + } } /// diff --git a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs index f7d3cf874f..d0d3f7d2a7 100644 --- a/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs +++ b/src/Umbraco.Web/Models/Mapping/MemberModelMapper.cs @@ -200,21 +200,33 @@ namespace Umbraco.Web.Models.Mapping if (Membership.Provider.Name != Constants.Conventions.Member.UmbracoMemberProviderName) { - throw new NotSupportedException("Editing member with a non-umbraco membership provider is currently not supported"); + //it's a generic provider so update the locked out property based on our know constant alias + var isLockedOutProperty = result.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == Constants.Conventions.Member.IsLockedOut); + if (isLockedOutProperty != null && isLockedOutProperty.Value.ToString() != "1") + { + isLockedOutProperty.View = "readonlyvalue"; + isLockedOutProperty.Value = ui.Text("general", "no"); + } + + return result; } - - var umbracoProvider = (global::umbraco.providers.members.UmbracoMembershipProvider) Membership.Provider; - - //This is kind of a hack because a developer is supposed to be allowed to set their property editor - would have been much easier - // if we just had all of the membeship provider fields on the member table :( - var isLockedOutProperty = result.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == umbracoProvider.LockPropertyTypeAlias); - if (isLockedOutProperty != null && isLockedOutProperty.Value.ToString() != "1") + else { - isLockedOutProperty.View = "readonlyvalue"; - isLockedOutProperty.Value = ui.Text("general", "no"); + var umbracoProvider = (global::umbraco.providers.members.UmbracoMembershipProvider)Membership.Provider; + + //This is kind of a hack because a developer is supposed to be allowed to set their property editor - would have been much easier + // if we just had all of the membeship provider fields on the member table :( + var isLockedOutProperty = result.SelectMany(x => x.Properties).FirstOrDefault(x => x.Alias == umbracoProvider.LockPropertyTypeAlias); + if (isLockedOutProperty != null && isLockedOutProperty.Value.ToString() != "1") + { + isLockedOutProperty.View = "readonlyvalue"; + isLockedOutProperty.Value = ui.Text("general", "no"); + } + + return result; } - return result; + } } @@ -227,17 +239,26 @@ namespace Umbraco.Web.Models.Mapping { if (Membership.Provider.Name != Constants.Conventions.Member.UmbracoMemberProviderName) { - throw new NotSupportedException("Editing member with a non-umbraco membership provider is currently not supported"); + return new Dictionary + { + {Constants.Conventions.Member.IsLockedOut, Constants.Conventions.Member.IsLockedOut}, + {Constants.Conventions.Member.IsApproved, Constants.Conventions.Member.IsApproved}, + {Constants.Conventions.Member.Comments, Constants.Conventions.Member.Comments} + }; } + else + { + var umbracoProvider = (global::umbraco.providers.members.UmbracoMembershipProvider)Membership.Provider; - var umbracoProvider = (global::umbraco.providers.members.UmbracoMembershipProvider) Membership.Provider; - - return new Dictionary + return new Dictionary { {Constants.Conventions.Member.IsLockedOut, umbracoProvider.LockPropertyTypeAlias}, {Constants.Conventions.Member.IsApproved, umbracoProvider.ApprovedPropertyTypeAlias}, {Constants.Conventions.Member.Comments, umbracoProvider.CommentPropertyTypeAlias} - }; + }; + } + + } } diff --git a/src/Umbraco.Web/Models/Trees/MenuItem.cs b/src/Umbraco.Web/Models/Trees/MenuItem.cs index 49a25ca5c9..ae4f8d519c 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItem.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItem.cs @@ -1,5 +1,8 @@ using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; +using Umbraco.Core.Models.EntityBase; +using Umbraco.Web.Trees; +using umbraco; using umbraco.interfaces; using System.Collections.Generic; using Umbraco.Core; @@ -12,6 +15,7 @@ namespace Umbraco.Web.Models.Trees [DataContract(Name = "menuItem", Namespace = "")] public class MenuItem { + #region Constructors public MenuItem() { AdditionalData = new Dictionary(); @@ -33,8 +37,10 @@ namespace Umbraco.Web.Models.Trees SeperatorBefore = false; Icon = legacyMenu.Icon; Action = legacyMenu; - } + } + #endregion + #region Properties internal IAction Action { get; set; } /// @@ -63,7 +69,130 @@ namespace Umbraco.Web.Models.Trees public bool SeperatorBefore { get; set; } [DataMember(Name = "cssclass")] - public string Icon { get; set; } + public string Icon { get; set; } + #endregion + + #region Constants + + /// + /// Used as a key for the AdditionalData to specify a specific dialog title instead of the menu title + /// + internal const string DialogTitleKey = "dialogTitle"; + + /// + /// Used to specify the URL that the dialog will launch to in an iframe + /// + internal const string ActionUrlKey = "actionUrl"; + + //TODO: some action's want to launch a new window like live editing, we support this in the menu item's metadata with + // a key called: "actionUrlMethod" which can be set to either: Dialog, BlankWindow. Normally this is always set to Dialog + // if a URL is specified in the "actionUrl" metadata. For now I'm not going to implement launching in a blank window, + // though would be v-easy, just not sure we want to ever support that? + internal const string ActionUrlMethodKey = "actionUrlMethod"; + + /// + /// Used to specify the angular view that the dialog will launch + /// + internal const string ActionViewKey = "actionView"; + + /// + /// Used to specify the js method to execute for the menu item + /// + internal const string JsActionKey = "jsAction"; + + /// + /// Used to specify an angular route to go to for the menu item + /// + internal const string ActionRouteKey = "actionRoute"; + + #endregion + + #region Methods + + /// + /// Sets the menu item to navigate to the specified angular route path + /// + /// + public void NavigateToRoute(string route) + { + AdditionalData[ActionRouteKey] = route; + } + + /// + /// Adds the required meta data to the menu item so that angular knows to attempt to call the Js method. + /// + /// + public void ExecuteLegacyJs(string jsToExecute) + { + SetJsAction(jsToExecute); + } + + /// + /// Sets the menu item to display a dialog based on an angular view path + /// + /// + /// + public void LaunchDialogView(string view, string dialogTitle) + { + SetDialogTitle(dialogTitle); + AdditionalData[ActionViewKey] = view; + } + + /// + /// Sets the menu item to display a dialog based on a url path in an iframe + /// + /// + /// + public void LaunchDialogUrl(string url, string dialogTitle) + { + SetDialogTitle(dialogTitle); + SetActionUrl(url); + } + + private void SetJsAction(string jsToExecute) + { + AdditionalData[JsActionKey] = jsToExecute; + } + + /// + /// Puts a dialog title into the meta data to be displayed on the dialog of the menu item (if there is one) + /// instead of the menu name + /// + /// + private void SetDialogTitle(string dialogTitle) + { + AdditionalData[DialogTitleKey] = dialogTitle; + } + + /// + /// Configures the menu item to launch a URL with the specified action (dialog or new window) + /// + /// + /// + private void SetActionUrl(string url, ActionUrlMethod method = ActionUrlMethod.Dialog) + { + AdditionalData[ActionUrlKey] = url; + AdditionalData[ActionUrlMethodKey] = method; + } + + internal void ConvertLegacyMenuItem(IUmbracoEntity item, string nodeType, string currentSection) + { + //First try to get a URL/title from the legacy action, + // if that doesn't work, try to get the legacy confirm view + + //in some edge cases, item can be null so we'll just convert those to "-1" and "" for id and name since these edge cases don't need that. + Attempt + .Try(LegacyTreeDataConverter.GetUrlAndTitleFromLegacyAction(Action, + item == null ? "-1" : item.Id.ToInvariantString(), + nodeType, + item == null ? "" : item.Name, currentSection), + action => LaunchDialogUrl(action.Url, action.DialogTitle)) + .OnFailure(() => LegacyTreeDataConverter.GetLegacyConfirmView(Action, currentSection), + view => LaunchDialogView( + view, + ui.GetText("defaultdialogs", "confirmdelete") + " '" + item.Name + "' ?")); + } + #endregion } } \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Trees/MenuItemExtensions.cs b/src/Umbraco.Web/Models/Trees/MenuItemExtensions.cs deleted file mode 100644 index 05ae312cbd..0000000000 --- a/src/Umbraco.Web/Models/Trees/MenuItemExtensions.cs +++ /dev/null @@ -1,116 +0,0 @@ -using Umbraco.Core; -using Umbraco.Core.Models.EntityBase; -using Umbraco.Web.Trees; -using umbraco; - -namespace Umbraco.Web.Models.Trees -{ - public static class MenuItemExtensions - { - /// - /// Used as a key for the AdditionalData to specify a specific dialog title instead of the menu title - /// - internal const string DialogTitleKey = "dialogTitle"; - - /// - /// Used to specify the URL that the dialog will launch to in an iframe - /// - internal const string ActionUrlKey = "actionUrl"; - - //TODO: some action's want to launch a new window like live editing, we support this in the menu item's metadata with - // a key called: "actionUrlMethod" which can be set to either: Dialog, BlankWindow. Normally this is always set to Dialog - // if a URL is specified in the "actionUrl" metadata. For now I'm not going to implement launching in a blank window, - // though would be v-easy, just not sure we want to ever support that? - internal const string ActionUrlMethodKey = "actionUrlMethod"; - - /// - /// Used to specify the angular view that the dialog will launch - /// - internal const string ActionViewKey = "actionView"; - - /// - /// Used to specify the js method to execute for the menu item - /// - internal const string JsActionKey = "jsAction"; - - /// - /// Adds the required meta data to the menu item so that angular knows to attempt to call the Js method. - /// - /// - /// - public static void LaunchLegacyJs(this MenuItem menuItem, string jsToExecute) - { - menuItem.SetJsAction(jsToExecute); - } - - /// - /// Sets the menu item to display a dialog based on an angular view path - /// - /// - /// - /// - public static void LaunchDialogView(this MenuItem menuItem, string view, string dialogTitle) - { - menuItem.SetDialogTitle(dialogTitle); - menuItem.AdditionalData[ActionViewKey] = view; - } - - /// - /// Sets the menu item to display a dialog based on a url path in an iframe - /// - /// - /// - /// - public static void LaunchDialogUrl(this MenuItem menuItem, string url, string dialogTitle) - { - menuItem.SetDialogTitle(dialogTitle); - menuItem.SetActionUrl(url); - } - - private static void SetJsAction(this MenuItem menuItem, string jsToExecute) - { - menuItem.AdditionalData[JsActionKey] = jsToExecute; - } - - /// - /// Puts a dialog title into the meta data to be displayed on the dialog of the menu item (if there is one) - /// instead of the menu name - /// - /// - /// - private static void SetDialogTitle(this MenuItem menuItem, string dialogTitle) - { - menuItem.AdditionalData[DialogTitleKey] = dialogTitle; - } - - /// - /// Configures the menu item to launch a URL with the specified action (dialog or new window) - /// - /// - /// - /// - private static void SetActionUrl(this MenuItem menuItem, string url, ActionUrlMethod method = ActionUrlMethod.Dialog) - { - menuItem.AdditionalData[ActionUrlKey] = url; - menuItem.AdditionalData[ActionUrlMethodKey] = method; - } - - internal static void ConvertLegacyMenuItem(this MenuItem menuItem, IUmbracoEntity item, string nodeType, string currentSection) - { - //First try to get a URL/title from the legacy action, - // if that doesn't work, try to get the legacy confirm view - - //in some edge cases, item can be null so we'll just convert those to "-1" and "" for id and name since these edge cases don't need that. - Attempt - .Try(LegacyTreeDataConverter.GetUrlAndTitleFromLegacyAction(menuItem.Action, - item == null ? "-1" : item.Id.ToInvariantString(), - nodeType, - item == null ? "" : item.Name, currentSection), - action => menuItem.LaunchDialogUrl(action.Url, action.DialogTitle)) - .OnFailure(() => LegacyTreeDataConverter.GetLegacyConfirmView(menuItem.Action, currentSection), - view => menuItem.LaunchDialogView( - view, - ui.GetText("defaultdialogs", "confirmdelete") + " '" + item.Name + "' ?")); - } - } -} \ No newline at end of file diff --git a/src/Umbraco.Web/Models/Trees/MenuItemList.cs b/src/Umbraco.Web/Models/Trees/MenuItemList.cs index 37944569af..d082226bf4 100644 --- a/src/Umbraco.Web/Models/Trees/MenuItemList.cs +++ b/src/Umbraco.Web/Models/Trees/MenuItemList.cs @@ -169,11 +169,11 @@ namespace Umbraco.Web.Models.Trees if (attribute.MethodName.IsNullOrWhiteSpace()) { //if no method name is supplied we will assume that the menu action is the type name of the current menu class - menuItem.AdditionalData.Add(MenuItemExtensions.JsActionKey, string.Format("{0}.{1}", attribute.ServiceName, this.GetType().Name)); + menuItem.AdditionalData.Add(MenuItem.JsActionKey, string.Format("{0}.{1}", attribute.ServiceName, this.GetType().Name)); } else { - menuItem.AdditionalData.Add(MenuItemExtensions.JsActionKey, string.Format("{0}.{1}", attribute.ServiceName, attribute.MethodName)); + menuItem.AdditionalData.Add(MenuItem.JsActionKey, string.Format("{0}.{1}", attribute.ServiceName, attribute.MethodName)); } } } diff --git a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs index 9cce00779f..4384ad4651 100644 --- a/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs +++ b/src/Umbraco.Web/Trees/LegacyTreeDataConverter.cs @@ -138,10 +138,10 @@ namespace Umbraco.Web.Trees view => menuItem.LaunchDialogView( view, ui.GetText("defaultdialogs", "confirmdelete") + " '" + xmlTreeNode.Text + "' ?")) - .OnFailure(() => menuItem.AdditionalData.ContainsKey(MenuItemExtensions.JsActionKey) + .OnFailure(() => menuItem.AdditionalData.ContainsKey(MenuItem.JsActionKey) ? Attempt.Fail(false) : Attempt.Succeed(true), - b => menuItem.LaunchLegacyJs(menuItem.Action.JsFunctionName)); + b => menuItem.ExecuteLegacyJs(menuItem.Action.JsFunctionName)); numAdded++; } diff --git a/src/Umbraco.Web/Trees/MemberTreeController.cs b/src/Umbraco.Web/Trees/MemberTreeController.cs index 6ea9086cc3..4ba3e10b62 100644 --- a/src/Umbraco.Web/Trees/MemberTreeController.cs +++ b/src/Umbraco.Web/Trees/MemberTreeController.cs @@ -81,11 +81,25 @@ namespace Umbraco.Web.Trees if (id == Constants.System.Root.ToInvariantString()) { - //set default - menu.DefaultMenuAlias = ActionNew.Instance.Alias; + // root actions + if (Member.InUmbracoMemberMode()) + { + //set default + menu.DefaultMenuAlias = ActionNew.Instance.Alias; - // root actions - menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)); + //Create the normal create action + menu.Items.Add(ui.Text("actions", ActionNew.Instance.Alias)); + } + else + { + //Create a custom create action - this does not launch a dialog, it just navigates to the create screen + // we'll create it baesd on the ActionNew so it maintains the same icon properties, name, etc... + var createMenuItem = new MenuItem(ActionNew.Instance); + //we want to go to this route: /member/member/edit/-1?create=true + createMenuItem.NavigateToRoute("/member/member/edit/-1?create=true"); + menu.Items.Add(createMenuItem); + } + menu.Items.Add(ui.Text("actions", ActionRefresh.Instance.Alias), true); return menu; } diff --git a/src/Umbraco.Web/Umbraco.Web.csproj b/src/Umbraco.Web/Umbraco.Web.csproj index 9729ea49a3..65b2011f6d 100644 --- a/src/Umbraco.Web/Umbraco.Web.csproj +++ b/src/Umbraco.Web/Umbraco.Web.csproj @@ -505,7 +505,6 @@ - diff --git a/src/Umbraco.Web/umbraco.presentation/umbraco/create/memberTasks.cs b/src/Umbraco.Web/umbraco.presentation/umbraco/create/memberTasks.cs index 4821f509d6..d09e93b85f 100644 --- a/src/Umbraco.Web/umbraco.presentation/umbraco/create/memberTasks.cs +++ b/src/Umbraco.Web/umbraco.presentation/umbraco/create/memberTasks.cs @@ -12,6 +12,7 @@ using umbraco.cms.businesslogic.member; namespace umbraco { + [Obsolete("this is no longer used and will be removed from the codebase in the future")] public class memberTasks : LegacyDialogTask { ///