/// <summary> /// Job that will close workflows. /// /// Called by the <see cref="IScheduler" /> when a /// <see cref="ITrigger" /> fires that is associated with /// the <see cref="IJob" />. /// </summary> public virtual void Execute( IJobExecutionContext context ) { JobDataMap dataMap = context.JobDetail.JobDataMap; // run a SQL query to do something var workflowTypeGuids = dataMap.GetString( "WorkflowTypes" ).Split(',').Select(Guid.Parse).ToList(); int? expirationAge = dataMap.GetString( "ExpirationAge" ).AsIntegerOrNull(); string closeStatus = dataMap.GetString( "CloseStatus" ); RockContext rockContext = new RockContext(); var workflowService = new WorkflowService( rockContext ); var qry = workflowService.Queryable() .Where( w => workflowTypeGuids.Contains( w.WorkflowType.Guid ) ); if ( expirationAge.HasValue ) { var expirationDate = RockDateTime.Now.AddMinutes( expirationAge.Value ); qry = qry.Where(w => w.CreatedDateTime <= expirationDate ); } var workflows = qry.ToList(); foreach(var workflow in workflows ) { workflow.MarkComplete(); workflow.Status = closeStatus; rockContext.SaveChanges(); } }
/// <summary> /// Called by the <see cref="IScheduler" /> when a <see cref="ITrigger" /> /// fires that is associated with the <see cref="IJob" />. /// </summary> /// <param name="context">The execution context.</param> /// <remarks> /// The implementation may wish to set a result object on the /// JobExecutionContext before this method exits. The result itself /// is meaningless to Quartz, but may be informative to /// <see cref="IJobListener" />s or /// <see cref="ITriggerListener" />s that are watching the job's /// execution. /// </remarks> public virtual void Execute( IJobExecutionContext context ) { foreach ( var workflowId in new WorkflowService( new RockContext() ).GetActive().Select(a => a.Id).ToList() ) { // create a new rockContext and service for every workflow to prevent a build-up of Context.ChangeTracker.Entries() var rockContext = new RockContext(); var workflowService = new WorkflowService( rockContext ); var workflow = workflowService.Queryable( "WorkflowType" ).FirstOrDefault( a => a.Id == workflowId ); if ( workflow != null ) { if ( !workflow.LastProcessedDateTime.HasValue || RockDateTime.Now.Subtract( workflow.LastProcessedDateTime.Value ).TotalSeconds >= ( workflow.WorkflowType.ProcessingIntervalSeconds ?? 0 ) ) { var errorMessages = new List<string>(); workflowService.Process( workflow, out errorMessages ); } } } }
/// <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> /// Binds the grid. /// </summary> private void BindGrid() { if ( _workflowType != null ) { pnlWorkflowList.Visible = true; if ( _workflowType != null ) { var rockContext = new RockContext(); var workflowService = new WorkflowService( rockContext ); var qry = workflowService .Queryable( "Activities.ActivityType,InitiatorPersonAlias.Person" ).AsNoTracking() .Where( w => w.WorkflowTypeId.Equals( _workflowType.Id ) ); // Activated Date Range Filter if ( drpActivated.LowerValue.HasValue ) { qry = qry.Where( w => w.ActivatedDateTime >= drpActivated.LowerValue.Value ); } if ( drpActivated.UpperValue.HasValue ) { DateTime upperDate = drpActivated.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( w => w.ActivatedDateTime.Value < upperDate ); } // State Filter List<string> states = cblState.SelectedValues; if ( states.Count == 1 ) // Don't filter if none or both options are selected { if ( states[0] == "Active" ) { qry = qry.Where( w => !w.CompletedDateTime.HasValue ); } else { qry = qry.Where( w => w.CompletedDateTime.HasValue ); } } // Completed Date Range Filter if ( drpCompleted.LowerValue.HasValue ) { qry = qry.Where( w => w.CompletedDateTime.HasValue && w.CompletedDateTime.Value >= drpCompleted.LowerValue.Value ); } if ( drpCompleted.UpperValue.HasValue ) { DateTime upperDate = drpCompleted.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( w => w.CompletedDateTime.HasValue && w.CompletedDateTime.Value < upperDate ); } string name = tbName.Text; if ( !string.IsNullOrWhiteSpace( name ) ) { qry = qry.Where( w => w.Name.StartsWith( name ) ); } int? personId = ppInitiator.SelectedValue; if ( personId.HasValue ) { qry = qry.Where( w => w.InitiatorPersonAlias.PersonId == personId.Value ); } string status = tbStatus.Text; if ( !string.IsNullOrWhiteSpace( status ) ) { qry = qry.Where( w => w.Status.StartsWith( status ) ); } // Filter query by any configured attribute filters if ( AvailableAttributes != null && AvailableAttributes.Any() ) { var attributeValueService = new AttributeValueService( rockContext ); var parameterExpression = attributeValueService.ParameterExpression; foreach ( var attribute in AvailableAttributes ) { var filterControl = phAttributeFilters.FindControl( "filter_" + attribute.Id.ToString() ); if ( filterControl != null ) { var filterValues = attribute.FieldType.Field.GetFilterValues( filterControl, attribute.QualifierValues, Rock.Reporting.FilterMode.SimpleFilter ); var expression = attribute.FieldType.Field.AttributeFilterExpression( attribute.QualifierValues, filterValues, parameterExpression ); if ( expression != null ) { var attributeValues = attributeValueService .Queryable() .Where( v => v.Attribute.Id == attribute.Id ); attributeValues = attributeValues.Where( parameterExpression, expression, null ); qry = qry.Where( w => attributeValues.Select( v => v.EntityId ).Contains( w.Id ) ); } } } } IQueryable<Workflow> workflows = null; var sortProperty = gWorkflows.SortProperty; if ( sortProperty != null ) { if ( sortProperty.Property == "Initiator" ) { if ( sortProperty.Direction == SortDirection.Ascending ) { workflows = qry .OrderBy( w => w.InitiatorPersonAlias.Person.LastName ) .ThenBy( w => w.InitiatorPersonAlias.Person.NickName ); } else { workflows = qry .OrderByDescending( w => w.InitiatorPersonAlias.Person.LastName ) .ThenByDescending( w => w.InitiatorPersonAlias.Person.NickName ); } } else { workflows = qry.Sort( sortProperty ); } } else { workflows = qry.OrderByDescending( s => s.CreatedDateTime ); } // Since we're not binding to actual workflow list, but are using AttributeField columns, // we need to save the workflows into the grid's object list var workflowObjectQry = workflows; if ( gWorkflows.AllowPaging ) { workflowObjectQry = workflowObjectQry.Skip( gWorkflows.PageIndex * gWorkflows.PageSize ).Take( gWorkflows.PageSize ); } gWorkflows.ObjectList = workflowObjectQry.ToList().ToDictionary( k => k.Id.ToString(), v => v as object ); gWorkflows.EntityTypeId = EntityTypeCache.Read<Workflow>().Id; var qryGrid = workflows.Select( w => new { w.Id, w.Name, Initiator = w.InitiatorPersonAlias.Person, Activities = w.Activities.Where( a => a.ActivatedDateTime.HasValue && !a.CompletedDateTime.HasValue ).OrderBy( a => a.ActivityType.Order ).Select( a => a.ActivityType.Name ), w.CreatedDateTime, Status = w.Status, IsCompleted = w.CompletedDateTime.HasValue } ); gWorkflows.SetLinqDataSource( qryGrid ); gWorkflows.DataBind(); } else { pnlWorkflowList.Visible = false; } } }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { WorkflowService workflowService = new WorkflowService(); SortProperty sortProperty = gWorkflows.SortProperty; var qry = workflowService.Queryable(); WorkflowType workflowType = this.ContextEntity<WorkflowType>(); if ( workflowType == null ) { pnlWorkflowList.Visible = false; return; } // if this isn't currently a persisted workflow type, and there are no records, hide the panel if ( !workflowType.IsPersisted ) { if ( qry.Count() == 0 ) { pnlWorkflowList.Visible = false; return; } } if (!string.IsNullOrWhiteSpace(workflowType.WorkTerm)) { gWorkflows.RowItemText = workflowType.WorkTerm; lGridTitle.Text = workflowType.WorkTerm.Pluralize(); } AttributeService attributeService = new AttributeService(); // add attributes with IsGridColumn to grid string qualifierValue = workflowType.Id.ToString(); var qryWorkflowTypeAttributes = attributeService.GetByEntityTypeId( new Workflow().TypeId ).AsQueryable() .Where( a => a.EntityTypeQualifierColumn.Equals( "WorkflowTypeId", StringComparison.OrdinalIgnoreCase ) && a.EntityTypeQualifierValue.Equals( qualifierValue ) ); qryWorkflowTypeAttributes = qryWorkflowTypeAttributes.Where( a => a.IsGridColumn ); List<Attribute> gridItems = qryWorkflowTypeAttributes.ToList(); foreach ( var item in gWorkflows.Columns.OfType<AttributeField>().ToList() ) { gWorkflows.Columns.Remove( item ); } foreach ( var item in gridItems.OrderBy( a => a.Order ).ThenBy( a => a.Name ) ) { string dataFieldExpression = item.Key; bool columnExists = gWorkflows.Columns.OfType<AttributeField>().FirstOrDefault( a => a.DataField.Equals( dataFieldExpression ) ) != null; if ( !columnExists ) { AttributeField boundField = new AttributeField(); boundField.DataField = dataFieldExpression; boundField.HeaderText = item.Name; boundField.SortExpression = string.Empty; int insertPos = gWorkflows.Columns.IndexOf( gWorkflows.Columns.OfType<DeleteField>().First() ); gWorkflows.Columns.Insert( insertPos, boundField ); } } pnlWorkflowList.Visible = true; qry = qry.Where( a => a.WorkflowTypeId.Equals( workflowType.Id ) ); if ( sortProperty != null ) { gWorkflows.DataSource = qry.Sort( sortProperty ).ToList(); } else { gWorkflows.DataSource = qry.OrderBy( s => s.Name ).ToList(); } gWorkflows.DataBind(); }
/// <summary> /// Called by the <see cref="IScheduler" /> when a <see cref="ITrigger" /> /// fires that is associated with the <see cref="IJob" />. /// </summary> /// <param name="context">The execution context.</param> /// <remarks> /// The implementation may wish to set a result object on the /// JobExecutionContext before this method exits. The result itself /// is meaningless to Quartz, but may be informative to /// <see cref="IJobListener" />s or /// <see cref="ITriggerListener" />s that are watching the job's /// execution. /// </remarks> public virtual void Execute( IJobExecutionContext context ) { int workflowsProcessed = 0; int workflowErrors = 0; int workflowExceptions = 0; var ProcessingErrors = new List<string>(); var exceptionMsgs = new List<string>(); foreach ( var workflowId in new WorkflowService( new RockContext() ) .GetActive() .Select( w => w.Id ) .ToList() ) { try { // create a new rockContext and service for every workflow to prevent a build-up of Context.ChangeTracker.Entries() var rockContext = new RockContext(); var workflowService = new WorkflowService( rockContext ); var workflow = workflowService.Queryable( "WorkflowType" ).FirstOrDefault( a => a.Id == workflowId ); if ( workflow != null ) { try { if ( !workflow.LastProcessedDateTime.HasValue || RockDateTime.Now.Subtract( workflow.LastProcessedDateTime.Value ).TotalSeconds >= ( workflow.WorkflowType.ProcessingIntervalSeconds ?? 0 ) ) { var errorMessages = new List<string>(); var processed = workflowService.Process( workflow, out errorMessages ); if ( processed ) { workflowsProcessed++; } else { workflowErrors++; ProcessingErrors.Add( string.Format( "{0} [{1}] - {2} [{3}]: {4}", workflow.WorkflowType.Name, workflow.WorkflowTypeId, workflow.Name, workflow.Id, errorMessages.AsDelimited( ", " ) ) ); } } } catch ( Exception ex ) { string workflowDetails = string.Format( "{0} [{1}] - {2} [{3}]", workflow.WorkflowType.Name, workflow.WorkflowTypeId, workflow.Name, workflow.Id ); exceptionMsgs.Add( workflowDetails + ": " + ex.Message ); throw new Exception( "Exception occurred processing workflow: " + workflowDetails, ex ); } } } catch ( Exception ex ) { ExceptionLogService.LogException( ex, null ); workflowExceptions++; } } var resultMsg = new StringBuilder(); resultMsg.AppendFormat( "{0} workflows processed", workflowsProcessed ); if ( workflowErrors > 0 ) { resultMsg.AppendFormat( ", {0} workflows reported an error", workflowErrors ); } if ( workflowExceptions > 0 ) { resultMsg.AppendFormat( ", {0} workflows caused an exception", workflowExceptions ); } if ( ProcessingErrors.Any() ) { resultMsg.Append( Environment.NewLine + ProcessingErrors.AsDelimited( Environment.NewLine ) ); } if ( exceptionMsgs.Any() ) { throw new Exception( "One or more exceptions occurred processing workflows..." + Environment.NewLine + exceptionMsgs.AsDelimited( Environment.NewLine ) ); } context.Result = resultMsg.ToString(); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { if ( _workflowType != null ) { pnlWorkflowList.Visible = true; var rockContext = new RockContext(); var workflowService = new WorkflowService( rockContext ); var qry = workflowService.Queryable( "Activities.ActivityType,InitiatorPersonAlias.Person" ) .Where( w => w.WorkflowTypeId.Equals( _workflowType.Id ) ); // Activated Date Range Filter var drp = new DateRangePicker(); drp.DelimitedValues = gfWorkflows.GetUserPreference( "Activated" ); if ( drp.LowerValue.HasValue ) { qry = qry.Where( w => w.ActivatedDateTime >= drp.LowerValue.Value ); } if ( drp.UpperValue.HasValue ) { DateTime upperDate = drp.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( w => w.ActivatedDateTime.Value < upperDate ); } // State Filter string state = gfWorkflows.GetUserPreference( "State" ); if (!string.IsNullOrWhiteSpace(state)) { // somewhat of a backwards comparison to account for value of "None" if ( !state.Equals( "Active" ) ) { qry = qry.Where( w => w.CompletedDateTime.HasValue ); } if ( !state.Equals( "Completed" ) ) { qry = qry.Where( w => !w.CompletedDateTime.HasValue ); } } // Completed Date Range Filter var drp2 = new DateRangePicker(); drp2.DelimitedValues = gfWorkflows.GetUserPreference( "Completed" ); if ( drp2.LowerValue.HasValue ) { qry = qry.Where( w => w.CompletedDateTime.HasValue && w.CompletedDateTime.Value >= drp2.LowerValue.Value ); } if ( drp2.UpperValue.HasValue ) { DateTime upperDate = drp2.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( w => w.CompletedDateTime.HasValue && w.CompletedDateTime.Value < upperDate ); } string name = gfWorkflows.GetUserPreference( "Name" ); if ( !string.IsNullOrWhiteSpace( name ) ) { qry = qry.Where( w => w.Name.StartsWith( name ) ); } int? personId = gfWorkflows.GetUserPreference( "Initiator" ).AsIntegerOrNull(); if ( personId.HasValue ) { qry = qry.Where( w => w.InitiatorPersonAlias.PersonId == personId.Value ); } string status = gfWorkflows.GetUserPreference( "Status" ); if ( !string.IsNullOrWhiteSpace( status ) ) { qry = qry.Where( w => w.Status.StartsWith( status ) ); } List<Workflow> workflows = null; var sortProperty = gWorkflows.SortProperty; if ( sortProperty != null ) { if ( sortProperty.Property == "Initiator" ) { if ( sortProperty.Direction == SortDirection.Ascending ) { workflows = qry .OrderBy( w => w.InitiatorPersonAlias.Person.LastName ) .ThenBy( w => w.InitiatorPersonAlias.Person.NickName ) .ToList(); } else { workflows = qry .OrderByDescending( w => w.InitiatorPersonAlias.Person.LastName ) .ThenByDescending( w => w.InitiatorPersonAlias.Person.NickName ) .ToList(); } } else { workflows = qry.Sort( sortProperty ).ToList(); } } else { workflows = qry.OrderByDescending( s => s.CreatedDateTime ).ToList(); } // Since we're not binding to actual workflow list, but are using AttributeField columns, // we need to save the workflows into the grid's object list gWorkflows.ObjectList = new Dictionary<string, object>(); workflows.ForEach( w => gWorkflows.ObjectList.Add( w.Id.ToString(), w ) ); gWorkflows.DataSource = workflows.Select( w => new { w.Id, w.Name, Initiator = ( w.InitiatorPersonAlias != null ? w.InitiatorPersonAlias.Person.FullName : "" ), Activities = w.ActiveActivities.Select( a => a.ActivityType.Name ).ToList().AsDelimited( "<br/>" ), w.CreatedDateTime, Status = string.Format( "<span class='label label-info'>{0}</span>", w.Status ), State = ( w.CompletedDateTime.HasValue ? "<span class='label label-default'>Completed</span>" : "<span class='label label-success'>Active</span>" ) } ).ToList(); gWorkflows.DataBind(); } else { pnlWorkflowList.Visible = false; } }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { if ( _workflowType != null ) { pnlWorkflowList.Visible = true; var rockContext = new RockContext(); var workflowService = new WorkflowService( rockContext ); var qry = workflowService .Queryable( "Activities.ActivityType,InitiatorPersonAlias.Person" ).AsNoTracking() .Where( w => w.WorkflowTypeId.Equals( _workflowType.Id ) ); // Activated Date Range Filter if ( drpActivated.LowerValue.HasValue ) { qry = qry.Where( w => w.ActivatedDateTime >= drpActivated.LowerValue.Value ); } if ( drpActivated.UpperValue.HasValue ) { DateTime upperDate = drpActivated.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( w => w.ActivatedDateTime.Value < upperDate ); } // State Filter List<string> states = cblState.SelectedValues; if ( states.Count == 1 ) // Don't filter if none or both options are selected { if ( states[0] == "Active" ) { qry = qry.Where( w => !w.CompletedDateTime.HasValue ); } else { qry = qry.Where( w => w.CompletedDateTime.HasValue ); } } // Completed Date Range Filter if ( drpCompleted.LowerValue.HasValue ) { qry = qry.Where( w => w.CompletedDateTime.HasValue && w.CompletedDateTime.Value >= drpCompleted.LowerValue.Value ); } if ( drpCompleted.UpperValue.HasValue ) { DateTime upperDate = drpCompleted.UpperValue.Value.Date.AddDays( 1 ); qry = qry.Where( w => w.CompletedDateTime.HasValue && w.CompletedDateTime.Value < upperDate ); } string name = tbName.Text; if ( !string.IsNullOrWhiteSpace( name ) ) { qry = qry.Where( w => w.Name.StartsWith( name ) ); } int? personId = ppInitiator.SelectedValue; if ( personId.HasValue ) { qry = qry.Where( w => w.InitiatorPersonAlias.PersonId == personId.Value ); } string status = tbStatus.Text; if ( !string.IsNullOrWhiteSpace( status ) ) { qry = qry.Where( w => w.Status.StartsWith( status ) ); } // Filter query by any configured attribute filters if ( AvailableAttributes != null && AvailableAttributes.Any() ) { var attributeValueService = new AttributeValueService( rockContext ); var parameterExpression = attributeValueService.ParameterExpression; foreach ( var attribute in AvailableAttributes ) { var filterControl = phAttributeFilters.FindControl( "filter_" + attribute.Id.ToString() ); if ( filterControl != null ) { var filterValues = attribute.FieldType.Field.GetFilterValues( filterControl, attribute.QualifierValues ); var expression = attribute.FieldType.Field.AttributeFilterExpression( attribute.QualifierValues, filterValues, parameterExpression ); if ( expression != null ) { var attributeValues = attributeValueService .Queryable() .Where( v => v.Attribute.Id == attribute.Id ); attributeValues = attributeValues.Where( parameterExpression, expression, null ); qry = qry.Where( w => attributeValues.Select( v => v.EntityId ).Contains( w.Id ) ); } } } } List<Workflow> workflows = null; var sortProperty = gWorkflows.SortProperty; if ( sortProperty != null ) { if ( sortProperty.Property == "Initiator" ) { if ( sortProperty.Direction == SortDirection.Ascending ) { workflows = qry .OrderBy( w => w.InitiatorPersonAlias.Person.LastName ) .ThenBy( w => w.InitiatorPersonAlias.Person.NickName ) .ToList(); } else { workflows = qry .OrderByDescending( w => w.InitiatorPersonAlias.Person.LastName ) .ThenByDescending( w => w.InitiatorPersonAlias.Person.NickName ) .ToList(); } } else { workflows = qry.Sort( sortProperty ).ToList(); } } else { workflows = qry.OrderByDescending( s => s.CreatedDateTime ).ToList(); } // Since we're not binding to actual workflow list, but are using AttributeField columns, // we need to save the workflows into the grid's object list gWorkflows.ObjectList = new Dictionary<string, object>(); workflows.ForEach( w => gWorkflows.ObjectList.Add( w.Id.ToString(), w ) ); gWorkflows.DataSource = workflows.Select( w => new { w.Id, w.Name, Initiator = ( w.InitiatorPersonAlias != null ? w.InitiatorPersonAlias.Person.FullName : "" ), Activities = w.ActiveActivities.Select( a => a.ActivityType.Name ).ToList().AsDelimited( "<br/>" ), w.CreatedDateTime, Status = string.Format( "<span class='label label-info'>{0}</span>", w.Status ), State = ( w.CompletedDateTime.HasValue ? "<span class='label label-default'>Completed</span>" : "<span class='label label-success'>Active</span>" ) } ).ToList(); gWorkflows.DataBind(); } else { pnlWorkflowList.Visible = false; } }