/// <summary>
 /// Deletes the specified item.
 /// </summary>
 /// <param name="item">The item.</param>
 /// <returns></returns>
 public override bool Delete( WorkflowActivityType item )
 {
     var activityService = new WorkflowActivityService( (RockContext)this.Context );
     foreach ( var activity in activityService.Queryable().Where( a => a.ActivityTypeId == item.Id ) )
     {
         activityService.Delete( activity );
     }
     return base.Delete( item );
 }
        /// <summary>
        /// Executes the specified workflow.
        /// </summary>
        /// <param name="rockContext">The rock context.</param>
        /// <param name="action">The action.</param>
        /// <param name="entity">The entity.</param>
        /// <param name="errorMessages">The error messages.</param>
        /// <returns></returns>
        public override bool Execute(RockContext rockContext, WorkflowAction action, Object entity, out List <string> errorMessages)
        {
            errorMessages = new List <string>();


            var activityToDelete = GetAttributeValue(action, "ActivityId", true).ResolveMergeFields(GetMergeFields(action)).AsIntegerOrNull();

            if (!activityToDelete.HasValue)
            {
                action.AddLogEntry("Invalid Activity Property", true);
                return(false);
            }

            WorkflowActivity activity = action.Activity.Workflow.Activities.Where(a => a.Id == activityToDelete).FirstOrDefault();


            if (activity != null)
            {
                action.AddLogEntry(activityToDelete.ToString());
                WorkflowActivityService workflowActivityService = new WorkflowActivityService(rockContext);
                workflowActivityService.Delete(activity);
            }
            else
            {
                errorMessages.Add(string.Format("'{0}' is not valid", activity));
            }


            List <string> workflowErrorMessages = new List <string>();

            errorMessages.AddRange(workflowErrorMessages);



            return(true);
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click( object sender, EventArgs e )
        {
            var rockContext = new RockContext();
            var service = new WorkflowService( rockContext );

            ParseControls( rockContext, true );

            Workflow dbWorkflow = null;

            if ( Workflow != null )
            {
                dbWorkflow = service.Get( Workflow.Id );

                if ( dbWorkflow != null )
                {
                    if ( !dbWorkflow.CompletedDateTime.HasValue && Workflow.CompletedDateTime.HasValue )
                    {
                        dbWorkflow.AddLogEntry( "Workflow Manually Completed." );
                        dbWorkflow.CompletedDateTime = Workflow.CompletedDateTime;
                    }
                    else if ( dbWorkflow.CompletedDateTime.HasValue && !Workflow.CompletedDateTime.HasValue )
                    {
                        dbWorkflow.AddLogEntry( "Workflow Manually Re-Activated." );
                        dbWorkflow.CompletedDateTime = null;
                    }

                    if ( dbWorkflow.Name.Trim() != Workflow.Name.Trim() )
                    {
                        dbWorkflow.AddLogEntry( string.Format( "Workflow name manually changed from '{0}' to '{0}'.", dbWorkflow.Name, tbName.Text ) );
                        dbWorkflow.Name = Workflow.Name;
                    }

                    if ( dbWorkflow.Status.Trim() != Workflow.Status.Trim() )
                    {
                        dbWorkflow.AddLogEntry( string.Format( "Workflow status manually changed from '{0}' to '{0}'.", dbWorkflow.Status, tbStatus.Text ) );
                        dbWorkflow.Status = Workflow.Status;
                    }

                    if ( !dbWorkflow.InitiatorPersonAliasId.Equals(Workflow.InitiatorPersonAliasId))
                    {
                        dbWorkflow.AddLogEntry( string.Format( "Workflow status manually changed from '{0}' to '{0}'.",
                            dbWorkflow.InitiatorPersonAlias != null ? dbWorkflow.InitiatorPersonAlias.Person.FullName : "",
                            Workflow.InitiatorPersonAlias != null ? Workflow.InitiatorPersonAlias.Person.FullName : "" ) );
                        dbWorkflow.InitiatorPersonAlias = Workflow.InitiatorPersonAlias;
                        dbWorkflow.InitiatorPersonAliasId = Workflow.InitiatorPersonAliasId;
                    }

                    if ( !Page.IsValid || !dbWorkflow.IsValid )
                    {
                        return;
                    }

                    foreach ( var activity in Workflow.Activities )
                    {
                        if ( !activity.IsValid )
                        {
                            return;
                        }
                        foreach ( var action in activity.Actions )
                        {
                            if ( !action.IsValid )
                            {
                                return;
                            }
                        }
                    }

                    rockContext.WrapTransaction( () =>
                    {
                        rockContext.SaveChanges();

                        dbWorkflow.LoadAttributes( rockContext );
                        foreach ( var attributeValue in Workflow.AttributeValues )
                        {
                            dbWorkflow.SetAttributeValue( attributeValue.Key, Workflow.GetAttributeValue( attributeValue.Key ) );
                        }
                        dbWorkflow.SaveAttributeValues( rockContext );

                        WorkflowActivityService workflowActivityService = new WorkflowActivityService( rockContext );
                        WorkflowActionService workflowActionService = new WorkflowActionService( rockContext );

                        var activitiesInUi = new List<Guid>();
                        var actionsInUI = new List<Guid>();
                        foreach ( var activity in Workflow.Activities )
                        {
                            activitiesInUi.Add( activity.Guid );
                            foreach ( var action in activity.Actions )
                            {
                                actionsInUI.Add( action.Guid );
                            }
                        }

                        // delete WorkflowActions that were removed in the UI
                        foreach ( var action in workflowActionService.Queryable()
                            .Where( a =>
                                a.Activity.WorkflowId.Equals( dbWorkflow.Id ) &&
                                !actionsInUI.Contains( a.Guid ) ) )
                        {
                            workflowActionService.Delete( action );
                        }

                        // delete WorkflowActivities that aren't assigned in the UI anymore
                        foreach ( var activity in workflowActivityService.Queryable()
                            .Where( a =>
                                a.WorkflowId.Equals( dbWorkflow.Id ) &&
                                !activitiesInUi.Contains( a.Guid ) ) )
                        {
                            workflowActivityService.Delete( activity );
                        }

                        rockContext.SaveChanges();

                        // add or update WorkflowActivities(and Actions) that are assigned in the UI
                        foreach ( var editorWorkflowActivity in Workflow.Activities )
                        {
                            // Add or Update the activity type
                            WorkflowActivity workflowActivity = dbWorkflow.Activities.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActivity.Guid ) );
                            if ( workflowActivity == null )
                            {
                                workflowActivity = new WorkflowActivity();
                                workflowActivity.ActivityTypeId = editorWorkflowActivity.ActivityTypeId;
                                dbWorkflow.Activities.Add( workflowActivity );
                            }

                            workflowActivity.AssignedPersonAliasId = editorWorkflowActivity.AssignedPersonAliasId;
                            workflowActivity.AssignedGroupId = editorWorkflowActivity.AssignedGroupId;
                            workflowActivity.ActivatedDateTime = editorWorkflowActivity.ActivatedDateTime;
                            workflowActivity.LastProcessedDateTime = editorWorkflowActivity.LastProcessedDateTime;

                            if ( !workflowActivity.CompletedDateTime.HasValue && editorWorkflowActivity.CompletedDateTime.HasValue )
                            {
                                workflowActivity.AddLogEntry( "Activity Manually Completed." );
                                workflowActivity.CompletedDateTime = RockDateTime.Now;
                            }
                            if ( workflowActivity.CompletedDateTime.HasValue && !editorWorkflowActivity.CompletedDateTime.HasValue )
                            {
                                workflowActivity.AddLogEntry( "Activity Manually Re-Activated." );
                                workflowActivity.CompletedDateTime = null;
                            }

                            // Save Activity Type
                            rockContext.SaveChanges();

                            // Save ActivityType Attributes
                            workflowActivity.LoadAttributes( rockContext );
                            foreach ( var attributeValue in editorWorkflowActivity.AttributeValues )
                            {
                                workflowActivity.SetAttributeValue( attributeValue.Key, editorWorkflowActivity.GetAttributeValue( attributeValue.Key ) );
                            }
                            workflowActivity.SaveAttributeValues( rockContext );

                            foreach ( var editorWorkflowAction in editorWorkflowActivity.Actions )
                            {
                                WorkflowAction workflowAction = workflowActivity.Actions.FirstOrDefault( a => a.Guid.Equals( editorWorkflowAction.Guid ) );
                                if ( workflowAction == null )
                                {
                                    // New action
                                    workflowAction = new WorkflowAction();
                                    workflowAction.ActionTypeId = editorWorkflowAction.ActionTypeId;
                                    workflowActivity.Actions.Add( workflowAction );
                                }

                                workflowAction.LastProcessedDateTime = editorWorkflowAction.LastProcessedDateTime;
                                workflowAction.FormAction = editorWorkflowAction.FormAction;

                                if ( !workflowAction.CompletedDateTime.HasValue && editorWorkflowAction.CompletedDateTime.HasValue )
                                {
                                    workflowAction.AddLogEntry( "Action Manually Completed." );
                                    workflowAction.CompletedDateTime = RockDateTime.Now;
                                }
                                if ( workflowAction.CompletedDateTime.HasValue && !editorWorkflowAction.CompletedDateTime.HasValue )
                                {
                                    workflowAction.AddLogEntry( "Action Manually Re-Activated." );
                                    workflowAction.CompletedDateTime = null;
                                }
                            }

                            // Save action updates
                            rockContext.SaveChanges();

                        }

                    } );

                }

                Workflow = service
                    .Queryable("WorkflowType,Activities.ActivityType,Activities.Actions.ActionType")
                    .FirstOrDefault( w => w.Id == Workflow.Id );

                var errorMessages = new List<string>();
                service.Process( Workflow, out errorMessages );

            }

            ShowReadonlyDetails();
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click( object sender, EventArgs e )
        {
            ParseControls( true );

            var rockContext = new RockContext();
            var service = new WorkflowTypeService( rockContext );

            WorkflowType workflowType = null;

            int? workflowTypeId = hfWorkflowTypeId.Value.AsIntegerOrNull();
            if ( workflowTypeId.HasValue )
            {
                workflowType = service.Get( workflowTypeId.Value );
            }

            if ( workflowType == null )
            {
                workflowType = new WorkflowType();
            }

            var validationErrors = new List<string>();

            // check for unique prefix
            string prefix = tbNumberPrefix.UntrimmedText;
            if ( !string.IsNullOrWhiteSpace( prefix ) &&
                prefix.ToUpper() != ( workflowType.WorkflowIdPrefix ?? string.Empty ).ToUpper() )
            {
                if ( service.Queryable().AsNoTracking()
                    .Any( w =>
                        w.Id != workflowType.Id &&
                        w.WorkflowIdPrefix == prefix ) )
                {
                    validationErrors.Add( "Workflow Number Prefix is already being used by another workflow type.  Please use a unique prefix." );
                }
                else
                {
                    workflowType.WorkflowIdPrefix = prefix;
                }
            }
            else
            {
                workflowType.WorkflowIdPrefix = prefix;
            }

            workflowType.IsActive = cbIsActive.Checked;
            workflowType.Name = tbName.Text;
            workflowType.Description = tbDescription.Text;
            workflowType.CategoryId = cpCategory.SelectedValueAsInt();
            workflowType.WorkTerm = tbWorkTerm.Text;
            workflowType.ModifiedByPersonAliasId = CurrentPersonAliasId;
            workflowType.ModifiedDateTime = RockDateTime.Now;

            int? mins = tbProcessingInterval.Text.AsIntegerOrNull();
            if ( mins.HasValue )
            {
                workflowType.ProcessingIntervalSeconds = mins.Value * 60;
            }
            else
            {
                workflowType.ProcessingIntervalSeconds = null;
            }

            workflowType.IsPersisted = cbIsPersisted.Checked;
            workflowType.LoggingLevel = ddlLoggingLevel.SelectedValueAsEnum<WorkflowLoggingLevel>();
            workflowType.IconCssClass = tbIconCssClass.Text;
            workflowType.SummaryViewText = ceSummaryViewText.Text;
            workflowType.NoActionMessage = ceNoActionMessage.Text;

            if ( validationErrors.Any() )
            {
                nbValidationError.Text = string.Format( "Please Correct the Following<ul><li>{0}</li></ul>",
                    validationErrors.AsDelimited( "</li><li>" ) );
                nbValidationError.Visible = true;

                return;
            }

            if ( !Page.IsValid || !workflowType.IsValid )
            {
                return;
            }

            foreach(var activityType in ActivityTypesState)
            {
                if (!activityType.IsValid)
                {
                    return;
                }
                foreach(var actionType in activityType.ActionTypes)
                {
                    if ( !actionType.IsValid )
                    {
                        return;
                    }
                }
            }

            rockContext.WrapTransaction( () =>
            {
                // Save the entity field changes to workflow type
                if ( workflowType.Id.Equals( 0 ) )
                {
                    service.Add( workflowType );
                }
                rockContext.SaveChanges();

                // Save the workflow type attributes
                SaveAttributes( new Workflow().TypeId, "WorkflowTypeId", workflowType.Id.ToString(), AttributesState, rockContext );

                WorkflowActivityTypeService workflowActivityTypeService = new WorkflowActivityTypeService( rockContext );
                WorkflowActivityService workflowActivityService = new WorkflowActivityService( rockContext );
                WorkflowActionService workflowActionService = new WorkflowActionService( rockContext );
                WorkflowActionTypeService workflowActionTypeService = new WorkflowActionTypeService( rockContext );
                WorkflowActionFormService workflowFormService = new WorkflowActionFormService( rockContext );
                WorkflowActionFormAttributeService workflowFormAttributeService = new WorkflowActionFormAttributeService( rockContext );

                // delete WorkflowActionTypes that aren't assigned in the UI anymore
                List<WorkflowActionType> actionTypesInDB = workflowActionTypeService.Queryable().Where( a => a.ActivityType.WorkflowTypeId.Equals( workflowType.Id ) ).ToList();
                List<WorkflowActionType> actionTypesInUI = new List<WorkflowActionType>();

                foreach ( var workflowActivity in ActivityTypesState )
                {
                    foreach ( var workflowAction in workflowActivity.ActionTypes )
                    {
                        actionTypesInUI.Add( workflowAction );
                    }
                }

                var deletedActionTypes = from actionType in actionTypesInDB
                                         where !actionTypesInUI.Select( u => u.Guid ).Contains( actionType.Guid )
                                         select actionType;
                foreach ( var actionType in deletedActionTypes.ToList() )
                {
                    if ( actionType.WorkflowForm != null )
                    {
                        workflowFormService.Delete( actionType.WorkflowForm );
                    }

                    // Delete any workflow actions of this type
                    int loopCounter = 0;
                    foreach ( var action in workflowActionService.Queryable().Where( a => a.ActionTypeId == actionType.Id ) )
                    {
                        workflowActionService.Delete( action );
                        loopCounter++;
                        if ( loopCounter > 100 )
                        {
                            rockContext.SaveChanges();
                            loopCounter = 0;
                        }
                    }
                    rockContext.SaveChanges();

                    workflowActionTypeService.Delete( actionType );
                }
                rockContext.SaveChanges();

                // delete WorkflowActivityTypes that aren't assigned in the UI anymore
                List<WorkflowActivityType> activityTypesInDB = workflowActivityTypeService.Queryable().Where( a => a.WorkflowTypeId.Equals( workflowType.Id ) ).ToList();
                var deletedActivityTypes = from activityType in activityTypesInDB
                                           where !ActivityTypesState.Select( u => u.Guid ).Contains( activityType.Guid )
                                           select activityType;
                foreach ( var activityType in deletedActivityTypes.ToList() )
                {
                    // Delete any workflow activities of this type
                    int loopCounter = 0;
                    foreach ( var activity in workflowActivityService.Queryable().Where( a => a.ActivityTypeId == activityType.Id ) )
                    {
                        workflowActivityService.Delete( activity );
                        loopCounter++;
                        if ( loopCounter > 100 )
                        {
                            rockContext.SaveChanges();
                            loopCounter = 0;
                        }
                    }
                    rockContext.SaveChanges();

                    workflowActivityTypeService.Delete( activityType );
                }
                rockContext.SaveChanges();

                // add or update WorkflowActivityTypes(and Actions) that are assigned in the UI
                int workflowActivityTypeOrder = 0;
                foreach ( var editorWorkflowActivityType in ActivityTypesState )
                {
                    // Add or Update the activity type
                    WorkflowActivityType workflowActivityType = workflowType.ActivityTypes.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActivityType.Guid ) );
                    if ( workflowActivityType == null )
                    {
                        workflowActivityType = new WorkflowActivityType();
                        workflowActivityType.Guid = editorWorkflowActivityType.Guid;
                        workflowType.ActivityTypes.Add( workflowActivityType );
                    }
                    workflowActivityType.IsActive = editorWorkflowActivityType.IsActive;
                    workflowActivityType.Name = editorWorkflowActivityType.Name;
                    workflowActivityType.Description = editorWorkflowActivityType.Description;
                    workflowActivityType.IsActivatedWithWorkflow = editorWorkflowActivityType.IsActivatedWithWorkflow;
                    workflowActivityType.Order = workflowActivityTypeOrder++;

                    // Save Activity Type
                    rockContext.SaveChanges();

                    // Save ActivityType Attributes
                    if ( ActivityAttributesState.ContainsKey( workflowActivityType.Guid ) )
                    {
                        SaveAttributes( new WorkflowActivity().TypeId, "ActivityTypeId", workflowActivityType.Id.ToString(), ActivityAttributesState[workflowActivityType.Guid], rockContext );
                    }

                    // Because the SaveAttributes above may have flushed the cached entity attribute cache, and it would get loaded again with
                    // a different context, manually reload the cache now with our context to prevent a database lock conflict (when database is
                    // configured without snapshot isolation turned on)
                    AttributeCache.LoadEntityAttributes( rockContext );

                    int workflowActionTypeOrder = 0;
                    foreach ( var editorWorkflowActionType in editorWorkflowActivityType.ActionTypes )
                    {
                        WorkflowActionType workflowActionType = workflowActivityType.ActionTypes.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActionType.Guid ) );
                        if ( workflowActionType == null )
                        {
                            // New action
                            workflowActionType = new WorkflowActionType();
                            workflowActionType.Guid = editorWorkflowActionType.Guid;
                            workflowActivityType.ActionTypes.Add( workflowActionType );
                        }
                        workflowActionType.CriteriaAttributeGuid = editorWorkflowActionType.CriteriaAttributeGuid;
                        workflowActionType.CriteriaComparisonType = editorWorkflowActionType.CriteriaComparisonType;
                        workflowActionType.CriteriaValue = editorWorkflowActionType.CriteriaValue;
                        workflowActionType.Name = editorWorkflowActionType.Name;
                        workflowActionType.EntityTypeId = editorWorkflowActionType.EntityTypeId;
                        workflowActionType.IsActionCompletedOnSuccess = editorWorkflowActionType.IsActionCompletedOnSuccess;
                        workflowActionType.IsActivityCompletedOnSuccess = editorWorkflowActionType.IsActivityCompletedOnSuccess;
                        workflowActionType.Attributes = editorWorkflowActionType.Attributes;
                        workflowActionType.AttributeValues = editorWorkflowActionType.AttributeValues;
                        workflowActionType.Order = workflowActionTypeOrder++;

                        if ( workflowActionType.WorkflowForm != null && editorWorkflowActionType.WorkflowForm == null )
                        {
                            // Form removed
                            workflowFormService.Delete( workflowActionType.WorkflowForm );
                            workflowActionType.WorkflowForm = null;
                        }

                        if ( editorWorkflowActionType.WorkflowForm != null )
                        {
                            if ( workflowActionType.WorkflowForm == null )
                            {
                                workflowActionType.WorkflowForm = new WorkflowActionForm();
                            }

                            workflowActionType.WorkflowForm.NotificationSystemEmailId = editorWorkflowActionType.WorkflowForm.NotificationSystemEmailId;
                            workflowActionType.WorkflowForm.IncludeActionsInNotification = editorWorkflowActionType.WorkflowForm.IncludeActionsInNotification;
                            workflowActionType.WorkflowForm.AllowNotes = editorWorkflowActionType.WorkflowForm.AllowNotes;
                            workflowActionType.WorkflowForm.Header = editorWorkflowActionType.WorkflowForm.Header;
                            workflowActionType.WorkflowForm.Footer = editorWorkflowActionType.WorkflowForm.Footer;
                            workflowActionType.WorkflowForm.Actions = editorWorkflowActionType.WorkflowForm.Actions;
                            workflowActionType.WorkflowForm.ActionAttributeGuid = editorWorkflowActionType.WorkflowForm.ActionAttributeGuid;

                            var editorGuids = editorWorkflowActionType.WorkflowForm.FormAttributes
                                .Select( a => a.Attribute.Guid )
                                .ToList();

                            foreach ( var formAttribute in workflowActionType.WorkflowForm.FormAttributes
                                .Where( a => !editorGuids.Contains( a.Attribute.Guid ) ).ToList() )
                            {
                                workflowFormAttributeService.Delete( formAttribute );
                            }

                            int attributeOrder = 0;
                            foreach ( var editorAttribute in editorWorkflowActionType.WorkflowForm.FormAttributes.OrderBy( a => a.Order ) )
                            {
                                int attributeId = AttributeCache.Read( editorAttribute.Attribute.Guid, rockContext ).Id;

                                var formAttribute = workflowActionType.WorkflowForm.FormAttributes
                                    .Where( a => a.AttributeId == attributeId )
                                    .FirstOrDefault();

                                if ( formAttribute == null )
                                {
                                    formAttribute = new WorkflowActionFormAttribute();
                                    formAttribute.Guid = editorAttribute.Guid;
                                    formAttribute.AttributeId = attributeId;
                                    workflowActionType.WorkflowForm.FormAttributes.Add( formAttribute );
                                }

                                formAttribute.Order = attributeOrder++;
                                formAttribute.IsVisible = editorAttribute.IsVisible;
                                formAttribute.IsReadOnly = editorAttribute.IsReadOnly;
                                formAttribute.IsRequired = editorAttribute.IsRequired;
                                formAttribute.HideLabel = editorAttribute.HideLabel;
                                formAttribute.PreHtml = editorAttribute.PreHtml;
                                formAttribute.PostHtml = editorAttribute.PostHtml;
                            }
                        }
                    }
                }

                rockContext.SaveChanges();

                foreach ( var activityType in workflowType.ActivityTypes )
                {
                    foreach ( var workflowActionType in activityType.ActionTypes )
                    {
                        workflowActionType.SaveAttributeValues( rockContext );
                    }
                }

            } );

            var qryParams = new Dictionary<string, string>();
            qryParams["workflowTypeId"] = workflowType.Id.ToString();
            NavigateToPage( RockPage.Guid, qryParams );
        }
        /// <summary>
        /// Handles the Click event of the btnSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
        protected void btnSave_Click(object sender, EventArgs e)
        {
            var rockContext = new RockContext();
            var service     = new WorkflowService(rockContext);

            ParseControls(rockContext, true);

            Workflow dbWorkflow = null;

            if (Workflow != null)
            {
                dbWorkflow = service.Get(Workflow.Id);

                if (dbWorkflow != null)
                {
                    if (!dbWorkflow.CompletedDateTime.HasValue && Workflow.CompletedDateTime.HasValue)
                    {
                        dbWorkflow.AddLogEntry("Workflow Manually Completed.");
                        dbWorkflow.CompletedDateTime = Workflow.CompletedDateTime;
                    }
                    else if (dbWorkflow.CompletedDateTime.HasValue && !Workflow.CompletedDateTime.HasValue)
                    {
                        dbWorkflow.AddLogEntry("Workflow Manually Re-Activated.");
                        dbWorkflow.CompletedDateTime = null;
                    }

                    if (dbWorkflow.Name.Trim() != Workflow.Name.Trim())
                    {
                        dbWorkflow.AddLogEntry(string.Format("Workflow name manually changed from '{0}' to '{0}'.", dbWorkflow.Name, tbName.Text));
                        dbWorkflow.Name = Workflow.Name;
                    }

                    if (dbWorkflow.Status.Trim() != Workflow.Status.Trim())
                    {
                        dbWorkflow.AddLogEntry(string.Format("Workflow status manually changed from '{0}' to '{0}'.", dbWorkflow.Status, tbStatus.Text));
                        dbWorkflow.Status = Workflow.Status;
                    }

                    if (!dbWorkflow.InitiatorPersonAliasId.Equals(Workflow.InitiatorPersonAliasId))
                    {
                        dbWorkflow.AddLogEntry(string.Format("Workflow status manually changed from '{0}' to '{0}'.",
                                                             dbWorkflow.InitiatorPersonAlias != null ? dbWorkflow.InitiatorPersonAlias.Person.FullName : "",
                                                             Workflow.InitiatorPersonAlias != null ? Workflow.InitiatorPersonAlias.Person.FullName : ""));
                        dbWorkflow.InitiatorPersonAlias   = Workflow.InitiatorPersonAlias;
                        dbWorkflow.InitiatorPersonAliasId = Workflow.InitiatorPersonAliasId;
                    }

                    if (!Page.IsValid || !dbWorkflow.IsValid)
                    {
                        return;
                    }

                    foreach (var activity in Workflow.Activities)
                    {
                        if (!activity.IsValid)
                        {
                            return;
                        }
                        foreach (var action in activity.Actions)
                        {
                            if (!action.IsValid)
                            {
                                return;
                            }
                        }
                    }

                    rockContext.WrapTransaction(() =>
                    {
                        rockContext.SaveChanges();

                        dbWorkflow.LoadAttributes(rockContext);
                        foreach (var attributeValue in Workflow.AttributeValues)
                        {
                            dbWorkflow.SetAttributeValue(attributeValue.Key, Workflow.GetAttributeValue(attributeValue.Key));
                        }
                        dbWorkflow.SaveAttributeValues(rockContext);

                        WorkflowActivityService workflowActivityService = new WorkflowActivityService(rockContext);
                        WorkflowActionService workflowActionService     = new WorkflowActionService(rockContext);

                        var activitiesInUi = new List <Guid>();
                        var actionsInUI    = new List <Guid>();
                        foreach (var activity in Workflow.Activities)
                        {
                            activitiesInUi.Add(activity.Guid);
                            foreach (var action in activity.Actions)
                            {
                                actionsInUI.Add(action.Guid);
                            }
                        }

                        // delete WorkflowActions that were removed in the UI
                        foreach (var action in workflowActionService.Queryable()
                                 .Where(a =>
                                        a.Activity.WorkflowId.Equals(dbWorkflow.Id) &&
                                        !actionsInUI.Contains(a.Guid)))
                        {
                            workflowActionService.Delete(action);
                        }

                        // delete WorkflowActivities that aren't assigned in the UI anymore
                        foreach (var activity in workflowActivityService.Queryable()
                                 .Where(a =>
                                        a.WorkflowId.Equals(dbWorkflow.Id) &&
                                        !activitiesInUi.Contains(a.Guid)))
                        {
                            workflowActivityService.Delete(activity);
                        }

                        rockContext.SaveChanges();

                        // add or update WorkflowActivities(and Actions) that are assigned in the UI
                        foreach (var editorWorkflowActivity in Workflow.Activities)
                        {
                            // Add or Update the activity type
                            WorkflowActivity workflowActivity = dbWorkflow.Activities.FirstOrDefault(a => a.Guid.Equals(editorWorkflowActivity.Guid));
                            if (workflowActivity == null)
                            {
                                workflowActivity = new WorkflowActivity();
                                workflowActivity.ActivityTypeId = editorWorkflowActivity.ActivityTypeId;
                                dbWorkflow.Activities.Add(workflowActivity);
                            }

                            workflowActivity.AssignedPersonAliasId = editorWorkflowActivity.AssignedPersonAliasId;
                            workflowActivity.AssignedGroupId       = editorWorkflowActivity.AssignedGroupId;
                            workflowActivity.ActivatedDateTime     = editorWorkflowActivity.ActivatedDateTime;
                            workflowActivity.LastProcessedDateTime = editorWorkflowActivity.LastProcessedDateTime;

                            if (!workflowActivity.CompletedDateTime.HasValue && editorWorkflowActivity.CompletedDateTime.HasValue)
                            {
                                workflowActivity.AddLogEntry("Activity Manually Completed.");
                                workflowActivity.CompletedDateTime = RockDateTime.Now;
                            }
                            if (workflowActivity.CompletedDateTime.HasValue && !editorWorkflowActivity.CompletedDateTime.HasValue)
                            {
                                workflowActivity.AddLogEntry("Activity Manually Re-Activated.");
                                workflowActivity.CompletedDateTime = null;
                            }


                            // Save Activity Type
                            rockContext.SaveChanges();

                            // Save ActivityType Attributes
                            workflowActivity.LoadAttributes(rockContext);
                            foreach (var attributeValue in editorWorkflowActivity.AttributeValues)
                            {
                                workflowActivity.SetAttributeValue(attributeValue.Key, editorWorkflowActivity.GetAttributeValue(attributeValue.Key));
                            }
                            workflowActivity.SaveAttributeValues(rockContext);

                            foreach (var editorWorkflowAction in editorWorkflowActivity.Actions)
                            {
                                WorkflowAction workflowAction = workflowActivity.Actions.FirstOrDefault(a => a.Guid.Equals(editorWorkflowAction.Guid));
                                if (workflowAction == null)
                                {
                                    // New action
                                    workflowAction = new WorkflowAction();
                                    workflowAction.ActionTypeId = editorWorkflowAction.ActionTypeId;
                                    workflowActivity.Actions.Add(workflowAction);
                                }

                                workflowAction.LastProcessedDateTime = editorWorkflowAction.LastProcessedDateTime;
                                workflowAction.FormAction            = editorWorkflowAction.FormAction;

                                if (!workflowAction.CompletedDateTime.HasValue && editorWorkflowAction.CompletedDateTime.HasValue)
                                {
                                    workflowAction.AddLogEntry("Action Manually Completed.");
                                    workflowAction.CompletedDateTime = RockDateTime.Now;
                                }
                                if (workflowAction.CompletedDateTime.HasValue && !editorWorkflowAction.CompletedDateTime.HasValue)
                                {
                                    workflowAction.AddLogEntry("Action Manually Re-Activated.");
                                    workflowAction.CompletedDateTime = null;
                                }
                            }

                            // Save action updates
                            rockContext.SaveChanges();
                        }
                    });
                }

                Workflow = service
                           .Queryable("WorkflowType,Activities.ActivityType,Activities.Actions.ActionType")
                           .FirstOrDefault(w => w.Id == Workflow.Id);

                var errorMessages = new List <string>();
                service.Process(Workflow, out errorMessages);
            }

            ShowReadonlyDetails();
        }