/// <summary> /// Gets the opportunity summary HTML. /// </summary> /// <param name="opportunitySummaryId">The opportunity summary identifier.</param> /// <returns></returns> public string GetOpportunitySummaryHtml(OpportunitySummary opportunitySummary) { var template = GetAttributeValue(AttributeKey.OpportunitySummaryTemplate); var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(this.RockPage, this.CurrentPerson, new Rock.Lava.CommonMergeFieldsOptions { GetLegacyGlobalMergeFields = false }); mergeFields.Add("OpportunitySummary", opportunitySummary); string result = null; using (var rockContext = new RockContext()) { var connectionOpportunity = new ConnectionOpportunityService(rockContext).Queryable().AsNoTracking().FirstOrDefault(a => a.Id == opportunitySummary.Id); mergeFields.Add("ConnectionOpportunity", connectionOpportunity); result = template.ResolveMergeFields(mergeFields); } return(result); }
/// <summary> /// Gets the summary data. /// </summary> private void GetSummaryData() { var midnightToday = RockDateTime.Today.AddDays(1); SummaryState = new List <ConnectionTypeSummary>(); var rockContext = new RockContext(); var connectionOpportunityService = new ConnectionOpportunityService(rockContext); var followingService = new FollowingService(rockContext); var opportunityEntityTypeId = EntityTypeCache.Get <ConnectionOpportunity>().Id; var followedOpportunityIds = followingService.Queryable() .AsNoTracking() .Where(f => f.PersonAliasId == CurrentPersonAliasId && f.EntityTypeId == opportunityEntityTypeId && string.IsNullOrEmpty(f.PurposeKey)) .Select(f => f.EntityId) .ToList(); var opportunityQuery = connectionOpportunityService.Queryable() .AsNoTracking() .Where(co => co.IsActive && co.ConnectionType.IsActive); var typeFilter = GetAttributeValue(AttributeKey.ConnectionTypes).SplitDelimitedValues().AsGuidList(); if (typeFilter.Any()) { opportunityQuery = opportunityQuery.Where(o => typeFilter.Contains(o.ConnectionType.Guid)); } var selfAssignedOpportunities = new List <int>(); var isSelfAssignedOpportunitiesQueried = false; var opportunities = opportunityQuery.ToList(); // Loop through opportunities foreach (var opportunity in opportunities) { // Check to see if person can edit the opportunity because of edit rights to this block or edit rights to // the opportunity bool canEdit = UserCanEdit || opportunity.IsAuthorized(Authorization.EDIT, CurrentPerson); bool campusSpecificConnector = false; var campusIds = new List <int>(); if (CurrentPersonId.HasValue) { // Check to see if person belongs to any connector group that is not campus specific if (!canEdit) { canEdit = opportunity .ConnectionOpportunityConnectorGroups .Any(g => !g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any(m => m.PersonId == CurrentPersonId.Value)); } // If user is not yet authorized to edit the opportunity, check to see if they are a member of one of the // campus-specific connector groups for the opportunity, and note the campus if (!canEdit) { foreach (var groupCampus in opportunity .ConnectionOpportunityConnectorGroups .Where(g => g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any(m => m.PersonId == CurrentPersonId.Value))) { campusSpecificConnector = true; canEdit = true; campusIds.Add(groupCampus.CampusId.Value); } } } if (opportunity.ConnectionType.EnableRequestSecurity && !isSelfAssignedOpportunitiesQueried) { isSelfAssignedOpportunitiesQueried = true; selfAssignedOpportunities = new ConnectionRequestService(rockContext) .Queryable() .Where(a => a.ConnectorPersonAlias.PersonId == CurrentPersonId.Value) .Select(a => a.ConnectionOpportunityId) .Distinct() .ToList(); } var canView = opportunity.IsAuthorized(Authorization.VIEW, CurrentPerson) || (opportunity.ConnectionType.EnableRequestSecurity && selfAssignedOpportunities.Contains(opportunity.Id)); // Is user is authorized to view this opportunity type... if (canView) { // Check if the opportunity's type has been added to summary yet, and if not, add it var connectionTypeSummary = SummaryState.Where(c => c.Id == opportunity.ConnectionTypeId).FirstOrDefault(); if (connectionTypeSummary == null) { connectionTypeSummary = new ConnectionTypeSummary { Id = opportunity.ConnectionTypeId, Name = opportunity.ConnectionType.Name, EnableRequestSecurity = opportunity.ConnectionType.EnableRequestSecurity, ConnectionRequestDetailPageId = opportunity.ConnectionType.ConnectionRequestDetailPageId, ConnectionRequestDetailPageRouteId = opportunity.ConnectionType.ConnectionRequestDetailPageRouteId, Opportunities = new List <OpportunitySummary>(), IconMarkup = opportunity.ConnectionType.IconCssClass.IsNullOrWhiteSpace() ? string.Empty : $@"<i class=""{opportunity.ConnectionType.IconCssClass}""></i>", Order = opportunity.ConnectionType.Order }; SummaryState.Add(connectionTypeSummary); } // get list of idle requests (no activity in past X days) var connectionRequestsQry = new ConnectionRequestService(rockContext).Queryable().Where(a => a.ConnectionOpportunityId == opportunity.Id); if (cpCampusFilter.SelectedCampusId.HasValue) { connectionRequestsQry = connectionRequestsQry.Where(a => a.CampusId.HasValue && a.CampusId == cpCampusFilter.SelectedCampusId); } var currentDateTime = RockDateTime.Now; int activeRequestCount = connectionRequestsQry .Where(cr => cr.ConnectionState == ConnectionState.Active || (cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < midnightToday) ) .Count(); // only show if the opportunity is active and there are active requests if (opportunity.IsActive || (!opportunity.IsActive && activeRequestCount > 0)) { // idle count is: // (the request is active OR future follow-up who's time has come) // AND // (where the activity is more than DaysUntilRequestIdle days old OR no activity but created more than DaysUntilRequestIdle days ago) List <int> idleConnectionRequests = connectionRequestsQry .Where(cr => ( cr.ConnectionState == ConnectionState.Active || (cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < midnightToday) ) && ( (cr.ConnectionRequestActivities.Any() && cr.ConnectionRequestActivities.Max(ra => ra.CreatedDateTime) < SqlFunctions.DateAdd("day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime)) || (!cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < SqlFunctions.DateAdd("day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime)) ) ) .Select(a => a.Id).ToList(); // get list of requests that have a status that is considered critical. List <int> criticalConnectionRequests = connectionRequestsQry .Where(r => r.ConnectionStatus.IsCritical && ( r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday) ) ) .Select(a => a.Id).ToList(); // Add the opportunity var opportunitySummary = new OpportunitySummary { Id = opportunity.Id, Order = opportunity.Order, Name = opportunity.Name, IsActive = opportunity.IsActive, IconCssClass = opportunity.IconCssClass, IdleConnectionRequests = idleConnectionRequests, CriticalConnectionRequests = criticalConnectionRequests, DaysUntilRequestIdle = opportunity.ConnectionType.DaysUntilRequestIdle, CanEdit = canEdit, IsFollowed = followedOpportunityIds.Contains(opportunity.Id) }; // If the user is limited requests with specific campus(es) set the list, otherwise leave it to be null opportunitySummary.CampusSpecificConnector = campusSpecificConnector; opportunitySummary.ConnectorCampusIds = campusIds.Distinct().ToList(); connectionTypeSummary.Opportunities.Add(opportunitySummary); } } } // Get a list of all the authorized opportunity ids var allOpportunities = SummaryState.SelectMany(s => s.Opportunities).Select(o => o.Id).Distinct().ToList(); // Get all the active and past-due future followup request ids, and include the campus id and personid of connector var activeRequestsQry = new ConnectionRequestService(rockContext) .Queryable().AsNoTracking() .Where(r => allOpportunities.Contains(r.ConnectionOpportunityId) && (r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday))) .Select(r => new { r.Id, r.ConnectionOpportunityId, r.CampusId, ConnectorPersonId = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.PersonId : -1 }); if (cpCampusFilter.SelectedCampusId.HasValue) { activeRequestsQry = activeRequestsQry.Where(a => a.CampusId.HasValue && a.CampusId == cpCampusFilter.SelectedCampusId); } var activeRequests = activeRequestsQry.ToList(); // Based on the active requests, set additional properties for each opportunity foreach (var opportunity in SummaryState.SelectMany(s => s.Opportunities)) { // Get the active requests for this opportunity that user is authorized to view (based on campus connector) var opportunityRequests = activeRequests .Where(r => r.ConnectionOpportunityId == opportunity.Id && ( !opportunity.CampusSpecificConnector || (r.CampusId.HasValue && opportunity.ConnectorCampusIds.Contains(r.CampusId.Value)) )) .ToList(); // The active requests assigned to the current person opportunity.AssignedToYouConnectionRequests = opportunityRequests.Where(r => r.ConnectorPersonId == CurrentPersonId).Select(a => a.Id).ToList(); // The active requests that are unassigned opportunity.UnassignedConnectionRequests = opportunityRequests.Where(r => r.ConnectorPersonId == -1).Select(a => a.Id).ToList(); // Flag indicating if current user is connector for any of the active types opportunity.HasActiveRequestsForConnector = opportunityRequests.Any(r => r.ConnectorPersonId == CurrentPersonId); // Total number of requests for opportunity/campus/connector opportunity.TotalRequests = opportunityRequests.Count(); } //Set the Idle tooltip var connectionTypes = opportunities.Where(o => allOpportunities.Contains(o.Id)).Select(o => o.ConnectionType).Distinct().ToList(); StringBuilder sb = new StringBuilder(); if (connectionTypes.Select(t => t.DaysUntilRequestIdle).Distinct().Count() == 1) { sb.Append(String.Format("Idle (no activity in {0} days)", connectionTypes.Select(t => t.DaysUntilRequestIdle).Distinct().First())); } else { sb.Append("Idle (no activity in several days)<br/><ul class='list-unstyled'>"); foreach (var connectionType in connectionTypes) { sb.Append(String.Format("<li>{0}: {1} days</li>", connectionType.Name, connectionType.DaysUntilRequestIdle)); } sb.Append("</ul>"); } var statusTemplate = GetAttributeValue(AttributeKey.StatusTemplate); var statusMergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(this.RockPage); statusMergeFields.Add("ConnectionOpportunities", allOpportunities); statusMergeFields.Add("ConnectionTypes", connectionTypes); statusMergeFields.Add("IdleTooltip", sb.ToString().EncodeHtml()); lStatusBarContent.Text = statusTemplate.ResolveMergeFields(statusMergeFields); BindSummaryData(); }
/// <summary> /// Gets the summary data. /// </summary> private void GetSummaryData() { SummaryState = new List <ConnectionTypeSummary>(); var rockContext = new RockContext(); var opportunities = new ConnectionOpportunityService(rockContext) .Queryable().AsNoTracking(); var typeFilter = GetAttributeValue("ConnectionTypes").SplitDelimitedValues().AsGuidList(); if (typeFilter.Any()) { opportunities = opportunities.Where(o => typeFilter.Contains(o.ConnectionType.Guid)); } // Loop through opportunities foreach (var opportunity in opportunities) { // Check to see if person can view the opportunity because of admin rights to this block or admin rights to // the opportunity bool canView = UserCanAdministrate || opportunity.IsAuthorized(Authorization.ADMINISTRATE, CurrentPerson); bool campusSpecificConnector = false; var campusIds = new List <int>(); if (CurrentPersonId.HasValue) { // Check to see if person belongs to any connector group that is not campus specific if (!canView) { canView = opportunity .ConnectionOpportunityConnectorGroups .Any(g => !g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any(m => m.PersonId == CurrentPersonId.Value)); } // If user is not yet authorized to view the opportunity, check to see if they are a member of one of the // campus-specific connector groups for the opportunity, and note the campus if (!canView) { foreach (var groupCampus in opportunity .ConnectionOpportunityConnectorGroups .Where(g => g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any(m => m.PersonId == CurrentPersonId.Value))) { campusSpecificConnector = true; canView = true; campusIds.Add(groupCampus.CampusId.Value); } } } // Is user is authorized to view this opportunity type... if (canView) { // Check if the opportunity's type has been added to summary yet, and if not, add it var connectionTypeSummary = SummaryState.Where(c => c.Id == opportunity.ConnectionTypeId).FirstOrDefault(); if (connectionTypeSummary == null) { connectionTypeSummary = new ConnectionTypeSummary { Id = opportunity.ConnectionTypeId, Name = opportunity.ConnectionType.Name, Opportunities = new List <OpportunitySummary>() }; SummaryState.Add(connectionTypeSummary); } // Count number of idle requests (no activity in past X days) var connectionRequestsQry = new ConnectionRequestService(rockContext).Queryable().Where(a => a.ConnectionOpportunityId == opportunity.Id); var currentDateTime = RockDateTime.Now; int idleCount = connectionRequestsQry .Where(cr => ( cr.ConnectionState == ConnectionState.Active || (cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < _midnightToday) ) && ( (cr.ConnectionRequestActivities.Any() && cr.ConnectionRequestActivities.Max(ra => ra.CreatedDateTime) < SqlFunctions.DateAdd("day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime))) || (!cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < SqlFunctions.DateAdd("day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime)) ) .Count(); // Count the number requests that have a status that is considered critical. int criticalCount = connectionRequestsQry .Where(r => r.ConnectionStatus.IsCritical && ( r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < _midnightToday) ) ) .Count(); // Add the opportunity var opportunitySummary = new OpportunitySummary { Id = opportunity.Id, Name = opportunity.Name, IconCssClass = opportunity.IconCssClass, IdleCount = idleCount, CriticalCount = criticalCount }; // If the user is limited requests with specific campus(es) set the list, otherwise leave it to be null opportunitySummary.CampusSpecificConnector = campusSpecificConnector; opportunitySummary.ConnectorCampusIds = campusIds.Distinct().ToList(); connectionTypeSummary.Opportunities.Add(opportunitySummary); } } // Get a list of all the authorized opportunity ids var allOpportunities = SummaryState.SelectMany(s => s.Opportunities).Select(o => o.Id).Distinct().ToList(); // Get all the active and past-due future followup request ids, and include the campus id and personid of connector var midnightToday = RockDateTime.Today.AddDays(1); var activeRequests = new ConnectionRequestService(rockContext) .Queryable().AsNoTracking() .Where(r => allOpportunities.Contains(r.ConnectionOpportunityId) && (r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday))) .Select(r => new { r.ConnectionOpportunityId, r.CampusId, ConnectorPersonId = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.PersonId : -1 }) .ToList(); // Based on the active requests, set additional properties for each opportunity foreach (var opportunity in SummaryState.SelectMany(s => s.Opportunities)) { // Get the active requests for this opportunity that user is authorized to view (based on campus connector) var opportunityRequests = activeRequests .Where(r => r.ConnectionOpportunityId == opportunity.Id && ( !opportunity.CampusSpecificConnector || (r.CampusId.HasValue && opportunity.ConnectorCampusIds.Contains(r.CampusId.Value)) )) .ToList(); // The count of active requests assigned to the current person opportunity.AssignedToYou = opportunityRequests.Count(r => r.ConnectorPersonId == CurrentPersonId); // The count of active requests that are unassigned opportunity.UnassignedCount = opportunityRequests.Count(r => r.ConnectorPersonId == -1); // Flag indicating if current user is connector for any of the active types opportunity.HasActiveRequestsForConnector = opportunityRequests.Any(r => r.ConnectorPersonId == CurrentPersonId); } //Set the Idle tooltip var connectionTypes = opportunities.Where(o => allOpportunities.Contains(o.Id)).Select(o => o.ConnectionType).Distinct().ToList(); StringBuilder sb = new StringBuilder(); if (connectionTypes.Select(t => t.DaysUntilRequestIdle).Distinct().Count() == 1) { sb.Append(String.Format("Idle (no activity in {0} days)", connectionTypes.Select(t => t.DaysUntilRequestIdle).Distinct().First())); } else { sb.Append("Idle (no activity in several days)<br/><ul class='list-unstyled'>"); foreach (var connectionType in connectionTypes) { sb.Append(String.Format("<li>{0}: {1} days</li>", connectionType.Name, connectionType.DaysUntilRequestIdle)); } sb.Append("</ul>"); } var statusTemplate = this.GetAttributeValue("StatusTemplate"); var statusMergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(this.RockPage); statusMergeFields.Add("ConnectionOpportunities", allOpportunities); statusMergeFields.Add("ConnectionTypes", connectionTypes); statusMergeFields.Add("IdleTooltip", sb.ToString()); lStatusBarContent.Text = statusTemplate.ResolveMergeFields(statusMergeFields); BindSummaryData(); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { OpportunitySummary opportunitySummary = null; if (SelectedOpportunityId.HasValue) { opportunitySummary = SummaryState.SelectMany(t => t.Opportunities.Where(o => o.Id == SelectedOpportunityId.Value)).FirstOrDefault(); } if (opportunitySummary != null) { using (var rockContext = new RockContext()) { // Get queryable of all requests that belong to the selected opportunity, and user is authorized to view (based on security or connector group) var requests = new ConnectionRequestService(rockContext) .Queryable().AsNoTracking() .Where(r => r.ConnectionOpportunityId == SelectedOpportunityId.Value && ( !opportunitySummary.CampusSpecificConnector || (r.CampusId.HasValue && opportunitySummary.ConnectorCampusIds.Contains(r.CampusId.Value)) )); // Filter by Requester if (ppRequester.PersonId.HasValue) { requests = requests .Where(r => r.PersonAlias != null && r.PersonAlias.PersonId == ppRequester.PersonId.Value); } // Filter by Connector if (tglMyOpportunities.Checked) { requests = requests .Where(r => r.ConnectorPersonAlias != null && r.ConnectorPersonAlias.PersonId == CurrentPersonId); } else if (ppConnector.PersonId.HasValue) { requests = requests .Where(r => r.ConnectorPersonAlias != null && r.ConnectorPersonAlias.PersonId == ppConnector.PersonId.Value); } // Filter by State if (tglMyOpportunities.Checked) { requests = requests .Where(r => r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < _midnightToday)); } else { var states = new List <ConnectionState>(); bool futureFollowup = false; foreach (string stateValue in cblState.SelectedValues) { futureFollowup = futureFollowup || stateValue.AsInteger() == -2; var state = stateValue.ConvertToEnumOrNull <ConnectionState>(); if (state.HasValue) { states.Add(state.Value); } } if (futureFollowup || states.Any()) { requests = requests .Where(r => (futureFollowup && r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < _midnightToday) || states.Contains(r.ConnectionState)); } } // Filter by Status List <int> statusIds = cblStatus.SelectedValuesAsInt; if (statusIds.Any()) { requests = requests .Where(r => statusIds.Contains(r.ConnectionStatusId)); } // Filter by Campus List <int> campusIds = cblCampus.SelectedValuesAsInt; if (campusIds.Count > 0) { requests = requests .Where(r => r.Campus != null && campusIds.Contains(r.CampusId.Value)); } // Filter by Last Activity Note List <int> lastActivityIds = cblLastActivity.SelectedValuesAsInt; if (lastActivityIds.Any()) { requests = requests .Where(r => lastActivityIds.Contains( r.ConnectionRequestActivities.OrderByDescending(a => a.CreatedDateTime).Select(a => a.ConnectionActivityTypeId).FirstOrDefault())); } SortProperty sortProperty = gRequests.SortProperty; if (sortProperty != null) { requests = requests.Sort(sortProperty); } else { requests = requests .OrderBy(r => r.PersonAlias.Person.LastName) .ThenBy(r => r.PersonAlias.Person.NickName); } gRequests.DataSource = requests.ToList() .Select(r => new { r.Id, r.Guid, PersonId = r.PersonAlias.PersonId, Name = r.PersonAlias.Person.FullNameReversed, Campus = r.Campus, Group = r.AssignedGroup != null ? r.AssignedGroup.Name : "", Connector = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.Person.FullName : "", LastActivity = FormatActivity(r.ConnectionRequestActivities.OrderByDescending(a => a.CreatedDateTime).FirstOrDefault()), LastActivityNote = gRequests.Columns[6].Visible ? r.ConnectionRequestActivities.OrderByDescending( a => a.CreatedDateTime).Select(a => a.Note).FirstOrDefault() : "", Status = r.ConnectionStatus.Name, StatusLabel = r.ConnectionStatus.IsCritical ? "warning" : "info", ConnectionState = r.ConnectionState, StateLabel = FormatStateLabel(r.ConnectionState, r.FollowupDate) }) .ToList(); gRequests.DataBind(); lOpportunityIcon.Text = string.Format("<i class='{0}'></i>", opportunitySummary.IconCssClass); lConnectionRequest.Text = String.Format("{0} Connection Requests", opportunitySummary.Name); } } else { pnlGrid.Visible = false; } }
/// <summary> /// Gets the summary data. /// </summary> private void GetSummaryData() { SummaryState = new List<ConnectionTypeSummary>(); var rockContext = new RockContext(); var opportunities = new ConnectionOpportunityService( rockContext ) .Queryable().AsNoTracking(); var typeFilter = GetAttributeValue( "ConnectionTypes" ).SplitDelimitedValues().AsGuidList(); if ( typeFilter.Any() ) { opportunities = opportunities.Where( o => typeFilter.Contains( o.ConnectionType.Guid ) ); } // Loop through opportunities foreach ( var opportunity in opportunities ) { // Check to see if person can view the opportunity because of admin rights to this block or admin rights to // the opportunity bool canView = UserCanAdministrate || opportunity.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson ); bool campusSpecificConnector = false; var campusIds = new List<int>(); if ( CurrentPersonId.HasValue ) { // Check to see if person belongs to any connector group that is not campus specific if ( !canView ) { canView = opportunity .ConnectionOpportunityConnectorGroups .Any( g => !g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any( m => m.PersonId == CurrentPersonId.Value ) ); } // If user is not yet authorized to view the opportunity, check to see if they are a member of one of the // campus-specific connector groups for the opportunity, and note the campus if ( !canView ) { foreach ( var groupCampus in opportunity .ConnectionOpportunityConnectorGroups .Where( g => g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any( m => m.PersonId == CurrentPersonId.Value ) ) ) { campusSpecificConnector = true; canView = true; campusIds.Add( groupCampus.CampusId.Value ); } } } // Is user is authorized to view this opportunity type... if ( canView ) { // Check if the opportunity's type has been added to summary yet, and if not, add it var connectionTypeSummary = SummaryState.Where( c => c.Id == opportunity.ConnectionTypeId ).FirstOrDefault(); if ( connectionTypeSummary == null ) { connectionTypeSummary = new ConnectionTypeSummary { Id = opportunity.ConnectionTypeId, Name = opportunity.ConnectionType.Name, Opportunities = new List<OpportunitySummary>() }; SummaryState.Add( connectionTypeSummary ); } // Count number of idle requests (no activity in past X days) var connectionRequestsQry = new ConnectionRequestService( rockContext ).Queryable().Where( a => a.ConnectionOpportunityId == opportunity.Id ); var currentDateTime = RockDateTime.Now; int activeRequestCount = connectionRequestsQry .Where( cr => cr.ConnectionState == ConnectionState.Active || ( cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < _midnightToday ) ) .Count(); // only show if the oppportunity is active and there are active requests if ( opportunity.IsActive || ( !opportunity.IsActive && activeRequestCount > 0 ) ) { // idle count is: // (the request is active OR future follow-up who's time has come) // AND // (where the activity is more than DaysUntilRequestIdle days old OR no activity but created more than DaysUntilRequestIdle days ago) int idleCount = connectionRequestsQry .Where( cr => ( cr.ConnectionState == ConnectionState.Active || ( cr.ConnectionState == ConnectionState.FutureFollowUp && cr.FollowupDate.HasValue && cr.FollowupDate.Value < _midnightToday ) ) && ( ( cr.ConnectionRequestActivities.Any() && cr.ConnectionRequestActivities.Max( ra => ra.CreatedDateTime ) < SqlFunctions.DateAdd( "day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime ) ) || ( !cr.ConnectionRequestActivities.Any() && cr.CreatedDateTime < SqlFunctions.DateAdd( "day", -cr.ConnectionOpportunity.ConnectionType.DaysUntilRequestIdle, currentDateTime ) ) ) ) .Count(); // Count the number requests that have a status that is considered critical. int criticalCount = connectionRequestsQry .Where( r => r.ConnectionStatus.IsCritical && ( r.ConnectionState == ConnectionState.Active || ( r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < _midnightToday ) ) ) .Count(); // Add the opportunity var opportunitySummary = new OpportunitySummary { Id = opportunity.Id, Name = opportunity.Name, IsActive = opportunity.IsActive, IconCssClass = opportunity.IconCssClass, IdleCount = idleCount, CriticalCount = criticalCount }; // If the user is limited requests with specific campus(es) set the list, otherwise leave it to be null opportunitySummary.CampusSpecificConnector = campusSpecificConnector; opportunitySummary.ConnectorCampusIds = campusIds.Distinct().ToList(); connectionTypeSummary.Opportunities.Add( opportunitySummary ); } } } // Get a list of all the authorized opportunity ids var allOpportunities = SummaryState.SelectMany( s => s.Opportunities ).Select( o => o.Id ).Distinct().ToList(); // Get all the active and past-due future followup request ids, and include the campus id and personid of connector var midnightToday = RockDateTime.Today.AddDays(1); var activeRequests = new ConnectionRequestService( rockContext ) .Queryable().AsNoTracking() .Where( r => allOpportunities.Contains( r.ConnectionOpportunityId ) && ( r.ConnectionState == ConnectionState.Active || ( r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday ) ) ) .Select( r => new { r.ConnectionOpportunityId, r.CampusId, ConnectorPersonId = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.PersonId : -1 } ) .ToList(); // Based on the active requests, set additional properties for each opportunity foreach ( var opportunity in SummaryState.SelectMany( s => s.Opportunities ) ) { // Get the active requests for this opportunity that user is authorized to view (based on campus connector) var opportunityRequests = activeRequests .Where( r => r.ConnectionOpportunityId == opportunity.Id && ( !opportunity.CampusSpecificConnector || ( r.CampusId.HasValue && opportunity.ConnectorCampusIds.Contains( r.CampusId.Value ) ) ) ) .ToList(); // The count of active requests assigned to the current person opportunity.AssignedToYou = opportunityRequests.Count( r => r.ConnectorPersonId == CurrentPersonId ); // The count of active requests that are unassigned opportunity.UnassignedCount = opportunityRequests.Count( r => r.ConnectorPersonId == -1 ); // Flag indicating if current user is connector for any of the active types opportunity.HasActiveRequestsForConnector = opportunityRequests.Any( r => r.ConnectorPersonId == CurrentPersonId ); } //Set the Idle tooltip var connectionTypes = opportunities.Where( o => allOpportunities.Contains( o.Id ) ).Select( o => o.ConnectionType ).Distinct().ToList(); StringBuilder sb = new StringBuilder(); if ( connectionTypes.Select( t => t.DaysUntilRequestIdle ).Distinct().Count() == 1 ) { sb.Append( String.Format( "Idle (no activity in {0} days)", connectionTypes.Select( t => t.DaysUntilRequestIdle ).Distinct().First() ) ); } else { sb.Append( "Idle (no activity in several days)<br/><ul class='list-unstyled'>" ); foreach ( var connectionType in connectionTypes ) { sb.Append( String.Format( "<li>{0}: {1} days</li>", connectionType.Name, connectionType.DaysUntilRequestIdle ) ); } sb.Append( "</ul>" ); } var statusTemplate = this.GetAttributeValue( "StatusTemplate" ); var statusMergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields(this.RockPage); statusMergeFields.Add( "ConnectionOpportunities", allOpportunities ); statusMergeFields.Add( "ConnectionTypes", connectionTypes ); statusMergeFields.Add( "IdleTooltip", sb.ToString() ); lStatusBarContent.Text = statusTemplate.ResolveMergeFields( statusMergeFields ); BindSummaryData(); }
/// <summary> /// Gets the opportunity summary HTML. /// </summary> /// <param name="opportunitySummaryId">The opportunity summary identifier.</param> /// <returns></returns> public string GetOpportunitySummaryHtml( OpportunitySummary opportunitySummary ) { var template = this.GetAttributeValue( "OpportunitySummaryTemplate" ); var mergeFields = Rock.Lava.LavaHelper.GetCommonMergeFields( this.RockPage, this.CurrentPerson, new Rock.Lava.CommonMergeFieldsOptions { GetLegacyGlobalMergeFields = false } ); mergeFields.Add( "OpportunitySummary", DotLiquid.Hash.FromAnonymousObject( opportunitySummary ) ); string result = null; using ( var rockContext = new RockContext() ) { var connectionOpportunity = new ConnectionOpportunityService( rockContext ).Queryable().AsNoTracking().FirstOrDefault( a => a.Id == opportunitySummary.Id ); mergeFields.Add( "ConnectionOpportunity", connectionOpportunity ); mergeFields.Add( "ConnectionRequests", connectionOpportunity.ConnectionRequests ); result = template.ResolveMergeFields( mergeFields ); } return result; }
/// <summary> /// Gets the summary data. /// </summary> private void GetSummaryData() { SummaryState = new List <ConnectionTypeSummary>(); var rockContext = new RockContext(); var opportunities = new ConnectionOpportunityService(rockContext) .Queryable().AsNoTracking(); var typeFilter = GetAttributeValue("ConnectionTypes").SplitDelimitedValues().AsGuidList(); if (typeFilter.Any()) { opportunities = opportunities.Where(o => typeFilter.Contains(o.ConnectionType.Guid)); } // Loop through opportunities foreach (var opportunity in opportunities) { // Check to see if person can view the opportunity because of admin rights to this block or admin rights to // the opportunity bool canView = UserCanAdministrate || opportunity.IsAuthorized(Authorization.ADMINISTRATE, CurrentPerson); bool campusSpecificConnector = false; var campusIds = new List <int>(); if (CurrentPersonId.HasValue) { // Check to see if person belongs to any connector group that is not campus specific if (!canView) { canView = opportunity .ConnectionOpportunityConnectorGroups .Any(g => !g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any(m => m.PersonId == CurrentPersonId.Value)); } // If user is not yet authorized to view the opportunity, check to see if they are a member of one of the // campus-specific connector groups for the opportunity, and note the campus if (!canView) { foreach (var groupCampus in opportunity .ConnectionOpportunityConnectorGroups .Where(g => g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any(m => m.PersonId == CurrentPersonId.Value))) { campusSpecificConnector = true; canView = true; campusIds.Add(groupCampus.CampusId.Value); } } } // Is user is authorized to view this opportunity type... if (canView) { // Check if the opportunity's type has been added to summary yet, and if not, add it var connectionTypeSummary = SummaryState.Where(c => c.Id == opportunity.ConnectionTypeId).FirstOrDefault(); if (connectionTypeSummary == null) { connectionTypeSummary = new ConnectionTypeSummary { Id = opportunity.ConnectionTypeId, Name = opportunity.ConnectionType.Name, Opportunities = new List <OpportunitySummary>() }; SummaryState.Add(connectionTypeSummary); } // Add the opportunity var opportunitySummary = new OpportunitySummary { Id = opportunity.Id, Name = opportunity.Name, IconCssClass = opportunity.IconCssClass }; // If the user is limited requests with specific campus(es) set the list, otherwise leave it to be null opportunitySummary.CampusSpecificConnector = campusSpecificConnector; opportunitySummary.ConnectorCampusIds = campusIds.Distinct().ToList(); connectionTypeSummary.Opportunities.Add(opportunitySummary); } } // Get a list of all the authorized opportunity ids var allOpportunities = SummaryState.SelectMany(s => s.Opportunities).Select(o => o.Id).Distinct().ToList(); // Get all the active and past-due future followup request ids, and include the campus id and personid of connector var midnightToday = RockDateTime.Today.AddDays(1); var activeRequests = new ConnectionRequestService(rockContext) .Queryable().AsNoTracking() .Where(r => allOpportunities.Contains(r.ConnectionOpportunityId) && (r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday))) .Select(r => new { r.ConnectionOpportunityId, r.CampusId, ConnectorPersonId = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.PersonId : -1 }) .ToList(); // Based on the active requests, set additional properties for each opportunity foreach (var opportunity in SummaryState.SelectMany(s => s.Opportunities)) { // Get the active requests for this opportunity that user is authorized to view (based on campus connector) var opportunityRequests = activeRequests .Where(r => r.ConnectionOpportunityId == opportunity.Id && ( !opportunity.CampusSpecificConnector || (r.CampusId.HasValue && opportunity.ConnectorCampusIds.Contains(r.CampusId.Value)) )) .ToList(); // The count of active requests opportunity.ActiveCount = opportunityRequests.Count(); // Flag indicating if current user is connector for any of the active types opportunity.HasActiveRequestsForConnector = opportunityRequests.Any(r => r.ConnectorPersonId == CurrentPersonId); } BindSummaryData(); }
/// <summary> /// Gets the summary data. /// </summary> private void GetSummaryData() { SummaryState = new List<ConnectionTypeSummary>(); var rockContext = new RockContext(); // Loop through every opportunity foreach ( var opportunity in new ConnectionOpportunityService( rockContext ) .Queryable().AsNoTracking() ) { // Check to see if person can view the opportunity because of admin rights to this block or admin rights to // the opportunity bool canView = UserCanAdministrate || opportunity.IsAuthorized( Authorization.ADMINISTRATE, CurrentPerson ); bool campusSpecificConnector = false; var campusIds = new List<int>(); if ( CurrentPersonId.HasValue ) { // Check to see if person belongs to any connector group that is not campus specific if ( !canView ) { canView = opportunity .ConnectionOpportunityConnectorGroups .Any( g => !g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any( m => m.PersonId == CurrentPersonId.Value ) ); } // If user is not yet authorized to view the opportunity, check to see if they are a member of one of the // campus-specific connector groups for the opportunity, and note the campus if ( !canView ) { foreach ( var groupCampus in opportunity .ConnectionOpportunityConnectorGroups .Where( g => g.CampusId.HasValue && g.ConnectorGroup != null && g.ConnectorGroup.Members.Any( m => m.PersonId == CurrentPersonId.Value ) ) ) { campusSpecificConnector = true; canView = true; campusIds.Add( groupCampus.CampusId.Value ); } } } // Is user is authorized to view this opportunity type... if ( canView ) { // Check if the opportunity's type has been added to summary yet, and if not, add it var connectionTypeSummary = SummaryState.Where( c => c.Id == opportunity.ConnectionTypeId ).FirstOrDefault(); if ( connectionTypeSummary == null ) { connectionTypeSummary = new ConnectionTypeSummary { Id = opportunity.ConnectionTypeId, Name = opportunity.ConnectionType.Name, Opportunities = new List<OpportunitySummary>() }; SummaryState.Add( connectionTypeSummary ); } // Add the opportunity var opportunitySummary = new OpportunitySummary { Id = opportunity.Id, Name = opportunity.Name, IconCssClass = opportunity.IconCssClass }; // If the user is limited requests with specific campus(es) set the list, otherwise leave it to be null opportunitySummary.CampusSpecificConnector = campusSpecificConnector; opportunitySummary.ConnectorCampusIds = campusIds.Distinct().ToList(); connectionTypeSummary.Opportunities.Add( opportunitySummary ); } } // Get a list of all the authorized opportunity ids var allOpportunities = SummaryState.SelectMany( s => s.Opportunities ).Select( o => o.Id ).Distinct().ToList(); // Get all the active and past-due future followup request ids, and include the campus id and personid of connector var midnightToday = RockDateTime.Today.AddDays(1); var activeRequests = new ConnectionRequestService( rockContext ) .Queryable().AsNoTracking() .Where( r => allOpportunities.Contains( r.ConnectionOpportunityId ) && ( r.ConnectionState == ConnectionState.Active || ( r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday ) ) ) .Select( r => new { r.ConnectionOpportunityId, r.CampusId, ConnectorPersonId = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.PersonId : -1 } ) .ToList(); // Based on the active requests, set additional properties for each opportunity foreach ( var opportunity in SummaryState.SelectMany( s => s.Opportunities ) ) { // Get the active requests for this opportunity that user is authorized to view (based on campus connector) var opportunityRequests = activeRequests .Where( r => r.ConnectionOpportunityId == opportunity.Id && ( !opportunity.CampusSpecificConnector || ( r.CampusId.HasValue && opportunity.ConnectorCampusIds.Contains( r.CampusId.Value ) ) ) ) .ToList(); // The count of active requests opportunity.ActiveCount = opportunityRequests.Count(); // Flag indicating if current user is connector for any of the active types opportunity.HasActiveRequestsForConnector = opportunityRequests.Any( r => r.ConnectorPersonId == CurrentPersonId ); } BindSummaryData(); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { OpportunitySummary opportunitySummary = null; if (SelectedOpportunityId.HasValue) { opportunitySummary = SummaryState.SelectMany(t => t.Opportunities.Where(o => o.Id == SelectedOpportunityId.Value)).FirstOrDefault(); } if (opportunitySummary != null) { using (var rockContext = new RockContext()) { // Get queryable of all requests that belong to the selected opportunity, and user is authorized to view (based on security or connector group) var requests = new ConnectionRequestService(rockContext) .Queryable().AsNoTracking() .Where(r => r.ConnectionOpportunityId == SelectedOpportunityId.Value && ( !opportunitySummary.CampusSpecificConnector || (r.CampusId.HasValue && opportunitySummary.ConnectorCampusIds.Contains(r.CampusId.Value)) )); // Filter by Requester if (ppRequester.PersonId.HasValue) { requests = requests .Where(r => r.PersonAlias != null && r.PersonAlias.PersonId == ppRequester.PersonId.Value); } // Filter by Connector if (tglMyOpportunities.Checked) { requests = requests .Where(r => r.ConnectorPersonAlias != null && r.ConnectorPersonAlias.PersonId == CurrentPersonId); } else if (ppConnector.PersonId.HasValue) { requests = requests .Where(r => r.ConnectorPersonAlias != null && r.ConnectorPersonAlias.PersonId == ppConnector.PersonId.Value); } // Filter by State var midnightToday = RockDateTime.Today.AddDays(1); if (tglMyOpportunities.Checked) { requests = requests .Where(r => r.ConnectionState == ConnectionState.Active || (r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday)); } else { var states = new List <ConnectionState>(); bool futureFollowup = false; foreach (string stateValue in cblState.SelectedValues) { futureFollowup = futureFollowup || stateValue.AsInteger() == -2; var state = stateValue.ConvertToEnumOrNull <ConnectionState>(); if (state.HasValue) { states.Add(state.Value); } } if (futureFollowup || states.Any()) { requests = requests .Where(r => (futureFollowup && r.ConnectionState == ConnectionState.FutureFollowUp && r.FollowupDate.HasValue && r.FollowupDate.Value < midnightToday) || states.Contains(r.ConnectionState)); } } // Filter by Status List <int> statusIds = cblStatus.SelectedValuesAsInt; if (statusIds.Any()) { requests = requests .Where(r => statusIds.Contains(r.ConnectionStatusId)); } // Filter by Campus List <int> campusIds = cblCampus.SelectedValuesAsInt; if (campusIds.Count > 0) { requests = requests .Where(r => r.Campus != null && campusIds.Contains(r.CampusId.Value)); } Guid groupTypeGuid = GetAttributeValue("GeofenceGroupType").AsGuid(); var groupLocations = rockContext.GroupLocations .Where(gl => gl.Group.GroupType.Guid == groupTypeGuid && gl.Location.GeoFence != null).ToList(); var results = ( from r in requests.ToList() let homeLocation = r.PersonAlias.Person.GetHomeLocation(rockContext) let region = groupLocations.Where(gl => homeLocation != null && homeLocation.GeoPoint != null && homeLocation.GeoPoint.Intersects(gl.Location.GeoFence) ).Select(gl => gl.Location).FirstOrDefault() select new ConnectionResult() { Id = r.Id, Guid = r.Guid, PersonId = r.PersonAlias.PersonId, PersonName = r.PersonAlias.Person.FullNameReversed, CampusName = r.Campus.Name, GroupName = r.AssignedGroup != null ? r.AssignedGroup.Name : "", ConnectorName = r.ConnectorPersonAlias != null ? r.ConnectorPersonAlias.Person.FullName : "", LastActivity = FormatActivity(r.ConnectionRequestActivities.OrderByDescending(a => a.CreatedDateTime).FirstOrDefault()), Status = r.ConnectionStatus, StatusLabel = r.ConnectionStatus.IsCritical ? "warning" : "info", State = r.ConnectionState, StateLabel = FormatStateLabel(r.ConnectionState, r.FollowupDate), RegionId = (region != null ? region.Id : 0), RegionName = (region != null ? region.Name : "No Region"), PersonCity = homeLocation != null ? homeLocation.City : "No Location Info", PersonState = homeLocation != null ? homeLocation.State : "No Location Info", PhoneNumber = String.Join(", ", r.PersonAlias.Person.PhoneNumbers.Where(p => p.IsUnlisted != true && !String.IsNullOrWhiteSpace(p.Number)).Select(p => p.NumberFormatted).ToList()) }).AsQueryable(); // Filter by Region List <int> regionIds = cblRegion.SelectedValuesAsInt; if (regionIds.Any()) { results = results .Where(r => regionIds.Contains(r.RegionId)); } //Sort in Memory SortProperty sortProperty = gRequests.SortProperty; if (sortProperty != null) { results = results.Sort(sortProperty); } else { results = results .OrderBy(r => r.PersonName); } gRequests.SetLinqDataSource(results); gRequests.DataBind(); lOpportunityIcon.Text = string.Format("<i class='{0}'></i>", opportunitySummary.IconCssClass); lConnectionRequest.Text = String.Format("{0} Connection Requests", opportunitySummary.Name); } } else { pnlGrid.Visible = false; } }