New selection model.

- highlight whole row
- don't do anything when selecting text
This commit is contained in:
Simon Howe
2016-07-27 20:37:35 +02:00
parent d0b99969ea
commit 29e67683b3
4 changed files with 68 additions and 48 deletions

View File

@@ -53,7 +53,7 @@ function getColumns(nodes) {
}
function renderIdCell(props, onClick) {
function renderIdCell(props) {
const style = {
width: 16,
flex: 'none',
@@ -61,7 +61,7 @@ function renderIdCell(props, onClick) {
};
return (
<div className="nodes-grid-id-column" onClick={onClick}>
<div className="nodes-grid-id-column">
<div className="content">
<div style={style}><i className="fa fa-square" /></div>
<div className="truncate">
@@ -87,15 +87,15 @@ class NodesGrid extends React.Component {
this.onMouseLeaveRow = this.onMouseLeaveRow.bind(this);
}
clickRow(ev, nodeId, nodeLabel) {
if (ev.target.className === 'node-details-relatives-link') {
clickRow(ev, node, el) {
if (ev.target.className === 'node-details-table-node-link') {
return;
}
this.props.clickNode(nodeId, nodeLabel);
this.props.clickNode(node.id, node.label, el.getBoundingClientRect());
}
renderIdCell(props) {
return renderIdCell(props, (ev) => this.clickRow(ev, props.id, props.label));
return renderIdCell(props);
}
onMouseEnterRow() {
@@ -144,6 +144,7 @@ class NodesGrid extends React.Component {
tbodyStyle={tbodyStyle}
topologyId={this.props.topologyId}
onSortChange={this.onSortChange}
onClickRow={this.clickRow}
{...detailsData}
sortBy={gridSortBy}
sortedDesc={gridSortedDesc}

View File

@@ -1,4 +1,5 @@
import React from 'react';
import ReactDOM from 'react-dom';
import classNames from 'classnames';
import NodeDetailsTableNodeLink from './node-details-table-node-link';
@@ -66,10 +67,20 @@ function renderValues(node, columns = [], columnWidths = []) {
export default class NodeDetailsTableRow extends React.Component {
constructor(props, context) {
super(props, context);
this.mouseDragOrigin = [0, 0];
this.storeLabelRef = this.storeLabelRef.bind(this);
this.onMouseDown = this.onMouseDown.bind(this);
this.onMouseUp = this.onMouseUp.bind(this);
this.onMouseEnter = this.onMouseEnter.bind(this);
this.onMouseLeave = this.onMouseLeave.bind(this);
}
storeLabelRef(ref) {
this.labelEl = ref;
}
onMouseEnter() {
const { node, onMouseEnterRow } = this.props;
onMouseEnterRow(node);
@@ -80,9 +91,30 @@ export default class NodeDetailsTableRow extends React.Component {
onMouseLeaveRow(node);
}
onMouseDown(ev) {
const { pageX, pageY } = ev;
this.mouseDragOrigin = [pageX, pageY];
}
onMouseUp(ev) {
const [originX, originY] = this.mouseDragOrigin;
const { pageX, pageY } = ev;
const thresholdPx = 2;
const movedTheMouseTooMuch = (
Math.abs(originX - pageX) > thresholdPx ||
Math.abs(originY - pageY) > thresholdPx
);
if (movedTheMouseTooMuch) {
return;
}
const { node, onClick } = this.props;
onClick(ev, node, ReactDOM.findDOMNode(this.labelEl));
}
render() {
const { node, nodeIdKey, topologyId, columns, onMouseEnterRow, onMouseLeaveRow, selected,
widths } = this.props;
const { node, nodeIdKey, topologyId, columns, onClick, onMouseEnterRow, onMouseLeaveRow,
selected, widths } = this.props;
const [firstColumnWidth, ...columnWidths] = widths;
const values = renderValues(node, columns, columnWidths);
const nodeId = node[nodeIdKey];
@@ -90,10 +122,12 @@ export default class NodeDetailsTableRow extends React.Component {
return (
<tr
onMouseDown={onClick && this.onMouseDown}
onMouseUp={onClick && this.onMouseUp}
onMouseEnter={onMouseEnterRow && this.onMouseEnter}
onMouseLeave={onMouseLeaveRow && this.onMouseLeave}
className={className}>
<td className="node-details-table-node-label truncate"
<td ref={this.storeLabelRef} className="node-details-table-node-label truncate"
style={{ width: firstColumnWidth }}>
{this.props.renderIdCell(Object.assign(node, {topologyId, nodeId}))}
</td>

View File

@@ -23,8 +23,9 @@ const COLUMN_WIDTHS = {
docker_container_uptime: '85px',
docker_container_restart_count: '80px',
docker_container_ips: '80px',
docker_container_created: '110px',
docker_container_state_human: '120px',
// 27 Jul 16 11:33 UTC
docker_container_created: '140px',
docker_container_state_human: '170px',
open_files_count: '80px',
ppid: '80px',
pid: '80px',
@@ -63,7 +64,7 @@ function getValueForSortBy(sortBy) {
}
}
return '';
return null;
};
}
@@ -205,8 +206,8 @@ export default class NodeDetailsTable extends React.Component {
render() {
const headers = this.renderHeaders();
const { nodeIdKey, columns, topologyId, onMouseEnter, onMouseLeave, onMouseEnterRow,
onMouseLeaveRow } = this.props;
const { nodeIdKey, columns, topologyId, onClickRow, onMouseEnter, onMouseLeave,
onMouseEnterRow, onMouseLeaveRow } = this.props;
let nodes = getSortedNodes(this.props.nodes, this.props.columns, this.state.sortBy,
this.state.sortedDesc);
const limited = nodes && this.state.limit > 0 && nodes.length > this.state.limit;
@@ -243,6 +244,7 @@ export default class NodeDetailsTable extends React.Component {
nodeIdKey={nodeIdKey}
widths={getColumnsWidths(this.getColumnHeaders())}
columns={columns}
onClick={onClickRow}
onMouseLeaveRow={onMouseLeaveRow}
onMouseEnterRow={onMouseEnterRow}
topologyId={topologyId} />

View File

@@ -1541,43 +1541,13 @@ h2 {
padding: 2px 2px;
.content {
padding: 1px 4px;
cursor: pointer;
border: 1px solid transparent;
border-radius: 4px;
display: flex;
div {
flex: 1;
}
}
.selected &, &:hover {
.content {
background-color: #d7ecf5;
}
}
.selected & .content {
border: 1px solid @weave-blue;
}
}
/*
.node-details-relatives {
color: inherit;
font-size: 90%;
white-space: normal;
opacity: 0.8;
line-height: 110%;
text-align: right;
margin-left: 0;
// margin-top: 0;
// display: inline-block;
float: right;
}
*/
.node-details-table-wrapper-wrapper {
flex: 1;
@@ -1603,10 +1573,23 @@ h2 {
height: 24px;
}
.node-details-table-node {
&.selected, &:hover {
background-color: @background-lighter-color;
}
tr:nth-child(even) {
background: @background-color;
}
tbody tr {
border: 1px solid transparent;
border-radius: 4px;
cursor: pointer;
}
tbody tr.selected, tbody tr:hover {
background-color: #d7ecf5;
border: 1px solid @weave-blue;
}
tbody tr.selected {
// box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.16);
}
}