/// <summary> /// Gets the grid field. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override System.Web.UI.WebControls.DataControlField GetGridField(Type entityType, string selection) { var result = new CallbackField(); result.OnFormatDataValue += FormatGridDataValue; return(result); }
/// <summary> /// Gets the grid field. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override System.Web.UI.WebControls.DataControlField GetGridField(Type entityType, string selection) { Guid?phoneType = null; bool enableOrigination = false; if (_currentPerson == null) { if (HttpContext.Current != null && HttpContext.Current.Items.Contains("CurrentPerson")) { _currentPerson = HttpContext.Current.Items["CurrentPerson"] as Rock.Model.Person; } } var selectionParts = selection.Split('|'); if (selectionParts.Length > 0) { phoneType = selectionParts[0].AsGuidOrNull(); } if (selectionParts.Length > 1) { enableOrigination = selectionParts[1].AsBoolean(); } var callbackField = new CallbackField(); callbackField.OnFormatDataValue += (sender, e) => { var phoneNumber = e.DataValue as PhoneNumber; if (phoneNumber != null) { if (enableOrigination) { if (_currentPerson == null) { e.FormattedValue = phoneNumber.NumberFormatted; return; } var jsScript = string.Format("javascript: Rock.controls.pbx.originate('{0}', '{1}', '{2}','{3}','{4}');", _currentPerson.Guid, phoneNumber.Number, _currentPerson.FullName, "", phoneNumber.ToString()); e.FormattedValue = string.Format("<a class='originate-call js-originate-call' href=\"{0}\">{1}</a>", jsScript, phoneNumber.NumberFormatted); } else { e.FormattedValue = phoneNumber.NumberFormatted; } } else { e.FormattedValue = string.Empty; return; } }; return(callbackField); }
/// <summary> /// Gets the grid field. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override System.Web.UI.WebControls.DataControlField GetGridField(Type entityType, string selection) { var callbackField = new CallbackField(); var selectionParts = selection.Split('|'); bool includeGender = selectionParts.Length > 0 && selectionParts[0].AsBoolean(); bool includeAge = selectionParts.Length > 1 && selectionParts[1].AsBoolean(); callbackField.OnFormatDataValue += (sender, e) => { var personList = e.DataValue as IEnumerable <KidInfo>; if (personList != null) { var formattedList = new List <string>(); foreach (var person in personList) { var formattedPerson = Rock.Model.Person.FormatFullName(person.NickName, person.LastName, person.SuffixValueId); var formattedGenderAge = string.Empty; if (includeGender && person.Gender != Gender.Unknown) { // return F for Female, M for Male if (person.Gender == Gender.Female) { formattedGenderAge += "F"; } else if (person.Gender == Gender.Male) { formattedGenderAge += "M"; } } int?age = Rock.Model.Person.GetAge(person.BirthDate); if (includeAge && age.HasValue) { formattedGenderAge += " " + age.Value.ToString(); } if (!string.IsNullOrWhiteSpace(formattedGenderAge)) { formattedPerson += " (" + formattedGenderAge.Trim() + ")"; } formattedList.Add(formattedPerson); } e.FormattedValue = formattedList.AsDelimited(", "); } else { e.FormattedValue = string.Empty; } }; return(callbackField); }
/// <summary> /// Gets the grid field. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override DataControlField GetGridField(Type entityType, string selection) { ComparisonType comparisonType; decimal totalAmountCutoff; string[] selectionValues = selection.Split('|'); if (selectionValues.Length < 2) { // shouldn't happen, but just in case, just do the default comparisonType = ComparisonType.GreaterThanOrEqualTo; totalAmountCutoff = 0.00M; } else { comparisonType = selectionValues[0].ConvertToEnum <ComparisonType>(ComparisonType.GreaterThanOrEqualTo); totalAmountCutoff = selectionValues[1].AsDecimalOrNull() ?? 0.00M; } // if it is just greater than or equal to 0, they want to show total giving, regardless of amount // so there is no need to do the comparison logic bool skipComparison = (comparisonType == ComparisonType.GreaterThanOrEqualTo && totalAmountCutoff == 0.00M); var callbackField = new CallbackField(); callbackField.ItemStyle.HorizontalAlign = HorizontalAlign.Right; callbackField.HeaderStyle.HorizontalAlign = HorizontalAlign.Right; callbackField.OnFormatDataValue += (sender, e) => { decimal?totalGiving = e.DataValue as decimal?; if (!totalGiving.HasValue || totalGiving.Value == 0.00M) { e.FormattedValue = string.Empty; } else if (skipComparison || ComparisonHelper.CompareNumericValues(comparisonType, totalGiving, totalAmountCutoff)) { // it meets the comparison criteria, so display total amount e.FormattedValue = totalGiving?.FormatAsCurrency(); } else { // if the total giving is an amount that doesn't meet the comparison criteria, show blank e.FormattedValue = string.Empty; } }; return(callbackField); }
/// <summary> /// Gets the grid field. /// </summary> /// <param name="entityType">Type of the entity.</param> /// <param name="selection">The selection.</param> /// <returns></returns> public override System.Web.UI.WebControls.DataControlField GetGridField(Type entityType, string selection) { var callbackField = new CallbackField(); string basePersonUrl = System.Web.VirtualPathUtility.ToAbsolute("~/Person/"); string baseGroupMemberUrl = System.Web.VirtualPathUtility.ToAbsolute("~/GroupMember/"); var selectionParts = selection.Split('|'); ShowAsLinkType showAsLinkType = selectionParts.Length > 0 ? selectionParts[0].ConvertToEnum <ShowAsLinkType>(ShowAsLinkType.NameOnly) : ShowAsLinkType.NameOnly; callbackField.OnFormatDataValue += (sender, e) => { var groupMemberList = e.DataValue as IEnumerable <MemberInfo>; if (groupMemberList != null) { var formattedList = new List <string>(); foreach (var groupMember in groupMemberList) { var formattedPersonFullName = Rock.Model.Person.FormatFullName(groupMember.NickName, groupMember.LastName, groupMember.SuffixValueId); string formattedValue; if (showAsLinkType == ShowAsLinkType.PersonLink) { formattedValue = "<a href='" + basePersonUrl + groupMember.PersonId.ToString() + "'>" + formattedPersonFullName + "</a>"; } else if (showAsLinkType == ShowAsLinkType.GroupMemberLink) { formattedValue = "<a href='" + baseGroupMemberUrl + groupMember.GroupMemberId.ToString() + "'>" + formattedPersonFullName + "</a>"; } else { formattedValue = formattedPersonFullName; } formattedList.Add(formattedValue); } e.FormattedValue = formattedList.AsDelimited(", "); } else { e.FormattedValue = string.Empty; } }; return(callbackField); }
/// <summary> /// Binds the grid. /// </summary> private void BindGrid() { var sortProperty = gList.SortProperty; if (gList.DataSource == null) { _calculatePercentageDifference = GetAttributeValue("CalculatePercentageDifference").AsBoolean(true); var attendanceSummaries = GetAttendance(); if (attendanceSummaries != null) { if (sortProperty != null) { attendanceSummaries.AsQueryable().Sort(sortProperty); } var groupTypes = attendanceSummaries.SelectMany(a => a.GroupTypeAttendanceSummaries.Select(g => g.GroupType).Distinct()).Distinct().ToList(); foreach (var column in gList.Columns.OfType <CallbackField>().ToList()) { gList.Columns.Remove(column); } foreach (var groupType in groupTypes) { foreach (var type in Enum.GetValues(typeof(ColumnType)).Cast <ColumnType>()) { var field = new CallbackField { ConvertEmptyStringToNull = true, DataFormatString = groupType.Id + "," + type, HeaderText = groupType.Name + " " + GetColumnHeader(type), DataField = "GroupTypeAttendanceSummaries", }; if (type == ColumnType.Difference) { field.ColumnPriority = ColumnPriority.DesktopSmall; } gList.Columns.Add(field); field.OnFormatDataValue += OnFormatDataValue; } } gList.DataSource = attendanceSummaries; } } gList.DataBind(); }
/// <summary> /// Adds the attribute columns. /// </summary> private void AddDynamicControls() { // Clear the filter controls phAttributeFilters.Controls.Clear(); // Remove attribute columns foreach (var column in gWorkflows.Columns.OfType <AttributeField>().ToList()) { gWorkflows.Columns.Remove(column); } if (AvailableAttributes != null) { foreach (var attribute in AvailableAttributes) { var control = attribute.FieldType.Field.FilterControl(attribute.QualifierValues, "filter_" + attribute.Id.ToString(), false, Rock.Reporting.FilterMode.SimpleFilter); if (control != null) { if (control is IRockControl) { var rockControl = ( IRockControl )control; rockControl.Label = attribute.Name; rockControl.Help = attribute.Description; phAttributeFilters.Controls.Add(control); } else { var wrapper = new RockControlWrapper(); wrapper.ID = control.ID + "_wrapper"; wrapper.Label = attribute.Name; wrapper.Controls.Add(control); phAttributeFilters.Controls.Add(wrapper); } } string dataFieldExpression = attribute.Key; bool columnExists = gWorkflows.Columns.OfType <AttributeField>().FirstOrDefault(a => a.DataField.Equals(dataFieldExpression)) != null; if (!columnExists) { AttributeField boundField = new AttributeField(); boundField.DataField = dataFieldExpression; boundField.AttributeId = attribute.Id; boundField.HeaderText = attribute.Name; boundField.Condensed = false; var attributeCache = Rock.Web.Cache.AttributeCache.Get(attribute.Id); if (attributeCache != null) { boundField.ItemStyle.HorizontalAlign = attributeCache.FieldType.Field.AlignValue; } gWorkflows.Columns.Add(boundField); } } } var dateField = new DateTimeField(); gWorkflows.Columns.Add(dateField); dateField.DataField = "CreatedDateTime"; dateField.SortExpression = "CreatedDateTime"; dateField.HeaderText = "Created"; dateField.FormatAsElapsedTime = true; var statusField = new BoundField(); gWorkflows.Columns.Add(statusField); statusField.DataField = "Status"; statusField.SortExpression = "Status"; statusField.HeaderText = "Status"; statusField.DataFormatString = "<span class='label label-info'>{0}</span>"; statusField.HtmlEncode = false; var stateField = new CallbackField(); gWorkflows.Columns.Add(stateField); stateField.DataField = "IsCompleted"; stateField.SortExpression = "CompletedDateTime"; stateField.HeaderText = "State"; stateField.HtmlEncode = false; stateField.OnFormatDataValue += (sender, e) => { if (( bool )e.DataValue) { e.FormattedValue = "<span class='label label-default'>Completed</span>"; } else { e.FormattedValue = "<span class='label label-success'>Active</span>"; } }; }
/// <summary> /// Binds the grid. /// </summary> /// <param name="report">The report.</param> /// <param name="gReport">The g report.</param> /// <param name="currentPerson">The current person.</param> /// <param name="dataViewFilterOverrides">The data view filter overrides.</param> /// <param name="databaseTimeoutSeconds">The database timeout seconds.</param> /// <param name="isCommunication">if set to <c>true</c> [is communication].</param> /// <param name="errorMessage">The error message.</param> public static void BindGrid(Report report, Grid gReport, Person currentPerson, DataViewFilterOverrides dataViewFilterOverrides, int?databaseTimeoutSeconds, bool isCommunication, out string errorMessage) { errorMessage = null; if (report != null) { var errors = new List <string>(); if (!report.EntityTypeId.HasValue) { gReport.Visible = false; return; } var rockContext = new RockContext(); if (!report.IsAuthorized(Authorization.VIEW, currentPerson)) { gReport.Visible = false; return; } Type entityType = EntityTypeCache.Get(report.EntityTypeId.Value, rockContext).GetEntityType(); if (entityType == null) { errorMessage = string.Format("Unable to determine entityType for {0}", report.EntityType); return; } gReport.EntityTypeId = report.EntityTypeId; bool isPersonDataSet = report.EntityTypeId == EntityTypeCache.Get(typeof(Rock.Model.Person), true, rockContext).Id; if (isPersonDataSet) { gReport.PersonIdField = "Id"; gReport.DataKeyNames = new string[] { "Id" }; } else { gReport.PersonIdField = null; } if (report.EntityTypeId.HasValue) { gReport.RowItemText = EntityTypeCache.Get(report.EntityTypeId.Value, rockContext).FriendlyName; } List <EntityField> entityFields = Rock.Reporting.EntityHelper.GetEntityFields(entityType, true, false); var selectedEntityFields = new Dictionary <int, EntityField>(); var selectedAttributes = new Dictionary <int, AttributeCache>(); var selectedComponents = new Dictionary <int, ReportField>(); // if there is a selectField, keep it to preserve which items are checked var selectField = gReport.Columns.OfType <SelectField>().FirstOrDefault(); gReport.Columns.Clear(); int columnIndex = 0; if (!string.IsNullOrWhiteSpace(gReport.PersonIdField)) { // if we already had a selectField, use it (to preserve checkbox state) gReport.Columns.Add(selectField ?? new SelectField()); columnIndex++; } var reportFieldSortExpressions = new Dictionary <Guid, string>(); gReport.CommunicateMergeFields = new List <string>(); gReport.CommunicationRecipientPersonIdFields = new List <string>(); foreach (var reportField in report.ReportFields.OrderBy(a => a.ColumnOrder)) { bool mergeField = reportField.IsCommunicationMergeField.HasValue && reportField.IsCommunicationMergeField.Value; bool recipientField = reportField.IsCommunicationRecipientField.HasValue && reportField.IsCommunicationRecipientField.Value; columnIndex++; if (reportField.ReportFieldType == ReportFieldType.Property) { var entityField = entityFields.FirstOrDefault(a => a.Name == reportField.Selection); if (entityField != null) { selectedEntityFields.Add(columnIndex, entityField); BoundField boundField = entityField.GetBoundFieldType(); boundField.DataField = string.Format("Entity_{0}_{1}", entityField.Name, columnIndex); boundField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? entityField.Title : reportField.ColumnHeaderText; boundField.SortExpression = boundField.DataField; reportFieldSortExpressions.AddOrReplace(reportField.Guid, boundField.SortExpression); boundField.Visible = reportField.ShowInGrid; gReport.Columns.Add(boundField); if (mergeField) { gReport.CommunicateMergeFields.Add($"{boundField.DataField}|{boundField.HeaderText.RemoveSpecialCharacters()}"); } if (recipientField) { gReport.CommunicationRecipientPersonIdFields.Add(boundField.DataField); } } } else if (reportField.ReportFieldType == ReportFieldType.Attribute) { Guid?attributeGuid = reportField.Selection.AsGuidOrNull(); if (attributeGuid.HasValue) { var attribute = AttributeCache.Get(attributeGuid.Value, rockContext); if (attribute != null && attribute.IsActive) { selectedAttributes.Add(columnIndex, attribute); BoundField boundField; if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.BOOLEAN.AsGuid())) { boundField = new BoolField(); } else if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.DEFINED_VALUE.AsGuid())) { boundField = new DefinedValueField(); } else { boundField = new CallbackField(); boundField.HtmlEncode = false; (boundField as CallbackField).OnFormatDataValue += (sender, e) => { string resultHtml = null; if (e.DataValue != null) { bool condensed = true; resultHtml = attribute.FieldType.Field.FormatValueAsHtml(gReport, e.DataValue.ToString(), attribute.QualifierValues, condensed); } e.FormattedValue = resultHtml ?? string.Empty; }; } boundField.DataField = string.Format("Attribute_{0}_{1}", attribute.Id, columnIndex); boundField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? attribute.Name : reportField.ColumnHeaderText; boundField.SortExpression = boundField.DataField; reportFieldSortExpressions.AddOrReplace(reportField.Guid, boundField.SortExpression); if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.INTEGER.AsGuid()) || attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.DATE.AsGuid()) || attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.FILTER_DATE.AsGuid())) { boundField.HeaderStyle.HorizontalAlign = HorizontalAlign.Right; boundField.ItemStyle.HorizontalAlign = HorizontalAlign.Right; } boundField.Visible = reportField.ShowInGrid; gReport.Columns.Add(boundField); if (mergeField) { gReport.CommunicateMergeFields.Add($"{boundField.DataField}|{boundField.HeaderText.RemoveSpecialCharacters()}"); } if (recipientField) { gReport.CommunicationRecipientPersonIdFields.Add(boundField.DataField); } } } } else if (reportField.ReportFieldType == ReportFieldType.DataSelectComponent) { selectedComponents.Add(columnIndex, reportField); DataSelectComponent selectComponent = DataSelectContainer.GetComponent(reportField.DataSelectComponentEntityType.Name); if (selectComponent != null) { try { DataControlField columnField = selectComponent.GetGridField(entityType, reportField.Selection ?? string.Empty); string fieldId = $"{selectComponent.ColumnPropertyName}_{columnIndex}"; if (columnField is BoundField) { (columnField as BoundField).DataField = $"Data_{fieldId}"; var customSortProperties = selectComponent.SortProperties(reportField.Selection ?? string.Empty); bool sortReversed = selectComponent.SortReversed(reportField.Selection ?? string.Empty); if (customSortProperties != null) { if (customSortProperties == string.Empty) { // disable sorting if customSortExpression set to string.empty columnField.SortExpression = string.Empty; } else { columnField.SortExpression = customSortProperties.Split(',').Select(a => string.Format("Sort_{0}_{1}", a, columnIndex)).ToList().AsDelimited(","); } } else { // use default sorting if customSortExpression was null columnField.SortExpression = (columnField as BoundField).DataField; } if (sortReversed == true && !string.IsNullOrWhiteSpace(columnField.SortExpression)) { columnField.SortExpression = columnField.SortExpression + " DESC"; } } columnField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? selectComponent.ColumnHeaderText : reportField.ColumnHeaderText; if (!string.IsNullOrEmpty(columnField.SortExpression)) { reportFieldSortExpressions.AddOrReplace(reportField.Guid, columnField.SortExpression); } columnField.Visible = reportField.ShowInGrid; gReport.Columns.Add(columnField); if (mergeField) { gReport.CommunicateMergeFields.Add($"Data_{fieldId}|{columnField.HeaderText.RemoveSpecialCharacters()}"); } if (recipientField) { string fieldName = (selectComponent is IRecipientDataSelect) ? $"Recipient_{fieldId}" : $"Data_{fieldId}"; gReport.CommunicationRecipientPersonIdFields.Add(fieldName); } } catch (Exception ex) { ExceptionLogService.LogException(ex, HttpContext.Current); errors.Add(string.Format("{0} - {1}", selectComponent, ex.Message)); } } } } // if no fields are specified, show the default fields (Previewable/All) for the EntityType var dataColumns = gReport.Columns.OfType <object>().Where(a => a.GetType() != typeof(SelectField)); if (dataColumns.Count() == 0) { // show either the Previewable Columns or all (if there are no previewable columns) bool showAllColumns = !entityFields.Any(a => a.FieldKind == FieldKind.Property && a.IsPreviewable); foreach (var entityField in entityFields.Where(a => a.FieldKind == FieldKind.Property)) { columnIndex++; selectedEntityFields.Add(columnIndex, entityField); BoundField boundField = entityField.GetBoundFieldType(); boundField.DataField = string.Format("Entity_{0}_{1}", entityField.Name, columnIndex); boundField.HeaderText = entityField.Name; boundField.SortExpression = boundField.DataField; boundField.Visible = showAllColumns || entityField.IsPreviewable; gReport.Columns.Add(boundField); } } try { gReport.Visible = true; gReport.ExportFilename = report.Name; SortProperty sortProperty = gReport.SortProperty; if (sortProperty == null) { var reportSort = new SortProperty(); var sortColumns = new Dictionary <string, SortDirection>(); foreach (var reportField in report.ReportFields.Where(a => a.SortOrder.HasValue).OrderBy(a => a.SortOrder.Value)) { if (reportFieldSortExpressions.ContainsKey(reportField.Guid)) { var sortField = reportFieldSortExpressions[reportField.Guid]; if (!string.IsNullOrWhiteSpace(sortField)) { sortColumns.Add(sortField, reportField.SortDirection); } } } if (sortColumns.Any()) { reportSort.Property = sortColumns.Select(a => a.Key + (a.Value == SortDirection.Descending ? " desc" : string.Empty)).ToList().AsDelimited(","); sortProperty = reportSort; } } var qryErrors = new List <string>(); System.Data.Entity.DbContext reportDbContext; dynamic qry = report.GetQueryable(entityType, selectedEntityFields, selectedAttributes, selectedComponents, sortProperty, dataViewFilterOverrides, databaseTimeoutSeconds ?? 180, isCommunication, out qryErrors, out reportDbContext); errors.AddRange(qryErrors); if (!string.IsNullOrEmpty(report.QueryHint) && reportDbContext is RockContext) { using (new QueryHintScope(reportDbContext as RockContext, report.QueryHint)) { gReport.SetLinqDataSource(qry); } } else { gReport.SetLinqDataSource(qry); } gReport.DataBind(); } catch (Exception ex) { Exception exception = ex; ExceptionLogService.LogException(ex, HttpContext.Current); while (exception != null) { if (exception is System.Data.SqlClient.SqlException) { // if there was a SQL Server Timeout, have the warning be a friendly message about that. if ((exception as System.Data.SqlClient.SqlException).Number == -2) { errorMessage = "This report did not complete in a timely manner. You can try again or adjust the timeout setting of this block."; return; } else { errors.Add(exception.Message); exception = exception.InnerException; } } else { errors.Add(exception.Message); exception = exception.InnerException; } } } if (errors.Any()) { errorMessage = "WARNING: There was a problem with one or more of the report's data components...<br/><br/> " + errors.AsDelimited("<br/>"); } } }
/// <summary> /// Adds the attribute columns. /// </summary> private void AddDynamicControls() { // Clear the filter controls phAttributeFilters.Controls.Clear(); // Remove attribute columns foreach (var column in gWorkflows.Columns.OfType <AttributeField>().ToList()) { gWorkflows.Columns.Remove(column); } if (AvailableAttributes != null) { foreach (var attribute in AvailableAttributes) { var control = attribute.FieldType.Field.FilterControl(attribute.QualifierValues, "filter_" + attribute.Id.ToString(), false, Rock.Reporting.FilterMode.SimpleFilter); if (control != null) { if (control is IRockControl) { var rockControl = (IRockControl)control; rockControl.Label = attribute.Name; rockControl.Help = attribute.Description; phAttributeFilters.Controls.Add(control); } else { var wrapper = new RockControlWrapper(); wrapper.ID = control.ID + "_wrapper"; wrapper.Label = attribute.Name; wrapper.Controls.Add(control); phAttributeFilters.Controls.Add(wrapper); } } string savedValue = gfWorkflows.GetUserPreference(MakeKeyUniqueToType(attribute.Key)); if (!string.IsNullOrWhiteSpace(savedValue)) { try { var values = JsonConvert.DeserializeObject <List <string> >(savedValue); attribute.FieldType.Field.SetFilterValues(control, attribute.QualifierValues, values); } catch { } } string dataFieldExpression = attribute.Key; bool columnExists = gWorkflows.Columns.OfType <AttributeField>().FirstOrDefault(a => a.DataField.Equals(dataFieldExpression)) != null; if (!columnExists) { AttributeField boundField = new AttributeField(); boundField.DataField = dataFieldExpression; boundField.AttributeId = attribute.Id; boundField.HeaderText = attribute.Name; boundField.Condensed = false; var attributeCache = Rock.Web.Cache.AttributeCache.Read(attribute.Id); if (attributeCache != null) { boundField.ItemStyle.HorizontalAlign = attributeCache.FieldType.Field.AlignValue; } gWorkflows.Columns.Add(boundField); } } } var dateField = new DateTimeField(); gWorkflows.Columns.Add(dateField); dateField.DataField = "CreatedDateTime"; dateField.SortExpression = "CreatedDateTime"; dateField.HeaderText = "Created"; dateField.FormatAsElapsedTime = true; var statusField = new BoundField(); gWorkflows.Columns.Add(statusField); statusField.DataField = "Status"; statusField.SortExpression = "Status"; statusField.HeaderText = "Status"; statusField.DataFormatString = "<span class='label label-info'>{0}</span>"; statusField.HtmlEncode = false; var stateField = new CallbackField(); gWorkflows.Columns.Add(stateField); stateField.DataField = "IsCompleted"; stateField.SortExpression = "CompletedDateTime"; stateField.HeaderText = "State"; stateField.HtmlEncode = false; stateField.OnFormatDataValue += (sender, e) => { if ((bool)e.DataValue) { e.FormattedValue = "<span class='label label-default'>Completed</span>"; } else { e.FormattedValue = "<span class='label label-success'>Active</span>"; } }; if (_canView) { var manageField = new LinkButtonField(); gWorkflows.Columns.Add(manageField); manageField.CssClass = "btn btn-default btn-sm fa fa-file-text-o"; manageField.Click += gWorkflows_Manage; } if (_canEdit) { var deleteField = new DeleteField(); gWorkflows.Columns.Add(deleteField); deleteField.Click += gWorkflows_Delete; } }
/// <summary> /// Binds the grid. /// </summary> /// <param name="report">The report.</param> /// <param name="gReport">The g report.</param> /// <param name="bindGridOptions">The bind grid options.</param> /// <exception cref="ArgumentNullException">Report must be specified</exception> /// <exception cref="Rock.Reporting.RockReportingException">Unable to determine EntityType type for {report.EntityType}</exception> public static void BindGrid(Report report, Grid gReport, BindGridOptions bindGridOptions) { if (report == null) { throw new ArgumentNullException("Report must be specified"); } if (!report.EntityTypeId.HasValue) { gReport.Visible = false; return; } var currentPerson = bindGridOptions?.CurrentPerson; var rockContext = new RockContext(); if (!report.IsAuthorized(Authorization.VIEW, currentPerson)) { gReport.Visible = false; return; } Type entityType = EntityTypeCache.Get(report.EntityTypeId.Value, rockContext).GetEntityType(); if (entityType == null) { throw new RockReportException(report, $"Unable to determine EntityType type for {report.EntityType} "); } Stopwatch stopwatch = Stopwatch.StartNew(); gReport.EntityTypeId = report.EntityTypeId; bool isPersonDataSet = report.EntityTypeId == EntityTypeCache.Get(typeof(Rock.Model.Person), true, rockContext).Id; if (isPersonDataSet) { gReport.PersonIdField = "Id"; gReport.DataKeyNames = new string[] { "Id" }; } else { gReport.PersonIdField = null; } if (report.EntityTypeId.HasValue) { gReport.RowItemText = EntityTypeCache.Get(report.EntityTypeId.Value, rockContext).FriendlyName; } List <EntityField> entityFields = Rock.Reporting.EntityHelper.GetEntityFields(entityType, true, false); var selectedEntityFields = new Dictionary <int, EntityField>(); var selectedAttributes = new Dictionary <int, AttributeCache>(); var selectedComponents = new Dictionary <int, ReportField>(); // if there is a selectField, keep it to preserve which items are checked var selectField = gReport.Columns.OfType <SelectField>().FirstOrDefault(); gReport.Columns.Clear(); int columnIndex = 0; if (!string.IsNullOrWhiteSpace(gReport.PersonIdField)) { // if we already had a selectField, use it (to preserve checkbox state) gReport.Columns.Add(selectField ?? new SelectField()); columnIndex++; } var reportFieldSortExpressions = new Dictionary <Guid, string>(); gReport.CommunicateMergeFields = new List <string>(); gReport.CommunicationRecipientPersonIdFields = new List <string>(); foreach (var reportField in report.ReportFields.OrderBy(a => a.ColumnOrder)) { bool isMergeField = reportField.IsCommunicationMergeField.HasValue && reportField.IsCommunicationMergeField.Value; bool isRecipientField = reportField.IsCommunicationRecipientField.HasValue && reportField.IsCommunicationRecipientField.Value; columnIndex++; if (reportField.ReportFieldType == ReportFieldType.Property) { var entityField = entityFields.FirstOrDefault(a => a.Name == reportField.Selection); if (entityField == null) { // if the reportField selection refers to a non-existant entityField, ignore this field continue; } selectedEntityFields.Add(columnIndex, entityField); BoundField boundField = entityField.GetBoundFieldType(); boundField.DataField = string.Format("Entity_{0}_{1}", entityField.Name, columnIndex); boundField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? entityField.Title : reportField.ColumnHeaderText; boundField.SortExpression = boundField.DataField; reportFieldSortExpressions.AddOrReplace(reportField.Guid, boundField.SortExpression); boundField.Visible = reportField.ShowInGrid; gReport.Columns.Add(boundField); if (isMergeField) { gReport.CommunicateMergeFields.Add($"{boundField.DataField}|{boundField.HeaderText.RemoveSpecialCharacters()}"); } if (isRecipientField) { gReport.CommunicationRecipientPersonIdFields.Add(boundField.DataField); } } else if (reportField.ReportFieldType == ReportFieldType.Attribute) { Guid?attributeGuid = reportField.Selection.AsGuidOrNull(); if (attributeGuid == null) { // if an attribute guid is not specified, just ignore this field continue; } var attribute = AttributeCache.Get(attributeGuid.Value, rockContext); if (attribute == null || !attribute.IsActive) { // if the attribute doesn't exist (or no longer exists), or if the active is not active, just ignore this field continue; } selectedAttributes.Add(columnIndex, attribute); BoundField boundField; if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.BOOLEAN.AsGuid())) { boundField = new BoolField(); } else if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.DEFINED_VALUE.AsGuid())) { boundField = new DefinedValueField(); } else { boundField = new CallbackField(); boundField.HtmlEncode = false; (boundField as CallbackField).OnFormatDataValue += (sender, e) => { string resultHtml = null; var attributeValue = e.DataValue ?? attribute.DefaultValueAsType; if (attributeValue != null) { bool condensed = true; resultHtml = attribute.FieldType.Field.FormatValueAsHtml(gReport, attributeValue.ToString(), attribute.QualifierValues, condensed); } e.FormattedValue = resultHtml ?? string.Empty; }; } boundField.DataField = string.Format("Attribute_{0}_{1}", attribute.Id, columnIndex); boundField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? attribute.Name : reportField.ColumnHeaderText; boundField.SortExpression = boundField.DataField; reportFieldSortExpressions.AddOrReplace(reportField.Guid, boundField.SortExpression); if (attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.INTEGER.AsGuid()) || attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.DATE.AsGuid()) || attribute.FieldType.Guid.Equals(Rock.SystemGuid.FieldType.FILTER_DATE.AsGuid())) { boundField.HeaderStyle.HorizontalAlign = HorizontalAlign.Right; boundField.ItemStyle.HorizontalAlign = HorizontalAlign.Right; } boundField.Visible = reportField.ShowInGrid; gReport.Columns.Add(boundField); if (isMergeField) { gReport.CommunicateMergeFields.Add($"{boundField.DataField}|{boundField.HeaderText.RemoveSpecialCharacters()}"); } if (isRecipientField) { gReport.CommunicationRecipientPersonIdFields.Add(boundField.DataField); } } else if (reportField.ReportFieldType == ReportFieldType.DataSelectComponent) { selectedComponents.Add(columnIndex, reportField); DataSelectComponent selectComponent = DataSelectContainer.GetComponent(reportField.DataSelectComponentEntityType.Name); if (selectComponent == null) { throw new RockReportFieldExpressionException(reportField, $"Unable to determine select component for {reportField.DataSelectComponentEntityType.Name}"); } DataControlField columnField = selectComponent.GetGridField(entityType, reportField.Selection ?? string.Empty); string fieldId = $"{selectComponent.ColumnPropertyName}_{columnIndex}"; if (columnField is BoundField) { (columnField as BoundField).DataField = $"Data_{fieldId}"; var customSortProperties = selectComponent.SortProperties(reportField.Selection ?? string.Empty); bool sortReversed = selectComponent.SortReversed(reportField.Selection ?? string.Empty); if (customSortProperties != null) { if (customSortProperties == string.Empty) { // disable sorting if customSortExpression set to string.empty columnField.SortExpression = string.Empty; } else { columnField.SortExpression = customSortProperties.Split(',').Select(a => string.Format("Sort_{0}_{1}", a, columnIndex)).ToList().AsDelimited(","); } } else { // use default sorting if customSortExpression was null columnField.SortExpression = (columnField as BoundField).DataField; } if (sortReversed == true && !string.IsNullOrWhiteSpace(columnField.SortExpression)) { columnField.SortExpression = columnField.SortExpression + " DESC"; } } columnField.HeaderText = string.IsNullOrWhiteSpace(reportField.ColumnHeaderText) ? selectComponent.ColumnHeaderText : reportField.ColumnHeaderText; if (!string.IsNullOrEmpty(columnField.SortExpression)) { reportFieldSortExpressions.AddOrReplace(reportField.Guid, columnField.SortExpression); } columnField.Visible = reportField.ShowInGrid; gReport.Columns.Add(columnField); if (isMergeField) { gReport.CommunicateMergeFields.Add($"Data_{fieldId}|{columnField.HeaderText.RemoveSpecialCharacters()}"); } if (isRecipientField) { string fieldName = (selectComponent is IRecipientDataSelect) ? $"Recipient_{fieldId}" : $"Data_{fieldId}"; gReport.CommunicationRecipientPersonIdFields.Add(fieldName); } } } // if no fields are specified, show the default fields (Previewable/All) for the EntityType var dataColumns = gReport.Columns.OfType <object>().Where(a => a.GetType() != typeof(SelectField)); if (dataColumns.Count() == 0) { // show either the Previewable Columns or all (if there are no previewable columns) bool showAllColumns = !entityFields.Any(a => a.FieldKind == FieldKind.Property && a.IsPreviewable); foreach (var entityField in entityFields.Where(a => a.FieldKind == FieldKind.Property)) { columnIndex++; selectedEntityFields.Add(columnIndex, entityField); BoundField boundField = entityField.GetBoundFieldType(); boundField.DataField = string.Format("Entity_{0}_{1}", entityField.Name, columnIndex); boundField.HeaderText = entityField.Name; boundField.SortExpression = boundField.DataField; boundField.Visible = showAllColumns || entityField.IsPreviewable; gReport.Columns.Add(boundField); } } try { gReport.Visible = true; gReport.ExportFilename = report.Name; SortProperty sortProperty = gReport.SortProperty; if (sortProperty == null) { var reportSort = new SortProperty(); var sortColumns = new Dictionary <string, SortDirection>(); foreach (var reportField in report.ReportFields.Where(a => a.SortOrder.HasValue).OrderBy(a => a.SortOrder.Value)) { if (reportFieldSortExpressions.ContainsKey(reportField.Guid)) { var sortField = reportFieldSortExpressions[reportField.Guid]; if (!string.IsNullOrWhiteSpace(sortField)) { sortColumns.Add(sortField, reportField.SortDirection); } } } if (sortColumns.Any()) { reportSort.Property = sortColumns.Select(a => a.Key + (a.Value == SortDirection.Descending ? " desc" : string.Empty)).ToList().AsDelimited(","); sortProperty = reportSort; } } var qryErrors = new List <string>(); var reportDbContext = bindGridOptions?.ReportDbContext; if (reportDbContext == null) { reportDbContext = Reflection.GetDbContextForEntityType(entityType); } ReportGetQueryableArgs reportGetQueryableArgs = new ReportGetQueryableArgs { ReportDbContext = reportDbContext as Rock.Data.DbContext, EntityFields = selectedEntityFields, Attributes = selectedAttributes, SelectComponents = selectedComponents, SortProperty = sortProperty, DataViewFilterOverrides = bindGridOptions?.DataViewFilterOverrides, DatabaseTimeoutSeconds = bindGridOptions?.DatabaseTimeoutSeconds ?? 180, IsCommunication = bindGridOptions?.IsCommunication ?? false }; dynamic qry = report.GetQueryable(reportGetQueryableArgs); if (!string.IsNullOrEmpty(report.QueryHint) && reportDbContext is RockContext) { using (new QueryHintScope(reportDbContext as RockContext, report.QueryHint)) { gReport.SetLinqDataSource(qry); } } else { gReport.SetLinqDataSource(qry); } gReport.DataBind(); stopwatch.Stop(); ReportService.AddRunReportTransaction(report.Id, Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds)); } catch (Exception ex) { Exception exception = ex; ExceptionLogService.LogException(ex, HttpContext.Current); // recursively find if there was a SQL timeout exception. // A SQL Timeout would be something we might expect, so we'll give that a friendly error message. var sqlTimeoutException = FindSqlTimeoutException(ex); if (sqlTimeoutException != null) { // if there was a SQL Server Timeout, have the warning be a friendly message about that. throw new RockReportException(report, "This report did not complete in a timely manner. You can try again or adjust the timeout setting of this block.", ex); } // if there isn't a SQL Exception, we'll throw the original exception (since it would be an exception that we wouldn't expect) throw; } }