Guest User

Untitled

a guest
Apr 24th, 2018
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.16 KB | None | 0 0
  1. import React, { Component } from "react";
  2. import DownloadButton from "./mini/DownloadButton.js";
  3. import {
  4. VictoryChart,
  5. VictoryBar,
  6. VictoryGroup,
  7. VictoryLegend,
  8. VictoryLabel,
  9. VictoryAxis,
  10. VictorySharedEvents,
  11. Point
  12. } from "victory";
  13.  
  14. class GroupedBars extends Component {
  15. constructor(props) {
  16. super(props);
  17.  
  18. this.state = {
  19. title: this.props.data.chart_title,
  20. subtitle: this.props.data.chart_subtitle,
  21. data: this.props.data,
  22. activeKey: null,
  23. activeCat: null,
  24. activeColor: this.props.theme.interactions.hover,
  25. isLegendClicked: false,
  26. clickedBar: false,
  27. activeClickedBar: null,
  28. svgrefs: [],
  29. domainY: [0, 100],
  30. domainX: [0, 100],
  31. fontSizes: this.fontSizes(this.props.columns)
  32. };
  33. }
  34.  
  35. fontSizes(columns) {
  36. if (columns === 4) {
  37. return {
  38. active: 8,
  39. label: 10,
  40. barLabel: 10,
  41. legend: [16, 13],
  42. legendLabel: 20,
  43. ticks: 12
  44. };
  45. } else if (columns === 6) {
  46. return {
  47. active: 8,
  48. label: 10,
  49. barLabel: 10,
  50. legend: [13, 11],
  51. legendLabel: 10,
  52. ticks: 12
  53. };
  54. } else if (columns === 12) {
  55. return {
  56. active: 8,
  57. label: 10,
  58. barLabel: 10,
  59. legend: [13, 11],
  60. legendLabel: 8,
  61. ticks: 12
  62. };
  63. }
  64. }
  65.  
  66. makeLegend(data) {
  67. let legData = data.data.map((item, idx) => {
  68. let fill = () => {
  69. if (item.title === this.state.activeKey) {
  70. return this.state.activeColor;
  71. } else {
  72. return this.props.colorscale[idx];
  73. }
  74. };
  75. return {
  76. name: item.title,
  77. symbol: {
  78. fill: fill()
  79. }
  80. };
  81. });
  82. return legData;
  83. }
  84.  
  85. getCurFill(cat, index, active) {
  86. if (this.state.activeCat === cat) {
  87. return this.state.activeColor;
  88. } else {
  89. return this.props.colorscale[index];
  90. }
  91. }
  92.  
  93. getLabelState(cat, index, active) {
  94. if (this.state.activeCat === cat) {
  95. return this.state.activeColor;
  96. } else {
  97. return "transparent";
  98. }
  99. }
  100.  
  101. componentDidUpdate(prevProps, prevState) {
  102. if (prevProps.columns !== this.props.columns) {
  103. this.setState({
  104. fontSizes: this.fontSizes(this.props.columns)
  105. });
  106. }
  107. }
  108.  
  109. render() {
  110. const activeStyle = [
  111. {
  112. target: "data",
  113. mutation: props => ({
  114. style: Object.assign({}, props.style, {
  115. fill: this.state.activeColor
  116. })
  117. })
  118. },
  119. {
  120. target: "labels",
  121. mutation: props => ({
  122. style: Object.assign({}, props.style, {
  123. display: "block",
  124. fill: this.state.activeColor,
  125. fontSize: this.state.fontSizes.active,
  126. fontWeight: "bold"
  127. })
  128. })
  129. }
  130. ];
  131. const normalStyle = [
  132. {
  133. target: "data",
  134. mutation: props => null
  135. },
  136. {
  137. target: "labels",
  138. mutation: props => null
  139. }
  140. ];
  141.  
  142. const legendLabelStyle = {
  143. fontSize: this.state.fontSizes.legendLabel,
  144. fontFamily: "Asap",
  145. fontWeight: a => {
  146. if (this.state.activeCat === a.name) {
  147. return "bold";
  148. } else {
  149. return "normal";
  150. }
  151. },
  152. fill: a => {
  153. if (this.state.activeCat === a.name) {
  154. return this.state.activeColor;
  155. } else {
  156. return "#555";
  157. }
  158. }
  159. };
  160.  
  161. const legendDataStyle = {
  162. fill: a => {
  163. if (this.state.activeCat === a.name) {
  164. return this.state.activeColor;
  165. } else {
  166. return a.symbol.fill;
  167. }
  168. }
  169. };
  170.  
  171. const events = [
  172. {
  173. childName: "all",
  174. target: "data",
  175. eventHandlers: {
  176. onMouseOver: (evt, obj, idx) => {
  177. console.log("over");
  178. let activeCat = obj.data[0].cat;
  179. let activeBar = `${obj.datum.cat}-${idx}`;
  180. this.setState({
  181. activeKey: activeCat,
  182. activeBar: activeBar
  183. });
  184. return activeStyle;
  185. },
  186. onClick: (evt, obj, idx) => {
  187. let clicked = `${obj.datum.cat}-${idx}`;
  188. if (this.state.clickedBar !== true) {
  189. this.setState({
  190. clickedBar: true,
  191. activeClickedBar: clicked
  192. });
  193. return activeStyle;
  194. } else {
  195. if (this.state.activeClickedBar === clicked) {
  196. this.setState({
  197. clickedBar: false,
  198. activeClickedBar: null
  199. });
  200. return normalStyle;
  201. } else {
  202. this.setState({
  203. clickedBar: true,
  204. activeClickedBar: clicked
  205. });
  206. return [
  207. {
  208. target: "data",
  209. eventKey: "all",
  210. childName: "all",
  211. mutation: props => null
  212. },
  213. {
  214. target: "labels",
  215. eventKey: "all",
  216. childName: "all",
  217. mutation: props => null
  218. },
  219. {
  220. target: "data",
  221. mutation: props => ({
  222. style: Object.assign(
  223. {},
  224. props.style,
  225. {
  226. fill: this.state.activeColor
  227. }
  228. )
  229. })
  230. },
  231. {
  232. target: "labels",
  233. mutation: props => ({
  234. style: Object.assign(
  235. {},
  236. props.style,
  237. {
  238. display: "block",
  239. fill: this.state
  240. .activeColor,
  241. fontSize: 8,
  242. fontWeight: "bold"
  243. }
  244. )
  245. })
  246. }
  247. ];
  248. }
  249. }
  250. },
  251. onMouseOut: (evt, obj, idx) => {
  252. if (obj.datum.cat !== undefined) {
  253. let clickedthing = `${obj.datum.cat}-${idx}`;
  254. if (this.state.activeClickedBar !== clickedthing) {
  255. this.setState({
  256. activeKey: null,
  257. activeBar: null
  258. });
  259. return normalStyle;
  260. }
  261. }
  262. }
  263. }
  264. },
  265. {
  266. childName: "legend",
  267. target: "data",
  268. eventHandlers: {
  269. onClick: (evt, obj, key) => {
  270. if (obj.datum !== undefined) {
  271. let refName = obj.datum.name;
  272. if (this.state.isLegendClicked !== true) {
  273. this.setState({
  274. activeCat: refName,
  275. isLegendClicked: true
  276. });
  277. } else {
  278. //Está cliqueada una leyenda
  279. if (this.state.activeCat === refName) {
  280. this.setState({
  281. activeCat: null,
  282. isLegendClicked: false
  283. });
  284. } else {
  285. this.setState({ activeCat: refName });
  286. }
  287. }
  288. }
  289. },
  290. onMouseOver: (evt, obj, key) => {
  291. if (this.state.isLegendClicked !== true) {
  292. if (obj.datum !== undefined) {
  293. this.setState({
  294. activeCat: obj.datum.name
  295. });
  296. }
  297. }
  298. },
  299. onMouseOut: (evt, obj, key) => {
  300. if (this.state.isLegendClicked !== true) {
  301. this.setState({ activeCat: null });
  302. return [
  303. {
  304. target: "data",
  305. mutation: props => null
  306. },
  307. {
  308. target: "labels",
  309. mutation: props => null
  310. }
  311. ];
  312. }
  313. }
  314. }
  315. }
  316. ];
  317.  
  318. const groups = () =>
  319. this.state.data.data.map((group, idx) => {
  320. return (
  321. <VictoryBar
  322. name={group.title}
  323. theme={this.props.theme}
  324. key={"bar-" + idx}
  325. colorscale={this.props.colorscale}
  326. title={group.title}
  327. data={group.data}
  328. style={{
  329. data: {
  330. width: 10,
  331. fill: (d, active) =>
  332. this.getCurFill(group.title, idx, active)
  333. }
  334. }}
  335. labelComponent={
  336. <VictoryLabel
  337. style={{
  338. fontSize: this.state.fontSizes.label,
  339. fontWeight: "bold",
  340. fill: (d, active) =>
  341. this.getLabelState(
  342. group.title,
  343. idx,
  344. active
  345. )
  346. }}
  347. text={d => `${d.y}%`}
  348. />
  349. }
  350. />
  351. );
  352. });
  353.  
  354. const RunLegend = () => {
  355. if (this.props.columns === 6) {
  356. return (
  357. <VictoryLegend
  358. title={[
  359. this.state.title.toUpperCase(),
  360. this.state.subtitle
  361. ]}
  362. titleOrientation="left"
  363. theme={this.props.theme}
  364. name="legend"
  365. data={this.makeLegend(this.state.data)}
  366. orientation="vertical"
  367. itemsPerRow={1}
  368. gutter={20}
  369. height={60}
  370. labelComponent={
  371. <VictoryLabel style={legendLabelStyle} />
  372. }
  373. dataComponent={
  374. <Point size={5} style={legendDataStyle} />
  375. }
  376. titleComponent={
  377. <VictoryLabel
  378. style={[
  379. {
  380. fontSize: this.state.fontSizes
  381. .legend[0],
  382. fontWeight: "bold"
  383. },
  384. {
  385. fontSize: this.state.fontSizes
  386. .legend[1],
  387. fontWeight: "normal"
  388. }
  389. ]}
  390. />
  391. }
  392. />
  393. );
  394. } else if (this.props.columns === 4) {
  395. return (
  396. <VictoryLegend
  397. titleOrientation="left"
  398. theme={this.props.theme}
  399. name="legend"
  400. data={this.makeLegend(this.state.data)}
  401. orientation="vertical"
  402. itemsPerRow={1}
  403. gutter={20}
  404. height={60}
  405. labelComponent={
  406. <VictoryLabel style={legendLabelStyle} />
  407. }
  408. dataComponent={
  409. <Point size={5} style={legendDataStyle} />
  410. }
  411. />
  412. );
  413. }
  414. };
  415.  
  416. const RunHTMLTitle = () => {
  417. if (this.props.columns === 4) {
  418. return (
  419. <div style={{ padding: "5px" }}>
  420. <p
  421. style={{
  422. fontFamily: "Asap",
  423. fontSize: 14,
  424. display: "block",
  425. margin: 0
  426. }}
  427. >
  428. {this.state.title.toUpperCase()}
  429. </p>
  430. <p
  431. style={{
  432. margin: 0,
  433. fontFamily: "Asap",
  434. fontSize: 12,
  435. fontWeight: "normal",
  436. display: "block"
  437. }}
  438. >
  439. {this.state.subtitle}
  440. </p>
  441. </div>
  442. );
  443. }
  444. };
  445.  
  446. return (
  447. <div className="chart-widget">
  448. {RunHTMLTitle()}
  449. <VictorySharedEvents events={events}>
  450. {RunLegend()}
  451. <VictoryChart
  452. padding={{ top: 10, left: 50, right: 50, bottom: 50 }}
  453. responsive={false}
  454. theme={this.props.theme}
  455. height={this.props.height}
  456. width={this.props.width}
  457. domain={{ y: [0, 100] }}
  458. domainPadding={{ x: 40, y: 0 }}
  459. >
  460. <VictoryAxis tickValues={this.props.ticks} />
  461. <VictoryAxis
  462. style={{
  463. tickLabels: {
  464. fontSize: this.state.fontSizes.ticks
  465. }
  466. }}
  467. dependentAxis
  468. />
  469.  
  470. <VictoryGroup
  471. name="BarGroup"
  472. categories={{ x: this.state.data.categories }}
  473. offset={14}
  474. >
  475. {groups()}
  476. </VictoryGroup>
  477. </VictoryChart>
  478. </VictorySharedEvents>
  479. <DownloadButton
  480. data={this.props.data}
  481. type="groupedbars"
  482. fields={[
  483. { label: "Compañía", value: "data.x" },
  484. { label: "Tipo", value: "title" },
  485. { label: "Porcentaje", value: "data.y" }
  486. ]}
  487. unwind={["data"]}
  488. />
  489. </div>
  490. );
  491. }
  492. }
  493.  
  494. export default GroupedBars;
Add Comment
Please, Sign In to add comment