|
1 import React from 'react'; |
|
2 import PropTypes from 'prop-types'; |
|
3 import { connect } from 'react-redux'; |
|
4 |
|
5 import _ from 'lodash'; |
|
6 import { FormattedMessage } from 'react-intl'; |
|
7 import { categoryColors } from '../utils'; |
|
8 |
|
9 import RowChart from '../ui/RowChart'; |
|
10 |
|
11 |
|
12 /** |
|
13 * TODO: As a first implementation we have chosen to delagate the barchart DOM drawing to D3. |
|
14 * This may not be the optimum solution. This may have to be rewrittten to use |
|
15 * React for elementt creation and D3 as the visualisation kernel. This |
|
16 */ |
|
17 const ChartsPage = ({ chartsCounts }) => ( |
|
18 <div className="col col-12"> |
|
19 <div className="row"> |
|
20 <h3><FormattedMessage id="charts.metacategories_title" defaultMessage="Metacategories" /></h3> |
|
21 </div> |
|
22 <RowChart {...chartsCounts.metacategories} /> |
|
23 |
|
24 { (chartsCounts.actions.data.length > 0) && ( |
|
25 <div className="row chart-actions-row"> |
|
26 <h3><FormattedMessage id="charts.call_to_actions_title" defaultMessage="Call to actions" /></h3> |
|
27 </div> |
|
28 )} |
|
29 { (chartsCounts.actions.data.length > 0) && <RowChart {...chartsCounts.actions} /> } |
|
30 |
|
31 { (chartsCounts.categories.data.length > 0) && ( |
|
32 <div className="row chart-actions-row"> |
|
33 <h3><FormattedMessage id="charts.categories_title" defaultMessage="Categories" /></h3> |
|
34 </div> |
|
35 )} |
|
36 { (chartsCounts.categories.data.length > 0) && <RowChart {...chartsCounts.categories} /> } |
|
37 |
|
38 </div> |
|
39 ); |
|
40 |
|
41 ChartsPage.propTypes = { |
|
42 chartsCounts: PropTypes.object.isRequired, |
|
43 metacategories: PropTypes.arrayOf(PropTypes.object).isRequired, |
|
44 topics: PropTypes.arrayOf(PropTypes.string).isRequired, |
|
45 }; |
|
46 |
|
47 export default connect( |
|
48 (state, props) => { |
|
49 const { topics, metacategories } = props; |
|
50 const annotations = state.annotations.items; |
|
51 const topicsList = topics.map(t => t.toLowerCase()); |
|
52 let tagsCount = _.reduce( |
|
53 metacategories, |
|
54 (res, m) => { |
|
55 res[`cat:${m.tag}`] = { |
|
56 id: m.id, |
|
57 count: 0, |
|
58 tag: m.tag, |
|
59 color: categoryColors[m.id], |
|
60 }; |
|
61 return res; |
|
62 }, |
|
63 {}, |
|
64 ); |
|
65 tagsCount = _.reduce( |
|
66 annotations, |
|
67 (res, annot) => { |
|
68 annot.tags.forEach((tg) => { |
|
69 const t = tg.toLowerCase(); |
|
70 if (t.startsWith('cat:')) { |
|
71 const s = t.substr(4); |
|
72 if (!(t in res)) { |
|
73 res[t] = { |
|
74 id: s, |
|
75 count: 0, |
|
76 tag: s, |
|
77 color: (categoryColors[s] || 'gray'), |
|
78 }; |
|
79 } |
|
80 res[t].count += 1; |
|
81 } else if (t.startsWith('need:')) { |
|
82 const s = t.substr(5); |
|
83 if (!(t in res)) { |
|
84 res[t] = { |
|
85 id: s, |
|
86 count: 0, |
|
87 tag: s, |
|
88 color: 'gray', |
|
89 }; |
|
90 } |
|
91 res[t].count += 1; |
|
92 } else if (topicsList.includes(t)) { |
|
93 if (!(t in res)) { |
|
94 res[t] = { |
|
95 id: t, |
|
96 count: 0, |
|
97 tag: t, |
|
98 color: 'gray', |
|
99 }; |
|
100 } |
|
101 res[t].count += 1; |
|
102 } |
|
103 }); |
|
104 return res; |
|
105 }, |
|
106 tagsCount, |
|
107 ); |
|
108 return { |
|
109 chartsCounts: { |
|
110 metacategories: { data: _.reduce(tagsCount, (res, v, k) => (k.startsWith('cat:') ? [...res, v] : res), []), tagPrefix: 'cat:' }, |
|
111 actions: { data: _.reduce(tagsCount, (res, v, k) => (k.startsWith('need:') ? [...res, v] : res), []), tagPrefix: 'need:' }, |
|
112 categories: { data: _.reduce(tagsCount, (res, v, k) => (topicsList.includes(k.toLowerCase()) ? [...res, v] : res), []), tagPrefix: '' }, |
|
113 }, |
|
114 }; |
|
115 }, |
|
116 )(ChartsPage); |