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)); }
//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); }
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"; } }
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); }
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); }
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); }
public GoogleChartPopupViewData(GoogleChartJson googleChartJson) { GoogleChartJson = googleChartJson; }
private static string GetFormattedGeospatialAreaTargetValue(PerformanceMeasureReportingPeriod performanceMeasureReportingPeriod, PerformanceMeasure performanceMeasure, GeospatialArea geospatialArea) { return($"{GoogleChartJson.GetFormattedValue(performanceMeasureReportingPeriod.GetGeospatialAreaTargetValue(performanceMeasure, geospatialArea), performanceMeasure.MeasurementUnitType)} ({performanceMeasureReportingPeriod.GetGeospatialAreaTargetValueLabel(performanceMeasure, geospatialArea)})"); }
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); }
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); }