Skip to content

Commit

Permalink
feat: allocations table
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanoshadjipetrou committed Mar 7, 2023
1 parent ab4d6a4 commit 6914ddc
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 40 deletions.
2 changes: 2 additions & 0 deletions src/app/components/Table/Expandable/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,10 @@ export function TableToolbar(props: TableToolbarProps) {
<FormGroup>
{props.columns.map((c, index) => (
<FormControlLabel
key={c.name}
control={
<Checkbox
key={c.name}
value={index}
color="primary"
checked={c.checked}
Expand Down
2 changes: 2 additions & 0 deletions src/app/components/Table/Simple/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ export interface SimpleTableProps {
title: string;
search: string;
sortBy: string;
forceExpand?: boolean;
rows: SimpleTableRow[];
formatNumbers?: boolean;
columns: SimpleTableColumn[];
onSearchChange: (value: string) => void;
onSortByChange: (value: string) => void;
Expand Down
92 changes: 53 additions & 39 deletions src/app/components/Table/Simple/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ArrowDownward from "@material-ui/icons/ArrowDownward";
import { TriangleXSIcon } from "app/assets/icons/TriangleXS";
import TableContainer from "@material-ui/core/TableContainer";
import { tablecell } from "app/components/Table/Simple/styles";
import { formatFinancialValue } from "app/utils/formatFinancialValue";
import { TableToolbar } from "app/components/Table/Expandable/Toolbar";
import { TableToolbarCols } from "app/components/Table/Expandable/data";
import {
Expand All @@ -36,9 +37,11 @@ function Row(props: {
columns: SimpleTableColumn[];
paddingLeft?: number;
visibleColumnsIndexes: number[];
formatNumbers?: boolean;
forceExpand?: boolean;
}) {
const classes = useRowStyles();
const [open, setOpen] = React.useState(false);
const [open, setOpen] = React.useState(Boolean(props.forceExpand));

const firstColumnWidth = props.columns.length > 3 ? "30%" : "";
const firstColumnPadding = props.paddingLeft ? props.paddingLeft : 40;
Expand Down Expand Up @@ -80,58 +83,65 @@ function Row(props: {
{filter(
props.columns,
(_c, index) => props.visibleColumnsIndexes.indexOf(index) > -1
).map((column: SimpleTableColumn, index: number) => (
<TableCell
key={column.key}
css={`
${tablecell}
width: calc(${columnWidthCalc});
${index === 0
? `padding-left: ${firstColumnPadding}px;width: ${firstColumnWidth}`
: ""}
`}
>
<div
).map((column: SimpleTableColumn, index: number) => {
const value = get(props.row, column.key, "");
let formattedValue =
props.formatNumbers && !Number.isNaN(value)
? formatFinancialValue(value, true)
: value;
return (
<TableCell
key={column.key}
css={`
width: 100%;
display: flex;
align-items: center;
flex-direction: row;
justify-content: space-between;
${tablecell}
width: calc(${columnWidthCalc});
${index === 0
? `padding-left: ${firstColumnPadding}px;width: ${firstColumnWidth}`
: ""}
`}
>
<div
css={`
gap: 12px;
width: 100%;
display: flex;
align-items: center;
flex-direction: row;
font-weight: ${index === 0 ? "bold" : "normal"};
font-family: "GothamNarrow-${index === 0 ? "Bold" : "Book"}",
"Helvetica Neue", sans-serif;
justify-content: space-between;
`}
>
<div
css={`
gap: 12px;
width: 100%;
display: flex;
align-items: center;
flex-direction: row;
font-weight: ${index === 0 ? "bold" : "normal"};
font-family: "GothamNarrow-${index === 0 ? "Bold" : "Book"}",
"Helvetica Neue", sans-serif;
> * {
@supports (-webkit-touch-callout: none) and
(not (translate: none)) {
&:not(:last-child) {
margin-right: 12px;
> * {
@supports (-webkit-touch-callout: none) and
(not (translate: none)) {
&:not(:last-child) {
margin-right: 12px;
}
}
}
}
> svg {
transition: transform 0.1s ease-in-out;
transform: rotate(${open ? "0deg" : "-180deg"});
}
`}
>
{index === 0 && props.row.children && <TriangleXSIcon />}
{get(props.row, column.key, "")}
> svg {
transition: transform 0.1s ease-in-out;
transform: rotate(${open ? "0deg" : "-180deg"});
}
`}
>
{index === 0 && props.row.children && <TriangleXSIcon />}
{formattedValue}
</div>
</div>
</div>
</TableCell>
))}
</TableCell>
);
})}
</TableRow>
<TableRow
css={`
Expand All @@ -155,6 +165,8 @@ function Row(props: {
key={child.name}
paddingLeft={40}
columns={props.columns}
forceExpand={props.forceExpand}
formatNumbers={props.formatNumbers}
visibleColumnsIndexes={props.visibleColumnsIndexes}
/>
))}
Expand Down Expand Up @@ -270,6 +282,8 @@ export function SimpleTable(props: SimpleTableProps) {
key={row.name}
row={row}
columns={props.columns}
forceExpand={props.forceExpand}
formatNumbers={props.formatNumbers}
visibleColumnsIndexes={visibleColumnsIndexes}
/>
))}
Expand Down
5 changes: 5 additions & 0 deletions src/app/components/ToolBoxPanel/components/filters/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,11 @@ export const pathnameToFilterGroups = {
(fg: FilterGroupProps) =>
fg.name === "Locations" || fg.name === "Components"
),
"/viz/allocations/table": filter(
filtergroups,
(fg: FilterGroupProps) =>
fg.name === "Locations" || fg.name === "Components"
),
"/viz/eligibility": filter(
filtergroups,
(fg: FilterGroupProps) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const locationsToNotShowImageExport = [
"/grant/<code>/commitment/table",
"/viz/pledges-contributions/map",
"/viz/pledges-contributions/table",
"/viz/allocations/table",
"/viz/budgets/map",
"/viz/allocations/map",
"/grants",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,8 @@ export function SubToolBoxPanel(props: SubToolBoxPanelProps) {
/>
)}
{(params.vizType === "allocations" ||
params.vizType === "allocation") && <AllocationsPeriods />}
params.vizType === "allocation") &&
params.subType !== "table" && <AllocationsPeriods />}
{params.vizType === "eligibility" && !isLocationDetail && (
<EligibilityYear />
)}
Expand Down
5 changes: 5 additions & 0 deletions src/app/hooks/useGetAllVizData.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DotChartModel } from "app/components/Charts/Eligibility/DotChart/data";
import { EligibilityScatterplotDataModel } from "app/components/Charts/Eligibility/Scatterplot/data";
import { DisbursementsTreemapDataItem } from "app/components/Charts/Investments/Disbursements/data";
import { BudgetsTreemapDataItem } from "app/components/Charts/Budgets/Treemap/data";
import { SimpleTableRow } from "app/components/Table/Simple/data";

export function useGetAllVizData() {
const allocations = useStoreState((state) => ({
Expand All @@ -26,6 +27,9 @@ export function useGetAllVizData() {
features: get(state.AllocationsGeomap.data, "data", []),
} as FeatureCollection)
);
const allocationsTable = useStoreState(
(state) => get(state.AllocationsTable.data, "data", []) as SimpleTableRow[]
);
const allocationsMCGeomap = useStoreState(
(state) =>
get(
Expand Down Expand Up @@ -284,6 +288,7 @@ export function useGetAllVizData() {
countries: allocationsGeomap,
multicountries: allocationsMCGeomap,
},
"/viz/allocations/table": allocationsTable,
// Budgets
"/viz/budgets/flow": budgetsFlow,
"/viz/budgets/time-cycle": budgetsTimeCycle,
Expand Down
8 changes: 8 additions & 0 deletions src/app/modules/country-detail-module/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { LocationGrants } from "app/modules/country-detail-module/sub-modules/gr
import { LocationResults } from "app/modules/country-detail-module/sub-modules/results";
import { AllocationsGeoMap } from "app/modules/viz-module/sub-modules/allocations/geomap";
import { InvestmentsGeoMap } from "app/modules/viz-module/sub-modules/investments/geomap";
import { AllocationsTableModule } from "app/modules/viz-module/sub-modules/allocations/table";
import { LocationDetailOverviewModule } from "app/modules/country-detail-module/sub-modules/overview";
import { LocationDetailDocumentsModule } from "app/modules/country-detail-module/sub-modules/documents";
import { LocationDetailEligibilityWrapper } from "app/modules/viz-module/sub-modules/eligibility/data-wrappers/location";
Expand Down Expand Up @@ -384,6 +385,13 @@ export default function CountryDetail() {
<Route path={`/location/:code/allocations/map`}>
<AllocationsGeoMap code={paramCode} />
</Route>
<Route path={`/location/:code/allocations/table`}>
<AllocationsTableModule
code={paramCode}
toolboxOpen={openToolboxPanel}
setOpenToolboxPanel={setOpenToolboxPanel}
/>
</Route>
<Route path={`/location/:code/allocations`}>
<AllocationsModule
code={paramCode}
Expand Down
7 changes: 7 additions & 0 deletions src/app/modules/viz-module/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { AllocationsModule } from "app/modules/viz-module/sub-modules/allocation
import { EligibilityModule } from "app/modules/viz-module/sub-modules/eligibility";
import { InvestmentsGeoMap } from "app/modules/viz-module/sub-modules/investments/geomap";
import { AllocationsGeoMap } from "app/modules/viz-module/sub-modules/allocations/geomap";
import { AllocationsTableModule } from "app/modules/viz-module/sub-modules/allocations/table";
import { PledgesContributionsTable } from "app/modules/viz-module/sub-modules/pledgescontributions/table";
import { PledgesContributionsGeoMap } from "app/modules/viz-module/sub-modules/pledgescontributions/geomap";
import { PledgesContributionsTreemap } from "app/modules/viz-module/sub-modules/pledgescontributions/treemap";
Expand Down Expand Up @@ -279,6 +280,12 @@ export default function VizModule() {
<Route path="/viz/allocations/map">
<AllocationsGeoMap />
</Route>
<Route path="/viz/allocations/table">
<AllocationsTableModule
toolboxOpen={openToolboxPanel}
setOpenToolboxPanel={setOpenToolboxPanel}
/>
</Route>
<Route path="/viz/allocations">
<AllocationsModule
toolboxOpen={openToolboxPanel}
Expand Down
77 changes: 77 additions & 0 deletions src/app/modules/viz-module/sub-modules/allocations/table/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React from "react";
import get from "lodash/get";
import filter from "lodash/filter";
import useTitle from "react-use/lib/useTitle";
import useDebounce from "react-use/lib/useDebounce";
import { SimpleTable } from "app/components/Table/Simple";
import { PageLoader } from "app/modules/common/page-loader";
import { SimpleTableRow } from "app/components/Table/Simple/data";
import { useStoreActions, useStoreState } from "app/state/store/hooks";
import { getAPIFormattedFilters } from "app/utils/getAPIFormattedFilters";

interface AllocationsTableProps {
code?: string;
toolboxOpen: boolean;
setOpenToolboxPanel: (value: boolean) => void;
}

export function AllocationsTableModule(props: AllocationsTableProps) {
useTitle(`The Data Explorer -${props.code ? " Location" : ""} Allocations`);

const [search, setSearch] = React.useState("");
const [sortBy, setSortBy] = React.useState("");

const fetchData = useStoreActions((store) => store.AllocationsTable.fetch);
const loading = useStoreState((state) => state.AllocationsTable.loading);
const appliedFilters = useStoreState((state) => state.AppliedFiltersState);
const data = useStoreState(
(state) => get(state.AllocationsTable.data, "data", []) as SimpleTableRow[]
);

function reloadData() {
const filterString = getAPIFormattedFilters(
props.code
? {
...appliedFilters,
locations: [...appliedFilters.locations, props.code],
}
: appliedFilters,
{ search, sortBy }
);
fetchData({ filterString });
}

React.useEffect(() => reloadData(), [props.code, sortBy, appliedFilters]);

const [,] = useDebounce(() => reloadData(), 500, [search]);

if (loading) {
return <PageLoader />;
}

const columns =
data.length > 0
? filter(Object.keys(data[0]), (key) => key !== "children").map(
(key) => ({
name: key === "name" ? "Component/Location" : `${key} (USD)`,
key,
})
)
: [];

return (
<>
<SimpleTable
title="Allocations"
search={search}
sortBy={sortBy}
rows={data}
onSearchChange={setSearch}
onSortByChange={setSortBy}
formatNumbers
columns={columns}
forceExpand={Boolean(props.code)}
/>
</>
);
}
4 changes: 4 additions & 0 deletions src/app/state/api/action-reducers/viz/allocations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@ export const AllocationsGeomap: ApiCallModel = {
export const AllocationsMCGeomap: ApiCallModel = {
...APIModel(`${process.env.REACT_APP_API}/allocations/geomap/multicountries`),
};

export const AllocationsTable: ApiCallModel = {
...APIModel(`${process.env.REACT_APP_API}/allocations/table`),
};
1 change: 1 addition & 0 deletions src/app/state/api/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export interface StoreModel {
AllocationsDrilldown: ApiCallModel;
AllocationsGeomap: ApiCallModel;
AllocationsMCGeomap: ApiCallModel;
AllocationsTable: ApiCallModel;
Eligibility: ApiCallModel;
EligibilityYears: ApiCallModel;
BudgetsFlow: ApiCallModel;
Expand Down
2 changes: 2 additions & 0 deletions src/app/state/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import Allocations, {
AllocationsGeomap,
AllocationsMCGeomap,
AllocationsPeriods,
AllocationsTable,
} from "app/state/api/action-reducers/viz/allocations";
import BudgetsFlow, {
BudgetsFlowDrilldownLevel1,
Expand Down Expand Up @@ -178,6 +179,7 @@ const storeContent: StoreModel = {
AllocationsDrilldown: persist(AllocationsDrilldown),
AllocationsGeomap: persist(AllocationsGeomap),
AllocationsMCGeomap: persist(AllocationsMCGeomap),
AllocationsTable: persist(AllocationsTable),
Eligibility: persist(Eligibility),
EligibilityYears: persist(EligibilityYears),
BudgetsGeomap: persist(BudgetsGeomap),
Expand Down
Loading

0 comments on commit 6914ddc

Please sign in to comment.