/* eslint react/jsx-no-bind: "off" */ import React from 'react'; import styled from 'styled-components'; import { connect } from 'react-redux'; import { List as makeList, Map as makeMap } from 'immutable'; import capitalize from 'lodash/capitalize'; import NodeDetailsTable from '../components/node-details/node-details-table'; import { clickNode } from '../actions/request-actions'; import { sortOrderChanged } from '../actions/app-actions'; import { shownNodesSelector } from '../selectors/node-filters'; import { trackAnalyticsEvent } from '../utils/tracking-utils'; import { findTopologyById } from '../utils/topology-utils'; import { TABLE_VIEW_MODE } from '../constants/naming'; import { windowHeightSelector } from '../selectors/canvas'; import { searchNodeMatchesSelector } from '../selectors/search'; import { getNodeColor } from '../utils/color-utils'; const IGNORED_COLUMNS = ['docker_container_ports', 'docker_container_id', 'docker_image_id', 'docker_container_command', 'docker_container_networks']; const Icon = styled.span` border-radius: ${props => props.theme.borderRadius.soft}; background-color: ${props => props.color}; margin-top: 3px; display: block; height: 12px; width: 12px; `; function topologyLabel(topologies, id) { const topology = findTopologyById(topologies, id); if (!topology) { return capitalize(id); } return topology.get('fullName'); } function getColumns(nodes, topologies) { const metricColumns = nodes .toList() .flatMap((n) => { const metrics = (n.get('metrics') || makeList()) .filter(m => !m.get('valueEmpty')) .map(m => makeMap({ dataType: 'number', id: m.get('id'), label: m.get('label') })); return metrics; }) .toSet() .toList() .sortBy(m => m.get('label')); const metadataColumns = nodes .toList() .flatMap((n) => { const metadata = (n.get('metadata') || makeList()) .map(m => makeMap({ dataType: m.get('dataType'), id: m.get('id'), label: m.get('label') })); return metadata; }) .toSet() .filter(n => !IGNORED_COLUMNS.includes(n.get('id'))) .toList() .sortBy(m => m.get('label')); const relativesColumns = nodes .toList() .flatMap((n) => { const metadata = (n.get('parents') || makeList()) .map(m => makeMap({ id: m.get('topologyId'), label: topologyLabel(topologies, m.get('topologyId')) })); return metadata; }) .toSet() .toList() .sortBy(m => m.get('label')); return relativesColumns.concat(metadataColumns, metricColumns).toJS(); } function renderIdCell({ rank, label, labelMinor, pseudo }) { const showSubLabel = Boolean(pseudo) && labelMinor; const title = showSubLabel ? `${label} (${labelMinor})` : label; return (
{label} {' '} {showSubLabel && {labelMinor}}
); } class NodesGrid extends React.Component { constructor(props, context) { super(props, context); this.onClickRow = this.onClickRow.bind(this); this.onSortChange = this.onSortChange.bind(this); this.saveTableRef = this.saveTableRef.bind(this); } onClickRow(ev, node) { trackAnalyticsEvent('scope.node.click', { layout: TABLE_VIEW_MODE, parentTopologyId: this.props.currentTopology.get('parentId'), topologyId: this.props.currentTopology.get('id'), }); this.props.clickNode(node.id, node.label, ev.target.getBoundingClientRect()); } onSortChange(sortedBy, sortedDesc) { this.props.sortOrderChanged(sortedBy, sortedDesc); } saveTableRef(ref) { this.tableRef = ref; } render() { const { nodes, gridSortedBy, gridSortedDesc, searchNodeMatches, searchQuery, windowHeight, topologies } = this.props; const height = this.tableRef ? windowHeight - this.tableRef.getBoundingClientRect().top - 30 : 0; const cmpStyle = { height, paddingLeft: 40, paddingRight: 40, }; // TODO: What are 24 and 18? Use a comment or extract into constants. const tbodyHeight = height - 24 - 18; const className = 'tour-step-anchor scroll-body'; const tbodyStyle = { height: `${tbodyHeight}px`, }; const detailsData = { columns: getColumns(nodes, topologies), id: '', label: this.props.currentTopology && this.props.currentTopology.get('fullName'), nodes: nodes .toList() .filter(n => !(searchQuery && searchNodeMatches.get(n.get('id'), makeMap()).isEmpty())) .toJS() }; return (
{nodes.size > 0 && ( )}
); } } function mapStateToProps(state) { return { currentTopology: state.get('currentTopology'), currentTopologyId: state.get('currentTopologyId'), gridSortedBy: state.get('gridSortedBy'), gridSortedDesc: state.get('gridSortedDesc'), nodes: shownNodesSelector(state), searchNodeMatches: searchNodeMatchesSelector(state), searchQuery: state.get('searchQuery'), selectedNodeId: state.get('selectedNodeId'), topologies: state.get('topologies'), windowHeight: windowHeightSelector(state), }; } export default connect( mapStateToProps, { clickNode, sortOrderChanged } )(NodesGrid);