public string GetHtmlForBlock( int blockId, int? entityTypeId = null, int? entityId = null )
        {
            RockContext rockContext = this.Service.Context as RockContext ?? new RockContext();
            Block block = new BlockService( rockContext ).Get( blockId );
            if ( block != null )
            {
                block.LoadAttributes();

                string liquidTemplate = block.GetAttributeValue( "LiquidTemplate" );

                var metricCategoryPairList = Rock.Attribute.MetricCategoriesFieldAttribute.GetValueAsGuidPairs( block.GetAttributeValue( "MetricCategories" ) );

                var metricGuids = metricCategoryPairList.Select( a => a.MetricGuid ).ToList();

                bool roundYValues = block.GetAttributeValue( "RoundValues" ).AsBooleanOrNull() ?? true;

                MetricService metricService = new MetricService( rockContext );
                var metrics = metricService.GetByGuids( metricGuids );
                List<object> metricsData = new List<object>();

                if ( metrics.Count() == 0 )
                {
                    return @"<div class='alert alert-warning'> 
								Please select a metric in the block settings.
							</div>";
                }

                MetricValueService metricValueService = new MetricValueService( rockContext );

                DateTime firstDayOfYear = new DateTime( RockDateTime.Now.Year, 1, 1 );
                DateTime currentDateTime = RockDateTime.Now;
                DateTime firstDayOfNextYear = new DateTime( RockDateTime.Now.Year + 1, 1, 1 );

                foreach ( var metric in metrics )
                {
                    var metricYTDData = JsonConvert.DeserializeObject( metric.ToJson(), typeof( MetricYTDData ) ) as MetricYTDData;
                    var qryMeasureValues = metricValueService.Queryable()
                        .Where( a => a.MetricId == metricYTDData.Id )
                        .Where( a => a.MetricValueDateTime >= firstDayOfYear && a.MetricValueDateTime < currentDateTime )
                        .Where( a => a.MetricValueType == MetricValueType.Measure );

                    //// if an entityTypeId/EntityId filter was specified, and the entityTypeId is the same as the metrics.EntityTypeId, filter the values to the specified entityId
                    //// Note: if a Metric or it's Metric Value doesn't have a context, include it regardless of Context setting
                    if ( entityTypeId.HasValue && ( metric.EntityTypeId == entityTypeId || metric.EntityTypeId == null ) )
                    {
                        if ( entityId.HasValue )
                        {
                            qryMeasureValues = qryMeasureValues.Where( a => a.EntityId == entityId || a.EntityId == null );
                        }
                    }

                    var lastMetricValue = qryMeasureValues.OrderByDescending( a => a.MetricValueDateTime ).FirstOrDefault();
                    if ( lastMetricValue != null )
                    {
                        metricYTDData.LastValue = lastMetricValue.YValue.HasValue ? Math.Round( lastMetricValue.YValue.Value, roundYValues ? 0 : 2 ) : (decimal?)null;
                        metricYTDData.LastValueDate = lastMetricValue.MetricValueDateTime.HasValue ? lastMetricValue.MetricValueDateTime.Value.Date : DateTime.MinValue;
                    }

                    decimal? sum = qryMeasureValues.Sum( a => a.YValue );
                    metricYTDData.CumulativeValue = sum.HasValue ? Math.Round( sum.Value, roundYValues ? 0 : 2 ) : (decimal?)null;

                    // figure out goal as of current date time by figuring out the slope of the goal
                    var qryGoalValuesCurrentYear = metricValueService.Queryable()
                        .Where( a => a.MetricId == metricYTDData.Id )
                        .Where( a => a.MetricValueDateTime >= firstDayOfYear && a.MetricValueDateTime < firstDayOfNextYear )
                        .Where( a => a.MetricValueType == MetricValueType.Goal );

                    // if an entityTypeId/EntityId filter was specified, and the entityTypeId is the same as the metrics.EntityTypeId, filter the values to the specified entityId
                    if ( entityTypeId.HasValue && metric.EntityTypeId == entityTypeId )
                    {
                        if ( entityId.HasValue )
                        {
                            qryGoalValuesCurrentYear = qryGoalValuesCurrentYear.Where( a => a.EntityId == entityId );
                        }
                    }

                    MetricValue goalLineStartPoint = qryGoalValuesCurrentYear.Where( a => a.MetricValueDateTime <= currentDateTime ).OrderByDescending( a => a.MetricValueDateTime ).FirstOrDefault();
                    MetricValue goalLineEndPoint = qryGoalValuesCurrentYear.Where( a => a.MetricValueDateTime >= currentDateTime ).FirstOrDefault();
                    if ( goalLineStartPoint != null && goalLineEndPoint != null )
                    {
                        var changeInX = goalLineEndPoint.DateTimeStamp - goalLineStartPoint.DateTimeStamp;
                        var changeInY = goalLineEndPoint.YValue - goalLineStartPoint.YValue;
                        if ( changeInX != 0 )
                        {
                            decimal? slope = changeInY / changeInX;
                            decimal goalValue = ( ( slope * ( currentDateTime.ToJavascriptMilliseconds() - goalLineStartPoint.DateTimeStamp ) ) + goalLineStartPoint.YValue ).Value;
                            metricYTDData.GoalValue = Math.Round( goalValue, roundYValues ? 0 : 2 );
                        }
                    }
                    else
                    {
                        // if there isn't a both a start goal and end goal within the date range, there wouldn't be a goal line shown in a line chart, so don't display a goal in liquid either
                        metricYTDData.GoalValue = null;
                    }

                    metricsData.Add( metricYTDData.ToLiquid() );
                }

                Dictionary<string, object> mergeValues = new Dictionary<string, object>();
                mergeValues.Add( "Metrics", metricsData );

                string resultHtml = liquidTemplate.ResolveMergeFields( mergeValues );

                // show liquid help for debug
                if ( block.GetAttributeValue( "EnableDebug" ).AsBoolean() )
                {
                    resultHtml += mergeValues.lavaDebugInfo();
                }

                return resultHtml;
            }

            return string.Format(
                @"<div class='alert alert-danger'> 
                    unable to find block_id: {1}
                </div>",
                blockId );
        }
Пример #2
0
        /// <summary>
        /// Gets the metric values.
        /// </summary>
        /// <param name="isPrimary">if set to <c>true</c> [is primary].</param>
        /// <returns></returns>
        protected List<MetricValue> GetMetricValues( bool isPrimary )
        {
            var rockContext = new RockContext();
            var metricService = new MetricService( rockContext );
            List<Guid> sourceGuids = null;
            var preKey = isPrimary ? string.Empty : "Comparison";
            IQueryable<MetricValue> metricValues = null;

            var attributeValue = GetAttributeValue( preKey + "MetricSource" );

            if ( string.IsNullOrWhiteSpace( attributeValue ) )
            {
                attributeValue = string.Empty;
            }

            var pairs = MetricCategoriesFieldAttribute.GetValueAsGuidPairs( attributeValue );
            sourceGuids = pairs.Select( p => p.MetricGuid ).ToList();

            if ( sourceGuids.Any() )
            {
                metricValues = metricService.GetByGuids( sourceGuids ).SelectMany( m => m.MetricValues );
            }
            else
            {
                nbMetricWarning.Visible = true;
                pnlMetricDisplay.Visible = false;
                return null;
            }

            if ( GetAttributeValue( preKey + "RespectCampusContext" ).AsBoolean() )
            {
                var campusContext = RockPage.GetCurrentContext( EntityTypeCache.Read( typeof( Campus ) ) );

                if ( campusContext != null )
                {
                    metricValues = FilterMetricValuesByPartition( metricValues, "Campus", campusContext.Id );
                }
            }

            if ( GetAttributeValue( preKey + "RespectGroupContext" ).AsBoolean() )
            {
                var groupTypeContext = RockPage.GetCurrentContext( EntityTypeCache.Read( typeof( GroupType ) ) );
                var groupContext = RockPage.GetCurrentContext( EntityTypeCache.Read( typeof( Group ) ) );

                if ( groupContext != null )
                {
                    metricValues = FilterMetricValuesByPartition( metricValues, "Group", groupContext.Id );
                }
                else if ( groupTypeContext != null )
                {
                    var groupTypeIds = new GroupTypeService( rockContext ).GetAllAssociatedDescendents( groupTypeContext.Id ).Select( gt => gt.Id );
                    var groupIds = new GroupService( rockContext ).Queryable().Where( g => groupTypeIds.Contains( g.GroupTypeId ) ).Select( g => g.Id );
                    metricValues = metricValues.Where( a => a.MetricValuePartitions.Any( mvp => mvp.MetricPartition.Label == "Group" && groupIds.Any( i => i == mvp.EntityId ) ) );
                }
            }

            if ( GetAttributeValue( preKey + "RespectDateContext" ).AsBoolean() )
            {
                var dateRangeString = RockPage.GetUserPreference( ContextPreferenceName );

                if ( !string.IsNullOrWhiteSpace( dateRangeString ) )
                {
                    var dateRange = SlidingDateRangePicker.CalculateDateRangeFromDelimitedValues( dateRangeString );
                    metricValues = metricValues.Where( v => v.MetricValueDateTime >= dateRange.Start && v.MetricValueDateTime <= dateRange.End );
                }
            }

            if ( GetAttributeValue( preKey + "RespectScheduleContext" ).AsBoolean() )
            {
                var scheduleContext = RockPage.GetCurrentContext( EntityTypeCache.Read( typeof( Schedule ) ) );

                if ( scheduleContext != null )
                {
                    metricValues = FilterMetricValuesByPartition( metricValues, "Schedule", scheduleContext.Id );
                }
            }

            return metricValues.ToList();
        }