Browse Source

feat: poll view improvements

develop
Ezerous 4 years ago
parent
commit
e81d1e8426
  1. 2
      packages/concordia-app/public/locales/en/translation.json
  2. 56
      packages/concordia-app/src/components/PollView/PollGraph/PollChartBar/index.jsx
  3. 49
      packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx
  4. 117
      packages/concordia-app/src/components/PollView/PollGraph/index.jsx
  5. 4
      packages/concordia-app/src/components/PollView/PollGraph/styles.css
  6. 12
      packages/concordia-app/src/components/PollView/index.jsx
  7. 4
      packages/concordia-app/src/constants/polls/PollGraph.js

2
packages/concordia-app/public/locales/en/translation.json

@ -90,7 +90,7 @@
"topic.poll.invalid.data.header": "This topic has a poll but the data are untrusted!", "topic.poll.invalid.data.header": "This topic has a poll but the data are untrusted!",
"topic.poll.invalid.data.sub.header": "The poll data downloaded from the poster have been tampered with.", "topic.poll.invalid.data.sub.header": "The poll data downloaded from the poster have been tampered with.",
"topic.poll.tab.graph.title": "Results", "topic.poll.tab.graph.title": "Results",
"topic.poll.tab.results.votes.count": "{{totalVotes}} votes casted", "topic.poll.tab.results.votes.count": "Total votes: {{totalVotes}}",
"topic.poll.tab.vote.form.button.submit": "Submit", "topic.poll.tab.vote.form.button.submit": "Submit",
"topic.poll.tab.vote.form.radio.label": "Select one of the options:", "topic.poll.tab.vote.form.radio.label": "Select one of the options:",
"topic.poll.tab.vote.title": "Vote", "topic.poll.tab.vote.title": "Vote",

56
packages/concordia-app/src/components/PollView/PollGraph/PollChartBar/index.jsx

@ -0,0 +1,56 @@
import React, { useMemo } from 'react';
import Chart from 'react-apexcharts';
import PropTypes from 'prop-types';
import { CHART_TYPE_BAR } from '../../../../constants/polls/PollGraph';
const PollChartBar = (props) => {
const { pollOptions, voteCounts } = props;
const chartOptions = useMemo(() => ({
chart: {
id: 'chart-bar',
},
theme: {
palette: 'palette8',
},
plotOptions: {
bar: {
horizontal: true,
distributed: true,
},
},
xaxis: {
categories: pollOptions,
tickAmount: 1,
labels: {
formatter(val) {
if (val.toFixed) return val.toFixed(0);
return val;
},
},
},
tooltip: {
enabled: false,
},
}), [pollOptions]);
const chartSeries = useMemo(() => [{
name: 'Votes',
data: voteCounts,
}], [voteCounts]);
return (
<Chart
options={chartOptions}
series={chartSeries}
type={CHART_TYPE_BAR}
/>
);
};
PollChartBar.propTypes = {
pollOptions: PropTypes.arrayOf(PropTypes.string).isRequired,
voteCounts: PropTypes.arrayOf(PropTypes.number).isRequired,
};
export default PollChartBar;

49
packages/concordia-app/src/components/PollView/PollGraph/PollChartDonut/index.jsx

@ -0,0 +1,49 @@
import React, { useMemo } from 'react';
import Chart from 'react-apexcharts';
import PropTypes from 'prop-types';
import { CHART_TYPE_DONUT } from '../../../../constants/polls/PollGraph';
const PollChartDonut = (props) => {
const { pollOptions, voteCounts } = props;
const chartOptions = useMemo(() => ({
chart: {
id: 'chart-donut',
},
theme: {
palette: 'palette8',
},
plotOptions: {
pie: {
donut: {
labels: {
show: true,
total: {
show: true,
label: 'Total Votes',
},
},
},
},
},
labels: pollOptions,
tooltip: {
enabled: false,
},
}), [pollOptions]);
return (
<Chart
options={chartOptions}
series={voteCounts}
type={CHART_TYPE_DONUT}
/>
);
};
PollChartDonut.propTypes = {
pollOptions: PropTypes.arrayOf(PropTypes.string).isRequired,
voteCounts: PropTypes.arrayOf(PropTypes.number).isRequired,
};
export default PollChartDonut;

117
packages/concordia-app/src/components/PollView/PollGraph/index.jsx

@ -1,79 +1,76 @@
import React, { useMemo } from 'react'; import React, { useMemo } from 'react';
import Chart from 'react-apexcharts'; import { Grid, Header, Tab } from 'semantic-ui-react';
import { Grid, Header } from 'semantic-ui-react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { CASTED_OPTION_COLOR, DEFAULT_OPTION_COLOR } from '../../../constants/polls/PollGraph'; import PollChartBar from './PollChartBar';
import PollChartDonut from './PollChartDonut';
import './styles.css';
const PollGraph = (props) => { const PollGraph = (props) => {
const { const { pollOptions, voteCounts } = props;
pollOptions, voteCounts, hasUserVoted, selectedOptionIndex,
} = props;
const { t } = useTranslation(); const { t } = useTranslation();
const chartOptions = useMemo(() => ({ const panes = useMemo(() => {
chart: { const chartBarPane = (
id: 'topic-poll', <Tab.Pane attached={false}>
}, <Grid columns="equal">
plotOptions: { <Grid.Row>
bar: { <Grid.Column />
horizontal: true, <Grid.Column width={8}>
}, <PollChartBar
}, pollOptions={pollOptions}
colors: [ voteCounts={voteCounts}
(value) => { />
if (hasUserVoted && value.dataPointIndex === selectedOptionIndex) { </Grid.Column>
return CASTED_OPTION_COLOR; <Grid.Column />
} </Grid.Row>
return DEFAULT_OPTION_COLOR; <Grid.Row>
}, <Grid.Column textAlign="center">
], <Header as="h4">
xaxis: { {t('topic.poll.tab.results.votes.count', {
categories: pollOptions, totalVotes: voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0),
}, })}
}), [hasUserVoted, pollOptions, selectedOptionIndex]); </Header>
</Grid.Column>
</Grid.Row>
</Grid>
</Tab.Pane>
);
const chartDonutPane = (
<Tab.Pane attached={false}>
<Grid columns="equal">
<Grid.Row>
<Grid.Column />
<Grid.Column width={8}>
<PollChartDonut
pollOptions={pollOptions}
voteCounts={voteCounts}
/>
</Grid.Column>
<Grid.Column />
</Grid.Row>
<Grid.Row />
</Grid>
</Tab.Pane>
);
const chartSeries = useMemo(() => [{ return ([
name: 'votes', { menuItem: { key: 'chart-bar', icon: 'chart bar' }, render: () => chartBarPane },
data: voteCounts, { menuItem: { key: 'chart-donut', icon: 'chart pie' }, render: () => chartDonutPane },
}], [voteCounts]); ]);
}, [pollOptions, t, voteCounts]);
return ( return (
<Grid columns="equal"> <Tab
<Grid.Row> menu={{ secondary: true }}
<Grid.Column /> panes={panes}
<Grid.Column width={8}> />
<Chart
options={chartOptions}
series={chartSeries}
type="bar"
/>
</Grid.Column>
<Grid.Column />
</Grid.Row>
<Grid.Row>
<Grid.Column textAlign="center">
<Header as="h4">
{t('topic.poll.tab.results.votes.count', {
totalVotes: voteCounts.reduce((accumulator, voteCount) => accumulator + voteCount, 0),
})}
</Header>
</Grid.Column>
</Grid.Row>
</Grid>
); );
}; };
PollGraph.defaultProps = {
hasUserVoted: false,
selectedOptionIndex: '',
};
PollGraph.propTypes = { PollGraph.propTypes = {
pollOptions: PropTypes.arrayOf(PropTypes.string).isRequired, pollOptions: PropTypes.arrayOf(PropTypes.string).isRequired,
voteCounts: PropTypes.arrayOf(PropTypes.number).isRequired, voteCounts: PropTypes.arrayOf(PropTypes.number).isRequired,
hasUserVoted: PropTypes.bool,
selectedOptionIndex: PropTypes.string,
}; };
export default PollGraph; export default PollGraph;

4
packages/concordia-app/src/components/PollView/PollGraph/styles.css

@ -0,0 +1,4 @@
#topic-poll-container .ui.segment.tab {
box-shadow: none;
border: none;
}

12
packages/concordia-app/src/components/PollView/index.jsx

@ -1,4 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react'; import React, {
useEffect, useMemo, useState,
} from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { VOTING_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames'; import { VOTING_CONTRACT } from 'concordia-shared/src/constants/contracts/ContractNames';
import { import {
@ -145,12 +147,10 @@ const PollView = (props) => {
<PollGraph <PollGraph
pollOptions={pollOptions} pollOptions={pollOptions}
voteCounts={voteCounts} voteCounts={voteCounts}
hasUserVoted={userHasVoted}
userVoteIndex={userVoteIndex}
/> />
) )
: null : null
), [chainDataLoading, orbitDataLoading, pollOptions, userHasVoted, userVoteIndex, voteCounts]); ), [chainDataLoading, orbitDataLoading, pollOptions, voteCounts]);
const panes = useMemo(() => { const panes = useMemo(() => {
const pollVotePane = ( const pollVotePane = (
@ -165,8 +165,8 @@ const PollView = (props) => {
); );
return ([ return ([
{ menuItem: t(VOTE_TAB.intl_display_name_id), render: () => pollVotePane },
{ menuItem: t(GRAPH_TAB.intl_display_name_id), render: () => pollGraphPane }, { menuItem: t(GRAPH_TAB.intl_display_name_id), render: () => pollGraphPane },
{ menuItem: t(VOTE_TAB.intl_display_name_id), render: () => pollVotePane },
]); ]);
}, [chainDataLoading, orbitDataLoading, pollGraphTab, pollVoteTab, t]); }, [chainDataLoading, orbitDataLoading, pollGraphTab, pollVoteTab, t]);
@ -182,7 +182,7 @@ const PollView = (props) => {
{!chainDataLoading && !orbitDataLoading ? ( {!chainDataLoading && !orbitDataLoading ? (
<> <>
<Header as="h3"> <Header as="h3">
<Icon name="chart pie" size="large" /> <Icon name="chart area" size="large" />
{pollQuestion} {pollQuestion}
</Header> </Header>
<Tab panes={panes} /> <Tab panes={panes} />

4
packages/concordia-app/src/constants/polls/PollGraph.js

@ -1,2 +1,2 @@
export const DEFAULT_OPTION_COLOR = '#3B5066'; export const CHART_TYPE_BAR = 'bar';
export const CASTED_OPTION_COLOR = '#0b2540'; export const CHART_TYPE_DONUT = 'donut';

Loading…
Cancel
Save