예제 #1
0
        private static GoogleChartDataTable GetGoogleChartDataTable(Dictionary <string, Dictionary <int, decimal> > fullCategoryYearDictionary, List <int> rangeOfYears, GoogleChartType columnDisplayType)
        {
            var googleChartRowCs             = new List <GoogleChartRowC>();
            var sortedYearCategoryDictionary =
                fullCategoryYearDictionary.OrderBy(x => x.Value.Sum(y => y.Value)).ThenBy(x => x.Key).ToList();

            foreach (var year in rangeOfYears.OrderBy(x => x))
            {
                var googleChartRowVs = new List <GoogleChartRowV> {
                    new GoogleChartRowV(year, year.ToString())
                };
                googleChartRowVs.AddRange(
                    sortedYearCategoryDictionary
                    .Select(x => x.Key)
                    .Select(category => fullCategoryYearDictionary[category][year])
                    .Select(value => new GoogleChartRowV(value, GoogleChartJson.GetFormattedValue((double)value, MeasurementUnitType.Dollars))));

                googleChartRowCs.Add(new GoogleChartRowC(googleChartRowVs));
            }

            var columnLabel        = FieldDefinition.ReportingYear.GetFieldDefinitionLabel();
            var googleChartColumns = new List <GoogleChartColumn> {
                new GoogleChartColumn(columnLabel, columnLabel, "string")
            };

            googleChartColumns.AddRange(
                sortedYearCategoryDictionary.Select(
                    x => new GoogleChartColumn(x.Key, x.Key, "number", new GoogleChartSeries(columnDisplayType, GoogleChartAxisType.Primary), null, null)));

            return(new GoogleChartDataTable(googleChartColumns, googleChartRowCs));
        }
예제 #2
0
        //TODO: The GetFullCategoryYearDictionary and GetGoogleChartDataTable functions are probably fine in this Extension class, but the ToGoogleChart functions are more about display and probably could be in a better location
        public static GoogleChartJson ToGoogleChart(this IEnumerable <ProjectGrantAllocationExpenditure> projectGrantAllocationExpenditures,
                                                    Func <ProjectGrantAllocationExpenditure, string> filterFunction,
                                                    List <string> filterValues,
                                                    Func <ProjectGrantAllocationExpenditure, IComparable> sortFunction,
                                                    List <int> rangeOfYears,
                                                    string chartContainerID,
                                                    string chartTitle,
                                                    GoogleChartType googleChartType,
                                                    bool isStacked)
        {
            var fullCategoryYearDictionary = GetFullCategoryYearDictionary(projectGrantAllocationExpenditures, filterFunction, filterValues, sortFunction, rangeOfYears);
            var googleChartDataTable       = GetGoogleChartDataTable(fullCategoryYearDictionary, rangeOfYears, googleChartType);
            var googleChartAxis            = new GoogleChartAxis("Annual Expenditures", MeasurementUnitTypeEnum.Dollars, GoogleChartAxisLabelFormat.Short);
            var googleChartConfiguration   = new GoogleChartConfiguration(chartTitle,
                                                                          isStacked,
                                                                          googleChartType,
                                                                          googleChartDataTable,
                                                                          new GoogleChartAxis(FieldDefinition.ReportingYear.GetFieldDefinitionLabel(), null, null),
                                                                          new List <GoogleChartAxis> {
                googleChartAxis
            });
            var googleChart = new GoogleChartJson(chartTitle, chartContainerID, googleChartConfiguration,
                                                  googleChartType, googleChartDataTable, null);

            return(googleChart);
        }
예제 #3
0
        private static void EnlargeGoogleChart(GoogleChartJson googleChartJson)
        {
            var       googleChartConfiguration = googleChartJson.GoogleChartConfiguration;
            const int fontSizeIncrease         = 8;

            googleChartConfiguration.TitlePosition = "top";

            // Use default TitleTextStyle for consistency across enlarged charts.
            googleChartConfiguration.TitleTextStyle = null;

            IncreaseGoogleChartTextStyleFontSizeIfPresent(googleChartConfiguration.LegendTextStyle, fontSizeIncrease / 2, false);
            IncreaseGoogleChartTextStyleFontSizeIfPresent(googleChartConfiguration.HorizontalAxis.TitleTextStyle, fontSizeIncrease, true);

            if (googleChartConfiguration.VerticalAxes != null)
            {
                foreach (var vaxis in googleChartConfiguration.VerticalAxes)
                {
                    IncreaseGoogleChartTextStyleFontSizeIfPresent(vaxis.TitleTextStyle, fontSizeIncrease, true);
                }
            }

            //Make lines thicker on Line and Combo charts (but NOT on area charts)
            if (!googleChartJson.ChartType.Equals(GoogleChartType.AreaChart.GoogleChartTypeDisplayName, StringComparison.InvariantCultureIgnoreCase))
            {
                googleChartConfiguration.LineWidth = 6;
            }

            //Since PieCharts are square, we have plenty of side area and this will always be the ideal legend placement
            if (googleChartJson.ChartType.Equals(GoogleChartType.PieChart.GoogleChartTypeDisplayName, StringComparison.InvariantCultureIgnoreCase))
            {
                googleChartConfiguration.Legend.Position = "labeled";
            }
        }
예제 #4
0
        public ForwardLookingFactSheetViewData(Person currentPerson,
                                               Models.Project project,
                                               ProjectLocationSummaryMapInitJson projectLocationSummaryMapInitJson,
                                               GoogleChartJson googleChartJson,
                                               List <GooglePieChartSlice> grantAllocationRequestAmountGooglePieChartSlices, Models.FirmaPage firmaPageFactSheetCustomText) : base(currentPerson, project)
        {
            PageTitle       = project.DisplayName;
            BreadCrumbTitle = "Fact Sheet";

            PerformanceMeasureExpectedValues = project.PerformanceMeasureExpecteds.GroupBy(x => x.PerformanceMeasure, new HavePrimaryKeyComparer <Models.PerformanceMeasure>())
                                               .OrderBy(x => x.Key.PerformanceMeasureSortOrder).ThenBy(x => x.Key.PerformanceMeasureDisplayName).ToList();

            KeyPhoto = project.KeyPhoto;
            ProjectImagesExceptKeyPhotoGroupedByTiming = project.ProjectImages.Where(x => !x.IsKeyPhoto && x.ProjectImageTiming != ProjectImageTiming.Unknown && !x.ExcludeFromFactSheet)
                                                         .GroupBy(x => x.ProjectImageTiming).OrderBy(x => x.Key.SortOrder).ToList();
            ProjectImagesPerTimingGroup = ProjectImagesExceptKeyPhotoGroupedByTiming.Count == 1 ? 6 : 2;
            Classifications             = project.ProjectClassifications.Select(x => x.Classification).ToList().SortByOrderThenName().ToList();

            ProjectLocationSummaryMapInitJson = projectLocationSummaryMapInitJson;
            GoogleChartJson = googleChartJson;
            GrantAllocationRequestAmountGooglePieChartSlices = grantAllocationRequestAmountGooglePieChartSlices;

            //Dynamically resize chart based on how much space the legend requires
            CalculatedChartHeight = 350 - (GrantAllocationRequestAmountGooglePieChartSlices.Count <= 2
                                        ? GrantAllocationRequestAmountGooglePieChartSlices.Count * 24
                                        : GrantAllocationRequestAmountGooglePieChartSlices.Count * 20);
            FactSheetPdfUrl = SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.FactSheetPdf(project));

            if (project.ProjectType == null)
            {
                TaxonomyColor = "blue";
            }
            else
            {
                switch (MultiTenantHelpers.GetTaxonomyLevel().ToEnum)
                {
                case TaxonomyLevelEnum.Leaf:
                    TaxonomyColor = project.ProjectType.ThemeColor;
                    break;

                case TaxonomyLevelEnum.Branch:
                    TaxonomyColor = project.ProjectType.TaxonomyBranch.ThemeColor;
                    break;

                case TaxonomyLevelEnum.Trunk:
                    TaxonomyColor = project.ProjectType.TaxonomyBranch.TaxonomyTrunk.ThemeColor;
                    break;
                }
            }

            ProjectTypeName             = project.ProjectType == null ? $"{Models.FieldDefinition.Project.GetFieldDefinitionLabel()} Taxonomy Not Set" : project.ProjectType.DisplayName;
            TaxonomyBranchName          = project.ProjectType == null ? $"{Models.FieldDefinition.Project.GetFieldDefinitionLabel()} Taxonomy Not Set" : project.ProjectType.TaxonomyBranch.DisplayName;
            ProjectTypeDisplayName      = Models.FieldDefinition.ProjectType.GetFieldDefinitionLabel();
            EstimatedTotalCost          = Project.EstimatedTotalCost.HasValue ? Project.EstimatedTotalCost.ToStringCurrency() : "";
            NoGrantAllocationIdentified = project.GetNoGrantAllocationIdentifiedAmount() != null?Project.GetNoGrantAllocationIdentifiedAmount().ToStringCurrency() : "";

            GrandAllocation             = project.ProjectGrantAllocationRequests.Any() ? project.ProjectGrantAllocationRequests.Sum(x => x.TotalAmount).ToStringCurrency() : ViewUtilities.Unknown;
            CustomFactSheetTextViewData = new ViewPageContentViewData(firmaPageFactSheetCustomText, false);
        }
        public static GoogleChartDataTable GetGoogleChartDataTableWithReportingPeriodsAsHorixontalAxis(PerformanceMeasure performanceMeasure,
                                                                                                       ICollection <PerformanceMeasureReportingPeriod> performanceMeasureReportingPeriods,
                                                                                                       bool hasTargets,
                                                                                                       IReadOnlyCollection <IGrouping <Tuple <string, int>, PerformanceMeasureReportingPeriodSubcategoryOptionReportedValue> > groupedBySubcategoryOption,
                                                                                                       IEnumerable <string> subcategoryOptions,
                                                                                                       bool hasToolTipWithTotal)
        {
            var googleChartRowCs = new List <GoogleChartRowC>();

            foreach (var performanceMeasureReportingPeriod in performanceMeasureReportingPeriods.OrderBy(x => x.PerformanceMeasureReportingPeriodBeginDate))
            {
                var googleChartRowVs = new List <GoogleChartRowV> {
                    new GoogleChartRowV(performanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodLabel)
                };
                if (hasTargets)
                {
                    googleChartRowVs.Add(new GoogleChartRowV(performanceMeasureReportingPeriod.TargetValue, GetFormattedTargetValue(performanceMeasureReportingPeriod, performanceMeasure)));
                }
                if (hasToolTipWithTotal)
                {
                    googleChartRowVs.Add(new GoogleChartRowV(null, FormattedDataTooltip(groupedBySubcategoryOption, performanceMeasureReportingPeriod, performanceMeasure.MeasurementUnitType)));
                }
                googleChartRowVs.AddRange(groupedBySubcategoryOption.OrderBy(x => x.Key.Item2).Select(x =>
                {
                    var calendarYearReportedValue = x.Where(isorv => isorv.PerformanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodLabel == performanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodLabel)
                                                    .Sum(isorv => isorv.ReportedValue) ?? 0;
                    return(new GoogleChartRowV(calendarYearReportedValue, GoogleChartJson.GetFormattedValue(calendarYearReportedValue, performanceMeasure.MeasurementUnitType)));
                }));

                googleChartRowCs.Add(new GoogleChartRowC(googleChartRowVs));
            }

            // reporting period is going to be the first column and it will be our horizontal axis
            var googleChartColumns = new List <GoogleChartColumn> {
                new GoogleChartColumn("Reporting Period", GoogleChartColumnDataType.String)
            };

            if (hasTargets)
            {
                // GoogleChartType for targets is always LINE; we also always render the target line first to stay consistent
                googleChartColumns.Add(new GoogleChartColumn(GetTargetColumnLabel(performanceMeasureReportingPeriods), GoogleChartColumnDataType.Number));
            }

            // add column with row tooltip
            if (hasToolTipWithTotal)
            {
                googleChartColumns.Add(new GoogleChartColumn(GoogleChartColumnDataType.String.ColumnDataType, "tooltip", new GoogleChartProperty()));
            }

            // all the subcategory option values are individual columns and series and they will be on the vertical axis
            googleChartColumns.AddRange(subcategoryOptions.Select(x => new GoogleChartColumn(x, GoogleChartColumnDataType.Number)));

            var googleChartDataTable = new GoogleChartDataTable(googleChartColumns, googleChartRowCs);

            return(googleChartDataTable);
        }
예제 #6
0
        public ViewResult FundingStatus()
        {
            var firmaPage       = FirmaPageTypeEnum.FundingStatusHeader.GetFirmaPage();
            var firmaPageFooter = FirmaPageTypeEnum.FundingStatusFooter.GetFirmaPage();

            // set up Funding Summary pie chart
            var summaryChartTitle       = "NTA Funding Summary";
            var summaryChartContainerID = summaryChartTitle.Replace(" ", "");
            var googlePieChartSlices    = ProjectModelExtensions.GetFundingStatusPieChartSlices();
            var googleChartDataTable    = ProjectModelExtensions.GetFundingStatusSummaryGoogleChartDataTable(googlePieChartSlices);
            var summaryConfiguration    = new GooglePieChartConfiguration(summaryChartTitle, MeasurementUnitTypeEnum.Dollars, googlePieChartSlices, GoogleChartType.PieChart, googleChartDataTable)
            {
                PieSliceText = "value-and-percentage"
            };

            summaryConfiguration.ChartArea.Top = 60;
            var summaryGoogleChart = new GoogleChartJson(summaryChartTitle, summaryChartContainerID, summaryConfiguration,
                                                         GoogleChartType.PieChart, googleChartDataTable, null);

            summaryGoogleChart.CanConfigureChart = false;

            // set up Funding by Owner Org Type column chart
            var statusByOrgTypeChartTitle = "NTA Funding Status by NTA Owner Organization Type";
            var orgTypeChartContainerID   = statusByOrgTypeChartTitle.Replace(" ", "");
            var googleChartAxisHorizontal = new GoogleChartAxis("NTA Organization Type", null, null)
            {
                Gridlines = new GoogleChartGridlinesOptions(-1, "transparent")
            };
            var googleChartAxis          = new GoogleChartAxis("Total Budget", MeasurementUnitTypeEnum.Dollars, GoogleChartAxisLabelFormat.Decimal);
            var googleChartAxisVerticals = new List <GoogleChartAxis> {
                googleChartAxis
            };
            var orgTypeToAmounts            = ProjectModelExtensions.GetFundingForAllProjectsByOwnerOrgType(CurrentFirmaSession);
            var orgTypeGoogleChartDataTable = ProjectModelExtensions.GetFundingStatusByOwnerOrgTypeGoogleChartDataTable(orgTypeToAmounts);
            var orgTypeChartConfig          = new GoogleChartConfiguration(statusByOrgTypeChartTitle, true, GoogleChartType.ColumnChart, orgTypeGoogleChartDataTable, googleChartAxisHorizontal, googleChartAxisVerticals);

            // need to ignore null GoogleChartSeries so the custom colors match up to the column chart correctly
            orgTypeChartConfig.SetSeriesIgnoringNullGoogleChartSeries(orgTypeGoogleChartDataTable);
            orgTypeChartConfig.Tooltip = new GoogleChartTooltip(true);
            orgTypeChartConfig.Legend.SetLegendPosition(GoogleChartLegendPosition.None);
            var orgTypeGoogleChart = new GoogleChartJson(statusByOrgTypeChartTitle, orgTypeChartContainerID, orgTypeChartConfig, GoogleChartType.ColumnChart, orgTypeGoogleChartDataTable, orgTypeToAmounts.Keys.Select(x => x.OrganizationTypeName).ToList());

            orgTypeGoogleChart.CanConfigureChart = false;

            var viewData = new FundingStatusViewData(CurrentFirmaSession, firmaPage, firmaPageFooter, summaryGoogleChart, orgTypeGoogleChart);

            return(RazorView <FundingStatus, FundingStatusViewData>(viewData));
        }
        public static List <GoogleChartJson> MakeGoogleChartJsons(PerformanceMeasure performanceMeasure, List <ProjectPerformanceMeasureReportingPeriodValue> projectPerformanceMeasureReportingPeriodValues)
        {
            var performanceMeasureSubcategoryOptionReportedValues = projectPerformanceMeasureReportingPeriodValues.SelectMany(x => x.PerformanceMeasureSubcategoryOptionReportedValues).GroupBy(x => x.PerformanceMeasureSubcategory);
            var performanceMeasureReportingPeriods = projectPerformanceMeasureReportingPeriodValues.Select(x => x.PerformanceMeasureReportingPeriod).Distinct(new HavePrimaryKeyComparer <PerformanceMeasureReportingPeriod>()).ToList();
            var googleChartJsons = new List <GoogleChartJson>();

            foreach (var groupedBySubcategory in performanceMeasureSubcategoryOptionReportedValues.Where(x => x.Key.ShowOnChart))
            {
                var performanceMeasureSubcategory = groupedBySubcategory.Key;
                Check.RequireNotNull(performanceMeasureSubcategory.ChartConfigurationJson, "All PerformanceMeasure Subcategories need to have a Google Chart Configuration Json");
                var groupedBySubcategoryOption = groupedBySubcategory.GroupBy(c => new Tuple <string, int>(c.ChartName, c.SortOrder)).ToList(); // Item1 is ChartName, Item2 is SortOrder
                var chartColumns = performanceMeasure.HasRealSubcategories ? groupedBySubcategoryOption.OrderBy(x => x.Key.Item2).Select(x => x.Key.Item1).ToList() : new List <string> {
                    performanceMeasure.DisplayName
                };
                var hasTargets           = GetTargetValueType(performanceMeasureReportingPeriods) != PerformanceMeasureTargetValueType.NoTarget;
                var googleChartDataTable = performanceMeasure.SwapChartAxes
                    ? GetGoogleChartDataTableWithReportingPeriodsAsVerticalAxis(performanceMeasure, hasTargets, performanceMeasureReportingPeriods, groupedBySubcategoryOption)
                    : GetGoogleChartDataTableWithReportingPeriodsAsHorixontalAxis(performanceMeasure, performanceMeasureReportingPeriods, hasTargets, groupedBySubcategoryOption, chartColumns, performanceMeasure.CanCalculateTotal);
                var legendTitle          = performanceMeasure.HasRealSubcategories ? performanceMeasureSubcategory.PerformanceMeasureSubcategoryDisplayName : performanceMeasure.DisplayName;
                var chartName            = $"{performanceMeasure.GetJavascriptSafeChartUniqueName()}PerformanceMeasureSubcategory{performanceMeasureSubcategory.PerformanceMeasureSubcategoryID}";
                var saveConfigurationUrl = SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x =>
                                                                                                             x.SaveChartConfiguration(performanceMeasure,
                                                                                                                                      performanceMeasureSubcategory.PerformanceMeasureSubcategoryID));

                var resetConfigurationUrl =
                    SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x =>
                                                                                      x.ResetChartConfiguration(performanceMeasure,
                                                                                                                performanceMeasureSubcategory.PerformanceMeasureSubcategoryID));

                var chartConfiguration = JsonConvert.DeserializeObject <GoogleChartConfiguration>(performanceMeasureSubcategory.ChartConfigurationJson);
                if (performanceMeasureSubcategory.PerformanceMeasure.CanCalculateTotal && !performanceMeasure.SwapChartAxes)
                {
                    chartConfiguration.Tooltip = new GoogleChartTooltip(true);
                }

                var googleChartJson = new GoogleChartJson(legendTitle, chartName, chartConfiguration,
                                                          performanceMeasureSubcategory.GoogleChartType, googleChartDataTable,
                                                          chartColumns, saveConfigurationUrl, resetConfigurationUrl);
                googleChartJsons.Add(googleChartJson);
            }
            return(googleChartJsons);
        }
예제 #8
0
 public FundingStatusViewData(FirmaSession currentFirmaSession, ProjectFirmaModels.Models.FirmaPage firmaPage, ProjectFirmaModels.Models.FirmaPage fundingStatusFooter, GoogleChartJson summaryGoogleChart, GoogleChartJson orgTypeGoogleChart) : base(currentFirmaSession, firmaPage)
 {
     FundingStatusFooterViewPageContentViewData  = new ViewPageContentViewData(fundingStatusFooter, currentFirmaSession);
     SummaryViewGoogleChartViewData              = new ViewGoogleChartViewData(summaryGoogleChart, summaryGoogleChart.GoogleChartConfiguration.Title, 350, true, true);
     StatusByOwnerOrgTypeViewGoogleChartViewData = new ViewGoogleChartViewData(orgTypeGoogleChart, orgTypeGoogleChart.GoogleChartConfiguration.Title, 400, true);
 }
        public BackwardLookingFactSheetViewData(FirmaSession currentFirmaSession, ProjectFirmaModels.Models.Project project,
                                                ProjectLocationSummaryMapInitJson projectLocationSummaryMapInitJson,
                                                GoogleChartJson projectFactSheetGoogleChart,
                                                List <GooglePieChartSlice> expenditureGooglePieChartSlices, List <string> chartColorRange,
                                                ProjectFirmaModels.Models.FirmaPage firmaPageFactSheet,
                                                List <TechnicalAssistanceParameter> technicalAssistanceParameters,
                                                bool withCustomAttributes,
                                                ProjectController.FactSheetPdfEnum factSheetPdfEnum) : base(currentFirmaSession, project)
        {
            PageTitle       = project.GetDisplayName();
            BreadCrumbTitle = "Fact Sheet";

            EstimatedTotalCost        = Project.GetEstimatedTotalRegardlessOfFundingType().HasValue ? Project.GetEstimatedTotalRegardlessOfFundingType().ToStringCurrency() : "";
            NoFundingSourceIdentified = project.GetNoFundingSourceIdentifiedAmount() != null?Project.GetNoFundingSourceIdentifiedAmount().ToStringCurrency() : "";

            ProjectedFunding = Project.GetProjectedFunding().ToStringCurrency();

            PerformanceMeasureReportedValues =
                project.GetPerformanceMeasureReportedValues().GroupBy(x => x.PerformanceMeasure).OrderBy(x => x.Key.PerformanceMeasureSortOrder).ThenBy(x => x.Key.PerformanceMeasureDisplayName).ToList();
            PerformanceMeasureExpectedValues = project.PerformanceMeasureExpecteds.GroupBy(x => x.PerformanceMeasure, new HavePrimaryKeyComparer <ProjectFirmaModels.Models.PerformanceMeasure>())
                                               .OrderBy(x => x.Key.PerformanceMeasureSortOrder).ThenBy(x => x.Key.PerformanceMeasureDisplayName).ToList();

            ShowExpectedPerformanceMeasures =
                MultiTenantHelpers.GetTenantAttributeFromCache().ShowExpectedPerformanceMeasuresOnFactSheet&&
                (project.ProjectStage == ProjectStage.Implementation || project.ProjectStage == ProjectStage.PostImplementation) && !PerformanceMeasureReportedValues.Any();

            ChartID  = $"fundingChartForProject{project.ProjectID}";
            KeyPhoto = project.GetKeyPhoto();
            ProjectImagesExceptKeyPhotoGroupedByTiming =
                project.ProjectImages.Where(x => !x.IsKeyPhoto && x.ProjectImageTiming != ProjectImageTiming.Unknown && !x.ExcludeFromFactSheet)
                .GroupBy(x => x.ProjectImageTiming)
                .OrderBy(x => x.Key.SortOrder)
                .ToList();
            ProjectImagesPerTimingGroup = ProjectImagesExceptKeyPhotoGroupedByTiming.Count == 1 ? 6 : 2;
            Classifications             = project.ProjectClassifications.Select(x => x.Classification).ToList().SortByOrderThenName().ToList();

            ProjectLocationSummaryMapInitJson = projectLocationSummaryMapInitJson;
            GoogleChartJson = projectFactSheetGoogleChart;

            ExpenditureGooglePieChartSlices = expenditureGooglePieChartSlices;
            ChartColorRange = chartColorRange;
            //Dynamically resize chart based on how much space the legend requires
            CalculatedChartHeight = 350 - ExpenditureGooglePieChartSlices.Count * 19;
            FactSheetPdfUrl       = SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.FactSheetPdf(project));

            FactSheetWithCustomAttributesPdfUrl = SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.FactSheetWithCustomAttributesPdf(project));

            if (project.GetTaxonomyLeaf() == null)
            {
                TaxonomyColor = "blue";
            }
            else
            {
                switch (MultiTenantHelpers.GetTaxonomyLevel().ToEnum)
                {
                case TaxonomyLevelEnum.Leaf:
                    TaxonomyColor = project.GetTaxonomyLeaf().ThemeColor;
                    break;

                case TaxonomyLevelEnum.Branch:
                    TaxonomyColor = project.GetTaxonomyLeaf().TaxonomyBranch.ThemeColor;
                    break;

                case TaxonomyLevelEnum.Trunk:
                    TaxonomyColor = project.GetTaxonomyLeaf().TaxonomyBranch.TaxonomyTrunk.ThemeColor;
                    break;
                }
            }
            TaxonomyLeafName                = project.GetTaxonomyLeaf() == null ? $"{FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} Taxonomy Not Set" : project.GetTaxonomyLeaf().GetDisplayName();
            TaxonomyBranchName              = project.GetTaxonomyLeaf() == null ? $"{FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} Taxonomy Not Set" : project.GetTaxonomyLeaf().TaxonomyBranch.GetDisplayName();
            TaxonomyLeafDisplayName         = FieldDefinitionEnum.TaxonomyLeaf.ToType().GetFieldDefinitionLabel();
            PrimaryContactPerson            = project.GetPrimaryContact();
            CustomFactSheetPageTextViewData = new ViewPageContentViewData(firmaPageFactSheet, false);
            TechnicalAssistanceParameters   = technicalAssistanceParameters;
            TechnicalAssistanceRequests     = project.TechnicalAssistanceRequests.ToList();

            ViewableProjectCustomAttributeTypes = HttpRequestStorage.DatabaseEntities.ProjectCustomAttributeTypes.ToList().Where(x => x.HasViewPermission(currentFirmaSession) && x.IsViewableOnFactSheet).ToList();
            ViewableProjectCustomAttributes     = project.ProjectCustomAttributes.Where(x => x.ProjectCustomAttributeType.HasViewPermission(currentFirmaSession) && ViewableProjectCustomAttributeTypes.Contains(x.ProjectCustomAttributeType)).ToList();

            WithCustomAttributes = withCustomAttributes;
            LastUpdated          = project.LastUpdatedDate;
            FactSheetPdfEnum     = factSheetPdfEnum;

            // No delay loading our fake image by default
            int fakeImageDelayInMilliseconds = 0;

            // When set the page is being rendered for PDF
            if (factSheetPdfEnum == ProjectController.FactSheetPdfEnum.Pdf)
            {
                // If we are printing for PDF, we have a fake 1x1 transparent image that we deliberately take time to load. This causes Headless Chrome
                // to delay printing the page until the map is ready to be viewed.
                //
                // We hope that 4 seconds is enough to allow the mapping components to load. Increase if they don't render properly.
                fakeImageDelayInMilliseconds = ForwardLookingFactSheetViewData.FactSheetPdfEmptyImageLoadDelayInMilliseconds;
            }

            FakeImageWithDelayUrl = new SitkaRoute <FakeImageController>(c => c.ReturnEmptyImageAfterDelayInMilliseconds(fakeImageDelayInMilliseconds)).BuildAbsoluteUrlHttpsFromExpression();

            ProjectLocationIsProvided = project.ProjectLocationPoint != null || project.ProjectLocations.Any();
        }
        public BackwardLookingFactSheetViewData(Person currentPerson, Models.Project project,
                                                ProjectLocationSummaryMapInitJson projectLocationSummaryMapInitJson,
                                                GoogleChartJson projectFactSheetGoogleChart,
                                                List <GooglePieChartSlice> expenditureGooglePieChartSlices, List <string> chartColorRange,
                                                Models.FirmaPage firmaPageFactSheet) : base(currentPerson, project)
        {
            PageTitle       = project.DisplayName;
            BreadCrumbTitle = "Fact Sheet";

            EstimatedTotalCost          = Project.EstimatedTotalCost.HasValue ? Project.EstimatedTotalCost.ToStringCurrency() : "";
            NoGrantAllocationIdentified = project.GetNoGrantAllocationIdentifiedAmount() != null?Project.GetNoGrantAllocationIdentifiedAmount().ToStringCurrency() : "";

            TotalFunding = Project.GetTotalFunding() != null?Project.GetTotalFunding().ToStringCurrency() : "";

            const bool userCanAddPhotosToThisProject = false;
            var        newPhotoForProjectUrl         = string.Empty;
            var        selectKeyImageUrl             = string.Empty;
            var        galleryName = $"ProjectImage{project.ProjectID}";

            ImageGalleryViewData = new ImageGalleryViewData(currentPerson,
                                                            galleryName,
                                                            project.ProjectImages,
                                                            userCanAddPhotosToThisProject,
                                                            newPhotoForProjectUrl,
                                                            selectKeyImageUrl,
                                                            true,
                                                            x => x.CaptionOnFullView,
                                                            "Photo");

            PerformanceMeasureReportedValues =
                project.GetReportedPerformanceMeasures().GroupBy(x => x.PerformanceMeasure).OrderBy(x => x.Key.PerformanceMeasureSortOrder).ThenBy(x => x.Key.PerformanceMeasureDisplayName).ToList();

            ChartID  = $"fundingChartForProject{project.ProjectID}";
            KeyPhoto = project.KeyPhoto;
            ProjectImagesExceptKeyPhotoGroupedByTiming =
                project.ProjectImages.Where(x => !x.IsKeyPhoto && x.ProjectImageTiming != ProjectImageTiming.Unknown && !x.ExcludeFromFactSheet)
                .GroupBy(x => x.ProjectImageTiming)
                .OrderBy(x => x.Key.SortOrder)
                .ToList();
            ProjectImagesPerTimingGroup = ProjectImagesExceptKeyPhotoGroupedByTiming.Count == 1 ? 6 : 2;
            Classifications             = project.ProjectClassifications.Select(x => x.Classification).ToList().SortByOrderThenName().ToList();

            ProjectLocationSummaryMapInitJson = projectLocationSummaryMapInitJson;
            GoogleChartJson = projectFactSheetGoogleChart;

            ExpenditureGooglePieChartSlices = expenditureGooglePieChartSlices;
            ChartColorRange = chartColorRange;
            //Dynamically resize chart based on how much space the legend requires
            CalculatedChartHeight = 350 - ExpenditureGooglePieChartSlices.Count * 19;
            FactSheetPdfUrl       = SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.FactSheetPdf(project));

            if (project.ProjectType == null)
            {
                TaxonomyColor = "blue";
            }
            else
            {
                switch (MultiTenantHelpers.GetTaxonomyLevel().ToEnum)
                {
                case TaxonomyLevelEnum.Leaf:
                    TaxonomyColor = project.ProjectType.ThemeColor;
                    break;

                case TaxonomyLevelEnum.Branch:
                    TaxonomyColor = project.ProjectType.TaxonomyBranch.ThemeColor;
                    break;

                case TaxonomyLevelEnum.Trunk:
                    TaxonomyColor = project.ProjectType.TaxonomyBranch.TaxonomyTrunk.ThemeColor;
                    break;
                }
            }
            ProjectTypeName                 = project.ProjectType == null ? $"{Models.FieldDefinition.Project.GetFieldDefinitionLabel()} Taxonomy Not Set" : project.ProjectType.DisplayName;
            TaxonomyBranchName              = project.ProjectType == null ? $"{Models.FieldDefinition.Project.GetFieldDefinitionLabel()} Taxonomy Not Set" : project.ProjectType.TaxonomyBranch.DisplayName;
            ProjectTypeDisplayName          = Models.FieldDefinition.ProjectType.GetFieldDefinitionLabel();
            PrimaryContactPerson            = project.GetPrimaryContact();
            CustomFactSheetPageTextViewData = new ViewPageContentViewData(firmaPageFactSheet, false);
        }
예제 #11
0
 public GoogleChartPopupViewData(GoogleChartJson googleChartJson)
 {
     GoogleChartJson = googleChartJson;
 }
예제 #12
0
 private static string GetFormattedGeospatialAreaTargetValue(PerformanceMeasureReportingPeriod performanceMeasureReportingPeriod, PerformanceMeasure performanceMeasure, GeospatialArea geospatialArea)
 {
     return($"{GoogleChartJson.GetFormattedValue(performanceMeasureReportingPeriod.GetGeospatialAreaTargetValue(performanceMeasure, geospatialArea), performanceMeasure.MeasurementUnitType)} ({performanceMeasureReportingPeriod.GetGeospatialAreaTargetValueLabel(performanceMeasure, geospatialArea)})");
 }
예제 #13
0
        public static List <GoogleChartJson> MakeGoogleChartJsons(PerformanceMeasure performanceMeasure, GeospatialArea geospatialArea, List <ProjectPerformanceMeasureReportingPeriodValue> projectPerformanceMeasureReportingPeriodValues)
        {
            var performanceMeasureSubcategoryOptionReportedValues = projectPerformanceMeasureReportingPeriodValues.SelectMany(x => x.PerformanceMeasureSubcategoryOptionReportedValues).GroupBy(x => x.PerformanceMeasureSubcategory);
            // This was changed to only use the performance measure reporting period from the actuals. Requested in PF#1901: https://projects.sitkatech.com/projects/projectfirma/cards/1901
            var performanceMeasureReportingPeriods = performanceMeasure.GetPerformanceMeasureReportingPeriodsFromActuals();
            var googleChartJsons = new List <GoogleChartJson>();

            bool hasTargets = performanceMeasure.HasTargets();
            bool hasGeospatialAreaTargets = false;

            if (geospatialArea != null)
            {
                hasGeospatialAreaTargets = performanceMeasure.GetGeospatialAreaTargetValueType(geospatialArea) != PerformanceMeasureTargetValueType.NoTarget;
            }

            if (performanceMeasureSubcategoryOptionReportedValues.Any())
            {
                foreach (var groupedBySubcategory in performanceMeasureSubcategoryOptionReportedValues.Where(x => x.Key.ShowOnChart()))
                {
                    var performanceMeasureSubcategory = groupedBySubcategory.Key;
                    Check.RequireNotNull(performanceMeasureSubcategory.ChartConfigurationJson, "All PerformanceMeasure Subcategories need to have a Google Chart Configuration Json");
                    var groupedBySubcategoryOption = groupedBySubcategory.GroupBy(c => new Tuple <string, int>(c.ChartName, c.SortOrder)).ToList(); // Item1 is ChartName, Item2 is SortOrder
                    var chartColumns = performanceMeasure.HasRealSubcategories() ? groupedBySubcategoryOption.OrderBy(x => x.Key.Item2).Select(x => x.Key.Item1).ToList() : new List <string> {
                        performanceMeasure.GetDisplayName()
                    };

                    var reverseTooltipOrder = performanceMeasureSubcategory.GoogleChartType == GoogleChartType.ColumnChart || performanceMeasureSubcategory.GoogleChartType == GoogleChartType.ComboChart;

                    var googleChartDataTable = GetGoogleChartDataTableWithReportingPeriodsAsHorizontalAxis(performanceMeasure, performanceMeasureReportingPeriods, hasTargets, hasGeospatialAreaTargets, geospatialArea, groupedBySubcategoryOption, chartColumns, performanceMeasure.IsSummable, reverseTooltipOrder, false);
                    var legendTitle          = performanceMeasure.HasRealSubcategories() ? performanceMeasureSubcategory.PerformanceMeasureSubcategoryDisplayName : performanceMeasure.GetDisplayName();
                    var chartName            = $"{performanceMeasure.GetJavascriptSafeChartUniqueName()}PerformanceMeasureSubcategory{performanceMeasureSubcategory.PerformanceMeasureSubcategoryID}";
                    var saveConfigurationUrl = SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x =>
                                                                                                                 x.SaveChartConfiguration(performanceMeasure,
                                                                                                                                          performanceMeasureSubcategory.PerformanceMeasureSubcategoryID, PerformanceMeasureSubcategoryChartConfiguration.ChartConfiguration));

                    var resetConfigurationUrl =
                        SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x =>
                                                                                          x.ResetChartConfiguration(performanceMeasure, performanceMeasureSubcategory.PerformanceMeasureSubcategoryID, PerformanceMeasureSubcategoryChartConfiguration.ChartConfiguration));

                    GoogleChartConfiguration chartConfiguration;
                    GoogleChartType          chartType;
                    if (hasGeospatialAreaTargets)
                    {
                        chartConfiguration = JsonConvert.DeserializeObject <GoogleChartConfiguration>(performanceMeasureSubcategory.GeospatialAreaTargetChartConfigurationJson);
                        chartType          = performanceMeasureSubcategory.GeospatialAreaTargetGoogleChartType;
                    }
                    else
                    {
                        chartConfiguration = JsonConvert.DeserializeObject <GoogleChartConfiguration>(performanceMeasureSubcategory.ChartConfigurationJson);
                        chartType          = performanceMeasureSubcategory.GoogleChartType;
                    }
                    if (performanceMeasureSubcategory.PerformanceMeasure.IsSummable)
                    {
                        chartConfiguration.Tooltip = new GoogleChartTooltip(true);
                    }

                    chartConfiguration.Series =
                        GoogleChartSeries.CalculateChartSeriesFromCurrentChartSeries(chartConfiguration.Series,
                                                                                     performanceMeasure, geospatialArea);

                    var googleChartJson = new GoogleChartJson(legendTitle, chartName, chartConfiguration,
                                                              chartType, googleChartDataTable,
                                                              chartColumns, saveConfigurationUrl, resetConfigurationUrl, false);
                    googleChartJsons.Add(googleChartJson);
                }

                // Add Cumulative charts if appropriate
                if (performanceMeasure.CanBeChartedCumulatively)
                {
                    foreach (var groupedBySubcategory in performanceMeasureSubcategoryOptionReportedValues.Where(x => x.Key.ShowOnCumulativeChart()))
                    {
                        var performanceMeasureSubcategory = groupedBySubcategory.Key;
                        var groupedBySubcategoryOption    = groupedBySubcategory.GroupBy(c => new Tuple <string, int>(c.ChartName, c.SortOrder)).ToList(); // Item1 is ChartName, Item2 is SortOrder
                        var chartColumns = performanceMeasure.HasRealSubcategories() ? groupedBySubcategoryOption.OrderBy(x => x.Key.Item2).Select(x => x.Key.Item1).ToList() : new List <string> {
                            performanceMeasure.GetDisplayName()
                        };

                        var reverseTooltipOrder  = performanceMeasureSubcategory.GoogleChartType == GoogleChartType.ColumnChart || performanceMeasureSubcategory.GoogleChartType == GoogleChartType.ComboChart;
                        var googleChartDataTable = GetGoogleChartDataTableWithReportingPeriodsAsHorizontalAxis(performanceMeasure, performanceMeasureReportingPeriods, hasTargets, hasGeospatialAreaTargets, geospatialArea, groupedBySubcategoryOption, chartColumns, performanceMeasure.IsSummable, reverseTooltipOrder, true);
                        var legendTitle          = performanceMeasure.HasRealSubcategories() ? performanceMeasureSubcategory.PerformanceMeasureSubcategoryDisplayName : performanceMeasure.GetDisplayName();
                        var chartName            = $"{performanceMeasure.GetJavascriptSafeChartUniqueName()}PerformanceMeasureSubcategory{performanceMeasureSubcategory.PerformanceMeasureSubcategoryID}Cumulative";
                        var saveConfigurationUrl = SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x => x.SaveChartConfiguration(performanceMeasure, performanceMeasureSubcategory.PerformanceMeasureSubcategoryID, PerformanceMeasureSubcategoryChartConfiguration.CumulativeConfiguration));

                        var resetConfigurationUrl = SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x => x.ResetChartConfiguration(performanceMeasure, performanceMeasureSubcategory.PerformanceMeasureSubcategoryID, PerformanceMeasureSubcategoryChartConfiguration.CumulativeConfiguration));

                        var chartConfiguration = !string.IsNullOrEmpty(performanceMeasureSubcategory.CumulativeChartConfigurationJson) ? JsonConvert.DeserializeObject <GoogleChartConfiguration>(performanceMeasureSubcategory.CumulativeChartConfigurationJson) : GoogleChartConfiguration.GetGoogleChartConfigurationFromJsonObject(performanceMeasureSubcategory.ChartConfigurationJson);

                        if (performanceMeasureSubcategory.PerformanceMeasure.IsSummable)
                        {
                            chartConfiguration.Tooltip = new GoogleChartTooltip(true);
                        }

                        chartConfiguration.Series =
                            GoogleChartSeries.CalculateChartSeriesFromCurrentChartSeries(chartConfiguration.Series,
                                                                                         performanceMeasure, geospatialArea);

                        var googleChartJson = new GoogleChartJson(legendTitle, chartName, chartConfiguration, performanceMeasureSubcategory.CumulativeGoogleChartType ?? GoogleChartType.ColumnChart, googleChartDataTable, chartColumns, saveConfigurationUrl, resetConfigurationUrl, true);
                        googleChartJsons.Add(googleChartJson);
                    }
                }
            }
            else if (performanceMeasure.HasTargets())
            {
                //build chart for just for targets if there is no project data
                var performanceMeasureSubcategory = performanceMeasure.PerformanceMeasureSubcategories.First();
                var legendTitle        = performanceMeasure.GetDisplayName();
                var chartName          = $"{performanceMeasure.GetJavascriptSafeChartUniqueName()}PerformanceMeasureSubcategory{performanceMeasureSubcategory.PerformanceMeasureSubcategoryID}";
                var chartConfiguration = performanceMeasure.GetDefaultPerformanceMeasureChartConfigurationJson();
                chartConfiguration.Series =
                    GoogleChartSeries.CalculateChartSeriesFromCurrentChartSeries(chartConfiguration.Series,
                                                                                 performanceMeasure, geospatialArea);
                var chartColumns = new List <string> {
                    performanceMeasure.GetDisplayName()
                };
                var reverseTooltipOrder  = performanceMeasureSubcategory.GoogleChartType == GoogleChartType.ColumnChart || performanceMeasureSubcategory.GoogleChartType == GoogleChartType.ComboChart;
                var googleChartDataTable = GetGoogleChartDataTableWithReportingPeriodsAsHorizontalAxis(performanceMeasure, performanceMeasureReportingPeriods, true, false, null, new List <IGrouping <Tuple <string, int>, PerformanceMeasureReportingPeriodSubcategoryOptionReportedValue> >(), chartColumns, false, reverseTooltipOrder, false);
                var saveConfigurationUrl = SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x => x.SaveChartConfiguration(performanceMeasure, performanceMeasureSubcategory.PerformanceMeasureSubcategoryID, PerformanceMeasureSubcategoryChartConfiguration.CumulativeConfiguration));

                var resetConfigurationUrl = SitkaRoute <PerformanceMeasureController> .BuildUrlFromExpression(x => x.ResetChartConfiguration(performanceMeasure, performanceMeasureSubcategory.PerformanceMeasureSubcategoryID, PerformanceMeasureSubcategoryChartConfiguration.CumulativeConfiguration));

                var googleChartJson = new GoogleChartJson(legendTitle, chartName, chartConfiguration, GoogleChartType.LineChart, googleChartDataTable, chartColumns, saveConfigurationUrl, resetConfigurationUrl, false);
                googleChartJsons.Add(googleChartJson);
            }

            return(googleChartJsons);
        }
예제 #14
0
        public static GoogleChartDataTable GetGoogleChartDataTableWithReportingPeriodsAsHorizontalAxis(PerformanceMeasure performanceMeasure,
                                                                                                       ICollection <PerformanceMeasureReportingPeriod> performanceMeasureReportingPeriods,
                                                                                                       bool hasTargets,
                                                                                                       bool hasGeospatialAreaTargets,
                                                                                                       GeospatialArea geospatialArea,
                                                                                                       IReadOnlyCollection <IGrouping <Tuple <string, int>, PerformanceMeasureReportingPeriodSubcategoryOptionReportedValue> > groupedBySubcategoryOption,
                                                                                                       IEnumerable <string> chartColumns,
                                                                                                       bool hasToolTipWithTotal,
                                                                                                       bool reverseTooltipOrder,
                                                                                                       bool showCumulativeResults)
        {
            var googleChartRowCs = new List <GoogleChartRowC>();

            foreach (var performanceMeasureReportingPeriod in performanceMeasureReportingPeriods.OrderBy(x => x.PerformanceMeasureReportingPeriodCalendarYear))
            {
                var googleChartRowVs = new List <GoogleChartRowV> {
                    new GoogleChartRowV(performanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodLabel)
                };
                var firstReportingPeriod      = performanceMeasureReportingPeriods.OrderBy(x => x.PerformanceMeasureReportingPeriodCalendarYear).First();
                var targetValue               = performanceMeasureReportingPeriod.GetTargetValue(performanceMeasure);
                var geospatialAreaTargetValue = hasGeospatialAreaTargets ? performanceMeasureReportingPeriod.GetGeospatialAreaTargetValue(performanceMeasure, geospatialArea) : null;

                if (hasToolTipWithTotal)
                {
                    var targetValueDescription = performanceMeasureReportingPeriod.GetTargetValueLabel(performanceMeasure);
                    var geospatialAreaTargetValueDescription = hasGeospatialAreaTargets ? performanceMeasureReportingPeriod.GetGeospatialAreaTargetValueLabel(performanceMeasure, geospatialArea) : string.Empty;

                    var formattedDataTooltip = FormattedDataTooltip(groupedBySubcategoryOption, performanceMeasureReportingPeriod, performanceMeasure.MeasurementUnitType, reverseTooltipOrder, targetValue, targetValueDescription, geospatialAreaTargetValue, geospatialAreaTargetValueDescription, showCumulativeResults, firstReportingPeriod);

                    googleChartRowVs.Add(new GoogleChartRowV(null, formattedDataTooltip));
                }
                if (hasTargets)
                {
                    googleChartRowVs.Add(new GoogleChartRowV(targetValue, GetFormattedTargetValue(performanceMeasureReportingPeriod, performanceMeasure)));
                }

                if (hasGeospatialAreaTargets)
                {
                    googleChartRowVs.Add(new GoogleChartRowV(geospatialAreaTargetValue, GetFormattedGeospatialAreaTargetValue(performanceMeasureReportingPeriod, performanceMeasure, geospatialArea)));
                }

                googleChartRowVs.AddRange(groupedBySubcategoryOption.OrderBy(x => x.Key.Item2).Select(x =>
                {
                    double calendarYearReportedValue;
                    if (showCumulativeResults)
                    {
                        calendarYearReportedValue = x.Where(pmsorv =>
                                                            pmsorv.PerformanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodCalendarYear <=
                                                            performanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodCalendarYear)
                                                    .Sum(pmsorv => pmsorv.ReportedValue) ?? 0;
                    }
                    else
                    {
                        calendarYearReportedValue = x.Where(pmsorv =>
                                                            pmsorv.PerformanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodCalendarYear ==
                                                            performanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodCalendarYear)
                                                    .Sum(pmsorv => pmsorv.ReportedValue) ?? 0;
                    }

                    return(new GoogleChartRowV(calendarYearReportedValue, GoogleChartJson.GetFormattedValue(calendarYearReportedValue, performanceMeasure.MeasurementUnitType)));
                }));

                googleChartRowCs.Add(new GoogleChartRowC(googleChartRowVs));
            }

            // reporting period is going to be the first column and it will be our horizontal axis
            var googleChartColumns = new List <GoogleChartColumn> {
                new GoogleChartColumn("Reporting Period", GoogleChartColumnDataType.String)
            };

            // add column with row tooltip
            if (hasToolTipWithTotal)
            {
                googleChartColumns.Add(new GoogleChartColumn(GoogleChartColumnDataType.String.ColumnDataType, "tooltip", new GoogleChartProperty()));
            }
            if (hasTargets)
            {
                // GoogleChartType for targets is always LINE; we also always render the target line first to stay consistent
                googleChartColumns.Add(new GoogleChartColumn(GetTargetColumnLabel(performanceMeasure), GoogleChartColumnDataType.Number));
            }
            if (hasGeospatialAreaTargets)
            {
                // GoogleChartType for targets is always LINE; we also always render the target line first to stay consistent
                googleChartColumns.Add(new GoogleChartColumn(GetGeospatialAreaTargetColumnLabel(performanceMeasure, geospatialArea), GoogleChartColumnDataType.Number));
            }
            // all the subcategory option values are individual columns and series and they will be on the vertical axis
            googleChartColumns.AddRange(chartColumns.Select(x => new GoogleChartColumn(x, GoogleChartColumnDataType.Number)));

            var googleChartDataTable = new GoogleChartDataTable(googleChartColumns, googleChartRowCs);

            return(googleChartDataTable);
        }
 private static string GetFormattedTargetValue(PerformanceMeasureReportingPeriod performanceMeasureReportingPeriod, PerformanceMeasure performanceMeasure)
 {
     return($"{GoogleChartJson.GetFormattedValue(performanceMeasureReportingPeriod.TargetValue, performanceMeasure.MeasurementUnitType)} ({performanceMeasureReportingPeriod.TargetValueDescription})");
 }
        private static GoogleChartDataTable GetGoogleChartDataTableWithReportingPeriodsAsVerticalAxis(PerformanceMeasure performanceMeasure,
                                                                                                      bool hasTargets,
                                                                                                      ICollection <PerformanceMeasureReportingPeriod> performanceMeasureReportingPeriods,
                                                                                                      IEnumerable <IGrouping <Tuple <string, int>, PerformanceMeasureReportingPeriodSubcategoryOptionReportedValue> > groupedBySubcategoryOption)
        {
            var googleChartRowCs = new List <GoogleChartRowC>();
            var targetRowVs      = new List <GoogleChartRowV>();

            if (hasTargets)
            {
                targetRowVs.Add(new GoogleChartRowV(GetTargetColumnLabel(performanceMeasureReportingPeriods)));
                targetRowVs.AddRange(performanceMeasureReportingPeriods.OrderBy(x => x.PerformanceMeasureReportingPeriodBeginDate)
                                     .Select(x => new GoogleChartRowV(x.TargetValue, GetFormattedTargetValue(x, performanceMeasure))));
                googleChartRowCs.Add(new GoogleChartRowC(targetRowVs));
            }

            foreach (var performanceMeasureSubcategoryOption in groupedBySubcategoryOption.OrderBy(x => x.Key.Item2))
            {
                var googleChartRowVs = new List <GoogleChartRowV> {
                    new GoogleChartRowV(performanceMeasureSubcategoryOption.Key.Item1)
                };
                googleChartRowVs.AddRange(performanceMeasureSubcategoryOption.OrderBy(x => x.PerformanceMeasureReportingPeriod.PerformanceMeasureReportingPeriodBeginDate).Select(irviso =>
                                                                                                                                                                                  new GoogleChartRowV(irviso.ReportedValue, GoogleChartJson.GetFormattedValue(irviso.ReportedValue, performanceMeasure.MeasurementUnitType))));
                googleChartRowCs.Add(new GoogleChartRowC(googleChartRowVs));
            }

            var googleChartColumns = new List <GoogleChartColumn> {
                new GoogleChartColumn(performanceMeasure.DisplayName, GoogleChartColumnDataType.String)
            };

            googleChartColumns.AddRange(performanceMeasureReportingPeriods.OrderBy(x => x.PerformanceMeasureReportingPeriodBeginDate).Select(x =>
                                                                                                                                             new GoogleChartColumn(x.PerformanceMeasureReportingPeriodID.ToString(), x.PerformanceMeasureReportingPeriodLabel, GoogleChartColumnDataType.Number.ColumnDataType)));

            var googleChartDataTable = new GoogleChartDataTable(googleChartColumns, googleChartRowCs);

            return(googleChartDataTable);
        }