Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev-4347 account spending tables #1706

Merged
merged 26 commits into from
Jun 2, 2020
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
24e71c8
Initial Table Container
ebdabbs May 22, 2020
affca38
added pagination and additional column mappings
ebdabbs May 22, 2020
136ecca
Merge remote-tracking branch 'origin/dev' into ftr/dev-4347-agency-bu…
ebdabbs May 26, 2020
698d41f
Added missing Fontawesome icons
ebdabbs May 26, 2020
40fb096
Store the agency's total obligation in Redux
ebdabbs May 26, 2020
6735b51
added unit tests
ebdabbs May 26, 2020
b350470
added data model for account spending row, parsing function, and sort…
May 27, 2020
e050da8
added loading and error states
May 28, 2020
0bf6de3
added BaseAccountSpendingRow test
May 28, 2020
722b2a0
added disabled prop
May 28, 2020
64f11e2
added pagination buttons when loading or errored
May 28, 2020
aaa4541
updated percentage function in base model
May 28, 2020
6de64d3
added styling for table and count tabs
May 29, 2020
0a4c413
added word-break
May 29, 2020
b0642b3
Merge branch 'dev' into ftr/dev-4347-account-spending-tables
May 29, 2020
5516767
updated tabs to use color variables
jameslee40 May 29, 2020
935dae9
Refactored CountTab onClick for performance reasons
jameslee40 May 29, 2020
a3d7648
added error state to AgencyContainerV2
jameslee40 May 29, 2020
bf90684
Refactored state naming
jameslee40 May 29, 2020
0b72344
Removed useless parenthesis
jameslee40 May 29, 2020
a34c352
Refactored function to useCallback
jameslee40 May 29, 2020
3d1e8a8
Removed value from button
jameslee40 May 29, 2020
9448b7c
moved params and setLoading inside callback instead of passing params
jameslee40 Jun 1, 2020
c56e2cb
Merge branch 'dev' into ftr/dev-4347-account-spending-tables
jameslee40 Jun 2, 2020
b8ecb06
updated data-transparency-ui version
jameslee40 Jun 2, 2020
04d499a
Merge branch 'dev' into ftr/dev-4347-account-spending-tables
jameslee40 Jun 2, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
"d3-interpolate": "^1.1.4",
"d3-scale": "^1.0.4",
"d3-time": "^1.0.11",
"data-transparency-ui": "github:fedspendingtransparency/data-transparency-ui#v1.1.1",
"data-transparency-ui": "github:fedspendingtransparency/data-transparency-ui#master",
"file-loader": "^3.0.1",
"fixed-data-table": "0.6.3",
"history": "^4.6.1",
Expand Down
5 changes: 5 additions & 0 deletions src/_scss/pages/agency/v2/_tabs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@
line-height: rem(20);
}
}

&:disabled {
color: $color-gray-medium;
background-color: $color-gray-lightest;
}
}
}
}
71 changes: 71 additions & 0 deletions src/_scss/pages/agency/v2/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,77 @@
@media(min-width: $tablet-screen) {
width: 70%;
}
.body__content {
@import '../../search/results/table/tableMessages';
.results-table-message-container {
position: relative;
background-color: rgb(246, 246, 246);
.results-table-loading {
margin-bottom: rem(100);
}
.no-results-container {
text-align: center;
margin-top: rem(100);
margin-bottom: rem(100);
.no-results-title {
h4 {
margin-bottom: 0;
vertical-align: bottom;
}
}
.no-results-message {
p {
margin-top: 0;
vertical-align: top;
}
}
}
.loading-animation {
@import "../../search/results/screens/loading";
}
.results-table-error {
.icon {
width: rem(36);
height: rem(36);
svg {
width: rem(36);
height: rem(36);
}
}
.title {
font-size: rem(20);
line-height: rem(45);
}
.description {
font-size: rem(16);
line-height: rem(10);
}
}
}
.usda-table {
td {
&:first-child {
@include span-columns(6 of 12, table);
text-align: left;
}
@include span-columns(2 of 12, table);
text-align: right;
word-break: break-word;
}

.table-header {
.table-header__label {
@include flex(0 1 auto);
text-align: right;
}

.table-header__sort {
margin-top: auto;
margin-bottom: auto;
}
}
}
}
.body__section {
@import './tabs';
@include display(flex);
Expand Down
4 changes: 4 additions & 0 deletions src/js/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import {
faBook,
faBuilding,
faCalendarAlt,
faCaretDown,
faCaretLeft,
faCaretRight,
faCaretUp,
faChartArea,
faChartBar,
faChartPie,
Expand Down Expand Up @@ -65,8 +67,10 @@ library.add(
faBook,
faBuilding,
faCalendarAlt,
faCaretDown,
faCaretLeft,
faCaretRight,
faCaretUp,
faChartArea,
faChartBar,
faChartPie,
Expand Down
47 changes: 28 additions & 19 deletions src/js/components/agency/v2/CountTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,37 @@ const propTypes = {
setActiveTab: PropTypes.func.isRequired,
active: PropTypes.bool,
count: PropTypes.number,
subCount: PropTypes.number
subCount: PropTypes.number,
disabled: PropTypes.bool
};

const CountTab = (props) => (
<button
className={`count-tabs__button${props.active ? ' count-tabs__button_active' : ''}`}
onClick={() => props.setActiveTab(props.type)}>
<div className="count-button">
<div className="count-button__label">
{props.label}
</div>
<div className="count-button__count">
{(props.count || props.count === 0) ? `${props.count}` : '--'}
</div>
{props.subHeading ? (
<div className="count-button__sub-heading">
With {(props.subCount || props.subCount === 0) ? `${props.subCount}` : '--'} {props.subHeading}

const CountTab = (props) => {
const setActiveTab = () => {
props.setActiveTab(props.type);
};

return (
<button
className={`count-tabs__button${props.active ? ' count-tabs__button_active' : ''}`}
onClick={setActiveTab}
disabled={props.disabled}>
<div className="count-button">
<div className="count-button__label">
{props.label}
</div>
) : <>&nbsp;</>}
</div>
</button>
);
<div className="count-button__count">
{(props.count || props.count === 0) ? `${props.count}` : '--'}
</div>
{props.subHeading ? (
<div className="count-button__sub-heading">
With {(props.subCount || props.subCount === 0) ? `${props.subCount}` : '--'} {props.subHeading}
</div>
) : <>&nbsp;</>}
</div>
</button>
);
};

CountTab.propTypes = propTypes;
export default CountTab;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import CountTabContainer from 'containers/agency/v2/accountSpending/CountTabContainer';
import TableContainer from 'containers/agency/v2/accountSpending/TableContainer';

const propTypes = {
fy: PropTypes.string,
Expand Down Expand Up @@ -45,6 +46,7 @@ const tabs = [

const AccountSpending = ({ agencyId, fy }) => {
const [activeTab, setActiveTab] = useState('budget_function');
const subHeading = tabs.find((tab) => tab.type === activeTab).subHeading;
return (
<div className="body__content">
<div className="count-tabs">
Expand All @@ -66,6 +68,11 @@ const AccountSpending = ({ agencyId, fy }) => {
active={activeTab === tab.type} />
))}
</div>
<TableContainer
agencyId={agencyId}
fy={fy}
type={activeTab}
subHeading={subHeading} />
</div>
</div>
);
Expand Down
83 changes: 53 additions & 30 deletions src/js/containers/agency/v2/AgencyContainerV2.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@
* Created by Maxwell Kendall 01/31/2020
*/

/* eslint-disable no-unused-vars */
/* eslint-disable react/prop-types */

import React, { useState, useEffect } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { useDispatch } from 'react-redux';
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { startCase, snakeCase } from "lodash";
import {
TooltipWrapper,
Picker
} from 'data-transparency-ui';

import { setAgencyOverview, resetAgency } from 'redux/actions/agency/agencyActions';
import { setBudgetaryResources } from 'redux/actions/agencyV2/agencyV2Actions';
import { fetchBudgetaryResources } from 'helpers/agencyV2Helper';
import BaseAgencyBudgetaryResources from 'models/v2/agency/BaseAgencyBudgetaryResources';

import { agencyPageMetaTags } from 'helpers/metaTagHelper';
import { scrollToY } from 'helpers/scrollToHelper';
Expand All @@ -32,10 +32,10 @@ import { defaultSortFy } from 'components/sharedComponents/pickers/FYPicker';
import ShareIcon from 'components/sharedComponents/stickyHeader/ShareIcon';

import AccountSpending from 'components/agency/v2/accountSpending/AccountSpending';
import Error from '../../../components/sharedComponents/Error';

require('pages/agency/v2/index.scss');

// document.querySelector('.site-navigation').offsetHeight + document.querySelector('.site-navigation').offsetTop
const scrollPositionOfSiteHeader = 96;

const TooltipComponent = () => (
Expand Down Expand Up @@ -70,15 +70,39 @@ const ComingSoon = () => (
</div>
);

const propTypes = {
params: PropTypes.shape({
agencyId: PropTypes.string
})
};

export const AgencyProfileV2 = ({
agencyOverview,
agencyId,
params,
clearAgency,
setOverview
params
}) => {
const dispatch = useDispatch();
const [activeSection, setActiveSection] = useState('overview');
const [selectedFy, setSelectedFy] = useState(FiscalYearHelper.defaultFiscalYear());
const [loading, setLoading] = useState(true);
const [error, setError] = useState(false);

useEffect(() => {
setLoading(true);
// request budgetary resources data for this agency
const budgetaryResourcesRequest = fetchBudgetaryResources(params.agencyId);
budgetaryResourcesRequest.promise
.then((res) => {
// parse the response using our data model
setLoading(false);
const budgetaryResources = Object.create(BaseAgencyBudgetaryResources);
budgetaryResources.populate(res.data);
// store the data model object in Redux
dispatch(setBudgetaryResources(budgetaryResources));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very Nice!

}).catch((err) => {
setError(true);
setLoading(false);
console.error(err);
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.catch() how are we handling errors for this content?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added error handling for this, as well as, rendering the error.

}, [params.agencyId]);

const componentByAgencySection = {
overview: <ComingSoon />,
Expand Down Expand Up @@ -154,7 +178,8 @@ export const AgencyProfileV2 = ({
<ShareIcon
slug={slug}
email={{
subject: `USAspending.gov Agency Profile: ${agencyOverview.name}`,
// TODO - add agency name when the data is available
subject: 'USAspending.gov Agency Profile: ',
body: `View the spending activity of this agency on USAspending.gov: ${getBaseUrl(slug)}`
}} />
<div className="sticky-header__toolbar-item">
Expand All @@ -166,7 +191,7 @@ export const AgencyProfileV2 = ({
</div>
</>
</StickyHeader>
<LoadingWrapper isLoading={false} >
<LoadingWrapper isLoading={loading} >
<main id="main-content" className="main-content usda__flex-row">
<div className="sidebar usda__flex-col">
<Sidebar
Expand All @@ -180,28 +205,26 @@ export const AgencyProfileV2 = ({
label: startCase(section)
}))} />
</div>
<div className="body usda__flex-col">
{Object.keys(componentByAgencySection).map((section) => (
<AgencySection key={section} section={section} >
{componentByAgencySection[section]}
</AgencySection>
))}
</div>
{error &&
<div className="body usda__flex-col">
<Error />
</div>}
{!error &&
<div className="body usda__flex-col">
{Object.keys(componentByAgencySection).map((section) => (
<AgencySection key={section} section={section} >
{componentByAgencySection[section]}
</AgencySection>
))}
</div>
}
</main>
</LoadingWrapper>
<Footer />
</div>
);
};

const mapStateToProps = (state) => ({
agencyOverview: state.agency.overview,
agencyId: state.agency.id
});

const mapDispatchToProps = (dispatch) => ({
clearAgency: () => dispatch(resetAgency()),
setOverview: (agency) => dispatch(setAgencyOverview(agency))
});
AgencyProfileV2.propTypes = propTypes;

export default connect(mapStateToProps, mapDispatchToProps)(AgencyProfileV2);
export default AgencyProfileV2;
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import { fetchSpendingCount } from 'helpers/agencyHelper';
import { fetchSpendingCount } from 'helpers/agencyV2Helper';
import CountTab from 'components/agency/v2/CountTab';

const propTypes = {
Expand Down Expand Up @@ -45,6 +45,7 @@ const CountTabContainer = (props) => {
subHeading={props.subHeading}
setActiveTab={props.setActiveTab}
active={props.active}
disabled={count === 0}
type={props.type} />
);
};
Expand Down
Loading