node-details-health-link-item.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import React from 'react';
  2. import moment from 'moment';
  3. import { connect } from 'react-redux';
  4. import stableStringify from 'json-stable-stringify';
  5. import NodeDetailsHealthItem from './node-details-health-item';
  6. import CloudLink from '../cloud-link';
  7. import { getMetricColor } from '../../utils/metric-utils';
  8. import { darkenColor } from '../../utils/color-utils';
  9. import { trackAnalyticsEvent } from '../../utils/tracking-utils';
  10. /**
  11. * @param {string} url
  12. * @param {string} time
  13. * @returns {string}
  14. */
  15. export function appendTime(url, time) {
  16. if (!url || !time) return url;
  17. // rudimentary check whether we have a cloud link
  18. const cloudLinkPathEnd = 'notebook/new/';
  19. const pos = url.indexOf(cloudLinkPathEnd);
  20. const timeUnix = moment(time).unix();
  21. if (pos !== -1) {
  22. let payload;
  23. const json = decodeURIComponent(url.substr(pos + cloudLinkPathEnd.length));
  24. try {
  25. payload = JSON.parse(json);
  26. payload.time = { queryEnd: timeUnix };
  27. } catch (e) {
  28. return url;
  29. }
  30. return `${url.substr(0, pos + cloudLinkPathEnd.length)}${encodeURIComponent(stableStringify(payload) || '')}`;
  31. }
  32. if (url.indexOf('?') !== -1) {
  33. return `${url}&time=${timeUnix}`;
  34. }
  35. return `${url}?time=${timeUnix}`;
  36. }
  37. class NodeDetailsHealthLinkItem extends React.Component {
  38. constructor(props) {
  39. super(props);
  40. this.state = {
  41. hovered: false
  42. };
  43. this.onMouseOver = this.onMouseOver.bind(this);
  44. this.onMouseOut = this.onMouseOut.bind(this);
  45. this.onClick = this.onClick.bind(this);
  46. }
  47. onMouseOver() {
  48. this.setState({hovered: true});
  49. }
  50. onMouseOut() {
  51. this.setState({hovered: false});
  52. }
  53. onClick() {
  54. trackAnalyticsEvent('scope.node.metric.click', { topologyId: this.props.topologyId });
  55. }
  56. render() {
  57. const {
  58. id, url, monitor, pausedAt, ...props
  59. } = this.props;
  60. const metricColor = getMetricColor(id);
  61. const labelColor = this.state.hovered && !props.valueEmpty && darkenColor(metricColor);
  62. const timedUrl = monitor === true ? appendTime(url, pausedAt) : '';
  63. return (
  64. <CloudLink
  65. alwaysShow
  66. className="node-details-health-link-item"
  67. onMouseOver={this.onMouseOver}
  68. onMouseOut={this.onMouseOut}
  69. onClick={this.onClick}
  70. url={timedUrl}
  71. >
  72. <NodeDetailsHealthItem
  73. {...props}
  74. hovered={this.state.hovered}
  75. labelColor={labelColor}
  76. metricColor={metricColor}
  77. />
  78. </CloudLink>
  79. );
  80. }
  81. }
  82. function mapStateToProps(state) {
  83. return {
  84. monitor: state.get('monitor'),
  85. pausedAt: state.get('pausedAt'),
  86. };
  87. }
  88. export default connect(mapStateToProps)(NodeDetailsHealthLinkItem);