public IEnumerable <ValidationResult> Validate(ValidationContext validationContext)
        {
            var projects = HttpRequestStorage.DatabaseEntities.Projects.ToList();

            if (!ProjectModelExtensions.IsProjectNameUnique(projects, ProjectName, ProjectID))
            {
                yield return(new SitkaValidationResult <EditProjectViewModel, string>(
                                 FirmaValidationMessages.ProjectNameUnique, m => m.ProjectName));
            }

            if (ImplementationStartYear < PlanningDesignStartYear)
            {
                yield return(new SitkaValidationResult <EditProjectViewModel, int?>(
                                 FirmaValidationMessages.ImplementationStartYearGreaterThanPlanningDesignStartYear,
                                 m => m.ImplementationStartYear));
            }

            if (CompletionYear < ImplementationStartYear)
            {
                yield return(new SitkaValidationResult <EditProjectViewModel, int?>(
                                 FirmaValidationMessages.CompletionYearGreaterThanEqualToImplementationStartYear,
                                 m => m.CompletionYear));
            }

            var isCompletedOrPostImplementation = ProjectStageID == ProjectStage.Completed.ProjectStageID || ProjectStageID == ProjectStage.PostImplementation.ProjectStageID;

            if (isCompletedOrPostImplementation && !CompletionYear.HasValue)
            {
                yield return(new SitkaValidationResult <EditProjectViewModel, int?>($"Since the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the {ProjectStage.ToType(ProjectStageID).ProjectStageDisplayName} stage, the {FieldDefinitionEnum.CompletionYear.ToType().GetFieldDefinitionLabel()} is required", m => m.CompletionYear));
            }

            if (isCompletedOrPostImplementation && CompletionYear > DateTime.Now.Year)
            {
                var errorMessage = $"{FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the {ProjectStage.ToType(ProjectStageID).ProjectStageDisplayName} stage: " +
                                   $"the {FieldDefinitionEnum.CompletionYear.ToType().GetFieldDefinitionLabel()} must be less than or equal to the current year";
                yield return(new SitkaValidationResult <EditProjectViewModel, int?>(errorMessage, m => m.CompletionYear));
            }

            if (HasExistingProjectUpdate && OldProjectStageID != ProjectStageID)
            {
                var errorMessage = $"There are updates to this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} that have not been submitted. Please delete the update if you want to change this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}'s stage.";
                yield return(new SitkaValidationResult <EditProjectViewModel, int>(errorMessage, m => m.ProjectStageID));
            }

            if (TaxonomyLeafID != null && (SecondaryProjectTaxonomyLeafIDs?.ToList() ?? new List <int>()).Contains(TaxonomyLeafID.Value))
            {
                yield return(new SitkaValidationResult <EditProjectViewModel, IEnumerable <int> >(
                                 $"Cannot have a {FieldDefinitionEnum.SecondaryProjectTaxonomyLeaf.ToType().GetFieldDefinitionLabel()} " +
                                 $"that is the same as the Primary {FieldDefinitionEnum.TaxonomyLeaf.ToType().GetFieldDefinitionLabel()}.",
                                 m => m.SecondaryProjectTaxonomyLeafIDs));
            }
        }
示例#2
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 ReportTemplateProjectModel(Project project)
        {
            // Private properties
            Project              = project;
            ProjectContacts      = project.ProjectContacts.ToList();
            ProjectOrganizations = project.ProjectOrganizations.ToList();
            ProjectImages        = project.ProjectImages.ToList();

            // Public properties
            ProjectName = Project.ProjectName;
            ProjectUrl  = GetProjectUrlForReport(project);
            PrimaryContactOrganization = Project.GetPrimaryContactOrganization() != null ? new ReportTemplateOrganizationModel(Project.GetPrimaryContactOrganization()) : null;
            ProjectStage = Project.ProjectStage.ProjectStageDisplayName;
            NumberOfReportedPerformanceMeasures = Project.PerformanceMeasureActuals.Count;
            ProjectPrimaryContact        = Project.GetPrimaryContact() != null ? new ReportTemplatePersonModel(Project.GetPrimaryContact()) : null;
            PlanningDesignStartYear      = ProjectModelExtensions.GetPlanningDesignStartYear(Project);
            ImplementationStartYear      = ProjectModelExtensions.GetImplementationStartYear(Project);
            CompletionYear               = ProjectModelExtensions.GetCompletionYear(Project);
            PrimaryTaxonomyLeaf          = Project.TaxonomyLeaf?.GetDisplayName();
            NumberOfReportedExpenditures = Project.ProjectFundingSourceExpenditures.Count;
            FundingType               = Project.FundingType?.FundingTypeDisplayName;
            EstimatedTotalCost        = Project.GetEstimatedTotalRegardlessOfFundingType()?.ToStringCurrency();
            SecuredFunding            = Project.GetSecuredFunding().ToStringCurrency();
            TargetedFunding           = Project.GetTargetedFunding().ToStringCurrency();
            NoFundingSourceIdentified = Project.GetNoFundingSourceIdentifiedAmount()?.ToStringCurrency();
            ProjectDescription        = Project.ProjectDescription;
            ProjectID          = Project.ProjectID;
            ProjectLastUpdated = Project.LastUpdatedDate;

            var projectStatus = project.GetCurrentProjectStatus();

            if (projectStatus != null)
            {
                CurrentProjectStatusColor = projectStatus.ProjectStatusColor;
                CurrentProjectStatus      = projectStatus.ProjectStatusDisplayName;
            }

            var finalProjectStatus = Project.FinalStatusReportStatusDescription;

            if (finalProjectStatus != null)
            {
                FinalStatusUpdateStatus = finalProjectStatus;
            }
        }
示例#4
0
        public IndexGridSpec(Person currentPerson, Dictionary <int, FundingType> fundingTypes, List <GeospatialAreaType> geospatialAreaTypes, List <ProjectFirmaModels.Models.ProjectCustomAttributeType> projectCustomAttributeTypes)
        {
            var userHasTagManagePermissions    = new FirmaAdminFeature().HasPermissionByPerson(currentPerson);
            var userHasDeletePermissions       = new ProjectDeleteFeature().HasPermissionByPerson(currentPerson);
            var userHasEmailViewingPermissions = new LoggedInAndNotUnassignedRoleUnclassifiedFeature().HasPermissionByPerson(currentPerson);

            if (userHasTagManagePermissions)
            {
                BulkTagModalDialogForm = new BulkTagModalDialogForm(SitkaRoute <TagController> .BuildUrlFromExpression(x => x.BulkTagProjects(null)), $"Tag Checked {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()}", $"Tag {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()}");
                AddCheckBoxColumn();
                Add("ProjectID", x => x.ProjectID, 0);
            }

            if (userHasDeletePermissions)
            {
                Add(string.Empty, x => DhtmlxGridHtmlHelpers.MakeDeleteIconAndLinkBootstrap(x.GetDeleteUrl(), true), 30, DhtmlxGridColumnFilterType.None);
            }

            Add(string.Empty, x => UrlTemplate.MakeHrefString(x.GetFactSheetUrl(), FirmaDhtmlxGridHtmlHelpers.FactSheetIcon.ToString()), 30, DhtmlxGridColumnFilterType.None);

            Add(FieldDefinitionEnum.ProjectName.ToType().ToGridHeaderString(), x => UrlTemplate.MakeHrefString(x.GetDetailUrl(), x.ProjectName), 300, DhtmlxGridColumnFilterType.Html);
            if (MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship())
            {
                Add(FieldDefinitionEnum.ProjectsStewardOrganizationRelationshipToProject.ToType().ToGridHeaderString(), x => x.GetCanStewardProjectsOrganization()?.GetShortNameAsUrl() ?? new HtmlString(""), 150, DhtmlxGridColumnFilterType.Html);
            }
            Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(), x => x.GetPrimaryContactOrganization().GetShortNameAsUrl(), 150, DhtmlxGridColumnFilterType.Html);
            Add(FieldDefinitionEnum.ProjectPrimaryContact.ToType().ToGridHeaderString(),
                x => x.GetPrimaryContact() != null ? UrlTemplate.MakeHrefString(x.GetPrimaryContact().GetDetailUrl(), x.GetPrimaryContact().GetFullNameLastFirst()) : new HtmlString(""),
                150, DhtmlxGridColumnFilterType.Html);
            if (userHasEmailViewingPermissions)
            {
                Add(FieldDefinitionEnum.ProjectPrimaryContactEmail.ToType().ToGridHeaderString(),
                    x => x.GetPrimaryContact() != null ? new HtmlString($"<a href='mailto:{x.GetPrimaryContact().Email}'> {x.GetPrimaryContact().Email}</a>") : new HtmlString(""),
                    200, DhtmlxGridColumnFilterType.SelectFilterHtmlStrict);
            }
            Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), x => x.ProjectStage.ProjectStageDisplayName, 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);

            Add($"Primary {FieldDefinitionEnum.TaxonomyLeaf.ToType().ToGridHeaderString()}", x => x.TaxonomyLeaf.GetDisplayNameAsUrl(), 200, DhtmlxGridColumnFilterType.Html);
            var enableSecondaryProjectTaxonomyLeaf = MultiTenantHelpers.GetTenantAttribute().EnableSecondaryProjectTaxonomyLeaf;

            if (enableSecondaryProjectTaxonomyLeaf)
            {
                Add(FieldDefinitionEnum.SecondaryProjectTaxonomyLeaf.ToType().ToGridHeaderStringPlural(), x => new HtmlString(string.Join(", ", x.SecondaryProjectTaxonomyLeafs.Select(y => y.TaxonomyLeaf.GetDisplayNameAsUrl().ToString()))), 300, DhtmlxGridColumnFilterType.Html);
            }

            // Agreements for this project
            Add(FieldDefinitionEnum.Agreement.ToType().ToGridHeaderStringPlural(), x => GetAgreementHrefsString(x), 100, DhtmlxGridColumnFilterType.Text);

            // TODO: add links to Cost Authorities
            Add(FieldDefinitionEnum.CostAuthorityWorkBreakdownStructure.ToType().ToGridHeaderStringPlural(), x => GetCostAuthorityHrefsString(x), 100, DhtmlxGridColumnFilterType.Text);

            Add($"Number Of Reported {MultiTenantHelpers.GetPerformanceMeasureName()} Records", x => x.PerformanceMeasureActuals.Count, 100);
            Add($"Number Of {FieldDefinitionEnum.ReportedExpenditure.ToType().GetFieldDefinitionLabel()} Records", x => x.ProjectFundingSourceExpenditures.Count, 100);
            Add(FieldDefinitionEnum.FundingType.ToType().ToGridHeaderString(), x => x.FundingTypeID.HasValue ? fundingTypes[x.FundingTypeID.Value].FundingTypeDisplayName : "", 300, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.SecuredFunding.ToType().ToGridHeaderString(), x => x.GetSecuredFunding(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.TargetedFunding.ToType().ToGridHeaderString(), x => x.GetTargetedFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.NoFundingSourceIdentified.ToType().ToGridHeaderString(), x => x.GetNoFundingSourceIdentifiedAmount(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            foreach (var projectCustomAttributeType in projectCustomAttributeTypes.OrderBy(x => x.ProjectCustomAttributeTypeName))
            {
                if (projectCustomAttributeType.IncludeInProjectGrid && projectCustomAttributeType.HasViewPermission(currentPerson))
                {
                    Add($"{projectCustomAttributeType.ProjectCustomAttributeTypeName}", a => a.GetProjectCustomAttributesValue(projectCustomAttributeType), 150, DhtmlxGridColumnFilterType.Text);
                }
            }
            foreach (var geospatialAreaType in geospatialAreaTypes.OrderBy(x => x.GeospatialAreaTypeName))
            {
                Add($"{geospatialAreaType.GeospatialAreaTypeNamePluralized}", a => a.GetProjectGeospatialAreaNamesAsHyperlinks(geospatialAreaType), 350, DhtmlxGridColumnFilterType.Html);
            }

            Add(FieldDefinitionEnum.ProjectDescription.ToType().ToGridHeaderString(), x => x.ProjectDescription, 200);
            if (userHasTagManagePermissions)
            {
                Add("Tags", x => new HtmlString(!x.ProjectTags.Any() ? string.Empty : string.Join(", ", x.ProjectTags.Select(pt => pt.Tag.GetDisplayNameAsUrl()))), 100, DhtmlxGridColumnFilterType.Html);
            }

            Add("# of Photos", x => x.ProjectImages.Count, 60);
        }
示例#5
0
        private void AddProjectCustomGridField(FirmaSession currentFirmaSession
                                               , ProjectCustomGridConfiguration projectCustomGridConfiguration
                                               , bool userHasEditProjectAsAdminPermissions
                                               , Dictionary <int, vProjectDetail> projectDetailsDictionary
                                               , Dictionary <int, ProjectFirmaModels.Models.TaxonomyLeaf> taxonomyLeafDictionary
                                               , string projectLabel
                                               , bool hasProjectApprovalPermissionBySession
                                               , string statusUpdateLabel
                                               , List <int> sitkaAdminPersonIDs)
        {
            switch (projectCustomGridConfiguration.ProjectCustomGridColumn.ToEnum)
            {
            // Non-optional fields
            // Project Name
            case ProjectCustomGridColumnEnum.ProjectName:
                Add(FieldDefinitionEnum.ProjectName.ToType().ToGridHeaderString(), x => UrlTemplate.MakeHrefString(x.GetDetailUrl(), x.ProjectName), 300, DhtmlxGridColumnFilterType.Html);
                break;

            case ProjectCustomGridColumnEnum.PrimaryContactOrganization:
                Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(),
                    x => OrganizationModelExtensions.GetShortNameAsUrl(projectDetailsDictionary[x.ProjectID].PrimaryContactOrganizationID, projectDetailsDictionary[x.ProjectID].PrimaryContactOrganizationDisplayName), 150, DhtmlxGridColumnFilterType.Html);
                break;

            case ProjectCustomGridColumnEnum.ProjectStage:
                Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), x => x.ProjectStage.ProjectStageDisplayName, 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
                break;

            case ProjectCustomGridColumnEnum.NumberOfExpectedPerformanceMeasureRecords:
                Add($"# Of Expected {MultiTenantHelpers.GetPerformanceMeasureName()} Records", x => projectDetailsDictionary[x.ProjectID].PerformanceMeasureExpectedCount, 100);
                break;

            case ProjectCustomGridColumnEnum.NumberOfReportedPerformanceMeasures:
                Add($"# Of Reported {MultiTenantHelpers.GetPerformanceMeasureName()} Records", x => projectDetailsDictionary[x.ProjectID].PerformanceMeasureActualCount, 100);
                break;

            case ProjectCustomGridColumnEnum.ProjectsStewardOrganizationRelationshipToProject:
                if (MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship())
                {
                    Add(FieldDefinitionEnum.ProjectsStewardOrganizationRelationshipToProject.ToType().ToGridHeaderString(), x => OrganizationModelExtensions.GetShortNameAsUrl(projectDetailsDictionary[x.ProjectID].CanStewardProjectsOrganizationID, projectDetailsDictionary[x.ProjectID].CanStewardProjectsOrganizationDisplayName), 150, DhtmlxGridColumnFilterType.Html);
                }
                break;

            case ProjectCustomGridColumnEnum.ProjectPrimaryContact:
                Add(FieldDefinitionEnum.ProjectPrimaryContact.ToType().ToGridHeaderString(),
                    x => projectDetailsDictionary[x.ProjectID].PrimaryContactPersonID.HasValue ?
                    new UserViewFeature().HasPermissionForPersonID(currentFirmaSession, projectDetailsDictionary[x.ProjectID].PrimaryContactPersonID.Value, sitkaAdminPersonIDs).HasPermission ? UrlTemplate.MakeHrefString(PersonModelExtensions.DetailUrlTemplate.ParameterReplace(projectDetailsDictionary[x.ProjectID].PrimaryContactPersonID.Value), projectDetailsDictionary[x.ProjectID].PrimaryContactPersonFullNameFirstLast) : new HtmlString(projectDetailsDictionary[x.ProjectID].PrimaryContactPersonFullNameFirstLast) : new HtmlString(""),
                    150, DhtmlxGridColumnFilterType.Html);
                break;

            case ProjectCustomGridColumnEnum.ProjectPrimaryContactEmail:
                var userHasEmailViewingPermissions = new LoggedInAndNotUnassignedRoleUnclassifiedFeature().HasPermissionByFirmaSession(currentFirmaSession);
                if (userHasEmailViewingPermissions)
                {
                    Add(FieldDefinitionEnum.ProjectPrimaryContactEmail.ToType().ToGridHeaderString(),
                        x => projectDetailsDictionary[x.ProjectID].PrimaryContactPersonID.HasValue ? new HtmlString($"<a href='mailto:{projectDetailsDictionary[x.ProjectID].PrimaryContactPersonEmail}'> {projectDetailsDictionary[x.ProjectID].PrimaryContactPersonEmail}</a>") : new HtmlString(""),
                        200, DhtmlxGridColumnFilterType.SelectFilterHtmlStrict);
                }
                break;

            case ProjectCustomGridColumnEnum.PlanningDesignStartYear:
                Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
                break;

            case ProjectCustomGridColumnEnum.ImplementationStartYear:
                Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
                break;

            case ProjectCustomGridColumnEnum.CompletionYear:
                Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
                break;

            case ProjectCustomGridColumnEnum.PrimaryTaxonomyLeaf:
                var gridHeaderString = MultiTenantHelpers.GetTenantAttributeFromCache().EnableSecondaryProjectTaxonomyLeaf
                        ? FieldDefinitionEnum.TaxonomyLeafDisplayNameForProject.ToType().ToGridHeaderString()
                        : FieldDefinitionEnum.TaxonomyLeaf.ToType().ToGridHeaderString();
                Add(gridHeaderString, x => UrlTemplate.MakeHrefString(TaxonomyLeafModelExtensions.DetailUrlTemplate.ParameterReplace(projectDetailsDictionary[x.ProjectID].TaxonomyLeafID), projectDetailsDictionary[x.ProjectID].TaxonomyLeafDisplayName), 240, DhtmlxGridColumnFilterType.Html);
                break;

            case ProjectCustomGridColumnEnum.SecondaryTaxonomyLeaf:
                if (MultiTenantHelpers.GetTenantAttributeFromCache().EnableSecondaryProjectTaxonomyLeaf)
                {
                    Add(FieldDefinitionEnum.SecondaryProjectTaxonomyLeaf.ToType().ToGridHeaderStringPlural()
                        , x => new HtmlString(string.Join(", ", x.SecondaryProjectTaxonomyLeafs.Select(y => taxonomyLeafDictionary[y.TaxonomyLeafID].GetDisplayNameAsUrl().ToString()))), 300, DhtmlxGridColumnFilterType.Html);
                }
                break;

            case ProjectCustomGridColumnEnum.NumberOfReportedExpenditures:
                Add($"# Of {FieldDefinitionEnum.ReportedExpenditure.ToType().GetFieldDefinitionLabel()} Records", x => projectDetailsDictionary[x.ProjectID].ProjectFundingSourceExpenditureCount, 100);
                break;

            case ProjectCustomGridColumnEnum.FundingType:
                Add(FieldDefinitionEnum.FundingType.ToType().ToGridHeaderString(), x => x.FundingType != null ? x.FundingType.FundingTypeDisplayName : "", 300, DhtmlxGridColumnFilterType.SelectFilterStrict);
                break;

            case ProjectCustomGridColumnEnum.EstimatedTotalCost:
                Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
                break;

            case ProjectCustomGridColumnEnum.SecuredFunding:
                Add(FieldDefinitionEnum.SecuredFunding.ToType().ToGridHeaderString(), x => x.GetSecuredFunding(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
                break;

            case ProjectCustomGridColumnEnum.TargetedFunding:
                Add(FieldDefinitionEnum.TargetedFunding.ToType().ToGridHeaderString(), x => x.GetTargetedFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
                break;

            case ProjectCustomGridColumnEnum.NoFundingSourceIdentified:
                Add(FieldDefinitionEnum.NoFundingSourceIdentified.ToType().ToGridHeaderString(), x => x.GetNoFundingSourceIdentifiedAmount(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
                break;

            case ProjectCustomGridColumnEnum.ProjectDescription:
                Add(FieldDefinitionEnum.ProjectDescription.ToType().ToGridHeaderString(), x => x.ProjectDescription, 200);
                break;

            case ProjectCustomGridColumnEnum.NumberOfPhotos:
                Add("# of Photos", x => projectDetailsDictionary[x.ProjectID].ProjectImageCount, 60);
                break;

            case ProjectCustomGridColumnEnum.ProjectID:
                Add(FieldDefinitionEnum.ProjectID.ToType().ToGridHeaderString(), x => x.ProjectID.ToString(), 140);
                break;

            case ProjectCustomGridColumnEnum.ProjectLastUpdated:
                Add(FieldDefinitionEnum.ProjectLastUpdated.ToType().ToGridHeaderString(), x => x.LastUpdatedDate, 140);
                break;

            case ProjectCustomGridColumnEnum.ProjectStatus:
                if (MultiTenantHelpers.GetTenantAttributeFromCache().UseProjectTimeline&& userHasEditProjectAsAdminPermissions)
                {
                    Add(FieldDefinitionEnum.Status.ToType().ToGridHeaderString()
                        , x => MakeProjectStatusAddLinkAndText(x, currentFirmaSession, projectDetailsDictionary[x.ProjectID], projectLabel, hasProjectApprovalPermissionBySession, statusUpdateLabel)
                        , 100
                        , DhtmlxGridColumnFilterType.SelectFilterHtmlStrict
                        );
                }
                break;

            case ProjectCustomGridColumnEnum.FinalStatusUpdateStatus:
                if (MultiTenantHelpers.GetTenantAttributeFromCache().UseProjectTimeline&& userHasEditProjectAsAdminPermissions)
                {
                    Add(FieldDefinitionEnum.FinalStatusUpdateStatus.ToType().ToGridHeaderString()
                        , x => projectDetailsDictionary[x.ProjectID].FinalStatusReportStatusDescription
                        , 100
                        , DhtmlxGridColumnFilterType.SelectFilterStrict
                        );
                }
                break;

            case ProjectCustomGridColumnEnum.GeospatialAreaName:
                break;

            case ProjectCustomGridColumnEnum.CustomAttribute:
                break;

            case ProjectCustomGridColumnEnum.ProjectCategory:
                if (MultiTenantHelpers.GetTenantAttributeFromCache().EnableProjectCategories)
                {
                    Add(FieldDefinitionEnum.ProjectCategory.ToType().ToGridHeaderString(), x => x.ProjectCategory.ProjectCategoryDisplayName, 140, DhtmlxGridColumnFilterType.SelectFilterStrict);
                }
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
示例#6
0
        public IEnumerable <ValidationResult> GetValidationResults()
        {
            var projects = HttpRequestStorage.DatabaseEntities.Projects.ToList();

            if (!Enum.IsDefined(typeof(ProjectCategoryEnum), ProjectCategoryEnum))
            {
                yield return(new SitkaValidationResult <BasicsViewModel, ProjectCategoryEnum>($"A valid value for {FieldDefinitionEnum.ProjectCategory.ToType().GetFieldDefinitionLabel()} is required.", m => m.ProjectCategoryEnum));
            }

            if (TaxonomyLeafID == -1)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>($"{MultiTenantHelpers.GetTaxonomyLeafDisplayNameForProject()} is required.", m => m.TaxonomyLeafID));
            }

            if (!ProjectModelExtensions.IsProjectNameUnique(projects, ProjectName, ProjectID))
            {
                yield return(new SitkaValidationResult <BasicsViewModel, string>(FirmaValidationMessages.ProjectNameUnique, m => m.ProjectName));
            }

            if (ImplementationStartYear < PlanningDesignStartYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(FirmaValidationMessages.ImplementationStartYearGreaterThanPlanningDesignStartYear, m => m.ImplementationStartYear));
            }

            if (CompletionYear < ImplementationStartYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(FirmaValidationMessages.CompletionYearGreaterThanEqualToImplementationStartYear, m => m.CompletionYear));
            }

            if (CompletionYear < PlanningDesignStartYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(FirmaValidationMessages.CompletionYearGreaterThanEqualToPlanningDesignStartYear, m => m.CompletionYear));
            }

            var currentYear = FirmaDateUtilities.CalculateCurrentYearToUseForUpToAllowableInputInReporting();

            if (ProjectStageID == ProjectStage.Implementation.ProjectStageID)
            {
                if (ImplementationStartYear > currentYear)
                {
                    yield return(new SitkaValidationResult <BasicsViewModel, int?>(
                                     FirmaValidationMessages.ImplementationYearMustBePastOrPresentForImplementationProjects,
                                     m => m.ImplementationStartYear));
                }
            }

            if (ImplementationStartYear == null && ProjectStageID != ProjectStage.Terminated.ProjectStageID && ProjectStageID != ProjectStage.Deferred.ProjectStageID)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(
                                 $"Implementation year is required when the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} stage is not Deferred or Terminated",
                                 m => m.ImplementationStartYear));
            }

            if (ProjectStageID == ProjectStage.Completed.ProjectStageID && !CompletionYear.HasValue)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>($"Since the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the Completed stage, the Completion year is required", m => m.CompletionYear));
            }

            if (ProjectStageID == ProjectStage.PostImplementation.ProjectStageID && !CompletionYear.HasValue)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>($"Since the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the Post-Implementation stage, the Completion year is required", m => m.CompletionYear));
            }

            if ((ProjectStageID == ProjectStage.Completed.ProjectStageID || ProjectStageID == ProjectStage.PostImplementation.ProjectStageID) && CompletionYear > currentYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(FirmaValidationMessages.CompletionYearMustBePastOrPresentForCompletedProjects, m => m.CompletionYear));
            }

            if (ProjectStageID == ProjectStage.PlanningDesign.ProjectStageID && PlanningDesignStartYear > currentYear)
            {
                yield return(new SitkaValidationResult <BasicsViewModel, int?>(
                                 $"Since the {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the Planning / Design stage, the Planning / Design start year must be less than or equal to the current year",
                                 m => m.PlanningDesignStartYear));
            }

            if (TaxonomyLeafID != null && SecondaryProjectTaxonomyLeafIDs.ToList().Contains(TaxonomyLeafID.Value))
            {
                yield return(new SitkaValidationResult <BasicsViewModel, IEnumerable <int> >(
                                 $"Cannot have a {FieldDefinitionEnum.SecondaryProjectTaxonomyLeaf.ToType().GetFieldDefinitionLabel()} " +
                                 $"that is the same as the Primary {FieldDefinitionEnum.TaxonomyLeaf.ToType().GetFieldDefinitionLabel()}.",
                                 m => m.SecondaryProjectTaxonomyLeafIDs));
            }
        }
示例#7
0
 public PendingGridSpec(FirmaSession currentFirmaSession)
 {
     // todo: fulfill "Include standard project grid with columns for “Stage” and “Approval Status”
     Add(string.Empty, x => DhtmlxGridHtmlHelpers.MakeDeleteIconAndLinkBootstrap(x.GetDeleteProposalUrl(), new ProjectDeleteProposalFeature().HasPermission(currentFirmaSession, x).HasPermission, true), 30, DhtmlxGridColumnFilterType.None);
     Add(string.Empty,
         x => DhtmlxGridHtmlHelpers.MakeEditIconAsHyperlinkBootstrap(x.GetProjectCreateUrl(),
                                                                     new ProjectCreateFeature().HasPermission(currentFirmaSession, x).HasPermission&&
                                                                     !(x.ProjectApprovalStatus == ProjectApprovalStatus.PendingApproval &&
                                                                       currentFirmaSession.Role == ProjectFirmaModels.Models.Role.Normal)), 30,
         DhtmlxGridColumnFilterType.None);
     Add(FieldDefinitionEnum.ProjectName.ToType().ToGridHeaderString(), x => UrlTemplate.MakeHrefString(x.GetDetailUrl(), x.ProjectName), 300, DhtmlxGridColumnFilterType.Html);
     Add("Submittal Status", a => a.ProjectApprovalStatus.ProjectApprovalStatusDisplayName, 110, DhtmlxGridColumnFilterType.SelectFilterStrict);
     Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), x => x.ProjectStage.ProjectStageDisplayName, 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
     if (MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship())
     {
         Add(FieldDefinitionEnum.ProjectsStewardOrganizationRelationshipToProject.ToType().ToGridHeaderString(), x => x.GetCanStewardProjectsOrganization().GetShortNameAsUrl(), 150,
             DhtmlxGridColumnFilterType.Html);
     }
     Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(), x => x.GetPrimaryContactOrganization().GetShortNameAsUrl(), 150, DhtmlxGridColumnFilterType.Html);
     Add(FieldDefinitionEnum.TaxonomyLeaf.ToType().ToGridHeaderString(), x => x.TaxonomyLeaf == null ? string.Empty : x.TaxonomyLeaf.GetDisplayName(), 300, DhtmlxGridColumnFilterType.Html);
     Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
     Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
     Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
     Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
     Add(FieldDefinitionEnum.SecuredFunding.ToType().ToGridHeaderString(), x => x.GetSecuredFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
     Add(FieldDefinitionEnum.TargetedFunding.ToType().ToGridHeaderString(), x => x.GetTargetedFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
     Add(FieldDefinitionEnum.NoFundingSourceIdentified.ToType().ToGridHeaderString(), x => x.GetNoFundingSourceIdentifiedAmount(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
     Add("Submitted By", a => a.SubmittedByPerson != null ? a.SubmittedByPerson.GetFullNameFirstLastAndOrgShortNameAsUrl(currentFirmaSession) : new HtmlString(null), 200);
     Add("Submitted Date", a => a.SubmissionDate, 120);
     Add("Last Updated", a => a.LastUpdatedDate, 120);
     Add(FieldDefinitionEnum.ProjectDescription.ToType().ToGridHeaderString(), x => x.ProjectDescription, 300);
 }
示例#8
0
        public DetailViewData(FirmaSession currentFirmaSession, ProjectFirmaModels.Models.Project project,
                              List <ProjectStage> projectStages,
                              ProjectBasicsViewData projectBasicsViewData, ProjectLocationSummaryViewData projectLocationSummaryViewData,
                              ProjectBudgetSummaryViewData projectBudgetSummaryViewData,
                              ProjectBudgetsAnnualViewData projectBudgetsAnnualViewData,
                              ProjectBudgetsAnnualByCostTypeViewData projectBudgetsAnnualByCostTypeViewData,
                              TechnicalAssistanceRequestsDetailViewData technicalAssistanceRequestDetailViewData,
                              PerformanceMeasureExpectedSummaryViewData performanceMeasureExpectedSummaryViewData,
                              PerformanceMeasureReportedValuesGroupedViewData performanceMeasureReportedValuesGroupedViewData,
                              ProjectExpendituresDetailViewData projectExpendituresDetailViewData,
                              ProjectExpendituresByCostTypeDetailViewData projectExpendituresByCostTypeDetailViewData,
                              ImageGalleryViewData imageGalleryViewData, EntityNotesViewData projectNotesViewData,
                              EntityNotesViewData internalNotesViewData,
                              EntityExternalLinksViewData entityExternalLinksViewData,
                              ProjectBasicsTagsViewData projectBasicsTagsViewData, bool userHasProjectAdminPermissions,
                              bool userHasEditProjectPermissions, bool userHasProjectUpdatePermissions,
                              bool userHasPerformanceMeasureActualManagePermissions, string mapFormID,
                              string editProjectCustomAttributesUrl,
                              string editSimpleProjectLocationUrl, string editDetailedProjectLocationUrl,
                              string editProjectOrganizationsUrl, string editPerformanceMeasureExpectedsUrl,
                              string editPerformanceMeasureActualsUrl, string editReportedExpendituresUrl,
                              bool reportFinancialsByCostType, AuditLogsGridSpec auditLogsGridSpec, string auditLogsGridDataUrl,
                              string editExternalLinksUrl, ProjectNotificationGridSpec projectNotificationGridSpec,
                              string projectNotificationGridName, string projectNotificationGridDataUrl, bool userCanEditProposal,
                              ProjectOrganizationsDetailViewData projectOrganizationsDetailViewData,
                              ProjectPotentialPartnerDetailViewData projectPotentialPartnerDetailViewData,
                              List <ProjectFirmaModels.Models.ClassificationSystem> classificationSystems,
                              string editProjectBoundingBoxFormID, List <GeospatialAreaType> geospatialAreaTypes,
                              DisplayProjectCustomAttributesViewData displayProjectCustomAttributeTypesViewData,
                              ProjectContactsDetailViewData projectContactsDetailViewData, string editProjectContactsUrl,
                              string editExpectedFundingUrl, ProjectTimelineDisplayViewData projectTimelineDisplayViewData,
                              bool userHasProjectTimelinePermissions, List <ProjectEvaluation> projectEvaluationsUserHasAccessTo,
                              bool userHasStartUpdateWorkflowPermission)
            : base(currentFirmaSession, project)
        {
            PageTitle       = project.GetDisplayName();
            BreadCrumbTitle = $"{FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} Detail";
            ProjectStages   = projectStages;

            EditProjectUrl = project.GetEditUrl();
            UserHasProjectAdminPermissions = userHasProjectAdminPermissions;
            UserHasEditProjectPermissions  = userHasEditProjectPermissions;
            UserHasPerformanceMeasureActualManagePermissions = userHasPerformanceMeasureActualManagePermissions;
            UserHasProjectTimelinePermissions = userHasProjectTimelinePermissions;
            CanLaunchProjectOrProposalWizard  = userHasStartUpdateWorkflowPermission;
            WithdrawUrl = SitkaRoute <ProjectCreateController> .BuildUrlFromExpression(c => c.Withdraw(project));

            var projectAlerts          = new List <string>();
            var proposedProjectListUrl = SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.Proposed());

            var backToAllProposalsText = "Back to all Proposals";
            var pendingProjectsListUrl = SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.Pending());

            var backToAllPendingProjectsText = $"Back to all Pending {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()}";

            var currentPerson = currentFirmaSession.Person;

            if (project.IsRejected())
            {
                var projectApprovalStatus = project.ProjectApprovalStatus;
                ProjectUpdateButtonText =
                    projectApprovalStatus == ProjectApprovalStatus.Draft ||
                    projectApprovalStatus == ProjectApprovalStatus.Returned
                        ? $"Edit Pending {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}"
                        : $"Review Pending {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}";
                ProjectWizardUrl = SitkaRoute <ProjectCreateController> .BuildUrlFromExpression(x => x.EditBasics(project.ProjectID));

                if (project.IsProposal())
                {
                    ProjectListUrl     = proposedProjectListUrl;
                    BackToProjectsText = backToAllProposalsText;
                }
                else if (project.IsPendingProject())
                {
                    ProjectListUrl     = pendingProjectsListUrl;
                    BackToProjectsText = backToAllPendingProjectsText;
                }

                if (userHasProjectAdminPermissions || currentPerson.CanStewardProject(project))
                {
                    projectAlerts.Add(
                        $"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} was rejected and can no longer be edited. It can be deleted, or preserved for archival purposes.");
                }
            }
            else if (project.IsProposal())
            {
                var projectApprovalStatus = project.ProjectApprovalStatus;
                ProjectUpdateButtonText =
                    projectApprovalStatus == ProjectApprovalStatus.Draft ||
                    projectApprovalStatus == ProjectApprovalStatus.Returned
                        ? "Edit Proposal"
                        : "Review Proposal";
                ProjectWizardUrl = SitkaRoute <ProjectCreateController> .BuildUrlFromExpression(x => x.EditBasics(project.ProjectID));

                ProjectListUrl     = proposedProjectListUrl;
                BackToProjectsText = backToAllProposalsText;
                if ((projectApprovalStatus == ProjectApprovalStatus.Draft || projectApprovalStatus == ProjectApprovalStatus.Returned) && (userHasProjectAdminPermissions || userHasStartUpdateWorkflowPermission))
                {
                    projectAlerts.Add(
                        $"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is in the Proposal stage. Any edits to this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} must be made using the Add New {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} workflow.");
                }
                else if (projectApprovalStatus == ProjectApprovalStatus.PendingApproval)
                {
                    if (userHasProjectAdminPermissions || currentPerson.IsPersonAProjectOwnerWhoCanStewardProjects() && currentPerson.CanStewardProject(project))
                    {
                        projectAlerts.Add($"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} has been submitted and is awaiting review.");
                    }
                    else if (userHasStartUpdateWorkflowPermission)
                    {
                        projectAlerts.Add($"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} has been submitted, no change can be made.");
                        CanLaunchProjectOrProposalWizard = false;
                        ShowWithdrawProjectButton        = true;
                    }
                }
            }
            else if (project.IsPendingProject())
            {
                var projectApprovalStatus = project.ProjectApprovalStatus;
                ProjectUpdateButtonText =
                    projectApprovalStatus == ProjectApprovalStatus.Draft ||
                    projectApprovalStatus == ProjectApprovalStatus.Returned
                        ? $"Edit Pending {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}"
                        : $"Review Pending {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}";
                ProjectWizardUrl = SitkaRoute <ProjectCreateController> .BuildUrlFromExpression(x => x.EditBasics(project.ProjectID));

                ProjectListUrl     = pendingProjectsListUrl;
                BackToProjectsText = backToAllPendingProjectsText;
                if ((projectApprovalStatus == ProjectApprovalStatus.Draft || projectApprovalStatus == ProjectApprovalStatus.Returned) && (userHasProjectAdminPermissions || userHasStartUpdateWorkflowPermission))
                {
                    projectAlerts.Add(
                        $"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is pending. Any edits to this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} must be made using the Add New {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} workflow.");
                }
                else if (projectApprovalStatus == ProjectApprovalStatus.PendingApproval)
                {
                    if (userHasProjectAdminPermissions || currentPerson.IsPersonAProjectOwnerWhoCanStewardProjects() && currentPerson.CanStewardProject(project))
                    {
                        projectAlerts.Add($"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} has been submitted and is awaiting review.");
                    }
                    else if (userHasStartUpdateWorkflowPermission)
                    {
                        projectAlerts.Add($"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} is pending, no change can be made.");
                        CanLaunchProjectOrProposalWizard = false;
                        ShowWithdrawProjectButton        = true;
                    }
                }
            }
            else
            {
                var latestUpdateState = project.GetLatestUpdateStateResilientToDuplicateUpdateBatches();
                ProjectUpdateButtonText =
                    latestUpdateState == ProjectUpdateState.Submitted ||
                    latestUpdateState == ProjectUpdateState.Returned
                        ? "Review Update"
                        : $"Update {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}";
                ProjectWizardUrl   = project.GetProjectUpdateUrl();
                ProjectListUrl     = FullProjectListUrl;
                BackToProjectsText = $"Back to all {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()}";


                if (currentPerson.IsPersonAProjectOwnerWhoCanStewardProjects())
                {
                    if (currentPerson.CanStewardProject(project))
                    {
                        projectAlerts.Add(
                            $"You are a {FieldDefinitionEnum.ProjectSteward.ToType().GetFieldDefinitionLabel()} for this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}. You may edit this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} by using the <i class=\"glyphicon glyphicon-edit\"></i> icon on each panel.<br/>");
                    }
                    else
                    {
                        projectAlerts.Add(
                            $"You are a {FieldDefinitionEnum.ProjectSteward.ToType().GetFieldDefinitionLabel()}, but not for this {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()}. You may only edit {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()} that are associated with your {FieldDefinitionEnum.ProjectStewardshipArea.ToType().GetFieldDefinitionLabel()}.");
                    }
                }
            }

            if (ProjectModelExtensions.GetLatestNotApprovedUpdateBatch(project) != null)
            {
                if (userHasEditProjectPermissions)
                {
                    projectAlerts.Add($"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} has an Update in progress. Changes made through this page will be overwritten when the Update is approved.");
                }
                else
                {
                    projectAlerts.Add($"This {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} has an Update in progress.");
                }
            }

            ProjectAlerts = projectAlerts;

            ProjectBasicsViewData     = projectBasicsViewData;
            ProjectBasicsTagsViewData = projectBasicsTagsViewData;

            EditProjectCustomAttributesUrl = editProjectCustomAttributesUrl;

            ProjectLocationSummaryViewData = projectLocationSummaryViewData;
            MapFormID = mapFormID;
            EditSimpleProjectLocationUrl   = editSimpleProjectLocationUrl;
            EditDetailedProjectLocationUrl = editDetailedProjectLocationUrl;

            EditProjectBoundingBoxUrl = SitkaRoute <ProjectLocationController> .BuildUrlFromExpression(c => c.EditProjectBoundingBox(project));

            EditProjectBoundingBoxFormID = editProjectBoundingBoxFormID;

            EditProjectOrganizationsUrl = editProjectOrganizationsUrl;

            PerformanceMeasureExpectedSummaryViewData = performanceMeasureExpectedSummaryViewData;
            EditPerformanceMeasureExpectedsUrl        = editPerformanceMeasureExpectedsUrl;

            PerformanceMeasureReportedValuesGroupedViewData = performanceMeasureReportedValuesGroupedViewData;
            EditPerformanceMeasureActualsUrl = editPerformanceMeasureActualsUrl;

            ProjectBudgetSummaryViewData           = projectBudgetSummaryViewData;
            ProjectBudgetsAnnualViewData           = projectBudgetsAnnualViewData;
            ProjectBudgetsAnnualByCostTypeViewData = projectBudgetsAnnualByCostTypeViewData;
            EditTechnicalAssistanceRequestsUrl     = SitkaRoute <TechnicalAssistanceRequestController> .BuildUrlFromExpression(c => c.EditTechnicalAssistanceRequestsForProject(project));

            TechnicalAssistanceRequestDetailViewData = technicalAssistanceRequestDetailViewData;
            EditExpectedFundingUrl = editExpectedFundingUrl;

            ProjectExpendituresDetailViewData           = projectExpendituresDetailViewData;
            ProjectExpendituresByCostTypeDetailViewData = projectExpendituresByCostTypeDetailViewData;
            EditReportedExpendituresUrl = editReportedExpendituresUrl;
            GeospatialAreaTypes         = geospatialAreaTypes;
            DisplayProjectCustomAttributeTypesViewData = displayProjectCustomAttributeTypesViewData;
            EditExternalLinksUrl = editExternalLinksUrl;
            ImageGalleryViewData = imageGalleryViewData;

            ProjectNotesViewData  = projectNotesViewData;
            InternalNotesViewData = internalNotesViewData;

            EntityExternalLinksViewData = entityExternalLinksViewData;

            ProjectUpdateBatchGridSpec = new ProjectUpdateBatchGridSpec
            {
                ObjectNameSingular  = $"{FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} Update",
                ObjectNamePlural    = $"{FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabel()} Updates",
                SaveFiltersInCookie = true
            };
            ProjectUpdateBatchGridName    = "projectUpdateBatch";
            ProjectUpdateBatchGridDataUrl =
                SitkaRoute <ProjectController> .BuildUrlFromExpression(x =>
                                                                       x.ProjectUpdateBatchGridJsonData(project.ProjectID));

            ReportFinancialsByCostType = reportFinancialsByCostType;

            AuditLogsGridSpec    = auditLogsGridSpec;
            AuditLogsGridName    = "projectAuditLogsGrid";
            AuditLogsGridDataUrl = auditLogsGridDataUrl;

            ProjectNotificationGridSpec        = projectNotificationGridSpec;
            ProjectNotificationGridName        = projectNotificationGridName;
            ProjectNotificationGridDataUrl     = projectNotificationGridDataUrl;
            ProjectOrganizationsDetailViewData = projectOrganizationsDetailViewData;

            // Potential Partner panel
            ProjectPotentialPartnerDetailViewData = projectPotentialPartnerDetailViewData;

            ProjectContactsDetailViewData = projectContactsDetailViewData;
            EditProjectContactsUrl        = editProjectContactsUrl;

            EditProjectGeospatialAreaFormID = ProjectGeospatialAreaController.GetEditProjectGeospatialAreasFormID();

            ProjectStewardCannotEditUrl =
                SitkaRoute <ProjectController> .BuildUrlFromExpression(c => c.ProjectStewardCannotEdit());

            ProjectStewardCannotEditPendingApprovalUrl =
                SitkaRoute <ProjectController> .BuildUrlFromExpression(c =>
                                                                       c.ProjectStewardCannotEditPendingApproval(project));

            ClassificationSystems = classificationSystems;

            ProjectAttachmentsDetailViewData = new ProjectAttachmentsDetailViewData(
                EntityAttachment.CreateFromProjectAttachment(project.ProjectAttachments),
                SitkaRoute <ProjectAttachmentController> .BuildUrlFromExpression(x => x.New(project)),
                project.ProjectName,
                new ProjectEditAsAdminFeature().HasPermission(currentFirmaSession, project).HasPermission,
                project.GetAllAttachmentTypes().ToList(),
                currentFirmaSession);

            ProjectTimelineDisplayViewData = projectTimelineDisplayViewData;

            ProjectEvaluationsUserHasAccessTo = projectEvaluationsUserHasAccessTo;

            ShowFactSheetButton = OfferProjectFactSheetLinkFeature.OfferProjectFactSheetLink(currentFirmaSession, project);
        }
        public ProjectsIncludingLeadImplementingGridSpec(ProjectFirmaModels.Models.Organization organization, FirmaSession currentFirmaSession, bool showSubmittalStatus)
        {
            Add(FieldDefinitionEnum.Project.ToType().ToGridHeaderString(), a => UrlTemplate.MakeHrefString(a.GetDetailUrl(), a.GetDisplayName()), 350, DhtmlxGridColumnFilterType.Html);

            if (showSubmittalStatus)
            {
                Add("Submittal Status", a => a.ProjectApprovalStatus.ProjectApprovalStatusDisplayName, 110, DhtmlxGridColumnFilterType.SelectFilterStrict);
            }


            if (MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship())
            {
                Add(FieldDefinitionEnum.ProjectsStewardOrganizationRelationshipToProject.ToType().ToGridHeaderString(), x => x.GetCanStewardProjectsOrganization().GetDisplayNameAsUrl(), 150,
                    DhtmlxGridColumnFilterType.SelectFilterHtmlStrict);
            }
            Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(), x => x.GetPrimaryContactOrganization().GetDisplayNameAsUrl(), 150, DhtmlxGridColumnFilterType.SelectFilterHtmlStrict);

            Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), a => a.ProjectStage.ProjectStageDisplayName, 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.ProjectOrganizationRelationshipType.ToType().ToGridHeaderStringPlural(FieldDefinitionEnum.ProjectOrganizationRelationshipType.ToType().GetFieldDefinitionLabelPluralized()),
                a => string.Join(", ", a.GetAssociatedOrganizationRelationships().Where(x => x.Organization.OrganizationID == organization.OrganizationID).Select(x => x.OrganizationRelationshipTypeName)), 180, DhtmlxGridColumnFilterType.Text);

            Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add($"# Of Reported {MultiTenantHelpers.GetPerformanceMeasureName()} Records", x => x.PerformanceMeasureActuals.Count, 100);
            Add($"# Of {FieldDefinitionEnum.ReportedExpenditure.ToType().GetFieldDefinitionLabel()} Records", x => x.ProjectFundingSourceExpenditures.Count, 100);
            Add(FieldDefinitionEnum.FundingType.ToType().ToGridHeaderString(), x => x.FundingType?.FundingTypeDisplayName, 300, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 85, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.SecuredFunding.ToType().ToGridHeaderString(), x => x.GetSecuredFunding(), 85, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.TargetedFunding.ToType().ToGridHeaderString(), x => x.GetTargetedFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.NoFundingSourceIdentified.ToType().ToGridHeaderString(), x => x.GetNoFundingSourceIdentifiedAmount(), 85, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            foreach (var geospatialAreaType in new List <GeospatialAreaType>())
            {
                Add($"{geospatialAreaType.GeospatialAreaTypeNamePluralized}", a => a.GetProjectGeospatialAreaNamesAsHyperlinks(geospatialAreaType), 350, DhtmlxGridColumnFilterType.Html);
            }
            Add(FieldDefinitionEnum.ProjectDescription.ToType().ToGridHeaderString(), x => x.ProjectDescription, 200);
            if (new FirmaAdminFeature().HasPermissionByFirmaSession(currentFirmaSession))
            {
                Add("Tags", x => new HtmlString(!x.ProjectTags.Any() ? string.Empty : string.Join(", ", x.ProjectTags.Select(pt => pt.Tag.GetDisplayNameAsUrl()))), 100, DhtmlxGridColumnFilterType.Html);
            }
            Add("# of Photos", x => x.ProjectImages.Count, 60);
        }
        public ProjectUpdateStatusGridSpec(FirmaSession currentFirmaSession, ProjectUpdateStatusFilterTypeEnum projectUpdateStatusFilterTypeEnum,
                                           bool canStewardProjects)
        {
            _canStewardProjects = canStewardProjects;

            AddViewEditColumn(projectUpdateStatusFilterTypeEnum);

            Add("Reporting Period Update Status",
                x =>
            {
                var projectUpdateState        = x.GetLatestUpdateStateResilientToDuplicateUpdateBatches();
                var latestApprovedUpdateBatch = x.GetLatestApprovedUpdateBatch();
                if (projectUpdateState == null ||
                    (projectUpdateState == ProjectUpdateState.Approved && latestApprovedUpdateBatch != null && !latestApprovedUpdateBatch.LastUpdateDate.IsDateInRange(FirmaDateUtilities.LastReportingPeriodStartDate(), FirmaDateUtilities.LastReportingPeriodEndDate())))
                {
                    return("Not Started");
                }

                return(projectUpdateState.ToEnum.ToString());
            },
                110,
                DhtmlxGridColumnFilterType.SelectFilterStrict);

            Add(FieldDefinitionEnum.ProjectName.ToType().ToGridHeaderString(), x => UrlTemplate.MakeHrefString(x.GetDetailUrl(), x.ProjectName), 180, DhtmlxGridColumnFilterType.Html);
            Add(FieldDefinitionEnum.OrganizationPrimaryContact.ToType().ToGridHeaderString(),
                x => x.GetPrimaryContact() == null ? ViewUtilities.NoneString.ToHTMLFormattedString() : x.GetPrimaryContact().GetFullNameFirstLastAndOrgShortNameAsUrl(currentFirmaSession),
                95);
            Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(),
                x => x.GetPrimaryContactOrganization().GetDisplayNameAsUrl(), 150, DhtmlxGridColumnFilterType.Html);
            Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), x => x.ProjectStage.ProjectStageDisplayName, 80, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.SecuredFunding.ToType().ToGridHeaderString(), x => x.GetSecuredFunding(), 95, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);

            if (projectUpdateStatusFilterTypeEnum != ProjectUpdateStatusFilterTypeEnum.MySubmittedProjects)
            {
                AddSubmitColumn();
            }

            Add("Last Updated", x => !x.ProjectUpdateBatches.Any() ? (DateTime?)null : x.ProjectUpdateBatches.Max(y => y.LastUpdateDate), 120);
            Add("Last Updated By", x => !x.ProjectUpdateBatches.Any() ? string.Empty : x.ProjectUpdateBatches.OrderByDescending(y => y.LastUpdateDate).First().LastUpdatePerson.GetFullNameFirstLast(), 120);

            Add("Last Submitted", x => x.GetLatestUpdateSubmittalDate(), 120);
            Add("Last Submitted By", x => x.GetLatestUpdateSubmittalPerson() != null ? x.GetLatestUpdateSubmittalPerson().GetFullNameFirstLast() : string.Empty, 120);

            Add("Last Approved", x =>
            {
                var latestApprovedUpdateBatch = x.GetLatestApprovedUpdateBatch();
                return(latestApprovedUpdateBatch?.LastUpdateDate);
            }, 120);
            Add("Last Approved By", x =>
            {
                var latestApprovedUpdateBatch = x.GetLatestApprovedUpdateBatch();
                return(latestApprovedUpdateBatch?.LastUpdatePerson.GetFullNameFirstLast());
            }, 120);
        }
        public BasicProjectInfoGridSpec(FirmaSession currentFirmaSession, bool allowTaggingFunctionality)
        {
            var userHasTagManagePermissions = new FirmaAdminFeature().HasPermissionByFirmaSession(currentFirmaSession);

            if (userHasTagManagePermissions && allowTaggingFunctionality)
            {
                BulkTagModalDialogForm = new BulkTagModalDialogForm(SitkaRoute <TagController> .BuildUrlFromExpression(x => x.BulkTagProjects(null)), $"Tag Checked {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()}", $"Tag {FieldDefinitionEnum.Project.ToType().GetFieldDefinitionLabelPluralized()}");
                AddCheckBoxColumn();
                Add("ProjectID", x => x.ProjectID, 0);
            }

            Add(string.Empty, x => UrlTemplate.MakeHrefString(x.GetFactSheetUrl(), FirmaDhtmlxGridHtmlHelpers.FactSheetIcon.ToString()), 30, DhtmlxGridColumnFilterType.None);
            Add(FieldDefinitionEnum.ProjectName.ToType().ToGridHeaderString(), x => UrlTemplate.MakeHrefString(x.GetDetailUrl(), x.ProjectName), 300, DhtmlxGridColumnFilterType.Html);
            if (MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship())
            {
                Add(FieldDefinitionEnum.ProjectsStewardOrganizationRelationshipToProject.ToType().ToGridHeaderString(), x => x.GetCanStewardProjectsOrganization().GetShortNameAsUrl(), 150,
                    DhtmlxGridColumnFilterType.Html);
            }
            Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(), x => x.GetPrimaryContactOrganization().GetShortNameAsUrl(), 150, DhtmlxGridColumnFilterType.Html);
            Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), x => x.ProjectStage.ProjectStageDisplayName, 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.FundingType.ToType().ToGridHeaderString(), x => x.FundingType?.FundingTypeDisplayName ?? string.Empty, 300, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.SecuredFunding.ToType().ToGridHeaderString(), x => x.GetSecuredFunding(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.TargetedFunding.ToType().ToGridHeaderString(), x => x.GetTargetedFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.NoFundingSourceIdentified.ToType().ToGridHeaderString(), x => x.GetNoFundingSourceIdentifiedAmount(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            foreach (var geospatialAreaType in new List <GeospatialAreaType>())
            {
                Add($"{geospatialAreaType.GeospatialAreaTypeNamePluralized}", a => a.GetProjectGeospatialAreaNamesAsHyperlinks(geospatialAreaType), 350, DhtmlxGridColumnFilterType.Html);
            }
            Add(FieldDefinitionEnum.ProjectDescription.ToType().ToGridHeaderString(), x => x.ProjectDescription, 300);
            if (userHasTagManagePermissions)
            {
                Add("Tags", x => new HtmlString(!x.ProjectTags.Any() ? string.Empty : string.Join(", ", x.ProjectTags.Select(pt => pt.Tag.GetDisplayNameAsUrl()))), 100, DhtmlxGridColumnFilterType.Html);
            }
        }
示例#12
0
        public UserProjectGridSpec(FirmaSession currentFirmaSession, Person person)
        {
            var userHasTagManagePermissions = new FirmaAdminFeature().HasPermissionByFirmaSession(currentFirmaSession);

            Add(string.Empty, x => UrlTemplate.MakeHrefString(x.GetFactSheetUrl(), FirmaDhtmlxGridHtmlHelpers.FactSheetIcon.ToString()), 30, DhtmlxGridColumnFilterType.None);
            Add(FieldDefinitionEnum.ProjectName.ToType().ToGridHeaderString(), x => UrlTemplate.MakeHrefString(x.GetDetailUrl(), x.ProjectName), 300, DhtmlxGridColumnFilterType.Html);

            Add($"Contact Type(s)", x => string.Join(", ", person.GetListOfContactTypeStringsForProject(x)), 300, DhtmlxGridColumnFilterType.Html);

            if (MultiTenantHelpers.HasCanStewardProjectsOrganizationRelationship())
            {
                Add(FieldDefinitionEnum.ProjectsStewardOrganizationRelationshipToProject.ToType().ToGridHeaderString(), x => x.GetCanStewardProjectsOrganization().GetShortNameAsUrl(), 150,
                    DhtmlxGridColumnFilterType.Html);
            }
            Add(FieldDefinitionEnum.IsPrimaryContactOrganization.ToType().ToGridHeaderString(), x => x.GetPrimaryContactOrganization().GetShortNameAsUrl(), 150, DhtmlxGridColumnFilterType.Html);
            Add(FieldDefinitionEnum.ProjectStage.ToType().ToGridHeaderString(), x => x.ProjectStage.ProjectStageDisplayName, 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.PlanningDesignStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetPlanningDesignStartYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.ImplementationStartYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetImplementationStartYear(x), 115, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.CompletionYear.ToType().ToGridHeaderString(), x => ProjectModelExtensions.GetCompletionYear(x), 90, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.FundingType.ToType().ToGridHeaderString(), x => x.FundingType?.FundingTypeDisplayName ?? string.Empty, 300, DhtmlxGridColumnFilterType.SelectFilterStrict);
            Add(FieldDefinitionEnum.EstimatedTotalCost.ToType().ToGridHeaderString(), x => x.GetEstimatedTotalRegardlessOfFundingType(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.ProjectedFunding.ToType().ToGridHeaderString(), x => x.GetProjectedFunding(), 100, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            Add(FieldDefinitionEnum.NoFundingSourceIdentified.ToType().ToGridHeaderString(), x => x.GetNoFundingSourceIdentifiedAmount(), 110, DhtmlxGridColumnFormatType.Currency, DhtmlxGridColumnAggregationType.Total);
            foreach (var geospatialAreaType in new List <GeospatialAreaType>())
            {
                Add($"{geospatialAreaType.GeospatialAreaTypeNamePluralized}", a => a.GetProjectGeospatialAreaNamesAsHyperlinks(geospatialAreaType), 350, DhtmlxGridColumnFilterType.Html);
            }
            Add(FieldDefinitionEnum.ProjectDescription.ToType().ToGridHeaderString(), x => x.ProjectDescription, 300);
            if (userHasTagManagePermissions)
            {
                Add("Tags", x => new HtmlString(!x.ProjectTags.Any() ? string.Empty : string.Join(", ", x.ProjectTags.Select(pt => pt.Tag.GetDisplayNameAsUrl()))), 100, DhtmlxGridColumnFilterType.Html);
            }
        }