Skip to content

Commit

Permalink
Support selecting progress visualisation method
Browse files Browse the repository at this point in the history
And refactor graphs to use a single component for both donut and bar use cases.
  • Loading branch information
woodwoerk committed Sep 27, 2023
1 parent 240100f commit 722f9bc
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 201 deletions.
2 changes: 2 additions & 0 deletions common/__generated__/graphql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions common/blocks.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { ColProps } from 'reactstrap';

export interface CommonContentBlockProps {
id?: string;
columnProps?: ColProps;
}
8 changes: 3 additions & 5 deletions common/preprocess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import { cloneDeep } from 'lodash';

import { ActionListAction } from '../components/dashboard/ActionList';
import {
Action,
ActionStatus,
ActionImplementationPhase,
Plan,
Sentiment,
ActionStatusSummary,
Expand Down Expand Up @@ -71,7 +68,8 @@ const cleanActionStatus = (action, actionStatuses) => {
const getStatusData = (
actions: ActionListAction[],
actionStatusSummaries: ActionStatusSummary[],
theme: Theme
theme: Theme,
unknownLabelText: string = ''
) => {
const progress: Progress = {
values: [],
Expand All @@ -94,7 +92,7 @@ const getStatusData = (
const statusCount = counts.get(identifier) ?? 0;
if (statusCount > 0) {
progress.values.push(statusCount);
progress.labels.push(label);
progress.labels.push(label || unknownLabelText);
progress.colors.push(theme.graphColors[color]);
if (sentiment == Sentiment.Positive) {
progress.good = progress.good + statusCount;
Expand Down
156 changes: 0 additions & 156 deletions components/actions/CategoryMetaBar.tsx

This file was deleted.

116 changes: 116 additions & 0 deletions components/common/BarChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import React from 'react';
import styled from 'styled-components';

import { Progress } from 'components/dashboard/ActionStatusGraphs';

const BarChartWrapper = styled.div`
margin-bottom: ${(props) => props.theme.spaces.s200};
h3 {
font-size: ${(props) => props.theme.fontSizeBase};
}
`;

const Status = styled.div`
color: ${(props) => props.theme.themeColors.black};
`;

const BarGraph = styled.div`
display: flex;
height: 1rem;
width: auto;
background-color: ${(props) => props.theme.themeColors.light};
`;

const Segment = styled.div<{ portion: number }>`
background-color: ${(props) => props.color};
width: ${(props) => props.portion}%;
height: 1rem;
`;

const Labels = styled.div`
display: flex;
width: auto;
`;

const SegmentLabel = styled.span<{ portion: number }>`
display: flex;
flex-direction: column;
flex-basis: ${(props) => props.portion}%;
text-align: left;
margin: ${(props) => props.theme.spaces.s050}
${(props) => props.theme.spaces.s050} 0 0;
font-size: ${(props) => props.theme.fontSizeSm};
font-family: ${(props) => props.theme.fontFamilyTiny};
line-height: ${(props) => props.theme.lineHeightMd};
span {
align-self: flex-start;
}
.value {
font-weight: ${(props) => props.theme.fontWeightBold};
}
`;

interface BarChartProps {
title: string;
data: Progress;
}

interface Segment {
id: string;
label: string;
value: string;
portion: number;
color: string;
}

function BarChart({ title, data }: BarChartProps) {
if (data.values.length < 1) {
return null;
}

const valueSum = data.values.reduce((total, value) => total + value, 0);
const segments = data.labels
.map((label, i) => ({
id: label,
label: data.labels[i],
value: `${Math.round((data.values[i] / valueSum) * 100)} %`,
portion: data.values[i] / valueSum,
color: data.colors[i],
}))
.filter(({ portion }) => portion > 0);

return (
<BarChartWrapper>
<h3>{title}</h3>
<div>
<Status>
<BarGraph>
{segments.map((segment) => (
<Segment
key={segment.id}
color={segment.color}
portion={segment.portion * 100}
/>
))}
</BarGraph>
<Labels>
{segments.map((segment) => (
<SegmentLabel
key={segment.id}
portion={(segments.length === 1 ? 1 : segment.portion) * 100}
>
<span className="value">{segment.value}</span>
<span> {segment.label}</span>
</SegmentLabel>
))}
</Labels>
</Status>
</div>
</BarChartWrapper>
);
}

export default BarChart;
21 changes: 15 additions & 6 deletions components/common/CategoryPageStreamField.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React from 'react';
import { Container, Row, Col, ColProps } from 'reactstrap';
import { usePlan } from 'context/plan';
import CategoryMetaBar from 'components/actions/CategoryMetaBar';
import { attributeHasValue } from 'components/common/AttributesBlock';
import { useTheme } from 'common/theme';
import {
Expand All @@ -13,17 +12,16 @@ import ActionAttribute from 'components/common/ActionAttribute';
import CategoryListBlock from 'components/contentblocks/CategoryListBlock';
import ExpandableFeedbackFormBlock from 'components/contentblocks/ExpandableFeedbackFormBlock';
import StreamField from 'components/common/StreamField';
import ActionStatusGraphsBlock from 'components/contentblocks/ActionStatusGraphsBlock';
import { ChartType } from 'components/dashboard/ActionStatusGraphs';

export type CategoryPage = { __typename: 'CategoryPage' } & NonNullable<
GetPlanPageGeneralQuery['planPage']
>;

type OmitUnion<T, K extends keyof any> = T extends any ? Omit<T, K> : never;

type OmitFields<T> = OmitUnion<
T,
'blockType' | 'field' | 'rawValue' | 'blocks'
>;
type OmitFields<T> = OmitUnion<T, 'blockType' | 'field' | 'rawValue'>;

interface WrapperProps {
children: React.ReactNode;
Expand Down Expand Up @@ -135,10 +133,21 @@ export const CategoryPageStreamField = ({
return null;
}

// The editor specifies whether to visualise action progress by implementation phase or status
const progressDataset = block.blocks[0].value || 'implementation_phase';

return (
<Wrapper withContainer={context === 'main'}>
<Col xs={12} {...customColumnProps}>
<CategoryMetaBar category={page.category.id} />
<ActionStatusGraphsBlock
categoryId={page.category.id}
chart={ChartType.BAR}
shownDatasets={{
progress: progressDataset !== 'implementation_phase', // TODO get proper types
phase: progressDataset === 'implementation_phase',
}}
columnProps={{ md: 12, lg: 12, xl: 12 }}
/>
</Col>
</Wrapper>
);
Expand Down
Loading

0 comments on commit 722f9bc

Please sign in to comment.