diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Dnn.EditBar.UI.csproj b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Dnn.EditBar.UI.csproj index db4a8e03d79..d0572329437 100644 --- a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Dnn.EditBar.UI.csproj +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Dnn.EditBar.UI.csproj @@ -96,6 +96,7 @@ + diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteStateMenu.cs b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteStateMenu.cs index 34f93abced7..14d0de7078a 100644 --- a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteStateMenu.cs +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteStateMenu.cs @@ -7,24 +7,15 @@ namespace Dnn.EditBar.UI.Items using System; using Dnn.EditBar.Library; - using Dnn.EditBar.Library.Items; - using DotNetNuke.Application; - using DotNetNuke.Entities.Content.Common; - using DotNetNuke.Entities.Content.Workflow; - using DotNetNuke.Entities.Portals; - using DotNetNuke.Entities.Tabs; - using DotNetNuke.Entities.Tabs.TabVersions; - using DotNetNuke.Security.Permissions; - using DotNetNuke.Services.Personalization; [Serializable] - public class CompleteStateMenu : BaseMenuItem + public class CompleteStateMenu : WorkflowBaseMenuItem { /// public override string Name { get; } = "CompleteState"; /// - public override string Text => "Submit"; + public override string Text => this.IsFirstState ? "Submit" : "Approve"; // (1) "Submit" -> (2..last-2) "Approve" -> (last) HIDDEN /// public override string CssClass => string.Empty; @@ -42,15 +33,9 @@ public class CompleteStateMenu : BaseMenuItem public override int Order { get; } = 78; /// - public override bool Visible() - { - var contentItem = Util.GetContentController().GetContentItem(TabController.CurrentPage.ContentItemId); - return Personalization.GetUserMode() == PortalSettings.Mode.Edit - && DotNetNukeContext.Current.Application.SKU == "DNN" // IsPlatform - && TabVersionSettings.Instance.IsVersioningEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // versioning is enabled - && TabWorkflowSettings.Instance.IsWorkflowEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // workflow is enabled - && ((WorkflowEngine.Instance.IsWorkflowOnDraft(contentItem) && PermissionProvider.Instance().CanAddContentToPage(TabController.CurrentPage)) - || (!WorkflowEngine.Instance.IsWorkflowCompleted(contentItem) && WorkflowSecurity.Instance.HasStateReviewerPermission(contentItem.StateID))); - } + public override bool Visible() => base.Visible() + && !this.IsLastState // not the last 'Published' state + && !this.IsPriorState // not the state that is before last 'Published' state + && (this.IsDraftWithPermissions || this.IsReviewOrOtherIntermediateStateWithPermissions); } } diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteWorkflowMenu.cs b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteWorkflowMenu.cs index 5ca5c38824a..983ff0361f8 100644 --- a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteWorkflowMenu.cs +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/CompleteWorkflowMenu.cs @@ -7,23 +7,15 @@ namespace Dnn.EditBar.UI.Items using System; using Dnn.EditBar.Library; - using Dnn.EditBar.Library.Items; - using DotNetNuke.Application; - using DotNetNuke.Entities.Content.Common; - using DotNetNuke.Entities.Content.Workflow; - using DotNetNuke.Entities.Portals; - using DotNetNuke.Entities.Tabs; - using DotNetNuke.Entities.Tabs.TabVersions; - using DotNetNuke.Services.Personalization; [Serializable] - public class CompleteWorkflowMenu : BaseMenuItem + public class CompleteWorkflowMenu : WorkflowBaseMenuItem { /// public override string Name { get; } = "CompleteWorkflow"; /// - public override string Text => "Approve"; + public override string Text => "Publish"; /// public override string CssClass => string.Empty; @@ -38,18 +30,12 @@ public class CompleteWorkflowMenu : BaseMenuItem public override string Loader { get; } = "CompleteWorkflow"; /// - public override int Order { get; } = 80; + public override int Order { get; } = 79; /// - public override bool Visible() - { - var contentItem = Util.GetContentController().GetContentItem(TabController.CurrentPage.ContentItemId); - return Personalization.GetUserMode() == PortalSettings.Mode.Edit - && DotNetNukeContext.Current.Application.SKU == "DNN" // IsPlatform - && TabVersionSettings.Instance.IsVersioningEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // versioning is enabled - && TabWorkflowSettings.Instance.IsWorkflowEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // workflow is enabled - && !WorkflowEngine.Instance.IsWorkflowCompleted(contentItem) // tab has new version that is not published - && WorkflowSecurity.Instance.HasStateReviewerPermission(contentItem.StateID); // user has workflow approval permission - } + public override bool Visible() => base.Visible() + && (this.IsReviewOrOtherIntermediateStateWithPermissions + || (this.IsPriorState && this.IsDraftWithPermissions) // for Save Draft workflow + || (this.IsLastState && this.HasUnpublishVersion && this.HasDraftPermission)); // for Direct Publish workflow } } diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardStateMenu.cs b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardStateMenu.cs index cc311b5deab..abdb3886b63 100644 --- a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardStateMenu.cs +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardStateMenu.cs @@ -7,24 +7,15 @@ namespace Dnn.EditBar.UI.Items using System; using Dnn.EditBar.Library; - using Dnn.EditBar.Library.Items; - using DotNetNuke.Application; - using DotNetNuke.Entities.Content.Common; - using DotNetNuke.Entities.Content.Workflow; - using DotNetNuke.Entities.Portals; - using DotNetNuke.Entities.Tabs; - using DotNetNuke.Entities.Tabs.TabVersions; - using DotNetNuke.Security.Permissions; - using DotNetNuke.Services.Personalization; [Serializable] - public class DiscardStateMenu : BaseMenuItem + public class DiscardStateMenu : WorkflowBaseMenuItem { /// public override string Name { get; } = "DiscardState"; /// - public override string Text => "Discard"; + public override string Text => "Reject"; // (1) HIDDEN -> (2..last) "Reject" /// public override string CssClass => string.Empty; @@ -39,18 +30,12 @@ public class DiscardStateMenu : BaseMenuItem public override string Loader { get; } = "DiscardState"; /// - public override int Order { get; } = 79; + public override int Order { get; } = 80; /// - public override bool Visible() - { - var contentItem = Util.GetContentController().GetContentItem(TabController.CurrentPage.ContentItemId); - return Personalization.GetUserMode() == PortalSettings.Mode.Edit - && DotNetNukeContext.Current.Application.SKU == "DNN" // IsPlatform - && TabVersionSettings.Instance.IsVersioningEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // versioning is enabled - && TabWorkflowSettings.Instance.IsWorkflowEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // workflow is enabled - && ((WorkflowEngine.Instance.IsWorkflowOnDraft(contentItem) && PermissionProvider.Instance().CanAddContentToPage(TabController.CurrentPage)) - || (!WorkflowEngine.Instance.IsWorkflowCompleted(contentItem) && WorkflowSecurity.Instance.HasStateReviewerPermission(contentItem.StateID))); - } + public override bool Visible() => base.Visible() + && !this.IsLastState // not the last 'Published' state + && !this.IsFirstState + && this.IsReviewOrOtherIntermediateStateWithPermissions; } } diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardWorkflowMenu.cs b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardWorkflowMenu.cs index eace3b35ce8..b5d55cc9374 100644 --- a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardWorkflowMenu.cs +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/DiscardWorkflowMenu.cs @@ -7,24 +7,15 @@ namespace Dnn.EditBar.UI.Items using System; using Dnn.EditBar.Library; - using Dnn.EditBar.Library.Items; - using DotNetNuke.Application; - using DotNetNuke.Entities.Content.Common; - using DotNetNuke.Entities.Content.Workflow; - using DotNetNuke.Entities.Portals; - using DotNetNuke.Entities.Tabs; - using DotNetNuke.Entities.Tabs.TabVersions; - using DotNetNuke.Security.Permissions; - using DotNetNuke.Services.Personalization; [Serializable] - public class DiscardWorkflowMenu : BaseMenuItem + public class DiscardWorkflowMenu : WorkflowBaseMenuItem { /// public override string Name { get; } = "DiscardWorkflow"; /// - public override string Text => "Reject"; + public override string Text => "Discard"; /// public override string CssClass => string.Empty; @@ -42,15 +33,8 @@ public class DiscardWorkflowMenu : BaseMenuItem public override int Order { get; } = 81; /// - public override bool Visible() - { - var contentItem = Util.GetContentController().GetContentItem(TabController.CurrentPage.ContentItemId); - return Personalization.GetUserMode() == PortalSettings.Mode.Edit - && DotNetNukeContext.Current.Application.SKU == "DNN" // IsPlatform - && TabVersionSettings.Instance.IsVersioningEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // versioning is enabled - && TabWorkflowSettings.Instance.IsWorkflowEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // workflow is enabled - && !WorkflowEngine.Instance.IsWorkflowCompleted(contentItem) // tab has new version that is not published - && WorkflowSecurity.Instance.HasStateReviewerPermission(contentItem.StateID); // user has workflow approval permission - } + public override bool Visible() => base.Visible() + && ((!this.IsLastState && (this.IsDraftWithPermissions || this.IsReviewOrOtherIntermediateStateWithPermissions)) + || (this.IsLastState && this.HasUnpublishVersion && this.HasDraftPermission)); // for Direct Publish workflow } } diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowBaseMenuItem.cs b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowBaseMenuItem.cs new file mode 100644 index 00000000000..aa797f417b0 --- /dev/null +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowBaseMenuItem.cs @@ -0,0 +1,67 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information + +namespace Dnn.EditBar.UI.Items +{ + using System.Linq; + + using Dnn.EditBar.Library.Items; + using DotNetNuke.Application; + using DotNetNuke.Entities.Content; + using DotNetNuke.Entities.Content.Common; + using DotNetNuke.Entities.Content.Workflow; + using DotNetNuke.Entities.Content.Workflow.Entities; + using DotNetNuke.Entities.Portals; + using DotNetNuke.Entities.Tabs; + using DotNetNuke.Entities.Tabs.TabVersions; + using DotNetNuke.Security.Permissions; + using DotNetNuke.Services.Personalization; + + public abstract class WorkflowBaseMenuItem : BaseMenuItem + { + private readonly IWorkflowEngine workflowEngine = WorkflowEngine.Instance; + + internal Workflow Workflow => WorkflowManager.Instance.GetWorkflow(this.WorkflowState.WorkflowID); + + internal WorkflowState WorkflowState => /*this.workflowState ??=*/ WorkflowStateManager.Instance.GetWorkflowState(this.ContentItem.StateID); + + internal bool IsEditMode => Personalization.GetUserMode() == PortalSettings.Mode.Edit; + + internal bool IsPlatform => DotNetNukeContext.Current.Application.SKU == "DNN"; + + internal bool IsWorkflowEnabled => this.IsVersioningEnabled && TabWorkflowSettings.Instance.IsWorkflowEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID); + + internal bool IsFirstState => this.WorkflowState.StateName == this.Workflow.FirstState.StateName; // 'Draft' + + internal bool IsPriorState => this.WorkflowState.StateName == this.PriorState?.StateName; + + internal bool IsLastState => this.WorkflowState.StateName == this.Workflow.LastState.StateName; // 'Published' + + internal bool IsDraftWithPermissions => this.workflowEngine.IsWorkflowOnDraft(this.ContentItem) && this.HasDraftPermission; + + internal bool IsReviewOrOtherIntermediateStateWithPermissions => !this.workflowEngine.IsWorkflowCompleted(this.ContentItem) && WorkflowSecurity.Instance.HasStateReviewerPermission(this.ContentItem.StateID); + + internal bool IsWorkflowCompleted => WorkflowEngine.Instance.IsWorkflowCompleted(TabController.CurrentPage.ContentItemId); + + internal bool HasBeenPublished => TabController.CurrentPage.HasBeenPublished; + + internal bool HasUnpublishVersion => TabVersionBuilder.Instance.GetUnPublishedVersion(TabController.CurrentPage.TabID) != null; + + internal bool HasUnpublishVersionWithPermissions => this.HasUnpublishVersion && WorkflowSecurity.Instance.HasStateReviewerPermission(this.ContentItem.StateID); + + internal bool HasDraftPermission => PermissionProvider.Instance().CanAddContentToPage(TabController.CurrentPage); + + private ContentItem ContentItem => Util.GetContentController().GetContentItem(TabController.CurrentPage.ContentItemId); + + private bool IsVersioningEnabled => TabVersionSettings.Instance.IsVersioningEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID); + + // State before the last one. + private WorkflowState PriorState => this.Workflow.States == null || !this.Workflow.States.Any() ? null : this.Workflow.States.OrderBy(s => s.Order).Reverse().Skip(1).FirstOrDefault(); + + public override bool Visible() => + this.IsEditMode + && this.IsPlatform + && this.IsWorkflowEnabled; + } +} diff --git a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowStateMenu.cs b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowStateMenu.cs index 282f605dbe2..1df72d3f2ce 100644 --- a/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowStateMenu.cs +++ b/Dnn.AdminExperience/EditBar/Dnn.EditBar.UI/Items/WorkflowStateMenu.cs @@ -5,24 +5,16 @@ namespace Dnn.EditBar.UI.Items { using System; - - using Dnn.EditBar.Library.Items; - using Dnn.PersonaBar.Pages.Components; - using DotNetNuke.Application; - using DotNetNuke.Entities.Content.Common; - using DotNetNuke.Entities.Portals; - using DotNetNuke.Entities.Tabs; - using DotNetNuke.Entities.Tabs.TabVersions; - using DotNetNuke.Services.Personalization; + using System.Linq; [Serializable] - public class WorkflowStateMenu : BaseMenuItem + public class WorkflowStateMenu : WorkflowBaseMenuItem { /// public override string Name { get; } = "WorkflowState"; /// - public override string Text => TabController.CurrentPage.HasBeenPublished && WorkflowHelper.IsWorkflowCompleted(TabController.CurrentPage) ? "Published" : "Draft"; + public override string Text => $"{this.Workflow.WorkflowName}:
{this.RenderStates()}"; /// public override string CssClass => string.Empty; @@ -39,14 +31,19 @@ public class WorkflowStateMenu : BaseMenuItem /// public override int Order { get; } = 77; - /// - public override bool Visible() + // render list of workflow states from first state to current workflow state + private string RenderStates() { - var contentItem = Util.GetContentController().GetContentItem(TabController.CurrentPage.ContentItemId); - return Personalization.GetUserMode() == PortalSettings.Mode.Edit - && DotNetNukeContext.Current.Application.SKU == "DNN" // IsPlatform - && TabVersionSettings.Instance.IsVersioningEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID) // versioning is enabled - && TabWorkflowSettings.Instance.IsWorkflowEnabled(PortalSettings.Current.PortalId, TabController.CurrentPage.TabID); // workflow is enabled + var currentState = $"{this.WorkflowState.StateName}"; + if (this.IsFirstState || this.IsLastState) + { + return currentState; + } + + // return "Draft > Review > Review2" for example + var pastStates = this.Workflow.States.Where(s => s.Order < this.WorkflowState.Order).OrderBy(s => s.Order).ToList(); + var pastStatesHtml = string.Join(" > ", pastStates.Select(s => $"{s.StateName}")); + return string.Join(" > ", pastStatesHtml, currentState); } } }