diff --git a/package.json b/package.json index 8bfa7573c8..bcb1ce1ede 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,7 @@ "react-dnd": "^2.4.0", "react-dnd-html5-backend": "^2.4.1", "react-dom": "15.6.1", - "react-ga": "^2.1.2", + "react-ga": "2.2.0", "react-helmet": "^5.0.0", "react-map-gl": "^2.0.2", "react-markdown": "^2.5.0", diff --git a/src/_scss/layouts/default/header/_positioning.scss b/src/_scss/layouts/default/header/_positioning.scss index c7ad4b54ac..2c556ab16d 100644 --- a/src/_scss/layouts/default/header/_positioning.scss +++ b/src/_scss/layouts/default/header/_positioning.scss @@ -20,8 +20,6 @@ } } .mobile-menu { - @include media($tablet-screen) { - display: none; - } + display: none; } } \ No newline at end of file diff --git a/src/_scss/pages/agency/_section.scss b/src/_scss/pages/agency/_section.scss index 08f130f5dd..cc42ef8bec 100644 --- a/src/_scss/pages/agency/_section.scss +++ b/src/_scss/pages/agency/_section.scss @@ -32,13 +32,13 @@ @import "pages/homepage/treemapSection"; .agency-viz-description { - margin-top: rem(20); + margin-top: rem(10); font-size: rem(12); } .usa-da-treemap-section { background: white; - padding-top: rem(50); + padding-top: rem(40); padding-bottom: rem(0); .treemap-inner-wrap { diff --git a/src/_scss/pages/agency/visualizations/_obligated.scss b/src/_scss/pages/agency/visualizations/_obligated.scss index f7604f2f75..b4a2c4b2b3 100644 --- a/src/_scss/pages/agency/visualizations/_obligated.scss +++ b/src/_scss/pages/agency/visualizations/_obligated.scss @@ -21,7 +21,8 @@ } .horizontal-bar { width: 100%; - height: rem(72); + height: rem(100); + padding-top: rem(15); .legend-container { color: $color-gray-medium; .key-label { diff --git a/src/_scss/pages/agency/visualizations/federalAccount/federalAccount.scss b/src/_scss/pages/agency/visualizations/federalAccount/federalAccount.scss index 6131c9f0a3..0dc3909689 100644 --- a/src/_scss/pages/agency/visualizations/federalAccount/federalAccount.scss +++ b/src/_scss/pages/agency/visualizations/federalAccount/federalAccount.scss @@ -27,6 +27,26 @@ } } + @import "pages/search/results/visualizations/rank/_pager"; + .visualization-pager-container { + @include display(flex); + @include align-items(center); + @include justify-content(center); + position: relative; + width: 100%; + + .prev-page { + @include flex(1 1 auto); + @include align-self(flex-start); + } + .next-page { + @include flex(1 1 auto); + @include align-self(flex-end); + button { + float: right; + } + } + } } } \ No newline at end of file diff --git a/src/js/components/agency/overview/AgencyOverview.jsx b/src/js/components/agency/overview/AgencyOverview.jsx index 438ab86f69..fb0091e90b 100644 --- a/src/js/components/agency/overview/AgencyOverview.jsx +++ b/src/js/components/agency/overview/AgencyOverview.jsx @@ -13,6 +13,9 @@ import * as MoneyFormatter from 'helpers/moneyFormatter'; import HorizontalBarItem from '../visualizations/obligated/HorizontalBarItem'; +// Temporarily use a hardcoded total budget authority +const federalBudget = 8361447130497.72; + const propTypes = { agency: PropTypes.object }; @@ -81,7 +84,9 @@ export default class AgencyOverview extends React.PureComponent { // Move props to variables for readability const budgetAuthority = props.agency.budgetAuthority; - const federalBudget = props.agency.federalBudget; + + // const federalBudget = props.agency.federalBudget; + const fy = parseInt(props.agency.activeFY, 10); const quarter = parseInt(props.agency.activeFQ, 10); @@ -127,12 +132,18 @@ export default class AgencyOverview extends React.PureComponent { // Generate visualization parameters let obligatedWidth = 0; - // Only check the percentage width if the data is available - if (props.agency.budgetAuthority !== 0 && props.agency.federalBudget !== 0) { - const percentageNumber = props.agency.budgetAuthority / props.agency.federalBudget; + // Temporarily use hardcoded Federal Budget + if (props.agency.budgetAuthority !== 0) { + const percentageNumber = props.agency.budgetAuthority / federalBudget; obligatedWidth = visualizationWidth * percentageNumber; } + // Only check the percentage width if the data is available + // if (props.agency.budgetAuthority !== 0 && props.agency.federalBudget !== 0) { + // const percentageNumber = props.agency.budgetAuthority / props.agency.federalBudget; + // obligatedWidth = visualizationWidth * percentageNumber; + // } + // Account for 10 pixels of left padding const padding = 10; const remainingWidth = visualizationWidth - obligatedWidth - padding; diff --git a/src/js/components/agency/visualizations/federalAccount/FederalAccountChart.jsx b/src/js/components/agency/visualizations/federalAccount/FederalAccountChart.jsx index 6e01b1b0e9..8364c65a42 100644 --- a/src/js/components/agency/visualizations/federalAccount/FederalAccountChart.jsx +++ b/src/js/components/agency/visualizations/federalAccount/FederalAccountChart.jsx @@ -6,6 +6,7 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { AngleLeft, AngleRight } from 'components/sharedComponents/icons/Icons'; import HorizontalChart from 'components/search/visualizations/rank/chart/HorizontalChart'; import BarChartLegend from 'components/search/visualizations/time/chart/BarChartLegend'; @@ -18,7 +19,10 @@ const propTypes = { dataSeries: PropTypes.array, descriptions: PropTypes.array, width: PropTypes.number, - labelWidth: PropTypes.number + labelWidth: PropTypes.number, + page: PropTypes.number, + changePage: PropTypes.func, + isLastPage: PropTypes.bool }; const rowHeight = 60; @@ -41,6 +45,9 @@ export default class FederalAccountChart extends React.Component { this.showTooltip = this.showTooltip.bind(this); this.hideTooltip = this.hideTooltip.bind(this); + + this.clickedNext = this.clickedNext.bind(this); + this.clickedPrev = this.clickedPrev.bind(this); } showTooltip(data) { @@ -56,12 +63,39 @@ export default class FederalAccountChart extends React.Component { }); } + clickedNext() { + if (this.props.loading || this.props.isLastPage) { + return; + } + + const nextPage = this.props.page + 1; + this.props.changePage(nextPage); + } + + clickedPrev() { + if (this.props.loading) { + return; + } + + const nextPage = Math.max(1, this.props.page - 1); + this.props.changePage(nextPage); + } + render() { let hideTooltip = ''; if (!this.state.showTooltip) { hideTooltip = 'hide'; } + let hidePrevious = ''; + if (this.props.page === 1) { + hidePrevious = 'hide'; + } + + let hideNext = ''; + if (this.props.isLastPage) { + hideNext = 'hide'; + } let isLoading = ''; if (this.props.loading) { @@ -97,6 +131,43 @@ export default class FederalAccountChart extends React.Component { +
+
+ +
+
+ +
+
+
diff --git a/src/js/components/agency/visualizations/federalAccount/FederalAccountVisualization.jsx b/src/js/components/agency/visualizations/federalAccount/FederalAccountVisualization.jsx index bb8125e56e..9a62ec9cdd 100644 --- a/src/js/components/agency/visualizations/federalAccount/FederalAccountVisualization.jsx +++ b/src/js/components/agency/visualizations/federalAccount/FederalAccountVisualization.jsx @@ -7,17 +7,23 @@ import React from 'react'; import PropTypes from 'prop-types'; import * as MoneyFormatter from 'helpers/moneyFormatter'; +import ChartMessage from 'components/search/visualizations/rank/RankVisualizationChartMessage'; + import FederalAccountChart from './FederalAccountChart'; const propTypes = { obligatedAmount: PropTypes.number, loading: PropTypes.bool, error: PropTypes.bool, + isInitialLoad: PropTypes.bool, linkSeries: PropTypes.array, labelSeries: PropTypes.array, dataSeries: PropTypes.array, descriptions: PropTypes.array, - asOfDate: PropTypes.string + asOfDate: PropTypes.string, + page: PropTypes.number, + isLastPage: PropTypes.bool, + changePage: PropTypes.func }; export default class FederalAccountVisualization extends React.Component { @@ -56,7 +62,35 @@ export default class FederalAccountVisualization extends React.Component { } render() { const obUnits = MoneyFormatter.calculateUnitForSingleValue(this.props.obligatedAmount); - const formattedObligation = `${MoneyFormatter.formatMoney(this.props.obligatedAmount / obUnits.unit)} ${obUnits.longLabel}`; + const formattedObligation = `${MoneyFormatter.formatMoneyWithPrecision(this.props.obligatedAmount / obUnits.unit, 1)} + ${obUnits.longLabel}`; + + let chart = null; + if (this.props.loading && this.props.isInitialLoad) { + // initial load + chart = (); + } + else if (this.props.error) { + // error + chart = (); + } + else if (this.props.dataSeries.length === 0) { + // no data + chart = (); + } + else { + chart = (); + } return (
- + {chart}
diff --git a/src/js/components/agency/visualizations/objectClass/MajorObjectClasses.jsx b/src/js/components/agency/visualizations/objectClass/MajorObjectClasses.jsx index 5d09714167..ecf3128c3f 100644 --- a/src/js/components/agency/visualizations/objectClass/MajorObjectClasses.jsx +++ b/src/js/components/agency/visualizations/objectClass/MajorObjectClasses.jsx @@ -18,7 +18,8 @@ const propTypes = { majorObjectClasses: PropTypes.object, toggleMinorObjectClass: PropTypes.func, showMinorObjectClass: PropTypes.bool, - totalObligation: PropTypes.number + totalObligation: PropTypes.number, + hasNegatives: PropTypes.bool }; export default class MajorObjectClasses extends React.Component { @@ -144,7 +145,7 @@ export default class MajorObjectClasses extends React.Component { x1={n.x1} y0={n.y0} y1={n.y1} - total={n.parent.value} + total={treeProps.totalObligation} key={n.data.major_object_class_code} objectClassID={n.data.major_object_class_code} color={cellColor} @@ -230,8 +231,15 @@ export default class MajorObjectClasses extends React.Component { } render() { + let greatThanOneHundredDescription = null; + if (this.props.hasNegatives) { + greatThanOneHundredDescription = (

Note: The object classes below add up to more + than 100% due to negative values not shown here. +

); + } return (
+ {greatThanOneHundredDescription} { this.createTooltip() }
Note: The object classes below add up to more + than 100% due to negative values not shown here. +

); + } + return (
+ {greatThanOneHundredDescription}

{this.props.majorObjectClass.major_object_class_name}

{totalSpend} | {percentage}
diff --git a/src/js/components/agency/visualizations/objectClass/ObjectClassTreeMap.jsx b/src/js/components/agency/visualizations/objectClass/ObjectClassTreeMap.jsx index c44fb6a8ab..7c31a0d549 100644 --- a/src/js/components/agency/visualizations/objectClass/ObjectClassTreeMap.jsx +++ b/src/js/components/agency/visualizations/objectClass/ObjectClassTreeMap.jsx @@ -19,7 +19,9 @@ const propTypes = { totalObligation: PropTypes.number, totalMinorObligation: PropTypes.number, showMinorObjectClasses: PropTypes.func, - asOfDate: PropTypes.string + asOfDate: PropTypes.string, + hasNegatives: PropTypes.bool, + minorHasNegatives: PropTypes.bool }; export default class ObjectClassTreeMap extends React.Component { @@ -67,12 +69,7 @@ export default class ObjectClassTreeMap extends React.Component { } generateHeader() { - let header = (
-
- -
- Hover over a segment for more information -
); + let header = ''; if (this.state.showMinorObjectClass === true) { header = (