/// <summary> /// Returns the field's current value(s) /// </summary> /// <param name="parentControl">The parent control.</param> /// <param name="value">Information about the value</param> /// <param name="configurationValues">The configuration values.</param> /// <param name="condensed">Flag indicating if the value should be condensed (i.e. for use in a grid column)</param> /// <returns></returns> public override string FormatValue( Control parentControl, string value, Dictionary<string, ConfigurationValue> configurationValues, bool condensed ) { string formattedValue = string.Empty; Guid guid = value.AsGuid(); if ( !guid.IsEmpty() ) { var workflowType = GetContextWorkflowType(); if ( workflowType != null ) { formattedValue = workflowType.ActivityTypes .Where( a => a.Guid.Equals( guid ) ) .Select( a => a.Name ) .FirstOrDefault(); } if ( string.IsNullOrWhiteSpace( formattedValue ) ) { formattedValue = new WorkflowActivityTypeService( new RockContext() ).Queryable() .Where( a => a.Guid.Equals( guid ) ) .Select( a => a.Name ) .FirstOrDefault(); } } return base.FormatValue( parentControl, formattedValue, null, condensed ); }
/// <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>(); Guid guid = GetAttributeValue( action, "Activity" ).AsGuid(); if ( guid.IsEmpty() ) { action.AddLogEntry( "Invalid Activity Property", true ); return false; } var workflow = action.Activity.Workflow; var activityType = new WorkflowActivityTypeService( rockContext ).Queryable() .Where( a => a.Guid.Equals( guid ) ).FirstOrDefault(); if ( activityType == null ) { action.AddLogEntry( "Invalid Activity Property", true ); return false; } WorkflowActivity.Activate( activityType, workflow ); action.AddLogEntry( string.Format( "Activated new '{0}' activity", activityType.ToString() ) ); return true; }
/// <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 workflowActivityGuid = action.GetWorklowAttributeValue( GetAttributeValue( action, "Activity" ).AsGuid() ).AsGuid(); if ( workflowActivityGuid.IsEmpty() ) { action.AddLogEntry( "Invalid Activity Property", true ); return false; } var attributeKey = GetAttributeValue( action, "WorkflowAttributeKey", true ); var attributeValue = GetAttributeValue( action, "WorkflowAttributeValue", true ); if ( string.IsNullOrWhiteSpace( attributeKey) || string.IsNullOrWhiteSpace(attributeValue) ) { action.AddLogEntry( "Invalid Workflow Property", true ); return false; } var activityType = new WorkflowActivityTypeService( rockContext ).Queryable() .Where( a => a.Guid.Equals( workflowActivityGuid ) ).FirstOrDefault(); if ( activityType == null ) { action.AddLogEntry( "Invalid Activity Property", true ); return false; } var entityType = EntityTypeCache.Read( typeof( Rock.Model.Workflow ) ); var workflowIds = new AttributeValueService( rockContext ) .Queryable() .AsNoTracking() .Where( a => a.Attribute.Key == attributeKey && a.Value == attributeValue && a.Attribute.EntityTypeId == entityType.Id ) .Select(a => a.EntityId); var workflows = new WorkflowService( rockContext ) .Queryable() //.AsNoTracking() .Where( w => w.WorkflowType.ActivityTypes.Any( a => a.Guid == activityType.Guid ) && workflowIds.Contains(w.Id) ) .ToList(); foreach (var workflow in workflows ) { WorkflowActivity.Activate( activityType, workflow ); action.AddLogEntry( string.Format( "Activated new '{0}' activity in {1} {2}", activityType.ToString(), workflow.TypeName, workflow.WorkflowId ) ); } return true; }
/// <summary> /// Creates the control(s) necessary for prompting user for a new value /// </summary> /// <param name="configurationValues">The configuration values.</param> /// <param name="id"></param> /// <returns> /// The control /// </returns> public override Control EditControl( Dictionary<string, ConfigurationValue> configurationValues, string id ) { ListControl editControl; editControl = new Rock.Web.UI.Controls.RockDropDownList { ID = id }; editControl.Items.Add( new ListItem() ); IEnumerable<WorkflowActivityType> activityTypes = null; var workflowType = GetContextWorkflowType(); if ( workflowType != null ) { activityTypes = workflowType.ActivityTypes; } if (activityTypes == null && configurationValues != null && configurationValues.ContainsKey( WORKFLOW_TYPE_KEY ) ) { Guid workflowTypeGuid = configurationValues[WORKFLOW_TYPE_KEY].Value.AsGuid(); if ( !workflowTypeGuid.IsEmpty() ) { activityTypes = new WorkflowActivityTypeService( new RockContext() ) .Queryable() .Where( t => t.WorkflowType.Guid.Equals( workflowTypeGuid ) ); } } if (activityTypes != null && activityTypes.Any() ) { foreach ( var activityType in activityTypes.OrderBy( a => a.Order ) ) { editControl.Items.Add( new ListItem( activityType.Name ?? "[New Activity]", activityType.Guid.ToString().ToUpper() ) ); } } return editControl; }
/// <summary> /// Restores the view-state information from a previous user control request that was saved by the <see cref="M:System.Web.UI.UserControl.SaveViewState" /> method. /// </summary> /// <param name="savedState">An <see cref="T:System.Object" /> that represents the user control state to be restored.</param> protected override void LoadViewState( object savedState ) { base.LoadViewState( savedState ); string json = ViewState["Workflow"] as string; if ( string.IsNullOrWhiteSpace( json ) ) { Workflow = new Workflow(); } else { Workflow = JsonConvert.DeserializeObject<Workflow>( json ); } // Wire up type objects since they are not serialized var rockContext = new RockContext(); var workflowTypeService = new WorkflowTypeService( rockContext ); var activityTypeService = new WorkflowActivityTypeService( rockContext ); var actionTypeService = new WorkflowActionTypeService( rockContext ); Workflow.WorkflowType = workflowTypeService.Get( Workflow.WorkflowTypeId ); foreach(var activity in Workflow.Activities) { activity.ActivityType = activityTypeService.Get( activity.ActivityTypeId ); foreach(var action in activity.Actions) { action.ActionType = actionTypeService.Get( action.ActionTypeId ); } } // Add new log entries since they are not serialized LogEntries = ViewState["LogEntries"] as List<string>; if ( LogEntries == null ) { LogEntries = new List<string>(); } LogEntries.ForEach( l => Workflow.AddLogEntry( l ) ); ExpandedActivities = ViewState["ExpandedActivities"] as List<Guid>; if (ExpandedActivities == null) { ExpandedActivities = new List<Guid>(); } }
protected void ddlActivateNewActivity_SelectedIndexChanged( object sender, EventArgs e ) { ParseControls(); int? activityTypeId = ddlActivateNewActivity.SelectedValueAsId(); if (activityTypeId.HasValue) { var activityType = new WorkflowActivityTypeService(new RockContext()).Get(activityTypeId.Value); if (activityType != null) { var activity = WorkflowActivity.Activate( activityType, Workflow ); activity.ActivityTypeId = activity.ActivityType.Id; activity.Guid = Guid.NewGuid(); foreach( var action in activity.Actions) { action.ActionTypeId = action.ActionType.Id; action.Guid = Guid.NewGuid(); } Workflow.AddLogEntry( string.Format( "Manually Activated new '{0}' activity", activityType.ToString() ) ); ExpandedActivities.Add( activity.Guid ); BuildControls( true, activity.Guid ); } } ddlActivateNewActivity.SelectedIndex = 0; }
/// <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(); WorkflowType workflowType; WorkflowTypeService service = new WorkflowTypeService( rockContext ); int workflowTypeId = int.Parse( hfWorkflowTypeId.Value ); if ( workflowTypeId == 0 ) { workflowType = new WorkflowType(); workflowType.IsSystem = false; workflowType.Name = string.Empty; } else { workflowType = service.Get( workflowTypeId ); } workflowType.Name = tbName.Text; workflowType.Description = tbDescription.Text; workflowType.CategoryId = cpCategory.SelectedValueAsInt(); workflowType.Order = 0; workflowType.WorkTerm = tbWorkTerm.Text; if ( !string.IsNullOrWhiteSpace( tbProcessingInterval.Text ) ) { workflowType.ProcessingIntervalSeconds = int.Parse( tbProcessingInterval.Text ); } workflowType.IsPersisted = cbIsPersisted.Checked; workflowType.LoggingLevel = ddlLoggingLevel.SelectedValueAsEnum<WorkflowLoggingLevel>(); workflowType.IsActive = cbIsActive.Checked; if ( !Page.IsValid ) { return; } if ( !workflowType.IsValid ) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction( () => { // Save the entity field changes to workflow type if ( workflowType.Id.Equals( 0 ) ) { service.Add( workflowType ); } rockContext.SaveChanges(); // Save the attributes SaveAttributes( new Workflow().TypeId, "WorkflowTypeId", workflowType.Id.ToString(), AttributesState, rockContext ); WorkflowActivityTypeService workflowActivityTypeService = new WorkflowActivityTypeService( 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<WorkflowActivityEditor> workflowActivityTypeEditorList = phActivities.Controls.OfType<WorkflowActivityEditor>().ToList(); List<WorkflowActionType> actionTypesInDB = workflowActionTypeService.Queryable().Where( a => a.ActivityType.WorkflowTypeId.Equals( workflowType.Id ) ).ToList(); List<WorkflowActionType> actionTypesInUI = new List<WorkflowActionType>(); foreach ( WorkflowActivityEditor workflowActivityTypeEditor in workflowActivityTypeEditorList ) { foreach ( WorkflowActionEditor editor in workflowActivityTypeEditor.Controls.OfType<WorkflowActionEditor>() ) { actionTypesInUI.Add( editor.WorkflowActionType ); } } var deletedActionTypes = from actionType in actionTypesInDB where !actionTypesInUI.Select( u => u.Guid ).Contains( actionType.Guid ) select actionType; deletedActionTypes.ToList().ForEach( actionType => { if (actionType.WorkflowForm != null) { workflowFormService.Delete( actionType.WorkflowForm ); } 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(); List<WorkflowActivityType> activityTypesInUI = workflowActivityTypeEditorList.Select( a => a.GetWorkflowActivityType() ).ToList(); var deletedActivityTypes = from activityType in activityTypesInDB where !activityTypesInUI.Select( u => u.Guid ).Contains( activityType.Guid ) select activityType; deletedActivityTypes.ToList().ForEach( activityType => { workflowActivityTypeService.Delete( activityType ); } ); rockContext.SaveChanges(); // add or update WorkflowActivityTypes(and Actions) that are assigned in the UI int workflowActivityTypeOrder = 0; foreach ( WorkflowActivityEditor workflowActivityTypeEditor in workflowActivityTypeEditorList ) { // Add or Update the activity type WorkflowActivityType editorWorkflowActivityType = workflowActivityTypeEditor.GetWorkflowActivityType(); WorkflowActivityType workflowActivityType = workflowType.ActivityTypes.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActivityType.Guid ) ); if ( workflowActivityType == null ) { workflowActivityType = new WorkflowActivityType(); workflowType.ActivityTypes.Add( workflowActivityType ); } workflowActivityType.IsActive = editorWorkflowActivityType.IsActive; workflowActivityType.Name = editorWorkflowActivityType.Name; workflowActivityType.Description = editorWorkflowActivityType.Description; workflowActivityType.IsActivatedWithWorkflow = editorWorkflowActivityType.IsActivatedWithWorkflow; workflowActivityType.Order = workflowActivityTypeOrder++; int workflowActionTypeOrder = 0; foreach ( WorkflowActionEditor workflowActionTypeEditor in workflowActivityTypeEditor.Controls.OfType<WorkflowActionEditor>() ) { WorkflowActionType editorWorkflowActionType = workflowActionTypeEditor.WorkflowActionType; WorkflowActionType workflowActionType = workflowActivityType.ActionTypes.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActionType.Guid ) ); if ( workflowActionType == null ) { // New action workflowActionType = new WorkflowActionType(); workflowActivityType.ActionTypes.Add( workflowActionType ); } 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.Header = editorWorkflowActionType.WorkflowForm.Header; workflowActionType.WorkflowForm.Footer = editorWorkflowActionType.WorkflowForm.Footer; workflowActionType.WorkflowForm.InactiveMessage = editorWorkflowActionType.WorkflowForm.InactiveMessage; workflowActionType.WorkflowForm.Actions = editorWorkflowActionType.WorkflowForm.Actions; 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) ) ) { workflowFormAttributeService.Delete(formAttribute); } int attributeOrder = 0; foreach ( var editorAttribute in editorWorkflowActionType.WorkflowForm.FormAttributes.OrderBy( a => a.Order ) ) { int attributeId = AttributeCache.Read( editorAttribute.Attribute.Guid ).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; } } } } 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 ) { 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 ) { 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(); } workflowType.IsActive = cbIsActive.Checked; workflowType.Name = tbName.Text; workflowType.Description = tbDescription.Text; workflowType.CategoryId = cpCategory.SelectedValueAsInt(); workflowType.Order = 0; workflowType.WorkTerm = tbWorkTerm.Text; workflowType.ProcessingIntervalSeconds = tbProcessingInterval.Text.AsIntegerOrNull(); workflowType.IsPersisted = cbIsPersisted.Checked; workflowType.LoggingLevel = ddlLoggingLevel.SelectedValueAsEnum<WorkflowLoggingLevel>(); workflowType.IconCssClass = tbIconCssClass.Text; 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 ); 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; deletedActionTypes.ToList().ForEach( actionType => { if ( actionType.WorkflowForm != null ) { workflowFormService.Delete( actionType.WorkflowForm ); } 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; deletedActivityTypes.ToList().ForEach( activityType => { 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 ); } 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> /// Updates the email status. /// </summary> /// <param name="actionGuid">The action unique identifier.</param> /// <param name="status">The status.</param> /// <param name="emailEventType">Type of the email event.</param> /// <param name="rockContext">The rock context.</param> /// <param name="ProcessWorkflow">if set to <c>true</c> [process workflow].</param> public static void UpdateEmailStatus( Guid actionGuid, string status, string emailEventType, RockContext rockContext, bool ProcessWorkflow ) { var action = new WorkflowActionService( rockContext ).Get( actionGuid ); if ( action != null && action.Activity != null ) { string attrKey = action.ActionType.Guid.ToString() + "_EmailStatus"; action.Activity.LoadAttributes( rockContext ); string currentStatus = action.Activity.GetAttributeValue( attrKey ); // Sometimes Clicked events are reported before opens. If this is the case, do not update the status from clicked to opened. bool updateStatus = true; if ( status == OPENED_STATUS && currentStatus == CLICKED_STATUS ) { updateStatus = false; } if ( !string.IsNullOrWhiteSpace( emailEventType ) && ( emailEventType != status || !updateStatus ) ) { action.AddLogEntry( string.Format( "Email Event Type: {0}", emailEventType ), true ); } if ( updateStatus ) { action.Activity.SetAttributeValue( attrKey, status ); action.Activity.SaveAttributeValues( rockContext ); action.AddLogEntry( string.Format( "Email Status Updated to '{0}'", status ), true ); } Guid? activityGuid = null; switch( status ) { case OPENED_STATUS: { activityGuid = GetActionAttributeValue( action, "OnOpenActivity" ).AsGuid(); break; } case CLICKED_STATUS: { activityGuid = GetActionAttributeValue( action, "OnClickedActivity" ).AsGuid(); break; } case FAILED_STATUS: { activityGuid = GetActionAttributeValue( action, "OnFailedActivity" ).AsGuid(); break; } } if ( activityGuid.HasValue ) { var workflow = action.Activity.Workflow; var activityType = new WorkflowActivityTypeService( rockContext ).Queryable() .Where( a => a.Guid.Equals( activityGuid.Value ) ).FirstOrDefault(); if ( workflow != null && activityType != null ) { WorkflowActivity.Activate( activityType, workflow ); action.AddLogEntry( string.Format( "Activated new '{0}' activity", activityType.ToString() ) ); if ( ProcessWorkflow ) { List<string> workflowErrors; new WorkflowService( rockContext ).Process( workflow, out workflowErrors ); } } } } }
/// <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>(); double hoursElapsed = HoursElapsed( action ); string emailStatus = EmailStatus( action ); if ( hoursElapsed <= 0 ) { SendEmail( rockContext, action ); } else { var timedOut = false; var activityTypeService = new WorkflowActivityTypeService( rockContext ); WorkflowActivityType unopenedActivityType = null; int? unopenedTimeout = null; Guid? guid = GetAttributeValue( action, "UnopenedTimeoutActivity" ).AsGuidOrNull(); if ( guid.HasValue ) { unopenedActivityType = activityTypeService.Queryable().Where( a => a.Guid.Equals( guid.Value ) ).FirstOrDefault(); unopenedTimeout = GetAttributeValue( action, "UnopenedTimeoutLength" ).AsIntegerOrNull(); if ( emailStatus != OPENED_STATUS && emailStatus != CLICKED_STATUS && unopenedActivityType != null && unopenedTimeout.HasValue && unopenedTimeout.Value < hoursElapsed ) { action.AddLogEntry( "Unopened Timeout Occurred", true ); WorkflowActivity.Activate( unopenedActivityType, action.Activity.Workflow, rockContext ); timedOut = true; } } WorkflowActivityType noActionActivityType = null; int? noActionTimeout = null; guid = GetAttributeValue( action, "NoActionTimeoutActivity" ).AsGuidOrNull(); if ( guid.HasValue ) { noActionActivityType = activityTypeService.Queryable().Where( a => a.Guid.Equals( guid.Value ) ).FirstOrDefault(); noActionTimeout = GetAttributeValue( action, "NoActionTimeoutLength" ).AsIntegerOrNull(); if ( emailStatus != CLICKED_STATUS && noActionActivityType != null && noActionTimeout.HasValue && noActionTimeout.Value < hoursElapsed ) { action.AddLogEntry( "No Action Timeout Occurred", true ); WorkflowActivity.Activate( noActionActivityType, action.Activity.Workflow, rockContext ); timedOut = true; } } if ( timedOut ) { UpdateEmailStatus( action.Guid, TIMEOUT_STATUS, string.Empty, rockContext, false ); return true; } } return false; }
/// <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 ) { WorkflowType workflowType; WorkflowTypeService service = new WorkflowTypeService(); int workflowTypeId = int.Parse( hfWorkflowTypeId.Value ); if ( workflowTypeId == 0 ) { workflowType = new WorkflowType(); workflowType.IsSystem = false; workflowType.Name = string.Empty; } else { workflowType = service.Get( workflowTypeId ); } workflowType.Name = tbName.Text; workflowType.Description = tbDescription.Text; workflowType.CategoryId = cpCategory.SelectedValueAsInt(); workflowType.Order = int.Parse( tbOrder.Text ); workflowType.WorkTerm = tbWorkTerm.Text; if ( !string.IsNullOrWhiteSpace( tbProcessingInterval.Text ) ) { workflowType.ProcessingIntervalSeconds = int.Parse( tbProcessingInterval.Text ); } workflowType.IsPersisted = cbIsPersisted.Checked; workflowType.LoggingLevel = ddlLoggingLevel.SelectedValueAsEnum<WorkflowLoggingLevel>(); workflowType.IsActive = cbIsActive.Checked; if ( !Page.IsValid ) { return; } if ( !workflowType.IsValid ) { // Controls will render the error messages return; } RockTransactionScope.WrapTransaction( () => { List<WorkflowActivityTypeEditor> workflowActivityTypeEditorList = phActivities.Controls.OfType<WorkflowActivityTypeEditor>().ToList(); // delete WorkflowActionTypes that aren't assigned in the UI anymore WorkflowActionTypeService workflowActionTypeService = new WorkflowActionTypeService(); List<WorkflowActionType> actionTypesInDB = workflowActionTypeService.Queryable().Where( a => a.ActivityType.WorkflowTypeId.Equals( workflowType.Id ) ).ToList(); List<WorkflowActionType> actionTypesInUI = new List<WorkflowActionType>(); foreach ( WorkflowActivityTypeEditor workflowActivityTypeEditor in workflowActivityTypeEditorList ) { foreach ( WorkflowActionTypeEditor editor in workflowActivityTypeEditor.Controls.OfType<WorkflowActionTypeEditor>() ) { actionTypesInUI.Add( editor.WorkflowActionType ); } } var deletedActionTypes = from actionType in actionTypesInDB where !actionTypesInUI.Select( u => u.Guid ).Contains( actionType.Guid ) select actionType; deletedActionTypes.ToList().ForEach( actionType => { workflowActionTypeService.Delete( actionType, CurrentPersonId ); workflowActionTypeService.Save( actionType, CurrentPersonId ); } ); // delete WorkflowActivityTypes that aren't assigned in the UI anymore WorkflowActivityTypeService workflowActivityTypeService = new WorkflowActivityTypeService(); List<WorkflowActivityType> activityTypesInDB = workflowActivityTypeService.Queryable().Where( a => a.WorkflowTypeId.Equals( workflowType.Id ) ).ToList(); List<WorkflowActivityType> activityTypesInUI = workflowActivityTypeEditorList.Select( a => a.GetWorkflowActivityType() ).ToList(); var deletedActivityTypes = from activityType in activityTypesInDB where !activityTypesInUI.Select( u => u.Guid ).Contains( activityType.Guid ) select activityType; deletedActivityTypes.ToList().ForEach( activityType => { workflowActivityTypeService.Delete( activityType, CurrentPersonId ); workflowActivityTypeService.Save( activityType, CurrentPersonId ); } ); // add or update WorkflowActivityTypes(and Actions) that are assigned in the UI int workflowActivityTypeOrder = 0; foreach ( WorkflowActivityTypeEditor workflowActivityTypeEditor in workflowActivityTypeEditorList ) { WorkflowActivityType editorWorkflowActivityType = workflowActivityTypeEditor.GetWorkflowActivityType(); WorkflowActivityType workflowActivityType = workflowType.ActivityTypes.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActivityType.Guid ) ); if ( workflowActivityType == null ) { workflowActivityType = editorWorkflowActivityType; workflowType.ActivityTypes.Add( workflowActivityType ); } else { workflowActivityType.Name = editorWorkflowActivityType.Name; workflowActivityType.Description = editorWorkflowActivityType.Description; workflowActivityType.IsActive = editorWorkflowActivityType.IsActive; workflowActivityType.IsActivatedWithWorkflow = editorWorkflowActivityType.IsActivatedWithWorkflow; } workflowActivityType.Order = workflowActivityTypeOrder++; int workflowActionTypeOrder = 0; foreach ( WorkflowActionTypeEditor workflowActionTypeEditor in workflowActivityTypeEditor.Controls.OfType<WorkflowActionTypeEditor>() ) { WorkflowActionType editorWorkflowActionType = workflowActionTypeEditor.WorkflowActionType; WorkflowActionType workflowActionType = workflowActivityType.ActionTypes.FirstOrDefault( a => a.Guid.Equals( editorWorkflowActionType.Guid ) ); if ( workflowActionType == null ) { workflowActionType = editorWorkflowActionType; workflowActivityType.ActionTypes.Add( workflowActionType ); } else { 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 ( workflowType.Id.Equals( 0 ) ) { service.Add( workflowType, CurrentPersonId ); } service.Save( workflowType, CurrentPersonId ); foreach ( var activityType in workflowType.ActivityTypes ) { foreach ( var workflowActionType in activityType.ActionTypes ) { Rock.Attribute.Helper.SaveAttributeValues( workflowActionType, CurrentPersonId ); } } } ); var qryParams = new Dictionary<string, string>(); qryParams["workflowTypeId"] = workflowType.Id.ToString(); NavigateToPage( RockPage.Guid, qryParams ); }