/// <summary> /// Binds the grid. /// </summary> protected void BindGrid() { AddScheduleColumns(); var rockContext = new RockContext(); var groupLocationService = new GroupLocationService(rockContext); var groupTypeService = new GroupTypeService(rockContext); var groupService = new GroupService(rockContext); var groupPaths = new List <CheckinAreaPath>(); var groupLocationQry = groupLocationService.Queryable().Where(gl => gl.Group.IsActive && !gl.Group.IsArchived); int groupTypeId; // if this page has a PageParam for groupTypeId use that to limit which groupTypeId to see. Otherwise, use the groupTypeId specified in the filter if (_groupTypeId.HasValue) { groupTypeId = _groupTypeId.Value; } else { groupTypeId = ddlGroupType.SelectedValueAsInt() ?? Rock.Constants.All.Id; } if (groupTypeId != Rock.Constants.All.Id) { var descendantGroupTypeIds = groupTypeService.GetCheckinAreaDescendants(groupTypeId).Select(a => a.Id); // filter to groups that either are of the GroupType or are of a GroupType that has the selected GroupType as a parent (ancestor) groupLocationQry = groupLocationQry.Where(a => a.Group.GroupType.Id == groupTypeId || descendantGroupTypeIds.Contains(a.Group.GroupTypeId)); groupPaths = groupTypeService.GetCheckinAreaDescendantsPath(groupTypeId).ToList(); } else { List <int> descendantGroupTypeIds = new List <int>(); foreach (GroupType groupType in GetTopGroupTypes(rockContext)) { descendantGroupTypeIds.Add(groupType.Id); groupPaths.AddRange(groupTypeService.GetCheckinAreaDescendantsPath(groupType.Id).ToList()); foreach (var childGroupType in groupTypeService.GetChildGroupTypes(groupType.Id)) { descendantGroupTypeIds.Add(childGroupType.Id); descendantGroupTypeIds.AddRange(groupTypeService.GetCheckinAreaDescendants(childGroupType.Id).Select(a => a.Id).ToList()); } } groupLocationQry = groupLocationQry.Where(a => descendantGroupTypeIds.Contains(a.Group.GroupTypeId)); } if (gGroupLocationSchedule.SortProperty != null) { groupLocationQry = groupLocationQry.Sort(gGroupLocationSchedule.SortProperty); } else { groupLocationQry = groupLocationQry.OrderBy(a => a.Group.Name).ThenBy(a => a.Location.Name); } var qryList = groupLocationQry .Where(a => a.Location != null) .Select(a => new { GroupLocationId = a.Id, a.Location, GroupId = a.GroupId, GroupName = a.Group.Name, ScheduleIdList = a.Schedules.Select(s => s.Id), GroupTypeId = a.Group.GroupTypeId }).ToList(); var locationService = new LocationService(rockContext); int parentLocationId = pkrParentLocation.SelectedValueAsInt() ?? Rock.Constants.All.Id; if (parentLocationId != Rock.Constants.All.Id) { var currentAndDescendantLocationIds = new List <int>(); currentAndDescendantLocationIds.Add(parentLocationId); currentAndDescendantLocationIds.AddRange(locationService.GetAllDescendents(parentLocationId).Select(a => a.Id)); qryList = qryList.Where(a => currentAndDescendantLocationIds.Contains(a.Location.Id)).ToList(); } // put stuff in a DataTable so we can dynamically have columns for each Schedule DataTable dataTable = new DataTable(); dataTable.Columns.Add("GroupLocationId"); dataTable.Columns.Add("GroupId"); dataTable.Columns.Add("GroupName"); dataTable.Columns.Add("GroupPath"); dataTable.Columns.Add("LocationName"); dataTable.Columns.Add("LocationPath"); foreach (var field in gGroupLocationSchedule.Columns.OfType <CheckBoxEditableField>()) { dataTable.Columns.Add(field.DataField, typeof(bool)); } var locationPaths = new Dictionary <int, string>(); foreach (var row in qryList) { DataRow dataRow = dataTable.NewRow(); dataRow["GroupLocationId"] = row.GroupLocationId; dataRow["GroupName"] = groupService.GroupAncestorPathName(row.GroupId); dataRow["GroupPath"] = groupPaths.Where(gt => gt.GroupTypeId == row.GroupTypeId).Select(gt => gt.Path).FirstOrDefault(); dataRow["LocationName"] = row.Location.Name; if (row.Location.ParentLocationId.HasValue) { int locationId = row.Location.ParentLocationId.Value; if (!locationPaths.ContainsKey(locationId)) { var locationNames = new List <string>(); var parentLocation = locationService.Get(locationId); while (parentLocation != null) { locationNames.Add(parentLocation.Name); parentLocation = parentLocation.ParentLocation; } if (locationNames.Any()) { locationNames.Reverse(); locationPaths.Add(locationId, locationNames.AsDelimited(" > ")); } else { locationPaths.Add(locationId, string.Empty); } } dataRow["LocationPath"] = locationPaths[locationId]; } foreach (var field in gGroupLocationSchedule.Columns.OfType <CheckBoxEditableField>()) { int scheduleId = int.Parse(field.DataField.Replace("scheduleField_", string.Empty)); dataRow[field.DataField] = row.ScheduleIdList.Any(a => a == scheduleId); } dataTable.Rows.Add(dataRow); } gGroupLocationSchedule.EntityTypeId = EntityTypeCache.Get <GroupLocation>().Id; gGroupLocationSchedule.DataSource = dataTable; gGroupLocationSchedule.DataBind(); }
/// <summary> /// Binds the grid. /// </summary> protected void BindGrid() { AddScheduleColumns(); var rockContext = new RockContext(); var groupLocationService = new GroupLocationService(rockContext); var groupTypeService = new GroupTypeService(rockContext); var groupService = new GroupService(rockContext); var groupLocationQry = groupLocationService.Queryable(); var templateGroupPaths = new Dictionary <int, List <CheckinAreaPath> >(); var currentAndDescendantGroupTypeIds = new List <int>(); foreach (var groupType in groupTypeService.Queryable().Where(a => this.LocalDeviceConfig.CurrentGroupTypeIds.Contains(a.Id))) { foreach (var parentGroupType in groupType.ParentGroupTypes) { if (!templateGroupPaths.ContainsKey(parentGroupType.Id)) { templateGroupPaths.Add(parentGroupType.Id, groupTypeService.GetCheckinAreaDescendantsPath(parentGroupType.Id).ToList()); } } currentAndDescendantGroupTypeIds.Add(groupType.Id); currentAndDescendantGroupTypeIds.AddRange(groupTypeService.GetCheckinAreaDescendants(groupType.Id).Select(a => a.Id).ToList()); } var groupPaths = new List <CheckinAreaPath>(); foreach (var path in templateGroupPaths) { groupPaths.AddRange(path.Value); } groupLocationQry = groupLocationQry.Where(a => currentAndDescendantGroupTypeIds.Contains(a.Group.GroupTypeId)); groupLocationQry = groupLocationQry.OrderBy(a => a.Group.Name).ThenBy(a => a.Location.Name); List <int> currentDeviceLocationIdList = this.GetGroupTypesLocations(rockContext).Select(a => a.Id).Distinct().ToList(); var qryList = groupLocationQry .Where(a => currentDeviceLocationIdList.Contains(a.LocationId)) .Select(a => new { GroupLocationId = a.Id, a.Location, GroupId = a.GroupId, GroupName = a.Group.Name, ScheduleIdList = a.Schedules.Select(s => s.Id), GroupTypeId = a.Group.GroupTypeId }).ToList(); var locationService = new LocationService(rockContext); // put stuff in a datatable so we can dynamically have columns for each Schedule DataTable dataTable = new DataTable(); dataTable.Columns.Add("GroupLocationId"); dataTable.Columns.Add("GroupId"); dataTable.Columns.Add("GroupName"); dataTable.Columns.Add("GroupPath"); dataTable.Columns.Add("LocationName"); dataTable.Columns.Add("LocationPath"); foreach (var field in gGroupLocationSchedule.Columns.OfType <CheckBoxEditableField>()) { dataTable.Columns.Add(field.DataField, typeof(bool)); } var locationPaths = new Dictionary <int, string>(); foreach (var row in qryList) { DataRow dataRow = dataTable.NewRow(); dataRow["GroupLocationId"] = row.GroupLocationId; dataRow["GroupName"] = groupService.GroupAncestorPathName(row.GroupId); dataRow["GroupPath"] = groupPaths.Where(gt => gt.GroupTypeId == row.GroupTypeId).Select(gt => gt.Path).FirstOrDefault(); dataRow["LocationName"] = row.Location.Name; if (row.Location.ParentLocationId.HasValue) { int locationId = row.Location.ParentLocationId.Value; if (!locationPaths.ContainsKey(locationId)) { var locationNames = new List <string>(); var parentLocation = locationService.Get(locationId); while (parentLocation != null) { locationNames.Add(parentLocation.Name); parentLocation = parentLocation.ParentLocation; } if (locationNames.Any()) { locationNames.Reverse(); locationPaths.Add(locationId, locationNames.AsDelimited(" > ")); } else { locationPaths.Add(locationId, string.Empty); } } dataRow["LocationPath"] = locationPaths[locationId]; } foreach (var field in gGroupLocationSchedule.Columns.OfType <CheckBoxEditableField>()) { int scheduleId = int.Parse(field.DataField.Replace("scheduleField_", string.Empty)); dataRow[field.DataField] = row.ScheduleIdList.Any(a => a == scheduleId); } dataTable.Rows.Add(dataRow); } gGroupLocationSchedule.EntityTypeId = EntityTypeCache.Get <GroupLocation>().Id; gGroupLocationSchedule.DataSource = dataTable; gGroupLocationSchedule.DataBind(); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { if (HasFilterErrors()) { return; } var checkinAreaFilter = CheckinManagerHelper.GetCheckinAreaFilter(this); CampusCache campus = GetCampusFromContext(); var selectedScheduleIds = lbSchedules.SelectedValues.AsIntegerList(); if (selectedScheduleIds.Any()) { btnShowFilter.AddCssClass("criteria-exists bg-warning"); } else { btnShowFilter.RemoveCssClass("criteria-exists bg-warning"); } CheckinManagerHelper.SaveRoomListFilterToCookie(selectedScheduleIds.ToArray()); var rockContext = new RockContext(); var groupService = new GroupService(rockContext); var groupTypeService = new GroupTypeService(rockContext); IEnumerable <CheckinAreaPath> checkinAreaPaths; if (checkinAreaFilter != null) { checkinAreaPaths = groupTypeService.GetCheckinAreaDescendantsPath(checkinAreaFilter.Id); } else { checkinAreaPaths = groupTypeService.GetAllCheckinAreaPaths(); } var selectedGroupTypeIds = checkinAreaPaths.Select(a => a.GroupTypeId).Distinct().ToArray(); var groupLocationService = new GroupLocationService(rockContext); var groupLocationsQuery = groupLocationService.Queryable() .Where(gl => selectedGroupTypeIds.Contains(gl.Group.GroupTypeId) && gl.Group.IsActive && (!gl.Group.IsArchived)); var parentLocationIdParameter = PageParameter(PageParameterKey.ParentLocationId).AsIntegerOrNull(); var locationIdParameter = PageParameter(PageParameterKey.LocationId).AsIntegerOrNull(); var locationGridField = gRoomList.ColumnsOfType <RockLiteralField>().FirstOrDefault(a => a.ID == "lRoomName"); if (locationGridField != null && !locationGridField.Visible) { locationGridField.Visible = true; } List <int> locationIds; if (locationIdParameter.HasValue) { // If LocationId is specified in the URL, list only items for the specified location. // Also, hide the Location Grid Column and set the PanelTitle as the location's name // This will take precedence over the selected campus+locations and/or <seealso cref="ParentLocationId"/> var locationService = new LocationService(rockContext); lPanelTitle.Text = locationService.GetSelect(locationIdParameter.Value, s => s.Name); locationIds = new List <int>(); locationIds.Add(locationIdParameter.Value); if (locationGridField != null) { // since a LocationId parameter was specified, the LocationGrid field doesn't need to be shown locationGridField.Visible = false; } } else if (parentLocationIdParameter.HasValue) { // If parentLocationId is specified, show the direct (first level) child locations of the specified ParentLocationId. // This will take precedence over the selected campus+locations. var locationService = new LocationService(rockContext); locationIds = locationService.Queryable() .Where(a => a.ParentLocationId.HasValue && a.ParentLocationId.Value == parentLocationIdParameter.Value) .Select(a => a.Id).ToList(); lPanelTitle.Text = string.Format("{0} Child Locations", locationService.GetSelect(parentLocationIdParameter.Value, s => s.Name)); } else { // Limit locations (rooms) to locations within the selected campus. locationIds = new LocationService(rockContext).GetAllDescendentIds(campus.LocationId.Value).ToList(); locationIds.Add(campus.LocationId.Value, true); lPanelTitle.Text = "Room List"; } groupLocationsQuery = groupLocationsQuery.Where(a => locationIds.Contains(a.LocationId)); if (selectedScheduleIds.Any()) { groupLocationsQuery = groupLocationsQuery.Where(a => a.Schedules.Any(s => s.IsActive && s.CheckInStartOffsetMinutes.HasValue && selectedScheduleIds.Contains(s.Id))); } else { groupLocationsQuery = groupLocationsQuery.Where(a => a.Schedules.Any(s => s.IsActive && s.CheckInStartOffsetMinutes.HasValue)); } var groupLocationList = groupLocationsQuery.Select(a => new GroupLocationInfo { LocationId = a.LocationId, LocationName = a.Location.Name, ParentGroupId = a.Group.ParentGroupId, ParentGroupName = a.Group.ParentGroup.Name, GroupId = a.Group.Id, GroupName = a.Group.Name, GroupTypeId = a.Group.GroupTypeId }).ToList(); var startDateTime = RockDateTime.Today; DateTime currentDateTime; if (campus != null) { currentDateTime = campus.CurrentDateTime; } else { currentDateTime = RockDateTime.Now; } // Get all Attendance records for the current day and location. var attendanceQuery = new AttendanceService(rockContext).Queryable().Where(a => a.StartDateTime >= startDateTime && a.DidAttend == true && a.StartDateTime <= currentDateTime && a.PersonAliasId.HasValue && a.Occurrence.GroupId.HasValue && a.Occurrence.LocationId.HasValue && a.Occurrence.ScheduleId.HasValue); // Limit attendances (rooms) to the groupLocations' LocationId and GroupIds that we'll be showing var groupLocationLocationIds = groupLocationList.Select(a => a.LocationId).Distinct().ToList(); var groupLocationGroupsIds = groupLocationList.Select(a => a.GroupId).Distinct().ToList(); attendanceQuery = attendanceQuery.Where(a => groupLocationLocationIds.Contains(a.Occurrence.LocationId.Value) && groupLocationGroupsIds.Contains(a.Occurrence.GroupId.Value)); attendanceQuery = attendanceQuery.Where(a => selectedGroupTypeIds.Contains(a.Occurrence.Group.GroupTypeId)); if (selectedScheduleIds.Any()) { attendanceQuery = attendanceQuery.Where(a => selectedScheduleIds.Contains(a.Occurrence.ScheduleId.Value)); } var rosterAttendeeAttendanceList = RosterAttendeeAttendance.Select(attendanceQuery).ToList(); var groupTypeIdsWithAllowCheckout = selectedGroupTypeIds .Select(a => GroupTypeCache.Get(a)) .Where(a => a != null) .Where(gt => gt.GetCheckInConfigurationAttributeValue(Rock.SystemKey.GroupTypeAttributeKey.CHECKIN_GROUPTYPE_ALLOW_CHECKOUT).AsBoolean()) .Select(a => a.Id) .Distinct().ToList(); var groupTypeIdsWithEnablePresence = selectedGroupTypeIds .Select(a => GroupTypeCache.Get(a)) .Where(a => a != null) .Where(gt => gt.GetCheckInConfigurationAttributeValue(Rock.SystemKey.GroupTypeAttributeKey.CHECKIN_GROUPTYPE_ENABLE_PRESENCE).AsBoolean()) .Select(a => a.Id) .Distinct(); var scheduleIds = rosterAttendeeAttendanceList.Select(a => a.ScheduleId.Value).Distinct().ToList(); var scheduleList = new ScheduleService(rockContext).GetByIds(scheduleIds).ToList(); var scheduleIdsWasScheduleOrCheckInActiveForCheckOut = new HashSet <int>(scheduleList.Where(a => a.WasScheduleOrCheckInActiveForCheckOut(currentDateTime)).Select(a => a.Id).ToList()); rosterAttendeeAttendanceList = rosterAttendeeAttendanceList.Where(a => { var allowCheckout = groupTypeIdsWithAllowCheckout.Contains(a.GroupTypeId); if (!allowCheckout) { /* * If AllowCheckout is false, remove all Attendees whose schedules are not currently active. Per the 'WasSchedule...ActiveForCheckOut()' * method below: "Check-out can happen while check-in is active or until the event ends (start time + duration)." This will help to keep * the list of 'Present' attendees cleaned up and accurate, based on the room schedules, since the volunteers have no way to manually mark * an Attendee as 'Checked-out'. * * If, on the other hand, AllowCheckout is true, it will be the volunteers' responsibility to click the [Check-out] button when an * Attendee leaves the room, in order to keep the list of 'Present' Attendees in order. This will also allow the volunteers to continue * 'Checking-out' Attendees in the case that the parents are running late in picking them up. */ return(scheduleIdsWasScheduleOrCheckInActiveForCheckOut.Contains(a.ScheduleId.Value)); } else { return(true); } }).ToList(); var attendancesByLocationId = rosterAttendeeAttendanceList .GroupBy(a => a.LocationId.Value).ToDictionary(k => k.Key, v => v.ToList()); _attendancesByLocationIdAndGroupId = attendancesByLocationId.ToDictionary( k => k.Key, v => v.Value.GroupBy(x => x.GroupId.Value).ToDictionary(x => x.Key, xx => xx.ToList())); _checkinAreaPathsLookupByGroupTypeId = checkinAreaPaths.ToDictionary(k => k.GroupTypeId, v => v); _showOnlyParentGroup = this.GetAttributeValue(AttributeKey.ShowOnlyParentGroup).AsBoolean(); var roomList = new List <RoomInfo>(); foreach (var groupLocation in groupLocationList) { AddToRoomList(roomList, groupLocation); } List <RoomInfo> sortedRoomList; if (_showOnlyParentGroup) { sortedRoomList = roomList.OrderBy(a => a.LocationName).ToList(); } else { sortedRoomList = new List <RoomInfo>(); sortedRoomList.AddRange(roomList.OfType <RoomInfoByGroup>().OrderBy(a => a.LocationName).ThenBy(a => a.GroupName).ToList()); } var checkedInCountField = gRoomList.ColumnsOfType <RockLiteralField>().FirstOrDefault(a => a.ID == "lCheckedInCount"); var presentCountField = gRoomList.ColumnsOfType <RockLiteralField>().FirstOrDefault(a => a.ID == "lPresentCount"); var checkedOutCountField = gRoomList.ColumnsOfType <RockLiteralField>().FirstOrDefault(a => a.ID == "lCheckedOutCount"); checkedOutCountField.Visible = groupTypeIdsWithAllowCheckout.Any(); // Always show Present Count regardless of the 'Enable Presence' setting. (A person gets automatically marked present if 'Enable Presence' is disabled.) presentCountField.Visible = true; if (groupTypeIdsWithEnablePresence.Any()) { // Presence is enabled, so records could be in the 'Checked-in' state // and Present column should be labeled 'Present'. checkedInCountField.Visible = true; presentCountField.HeaderText = "Present"; } else { // https://app.asana.com/0/0/1199637795718017/f // 'Enable Presence' is disabled, so a person automatically gets marked present. // So, no records will be in the 'Checked-In (but no present)' state. // Also, a user thinks of 'Present' as 'Checked-In' if they don't use the 'Enable Presence' feature checkedInCountField.Visible = false; presentCountField.HeaderText = "Checked-In"; } if (_showOnlyParentGroup) { gRoomList.DataKeyNames = new string[1] { "LocationId" }; } else { gRoomList.DataKeyNames = new string[2] { "LocationId", "GroupId" }; } gRoomList.DataSource = sortedRoomList; gRoomList.DataBind(); }