Пример #1
0
        /// <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 RockBoundField();

            // Disable encoding of field content because the value contains markup.
            result.HtmlEncode = false;

            return(result);
        }
Пример #2
0
        /// <summary>
        /// Raises the <see cref="E:System.Web.UI.Control.Init" /> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs" /> object that contains the event data.</param>
        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            if (!this.IsPostBack)
            {
                BindFilter();
            }

            rFilter.ApplyFilterClick   += rFilter_ApplyFilterClick;
            rFilter.DisplayFilterValue += rFilter_DisplayFilterValue;

            gCommunicationTemplates.DataKeyNames      = new string[] { "Id" };
            gCommunicationTemplates.Actions.ShowAdd   = true;
            gCommunicationTemplates.Actions.AddClick += Actions_AddClick;
            gCommunicationTemplates.GridRebind       += gCommunicationTemplates_GridRebind;

            // The created by column/filter should only be displayed if user is allowed to approve
            _canEdit            = IsUserAuthorized(Authorization.EDIT);
            ppCreatedBy.Visible = _canEdit;
            RockBoundField createdByField = gCommunicationTemplates.ColumnsOfType <RockBoundField>().FirstOrDefault(a => a.DataField == "CreatedByPersonAlias.Person.FullName");

            createdByField.Visible = _canEdit;

            SecurityField securityField = gCommunicationTemplates.ColumnsOfType <SecurityField>().FirstOrDefault();

            securityField.EntityTypeId = EntityTypeCache.Read(typeof(Rock.Model.CommunicationTemplate)).Id;

            // make a custom delete confirmation dialog
            gCommunicationTemplates.ShowConfirmDeleteDialog = false;

            string deleteScript = @"
    $('table.js-grid-communicationtemplate-list a.grid-delete-button').click(function( e ){
        var $btn = $(this);
        e.preventDefault();
        Rock.dialogs.confirm('Are you sure you want to delete this template?', function (result) {
            if (result) {
                if ( $btn.closest('tr').hasClass('js-has-communications') ) {
                    Rock.dialogs.confirm('Deleting this template will unlink it from communications that have used it. If you would like to keep the link consider inactivating the template instead. Are you sure you wish to delete this template?', function (result) {
                        if (result) {
                            window.location = e.target.href ? e.target.href : e.target.parentElement.href;
                        }
                    });
                } else {
                    window.location = e.target.href ? e.target.href : e.target.parentElement.href;
                }
            }
        });
    });
";

            ScriptManager.RegisterStartupScript(gCommunicationTemplates, gCommunicationTemplates.GetType(), "deleteCommunicationTemplateScript", deleteScript, true);
        }
Пример #3
0
        /// <summary>
        /// Binds the attendees grid.
        /// </summary>
        private void BindGiversGrid()
        {
            // Get all the selected criteria values
            var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues(drpSlidingDateRange.DelimitedValues);
            var start     = dateRange.Start;
            var end       = dateRange.End;

            var minAmount = nreAmount.LowerValue;
            var maxAmount = nreAmount.UpperValue;

            var currencyTypeIds = new List <int>();

            cblCurrencyTypes.SelectedValues.ForEach(i => currencyTypeIds.Add(i.AsInteger()));

            var sourceTypeIds = new List <int>();

            cblTransactionSource.SelectedValues.ForEach(i => sourceTypeIds.Add(i.AsInteger()));

            var accountIds = new List <int>();

            foreach (var cblAccounts in phAccounts.Controls.OfType <RockCheckBoxList>())
            {
                accountIds.AddRange(cblAccounts.SelectedValuesAsInt);
            }

            var dataViewId = dvpDataView.SelectedValueAsInt();

            GiversViewBy viewBy = GiversViewBy.Giver;

            if (!HideViewByOption)
            {
                viewBy = hfViewBy.Value.ConvertToEnumOrNull <GiversViewBy>() ?? GiversViewBy.Giver;
            }

            // Clear all the existing grid columns
            var selectField    = new SelectField();
            var oldSelectField = gGiversGifts.ColumnsOfType <SelectField>().FirstOrDefault();

            if (oldSelectField != null)
            {
                selectField.SelectedKeys.AddRange(oldSelectField.SelectedKeys);
            }

            gGiversGifts.Columns.Clear();

            // Add a column for selecting rows
            gGiversGifts.Columns.Add(selectField);

            // Add a column for the person's name
            gGiversGifts.Columns.Add(
                new RockBoundField
            {
                DataField      = "PersonName",
                HeaderText     = "Person",
                SortExpression = "LastName,NickName"
            });

            // add a column for email (but is only included on excel export)
            gGiversGifts.Columns.Add(
                new RockBoundField
            {
                DataField           = "Email",
                HeaderText          = "Email",
                SortExpression      = "Email",
                Visible             = false,
                ExcelExportBehavior = ExcelExportBehavior.AlwaysInclude
            });

            // Add a column for total amount
            gGiversGifts.Columns.Add(
                new CurrencyField
            {
                DataField      = "TotalAmount",
                HeaderText     = "Total",
                SortExpression = "TotalAmount"
            });


            // Add columns for the selected account totals
            if (accountIds.Any())
            {
                var accounts = new FinancialAccountService(_rockContext)
                               .Queryable().AsNoTracking()
                               .Where(a => accountIds.Contains(a.Id))
                               .ToList();

                foreach (int accountId in accountIds)
                {
                    var account = accounts.FirstOrDefault(a => a.Id == accountId);
                    if (account != null)
                    {
                        gGiversGifts.Columns.Add(
                            new CurrencyField
                        {
                            DataField      = account.Id.ToString(),
                            HeaderText     = account.Name,
                            SortExpression = account.Id.ToString()
                        });
                    }
                }
            }

            // Add a column for the number of gifts
            var numberGiftsField = new RockBoundField
            {
                DataField        = "NumberGifts",
                HeaderText       = "Number of Gifts",
                SortExpression   = "NumberGifts",
                DataFormatString = "{0:N0}",
            };

            numberGiftsField.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
            gGiversGifts.Columns.Add(numberGiftsField);

            // Add a column to indicate if this is a first time giver
            gGiversGifts.Columns.Add(
                new BoolField
            {
                DataField      = "IsFirstEverGift",
                HeaderText     = "Is First Gift",
                SortExpression = "IsFirstEverGift"
            });

            // Add a column for the first gift date ( that matches criteria )
            gGiversGifts.Columns.Add(
                new DateField
            {
                DataField      = "FirstGift",
                HeaderText     = "First Gift",
                SortExpression = "FirstGift"
            });

            // Add a column for the first-ever gift date ( to any tax-deductible account )
            gGiversGifts.Columns.Add(
                new DateField
            {
                DataField      = "FirstEverGift",
                HeaderText     = "First Gift Ever",
                SortExpression = "FirstEverGift"
            });


            var transactionDetailService = new FinancialTransactionDetailService(_rockContext);
            var personService            = new PersonService(_rockContext);

            // If dataview was selected get the person id's returned by the dataview
            var dataViewPersonIds = new List <int>();

            if (dataViewId.HasValue)
            {
                var dataView = new DataViewService(_rockContext).Get(dataViewId.Value);
                if (dataView != null)
                {
                    var errorMessages = new List <string>();
                    ParameterExpression paramExpression = personService.ParameterExpression;
                    Expression          whereExpression = dataView.GetExpression(personService, paramExpression, out errorMessages);

                    SortProperty sortProperty        = null;
                    var          dataViewPersonIdQry = personService
                                                       .Queryable().AsNoTracking()
                                                       .Where(paramExpression, whereExpression, sortProperty)
                                                       .Select(p => p.Id);
                    dataViewPersonIds = dataViewPersonIdQry.ToList();
                }
            }

            // Check to see if grid should display only people who gave a certain number of times and if so
            // set the min value
            int minCount          = 0;
            var previousPersonIds = new List <int>();

            if (radByPattern.Checked)
            {
                minCount = tbPatternXTimes.Text.AsInteger();
                var missedStart = drpPatternDateRange.LowerValue;
                var missedEnd   = drpPatternDateRange.UpperValue;
                if (missedStart.HasValue && missedEnd.HasValue)
                {
                    // Get the givingids that gave any amount during the pattern's date range. These
                    // are needed so that we know who to exclude from the result set
                    var previousGivingIds = transactionDetailService
                                            .Queryable().AsNoTracking()
                                            .Where(d =>
                                                   d.Transaction.TransactionDateTime.HasValue &&
                                                   d.Transaction.TransactionDateTime.Value >= missedStart.Value &&
                                                   d.Transaction.TransactionDateTime.Value < missedEnd.Value &&
                                                   accountIds.Contains(d.AccountId) &&
                                                   d.Amount != 0.0M)
                                            .Select(d => d.Transaction.AuthorizedPersonAlias.Person.GivingId);

                    // Now get the person ids from the givingids
                    previousPersonIds = personService
                                        .Queryable().AsNoTracking()
                                        .Where(p => previousGivingIds.Contains(p.GivingId))
                                        .Select(p => p.Id)
                                        .ToList();
                }
            }

            // Call the stored procedure to get all the giving data that matches the selected criteria.
            // The stored procedure returns two tables. First is a list of all matching transaction summary
            // information and the second table is each giving leader's first-ever gift date to a tax-deductible account
            DataSet ds = FinancialTransactionDetailService.GetGivingAnalytics(start, end, minAmount, maxAmount,
                                                                              accountIds, currencyTypeIds, sourceTypeIds, dataViewId, viewBy);

            // Get the results table
            DataTable dtResults = ds.Tables[0];

            // Get the first-ever gift dates and load them into a dictionary for faster matching
            DataTable dtFirstEver   = ds.Tables[1];
            var       firstEverVals = new Dictionary <int, DateTime>();

            foreach (DataRow row in ds.Tables[1].Rows)
            {
                if (!DBNull.Value.Equals(row["FirstEverGift"]))
                {
                    firstEverVals.Add((int)row["PersonId"], (DateTime)row["FirstEverGift"]);
                }
            }

            // Add columns to the result set for the first-ever data
            dtResults.Columns.Add(new DataColumn("IsFirstEverGift", typeof(bool)));
            dtResults.Columns.Add(new DataColumn("FirstEverGift", typeof(DateTime)));

            foreach (DataRow row in dtResults.Rows)
            {
                bool rowValid = true;

                // Get the person id
                int personId = (int)row["Id"];

                if (radByPattern.Checked)
                {
                    // If pattern was specified check minimum gifts and other date range
                    int numberGifts = (int)row["NumberGifts"];
                    if (numberGifts < minCount)
                    {
                        rowValid = false;
                    }
                    else
                    {
                        // If this giving leader gave during the pattern date, remove the row since we
                        // only want those who did not
                        if (previousPersonIds.Contains(personId))
                        {
                            rowValid = false;
                        }
                    }
                }

                if (dataViewId.HasValue)
                {
                    // If a dataview filter was specified, and this row is not part of dataview,
                    // remove it
                    if (!dataViewPersonIds.Contains(personId))
                    {
                        rowValid = false;

                        // Remove person id from list so that list can be used later to optionally
                        // add rows for remaining people who were in the dataview, but not in the
                        // result set
                        dataViewPersonIds.Remove(personId);
                    }
                }

                if (rowValid)
                {
                    // Set the first ever information for each row
                    bool     isFirstEverGift = false;
                    DateTime firstGift       = (DateTime)row["FirstGift"];
                    if (firstEverVals.ContainsKey(personId))
                    {
                        DateTime firstEverGift = firstEverVals[personId];
                        isFirstEverGift = firstEverGift.Equals(firstGift);

                        row["FirstEverGift"] = firstEverGift;
                    }

                    // If only first time givers should be included, remove any that are not
                    if (radFirstTime.Checked && !isFirstEverGift)
                    {
                        rowValid = false;
                    }
                    else
                    {
                        row["IsFirstEverGift"] = isFirstEverGift;
                    }
                }

                if (!rowValid)
                {
                    row.Delete();
                }
            }

            // if dataview was selected and it includes people not in the result set,
            if (dataViewId.HasValue && rblDataViewAction.SelectedValue == "All" && dataViewPersonIds.Any())
            {
                // Query for the names of each of these people
                foreach (var person in personService
                         .Queryable().AsNoTracking()
                         .Select(p => new {
                    p.Id,
                    p.Guid,
                    p.NickName,
                    p.LastName,
                    p.Email
                }))
                {
                    // Check for a first ever gift date
                    var firstEverGiftDate = firstEverVals
                                            .Where(f => f.Key == person.Id)
                                            .Select(f => f.Value)
                                            .FirstOrDefault();

                    DataRow row = dtResults.NewRow();
                    row["Id"]              = person.Id;
                    row["Guid"]            = person.Guid;
                    row["NickName"]        = person.NickName;
                    row["LastName"]        = person.LastName;
                    row["PersonName"]      = person.NickName + " " + person.LastName;
                    row["Email"]           = person.Email;
                    row["IsFirstEverGift"] = false;
                    row["FirstEverGift"]   = firstEverGiftDate;
                    dtResults.Rows.Add(row);
                }
            }

            // Update the changes (deletes) in the datatable
            dtResults.AcceptChanges();

            // Calculate Total
            if (viewBy == GiversViewBy.Giver)
            {
                pnlTotal.Visible = true;
                object amountTotalObj = dtResults.Compute("Sum(TotalAmount)", null);
                if (amountTotalObj != null)
                {
                    decimal amountTotal = amountTotalObj.ToString().AsDecimal();
                    lTotal.Text = amountTotal.FormatAsCurrency();
                }
                else
                {
                    lTotal.Text = string.Empty;
                }
            }
            else
            {
                pnlTotal.Visible = false;
            }

            // Sort the results
            System.Data.DataView dv = dtResults.DefaultView;
            if (gGiversGifts.SortProperty != null)
            {
                try
                {
                    var sortProperties = new List <string>();
                    foreach (string prop in gGiversGifts.SortProperty.Property.SplitDelimitedValues(false))
                    {
                        sortProperties.Add(string.Format("[{0}] {1}", prop, gGiversGifts.SortProperty.DirectionString));
                    }
                    dv.Sort = sortProperties.AsDelimited(", ");
                }
                catch
                {
                    dv.Sort = "[LastName] ASC, [NickName] ASC";
                }
            }
            else
            {
                dv.Sort = "[LastName] ASC, [NickName] ASC";
            }

            gGiversGifts.DataSource = dv;
            gGiversGifts.DataBind();
        }
Пример #4
0
        private void CreateGrids(RockContext rockContext)
        {
            if (ContentChannels.Any())
            {
                this.Visible = true;

                phContentChannelGrids.Controls.Clear();

                foreach (var contentChannel in ContentChannels)
                {
                    bool canEdit = UserCanEdit || contentChannel.IsAuthorized(Authorization.EDIT, CurrentPerson);

                    string iconClass = "fa fa-bullhorn";
                    if (!string.IsNullOrWhiteSpace(contentChannel.IconCssClass))
                    {
                        iconClass = contentChannel.IconCssClass;
                    }

                    var pwItems = new PanelWidget();
                    phContentChannelGrids.Controls.Add(pwItems);
                    pwItems.ID       = string.Format("pwItems_{0}", contentChannel.Id);
                    pwItems.Title    = string.Format("<i class='{0}'></i> {1}", iconClass, contentChannel.Name);
                    pwItems.Expanded = ExpandedPanels.Contains(contentChannel.Id);

                    var divItems = new HtmlGenericControl("div");
                    pwItems.Controls.Add(divItems);
                    divItems.ID = string.Format("divItems_{0}", contentChannel.Id);
                    divItems.AddCssClass("grid");
                    divItems.AddCssClass("grid-panel");

                    Grid gItems = new Grid();
                    divItems.Controls.Add(gItems);
                    gItems.ID                = string.Format("gItems_{0}", contentChannel.Id);
                    gItems.DataKeyNames      = new string[] { "Id" };
                    gItems.EmptyDataText     = "No Items Found";
                    gItems.RowItemText       = "Item";
                    gItems.AllowSorting      = true;
                    gItems.Actions.ShowAdd   = canEdit;
                    gItems.IsDeleteEnabled   = canEdit;
                    gItems.Actions.AddClick += gItems_Add;
                    gItems.RowSelected      += gItems_Edit;
                    gItems.GridRebind       += gItems_GridRebind;

                    //
                    // Add the "Link Existing Item" button.
                    //
                    if (OccurrenceId.HasValue)
                    {
                        var lbtnLinkExisting = new LinkButton();
                        lbtnLinkExisting.Attributes.Add("title", "Link Existing Item");
                        lbtnLinkExisting.CommandArgument = contentChannel.Id.ToString();
                        lbtnLinkExisting.CssClass        = "btn btn-default btn-sm";
                        lbtnLinkExisting.Click          += lbtnLinkExisting_Click;
                        lbtnLinkExisting.Text            = "<i class='fa fa-link'></i>";

                        gItems.Actions.AddCustomActionControl(lbtnLinkExisting);
                    }

                    gItems.Columns.Add(new RockBoundField
                    {
                        DataField      = "Title",
                        HeaderText     = "Title",
                        SortExpression = "Title"
                    });

                    if (contentChannel.ContentChannelType.DateRangeType != ContentChannelDateType.NoDates)
                    {
                        RockBoundField startDateTimeField;
                        RockBoundField expireDateTimeField;
                        if (contentChannel.ContentChannelType.IncludeTime)
                        {
                            startDateTimeField  = new DateTimeField();
                            expireDateTimeField = new DateTimeField();
                        }
                        else
                        {
                            startDateTimeField  = new DateField();
                            expireDateTimeField = new DateField();
                        }

                        startDateTimeField.DataField      = "StartDateTime";
                        startDateTimeField.HeaderText     = contentChannel.ContentChannelType.DateRangeType == ContentChannelDateType.DateRange ? "Start" : "Active";
                        startDateTimeField.SortExpression = "StartDateTime";
                        gItems.Columns.Add(startDateTimeField);

                        expireDateTimeField.DataField      = "ExpireDateTime";
                        expireDateTimeField.HeaderText     = "Expire";
                        expireDateTimeField.SortExpression = "ExpireDateTime";
                        if (contentChannel.ContentChannelType.DateRangeType == ContentChannelDateType.DateRange)
                        {
                            gItems.Columns.Add(expireDateTimeField);
                        }
                    }

                    if (!contentChannel.ContentChannelType.DisablePriority)
                    {
                        var priorityField = new RockBoundField
                        {
                            DataField        = "Priority",
                            HeaderText       = "Priority",
                            SortExpression   = "Priority",
                            DataFormatString = "{0:N0}",
                        };
                        priorityField.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
                        gItems.Columns.Add(priorityField);
                    }

                    // Add attribute columns
                    int    entityTypeId = EntityTypeCache.Read(typeof(Rock.Model.ContentChannelItem)).Id;
                    string qualifier    = contentChannel.ContentChannelTypeId.ToString();
                    foreach (var attribute in new AttributeService(rockContext).Queryable()
                             .Where(a =>
                                    a.EntityTypeId == entityTypeId &&
                                    a.IsGridColumn &&
                                    a.EntityTypeQualifierColumn.Equals("ContentChannelTypeId", StringComparison.OrdinalIgnoreCase) &&
                                    a.EntityTypeQualifierValue.Equals(qualifier))
                             .OrderBy(a => a.Order)
                             .ThenBy(a => a.Name))
                    {
                        string dataFieldExpression = attribute.Key;
                        bool   columnExists        = gItems.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;

                            var attributeCache = Rock.Web.Cache.AttributeCache.Read(attribute.Id);
                            if (attributeCache != null)
                            {
                                boundField.ItemStyle.HorizontalAlign = attributeCache.FieldType.Field.AlignValue;
                            }

                            gItems.Columns.Add(boundField);
                        }
                    }

                    if (contentChannel.RequiresApproval && !contentChannel.ContentChannelType.DisableStatus)
                    {
                        var statusField = new BoundField();
                        gItems.Columns.Add(statusField);
                        statusField.DataField      = "Status";
                        statusField.HeaderText     = "Status";
                        statusField.SortExpression = "Status";
                        statusField.HtmlEncode     = false;
                    }

                    var deleteField = new DeleteField();
                    gItems.Columns.Add(deleteField);
                    deleteField.Click += gItems_Delete;
                }
            }
            else
            {
                this.Visible = false;
            }
        }
Пример #5
0
        /// <summary>
        /// Binds the group members grid.
        /// </summary>
        protected void BindParticipantsGrid(bool isExporting = false, bool isCommunication = false)
        {
            if (_stepType == null)
            {
                pnlSteps.Visible = false;
                return;
            }

            pnlSteps.Visible = true;
            rFilter.Visible  = true;
            gSteps.Visible   = true;

            var campusCount = CampusCache.All(false).Count;

            if (campusCount <= 1)
            {
                var campusColumn = gSteps.ColumnsOfType <RockBoundField>().Where(a => a.DataField == "CampusName").FirstOrDefault();
                if (campusColumn != null)
                {
                    campusColumn.Visible = false;
                }
            }

            lHeading.Text = string.Format("{0} Steps", _stepType.Name);

            _fullNameField     = gSteps.ColumnsOfType <RockLiteralField>().Where(a => a.ID == "lExportFullName").FirstOrDefault();
            _nameWithHtmlField = gSteps.ColumnsOfType <RockLiteralField>().Where(a => a.ID == "lNameWithHtml").FirstOrDefault();

            var dataContext = GetDataContext();

            var stepService = new StepService(dataContext);

            var qry = stepService.Queryable()
                      .Include(x => x.StepStatus)
                      .Include(x => x.PersonAlias.Person)
                      .AsNoTracking()
                      .Where(x => x.StepTypeId == _stepType.Id);

            // Filter by First Name
            string firstName = tbFirstName.Text;

            if (!string.IsNullOrWhiteSpace(firstName))
            {
                qry = qry.Where(m =>
                                m.PersonAlias.Person.FirstName.StartsWith(firstName) ||
                                m.PersonAlias.Person.NickName.StartsWith(firstName));
            }

            // Filter by Last Name
            string lastName = tbLastName.Text;

            if (!string.IsNullOrWhiteSpace(lastName))
            {
                qry = qry.Where(m => m.PersonAlias.Person.LastName.StartsWith(lastName));
            }

            // Filter by Step Status
            var validStatusIds = _stepType.StepProgram.StepStatuses.Select(r => r.Id).ToList();

            var statusIds = new List <int>();

            foreach (var statusId in cblStepStatus.SelectedValues.AsIntegerList())
            {
                if (validStatusIds.Contains(statusId))
                {
                    statusIds.Add(statusId);
                }
            }

            if (statusIds.Any())
            {
                qry = qry.Where(m => statusIds.Contains(m.StepStatusId ?? 0));
            }

            // Filter By Start Date
            var startDateRange = DateRangePicker.CalculateDateRangeFromDelimitedValues(drpDateStarted.DelimitedValues);

            if (startDateRange.Start.HasValue)
            {
                qry = qry.Where(m =>
                                m.StartDateTime.HasValue &&
                                m.StartDateTime.Value >= startDateRange.Start.Value);
            }

            if (startDateRange.End.HasValue)
            {
                var exclusiveEndDate = startDateRange.End.Value.Date.AddDays(1);
                qry = qry.Where(m =>
                                m.StartDateTime.HasValue &&
                                m.StartDateTime.Value < exclusiveEndDate);
            }

            // Filter by Date Completed
            var completedDateRange = DateRangePicker.CalculateDateRangeFromDelimitedValues(drpDateCompleted.DelimitedValues);

            if (completedDateRange.Start.HasValue)
            {
                qry = qry.Where(m =>
                                m.CompletedDateTime.HasValue &&
                                m.CompletedDateTime.Value >= completedDateRange.Start.Value);
            }

            if (completedDateRange.End.HasValue)
            {
                var exclusiveEndDate = completedDateRange.End.Value.Date.AddDays(1);
                qry = qry.Where(m =>
                                m.CompletedDateTime.HasValue &&
                                m.CompletedDateTime.Value < exclusiveEndDate);
            }

            // Filter by Note
            string note = tbNote.Text;

            if (!string.IsNullOrWhiteSpace(note))
            {
                qry = qry.Where(m => m.Note.Contains(note));
            }

            var campusId = cpCampusFilter.SelectedCampusId;

            if (campusId != null)
            {
                qry = qry.Where(m => m.CampusId == campusId);
            }

            // Filter query by any configured attribute filters
            if (AvailableAttributes != null && AvailableAttributes.Any())
            {
                foreach (var attribute in AvailableAttributes)
                {
                    var filterControl = phAttributeFilters.FindControl("filter_" + attribute.Id.ToString());
                    qry = attribute.FieldType.Field.ApplyAttributeQueryFilter(qry, filterControl, attribute, stepService, Rock.Reporting.FilterMode.SimpleFilter);
                }
            }

            // Apply Grid Sort
            var sortProperty = gSteps.SortProperty;

            if (sortProperty != null)
            {
                qry = qry.Sort(sortProperty);
            }
            else
            {
                qry = qry.OrderBy(a => a.PersonAlias.Person.LastName).ThenBy(a => a.PersonAlias.Person.FirstName);
            }

            var stepIdQuery = qry.Select(m => m.Id);

            _inactiveStatus = DefinedValueCache.Get(Rock.SystemGuid.DefinedValue.PERSON_RECORD_STATUS_INACTIVE);

            gSteps.EntityTypeId = new Step().TypeId;

            _stepStatusField = gSteps.ColumnsOfType <RockLiteralField>().FirstOrDefault(a => a.ID == lStepStatusHtml.ID);

            _stepDateStartedField = gSteps.ColumnsOfType <RockBoundField>().FirstOrDefault(a => a.HeaderText == "Date Started");

            if (_stepDateStartedField != null)
            {
                _stepDateStartedField.Visible = _stepType.HasEndDate;
            }

            _showNoteColumn = GetAttributeValue(AttributeKey.ShowNoteColumn).AsBoolean();

            gSteps.ColumnsOfType <RockBoundField>().First(a => a.DataField == "Note").Visible = _showNoteColumn;

            var hasDuration = _stepType.HasEndDate;

            var qrySteps = qry.Select(x => new StepParticipantListViewModel
            {
                Id                = x.Id,
                PersonId          = x.PersonAlias.PersonId,
                LastName          = x.PersonAlias.Person.LastName,
                NickName          = x.PersonAlias.Person.NickName,
                StartedDateTime   = x.StartDateTime,
                CompletedDateTime = x.CompletedDateTime,
                StepStatusName    = (x.StepStatus == null ? "" : x.StepStatus.Name),
                IsCompleted       = (x.StepStatus == null ? false : x.StepStatus.IsCompleteStatus),
                Note              = x.Note,
                CampusName        = x.Campus == null ? string.Empty : x.Campus.Name,
                Person            = x.PersonAlias.Person
            });

            // Add the Step data models to the grid object list to allow custom attribute values to be read.
            if (this.AvailableAttributes != null &&
                this.AvailableAttributes.Any())
            {
                gSteps.ObjectList = qry.ToDictionary(k => k.Id.ToString(), v => ( object )v);
            }

            gSteps.SetLinqDataSource(qrySteps);

            gSteps.DataBind();
        }
        private void CreateGrids(RockContext rockContext)
        {
            if (ContentChannels.Any())
            {
                this.Visible = true;

                // TODO: security
                bool canEdit = true;

                phContentChannelGrids.Controls.Clear();

                foreach (var contentChannel in ContentChannels)
                {
                    var pwItems = new PanelWidget();
                    phContentChannelGrids.Controls.Add(pwItems);
                    pwItems.ID       = string.Format("pwItems_{0}", contentChannel.Id);
                    pwItems.Title    = contentChannel.Name;
                    pwItems.Expanded = ExpandedPanels.Contains(contentChannel.Id);

                    var divItems = new HtmlGenericControl("div");
                    pwItems.Controls.Add(divItems);
                    divItems.ID = string.Format("divItems_{0}", contentChannel.Id);
                    divItems.AddCssClass("grid");
                    divItems.AddCssClass("grid-panel");

                    Grid gItems = new Grid();
                    divItems.Controls.Add(gItems);
                    gItems.ID                = string.Format("gItems_{0}", contentChannel.Id);
                    gItems.DataKeyNames      = new string[] { "Id" };
                    gItems.EmptyDataText     = "No Items Found";
                    gItems.RowItemText       = "Item";
                    gItems.AllowSorting      = true;
                    gItems.Actions.ShowAdd   = canEdit;
                    gItems.IsDeleteEnabled   = canEdit;
                    gItems.Actions.AddClick += gItems_Add;
                    gItems.RowSelected      += gItems_Edit;
                    gItems.GridRebind       += gItems_GridRebind;

                    gItems.Columns.Add(new RockBoundField
                    {
                        DataField      = "Title",
                        HeaderText     = "Title",
                        SortExpression = "Title"
                    });

                    if (contentChannel.ContentChannelType.IncludeTime)
                    {
                        gItems.Columns.Add(new DateTimeField
                        {
                            DataField      = "StartDateTime",
                            HeaderText     = contentChannel.ContentChannelType.DateRangeType == ContentChannelDateType.DateRange ? "Start" : "Active",
                            SortExpression = "StartDateTime"
                        });

                        if (contentChannel.ContentChannelType.DateRangeType == ContentChannelDateType.DateRange)
                        {
                            gItems.Columns.Add(new DateTimeField
                            {
                                DataField      = "ExpireDateTime",
                                HeaderText     = "Expire",
                                SortExpression = "ExpireDateTime"
                            });
                        }
                    }
                    else
                    {
                        gItems.Columns.Add(new DateField
                        {
                            DataField      = "StartDateTime",
                            HeaderText     = contentChannel.ContentChannelType.DateRangeType == ContentChannelDateType.DateRange ? "Start" : "Active",
                            SortExpression = "StartDateTime"
                        });

                        if (contentChannel.ContentChannelType.DateRangeType == ContentChannelDateType.DateRange)
                        {
                            gItems.Columns.Add(new DateField
                            {
                                DataField      = "ExpireDateTime",
                                HeaderText     = "Expire",
                                SortExpression = "ExpireDateTime"
                            });
                        }
                    }

                    if (!contentChannel.ContentChannelType.DisablePriority)
                    {
                        var priorityField = new RockBoundField
                        {
                            DataField        = "Priority",
                            HeaderText       = "Priority",
                            SortExpression   = "Priority",
                            DataFormatString = "{0:N0}",
                        };
                        priorityField.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
                        gItems.Columns.Add(priorityField);
                    }

                    // Add attribute columns
                    int    entityTypeId = EntityTypeCache.Read(typeof(Rock.Model.ContentChannelItem)).Id;
                    string qualifier    = contentChannel.ContentChannelTypeId.ToString();
                    foreach (var attribute in new AttributeService(rockContext).Queryable()
                             .Where(a =>
                                    a.EntityTypeId == entityTypeId &&
                                    a.IsGridColumn &&
                                    a.EntityTypeQualifierColumn.Equals("ContentChannelTypeId", StringComparison.OrdinalIgnoreCase) &&
                                    a.EntityTypeQualifierValue.Equals(qualifier))
                             .OrderBy(a => a.Order)
                             .ThenBy(a => a.Name))
                    {
                        string dataFieldExpression = attribute.Key;
                        bool   columnExists        = gItems.Columns.OfType <AttributeField>().FirstOrDefault(a => a.DataField.Equals(dataFieldExpression)) != null;
                        if (!columnExists)
                        {
                            AttributeField boundField = new AttributeField();
                            boundField.DataField      = dataFieldExpression;
                            boundField.HeaderText     = attribute.Name;
                            boundField.SortExpression = string.Empty;

                            var attributeCache = Rock.Web.Cache.AttributeCache.Read(attribute.Id);
                            if (attributeCache != null)
                            {
                                boundField.ItemStyle.HorizontalAlign = attributeCache.FieldType.Field.AlignValue;
                            }

                            gItems.Columns.Add(boundField);
                        }
                    }

                    if (contentChannel.RequiresApproval)
                    {
                        var statusField = new BoundField();
                        gItems.Columns.Add(statusField);
                        statusField.DataField      = "Status";
                        statusField.HeaderText     = "Status";
                        statusField.SortExpression = "Status";
                        statusField.HtmlEncode     = false;
                    }

                    var deleteField = new DeleteField();
                    gItems.Columns.Add(deleteField);
                    deleteField.Click += gItems_Delete;
                }
            }
            else
            {
                this.Visible = false;
            }
        }