using System; using System.Collections.Generic; using System.Web.UI.WebControls; using System.Text; using System.Web.UI; using CMS.CMSHelper; using CMS.GlobalHelper; using CMS.PortalEngine; using CMS.SettingsProvider; using CMS.WorkflowEngine; using CMS.ExtendedControls.ActionsConfig; using CMS.Controls; using CMS.ExtendedControls; using CMS.UIControls; using CMS.WorkflowEngine.Definitions; using CMS.SiteProvider; using CMS.FormControls; public partial class CMSModules_Automation_Controls_AutomationMenu : BaseEditMenu { #region "Variables" // Actions protected NextStepAction next = null; protected PreviousStepAction previous = null; protected HeaderAction delete = null; protected HeaderAction start = null; protected NextStepAction specific = null; private WorkflowStepInfo mStep = null; private CMSAutomationManager mAutomationManager = null; private bool? mAllowSave = null; #endregion #region "Public properties" /// /// Menu control /// public override HeaderActions HeaderActions { get { return menu; } } /// /// Indicates if Save action is allowed. /// public override bool AllowSave { get { if (mAllowSave == null) { return AutomationManager.AllowSave; } return mAllowSave.Value; } set { mAllowSave = value; } } /// /// Indicates if the menu is enabled /// public override bool Enabled { get { return menu.Enabled; } set { menu.Enabled = value; } } /// /// Object instance /// public BaseInfo InfoObject { get { return AutomationManager.InfoObject; } } /// /// State object /// public AutomationStateInfo StateObject { get { return AutomationManager.StateObject; } } /// /// Automation manager /// public AutomationManager Manager { get { return AutomationManager.Manager; } } /// /// Automation manager control /// public CMSAutomationManager AutomationManager { get { if (mAutomationManager == null) { mAutomationManager = ControlsHelper.GetChildControl(Page, typeof(CMSAutomationManager)) as CMSAutomationManager; if (mAutomationManager == null) { throw new Exception("[AutomationMenu.AutomationManager]: Missing automation manager."); } } return mAutomationManager; } } /// /// If true, the access permissions to the items are checked. /// public override bool CheckPermissions { get { return AutomationManager.CheckPermissions; } set { AutomationManager.CheckPermissions = value; } } /// /// Indicates if the control should perform the operations. /// public override bool StopProcessing { get { return AutomationManager.StopProcessing; } set { AutomationManager.StopProcessing = value; } } /// /// Current step /// protected WorkflowStepInfo Step { get { if (mStep == null) { mStep = AutomationManager.Step; } return mStep; } } #endregion #region "Constructors" /// /// Constructor /// public CMSModules_Automation_Controls_AutomationMenu() { RefreshInterval = 500; } #endregion #region "Page events" protected override void OnLoad(EventArgs e) { // Handle callback in OnLoad event because of ShortIDs var parameters = Request.Form["params"]; if (parameters != null) { if (parameters.StartsWith(CALLBACK_ID + ClientID)) { string[] args = parameters.Split(new string[] { CALLBACK_SEP }, StringSplitOptions.None); AutomationManager.Mode = FormModeEnum.Update; AutomationManager.ClearObject(); AutomationManager.ObjectType = ValidationHelper.GetString(args[1], null); AutomationManager.ObjectID = ValidationHelper.GetInteger(args[2], 0); Response.Clear(); if (Step != null) { Response.Write(CALLBACK_ID + AutomationManager.GetAutomationInfo() + CALLBACK_SEP + AutomationManager.RefreshActionContent.ToString().ToLowerCSafe() + CALLBACK_SEP + Step.StepID); } else { Response.Write(CALLBACK_ID + AutomationManager.GetAutomationInfo() + CALLBACK_SEP + "false" + CALLBACK_SEP + "0"); } Response.End(); return; } } base.OnLoad(e); if (!string.IsNullOrEmpty(HelpTopicName)) { helpElem.TopicName = HelpTopicName; pnlHelp.Visible = true; } if (!string.IsNullOrEmpty(HelpName)) { helpElem.HelpName = HelpName; } // Perform full post-back if not in update panel menu.PerformFullPostBack = !ControlsHelper.IsInUpdatePanel(this); } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); ReloadMenu(); // Display information AutomationManager.ShowAutomationInfo(); // Hide menu if no actions Visible &= menu.Visible || pnlHelp.Visible || !string.IsNullOrEmpty(pnlDoc.Label.Text); if (Visible) { RegisterActionScripts(); } } protected override void Render(HtmlTextWriter writer) { base.Render(writer); PostBackOptions opt = new PostBackOptions(this, null) { PerformValidation = false }; Page.ClientScript.RegisterForEventValidation(opt); } /// /// Registers action scripts /// private void RegisterActionScripts() { StringBuilder sb = new StringBuilder(); bool addComment = false; sb.Append("function CheckConsistency_", ClientID, "() { ", AutomationManager.GetJSFunction("CONS", null, null), "; } \n"); if (next != null) { addComment = true; sb.Append("function MoveNext_", ClientID, "(stepId, comment) { ", next.OnClientClick, AutomationManager.GetJSFunction(next.EventName, "stepId", "comment"), "; } \n"); } if (specific != null) { addComment = true; sb.Append("function MoveSpecific_", ClientID, "(stepId, comment) { ", specific.OnClientClick, AutomationManager.GetJSFunction(specific.EventName, "stepId", "comment"), "; } \n"); } if (previous != null) { addComment = true; sb.Append("function MovePrevious_", ClientID, "(historyId, comment) { ", previous.OnClientClick, AutomationManager.GetJSFunction(previous.EventName, "historyId", "comment"), "; } \n"); } if (addComment) { sb.Append("function AddComment_", ClientID, "(name, stateId, menuId) { ", AutomationManager.GetJSFunction(ComponentEvents.COMMENT, "name|stateId|menuId", null), "; } \n"); } // Register the script if (sb.Length > 0) { ControlsHelper.RegisterClientScriptBlock(this, Page, typeof(string), "AutoMenuActions" + ClientID, ScriptHelper.GetScript(sb.ToString())); } } #endregion #region "Methods" private void ClearProperties() { // Clear actions next = null; specific = null; previous = null; delete = null; start = null; mStep = null; // Clear security result AutomationManager.ClearProperties(); } private void ReloadMenu() { if (StopProcessing) { return; } // Handle several reloads ClearProperties(); if (!HideStandardButtons) { // If content should be refreshed if (AutomationManager.RefreshActionContent) { // Display action message WorkflowActionInfo action = WorkflowActionInfoProvider.GetWorkflowActionInfo(Step.StepActionID); string name = (action != null) ? action.ActionDisplayName : Step.StepDisplayName; string str = (action != null) ? "workflow.actioninprogress" : "workflow.stepinprogress"; string text = string.Format(ResHelper.GetString(str, ResourceCulture), HTMLHelper.HTMLEncode(ResHelper.LocalizeString(name))); text = String.Concat("\"", ", text, ""); InformationText = text; EnsureRefreshScript(); } // Object update if (AutomationManager.Mode == FormModeEnum.Update) { if (InfoObject != null) { // Get current process WorkflowInfo process = AutomationManager.Process; string objectName = HTMLHelper.HTMLEncode(ResHelper.GetString(InfoObject.Generalized.GetObjectTypeResourceKey()).ToLowerCSafe()); // Next step action if (AutomationManager.IsActionAllowed(ComponentEvents.AUTOMATION_MOVE_NEXT)) { next = new NextStepAction(Page) { Tooltip = string.Format(ResHelper.GetString("EditMenu.NextStep", ResourceCulture), objectName), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_MOVE_NEXT, null), }; } // Move to specific step action if (AutomationManager.IsActionAllowed(ComponentEvents.AUTOMATION_MOVE_SPEC)) { var steps = WorkflowStepInfoProvider.GetWorkflowSteps("StepWorkflowID=" + process.WorkflowID + " AND StepType<>" + (int)WorkflowStepTypeEnum.Start, "StepDisplayName"); specific = new NextStepAction(Page) { ImageUrl = GetImageUrl("CMSModules/CMS_Content/EditMenu/specific.png"), SmallImageUrl = GetImageUrl("CMSModules/CMS_Content/EditMenu/16/specific.png"), Text = GetString("AutoMenu.SpecificStepIcon"), Tooltip = string.Format(ResHelper.GetString("AutoMenu.SpecificStepMultiple", ResourceCulture), objectName), CommandName = ComponentEvents.AUTOMATION_MOVE_SPEC, EventName = ComponentEvents.AUTOMATION_MOVE_SPEC, // Make action inactive OnClientClick = null, Inactive = true }; foreach (var s in steps) { string stepName = HTMLHelper.HTMLEncode(ResHelper.LocalizeString(s.StepDisplayName)); NextStepAction spc = new NextStepAction(Page) { ImageUrl = GetImageUrl("CMSModules/CMS_Content/EditMenu/specific.png"), SmallImageUrl = GetImageUrl("CMSModules/CMS_Content/EditMenu/16/specific.png"), Text = string.Format(ResHelper.GetString("AutoMenu.SpecificStepTo", ResourceCulture), stepName), Tooltip = string.Format(ResHelper.GetString("AutoMenu.SpecificStep", ResourceCulture), objectName), CommandName = ComponentEvents.AUTOMATION_MOVE_SPEC, EventName = ComponentEvents.AUTOMATION_MOVE_SPEC, CommandArgument = s.StepID.ToString(), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_MOVE_SPEC, "if(!confirm(" + ScriptHelper.GetString(string.Format(ResHelper.GetString("autoMenu.MoveSpecificConfirmation"), objectName, ResHelper.LocalizeString(s.StepDisplayName))) + ")) { return false; }"), }; // Process action appearance ProcessAction(spc, Step, s); // Add step specific.AlternativeActions.Add(spc); } // Add comment AddCommentAction(ComponentEvents.AUTOMATION_MOVE_SPEC, specific, objectName); } // Previous step action if (AutomationManager.IsActionAllowed(ComponentEvents.AUTOMATION_MOVE_PREVIOUS)) { var prevSteps = Manager.GetPreviousSteps(InfoObject, StateObject); int prevStepsCount = prevSteps.Count; if (prevStepsCount > 0) { previous = new PreviousStepAction(Page) { Tooltip = string.Format(ResHelper.GetString("EditMenu.PreviousStep", ResourceCulture), objectName), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_MOVE_PREVIOUS, null) }; // For managers allow move to specified step if (WorkflowStepInfoProvider.CanUserManageAutomationProcesses(CMSContext.CurrentUser, InfoObject.Generalized.ObjectSiteName)) { if (prevStepsCount > 1) { foreach (var s in prevSteps) { previous.AlternativeActions.Add(new PreviousStepAction(Page) { Text = string.Format(ResHelper.GetString("EditMenu.PreviousStepTo", ResourceCulture), HTMLHelper.HTMLEncode(ResHelper.LocalizeString(s.StepDisplayName))), Tooltip = string.Format(ResHelper.GetString("EditMenu.PreviousStep", ResourceCulture), objectName), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_MOVE_PREVIOUS, null), CommandArgument = s.RelatedHistoryID.ToString() }); } } } // Add comment AddCommentAction(ComponentEvents.AUTOMATION_MOVE_PREVIOUS, previous, objectName); } } if (AutomationManager.IsActionAllowed(ComponentEvents.AUTOMATION_REMOVE)) { delete = new HeaderAction() { ImageUrl = GetImageUrl("CMSModules/CMS_Content/EditMenu/reject.png"), SmallImageUrl = GetImageUrl("CMSModules/CMS_Content/EditMenu/16/reject.png"), CommandName = ComponentEvents.AUTOMATION_REMOVE, EventName = ComponentEvents.AUTOMATION_REMOVE, Text = ResHelper.GetString("autoMenu.RemoveState", ResourceCulture), Tooltip = string.Format(ResHelper.GetString("autoMenu.RemoveStateDesc", ResourceCulture), objectName), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_REMOVE, "if(!confirm(" + ScriptHelper.GetString(string.Format(ResHelper.GetString("autoMenu.RemoveStateConfirmation"), objectName)) + ")) { return false; }") }; } // Handle multiple next steps if (next != null) { string actionName = ComponentEvents.AUTOMATION_MOVE_NEXT; // Get next step info List steps = AutomationManager.NextSteps; int stepsCount = steps.Count; if (stepsCount > 0) { var nextS = steps[0]; // Only one next step if (stepsCount == 1) { if (nextS.StepIsFinished) { next.Text = ResHelper.GetString("EditMenu.IconFinish", ResourceCulture); next.Tooltip = string.Format(ResHelper.GetString("EditMenu.Finish", ResourceCulture), objectName); } // Process action appearance ProcessAction(next, Step, nextS); } // Multiple next steps else { // Check if not all steps finish steps if (steps.Exists(s => !s.StepIsFinished)) { next.Tooltip = string.Format(ResHelper.GetString("EditMenu.NextStepMultiple", ResourceCulture), objectName); } else { next.Text = ResHelper.GetString("EditMenu.IconFinish", ResourceCulture); next.Tooltip = string.Format(ResHelper.GetString("EditMenu.NextStepMultiple", ResourceCulture), objectName); } // Make action inactive next.OnClientClick = null; next.Inactive = true; // Process action appearance ProcessAction(next, Step, null); string itemText = "EditMenu.NextStepTo"; string itemDesc = "EditMenu.NextStep"; foreach (var s in steps) { NextStepAction nxt = new NextStepAction(Page) { Text = string.Format(ResHelper.GetString(itemText, ResourceCulture), HTMLHelper.HTMLEncode(ResHelper.LocalizeString(s.StepDisplayName))), Tooltip = string.Format(ResHelper.GetString(itemDesc, ResourceCulture), objectName), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_MOVE_NEXT, null), CommandArgument = s.StepID.ToString() }; if (s.StepIsFinished) { nxt.Text = string.Format(ResHelper.GetString("EditMenu.FinishTo", ResourceCulture), HTMLHelper.HTMLEncode(ResHelper.LocalizeString(s.StepDisplayName))); nxt.Tooltip = string.Format(ResHelper.GetString("EditMenu.Finish", ResourceCulture), objectName); } // Process action appearance ProcessAction(nxt, Step, s); // Add step next.AlternativeActions.Add(nxt); } } // Add comment AddCommentAction(actionName, next, objectName); } else { bool displayAction = false; if (!Step.StepAllowBranch) { // Transition exists, but condition doesn't match var transitions = Manager.GetStepTransitions(Step); if (transitions.Count > 0) { WorkflowStepInfo s = WorkflowStepInfoProvider.GetWorkflowStepInfo(transitions[0].TransitionEndStepID); // Finish text if (s.StepIsFinished) { next.Text = ResHelper.GetString("EditMenu.IconFinish", ResourceCulture); next.Tooltip = string.Format(ResHelper.GetString("EditMenu.Finish", ResourceCulture), objectName); } // Inform user displayAction = true; next.Enabled = false; // Process action appearance ProcessAction(next, Step, null); } } if (!displayAction) { // There is not next step next = null; } } } // Handle start button if (AutomationManager.IsActionAllowed(ComponentEvents.AUTOMATION_START) && (process.WorkflowRecurrenceType != ProcessRecurrenceTypeEnum.NonRecurring)) { start = new HeaderAction() { ImageUrl = GetImageUrl("Objects/MA_AutomationState/add.png"), SmallImageUrl = GetImageUrl("Objects/MA_AutomationState/add.png"), CommandName = ComponentEvents.AUTOMATION_START, EventName = ComponentEvents.AUTOMATION_START, Text = ResHelper.GetString("autoMenu.StartState", ResourceCulture), Tooltip = string.Format(ResHelper.GetString("autoMenu.StartStateDesc", ResourceCulture), objectName), CommandArgument = process.WorkflowID.ToString(), OnClientClick = RaiseGetClientValidationScript(ComponentEvents.AUTOMATION_START, "if(!confirm(" + ScriptHelper.GetString(string.Format(ResHelper.GetString("autoMenu.startSameProcessConfirmation", ResourceCulture), objectName)) + ")) { return false; }") }; } } } // Ensure correct design with backward compatibility if (string.IsNullOrEmpty(LinkCssClass)) { if (!IsLiveSite) { menu.LinkCssClass = "MenuItemEdit"; } } else { menu.LinkCssClass = LinkCssClass; } } // Add actions in correct order menu.ActionsList.Clear(); AddAction(previous); AddAction(next); AddAction(specific); AddAction(delete); AddAction(start); // Set the information text if (!String.IsNullOrEmpty(InformationText)) { lblInfo.Text = InformationText; lblInfo.CssClass = "LeftAlign EditMenuInfo"; lblInfo.Visible = true; } } private void EnsureRefreshScript() { PostBackOptions options = new PostBackOptions(this) { PerformValidation = false }; string postback = ControlsHelper.GetPostBackEventReference(menu, options, false, true); string externalRefreshScript = null; if (!string.IsNullOrEmpty(OnClientStepChanged)) { externalRefreshScript = string.Format("clearInterval(refTimerId_{0}); {1};", ClientID, OnClientStepChanged); } string commonScript = @" String.prototype.startsWith = function (str) { return (this.match('^' + str) == str); }; function VerifyData(incomingData) { if (incomingData.startsWith('" + CALLBACK_ID + @"')) { return incomingData.replace('" + CALLBACK_ID + @"', ''); } else { data = null; } return data; } "; ScriptHelper.RegisterStartupScript(Page, typeof(string), "refCommon", commonScript, true); StringBuilder sb = new StringBuilder(); sb.Append(@" var refTimerId_", ClientID, @" = 0; function RfMenu_DoPostBack_", ClientID, @"() {", postback, @"} function RfMenu_Succ_", ClientID, @"(data, textStatus, jqXHR) { if(data != null) { var hdn = document.getElementById('", hdnParam.ClientID, @"'); var args = data.split('", CALLBACK_SEP, @"'); var stop = (args[1] == 'false'); var stepId = args[2]; if(stop) { clearInterval(refTimerId_", ClientID, @"); setTimeout('RfMenu_DoPostBack_", ClientID, "()', ", RefreshInterval, @"); } else { // Step changed if(hdn.value != stepId) { var lbl = document.getElementById('", AutomationManager.AutomationInfoLabel.ClientID, @"'); if(lbl != null) { lbl.innerHTML = args[0]; }", externalRefreshScript, @" } } hdn.value = stepId; } else { clearInterval(refTimerId_", ClientID, @"); setTimeout('RfMenu_DoPostBack_", ClientID, "()', ", RefreshInterval, @"); } } function RfMenu_Err_", ClientID, @"(jqXHR, textStatus, errorThrown) { var err = ''; if ((errorThrown != undefined) && (errorThrown != null) && (errorThrown != '')) { err = ' (' + errorThrown + ')'; clearInterval(refTimerId_", ClientID, @"); alert(err); } } function RfMenu_", ClientID, @"() { $j.ajax({ cache: false, type: 'POST', data: 'params=", CALLBACK_ID + ClientID, CALLBACK_SEP, AutomationManager.ObjectType, CALLBACK_SEP, AutomationManager.ObjectID, CALLBACK_SEP, @"', context: document.body, success: RfMenu_Succ_" + ClientID, @", error: RfMenu_Err_", ClientID, @", dataType: 'text', dataFilter: VerifyData }); } refTimerId_", ClientID, @" = setInterval('RfMenu_", ClientID, "()', 200);"); ScriptHelper.RegisterStartupScript(Page, typeof(string), "ref_" + ClientID, sb.ToString(), true); } private void ProcessAction(HeaderAction action, WorkflowStepInfo currentStep, WorkflowStepInfo nextStep) { if (action == null) { return; } string nextStepName = null; SourcePoint def = null; if (nextStep != null) { WorkflowTransitionInfo transition = nextStep.RelatedTransition; if (transition != null) { def = currentStep.GetSourcePoint(transition.TransitionSourcePointGUID); nextStepName = HTMLHelper.HTMLEncode(ResHelper.LocalizeString(nextStep.StepDisplayName)); } } else { def = currentStep.StepDefinition.DefinitionPoint; } if (def != null) { if (!string.IsNullOrEmpty(def.Text)) { action.Text = string.Format(HTMLHelper.HTMLEncode(ResHelper.LocalizeString(def.Text)), nextStepName); } if (!string.IsNullOrEmpty(def.Tooltip)) { action.Tooltip = string.Format(ResHelper.LocalizeString(def.Tooltip), action.Text); } } } /// /// Adds menu action. /// /// Action protected void AddAction(HeaderAction action) { if (action != null) { // Action menu.ActionsList.Add(action); } } /// /// Adds comment action. /// /// Action name /// Current action /// Current step /// Object name private void AddCommentAction(string name, HeaderAction action, string objectName) { AutomationManager.RenderScript = true; CommentAction comment = new CommentAction(Page, name) { Tooltip = string.Format(ResHelper.GetString("EditMenu.Comment" + name, ResourceCulture), objectName), OnClientClick = string.Format("AddComment_{0}('{1}',{2},'{0}');", ClientID, name, StateObject.StateID), }; action.AlternativeActions.Add(comment); } #endregion }