+
+ {this.renderItem('fa fa-th', !gridMode, this.disableGridMode)}
+ {this.renderItem('fa fa-bars', gridMode, this.enableGridMode)}
+
+
+ );
+ }
+}
+
+function mapStateToProps(state) {
+ return {
+ gridMode: state.get('gridMode'),
+ };
+}
+
+export default connect(
+ mapStateToProps,
+ { toggleGridMode }
+)(GridModeSelector);
diff --git a/client/app/scripts/components/node-details/node-details-table-node-metric.js b/client/app/scripts/components/node-details/node-details-table-node-metric.js
index 4b1ec52610..b0dc2b79d2 100644
--- a/client/app/scripts/components/node-details/node-details-table-node-metric.js
+++ b/client/app/scripts/components/node-details/node-details-table-node-metric.js
@@ -4,7 +4,7 @@ import { formatMetric } from '../../utils/string-utils';
function NodeDetailsTableNodeMetric(props) {
return (
-
-
+ |
{
+ //
+ // Beauty hack: adjust first column width if there are only few columns;
+ // this assumes the other columns are narrow metric columns of 20% table width
+ //
+ if (i === 0) {
+ if (headers.length === 2) {
+ return '66%';
+ } else if (headers.length === 3) {
+ return '50%';
+ } else if (headers.length >= 3 && headers.length < 5) {
+ return '33%';
+ }
+ }
+
+ //
+ // More beauty hacking, ports and counts can only get so big, free up WS for other longer
+ // fields like IPs!
+ //
+ return COLUMN_WIDTHS[h.id];
+ });
+}
+
+
export default class NodeDetailsTable extends React.Component {
constructor(props, context) {
@@ -101,33 +134,20 @@ export default class NodeDetailsTable extends React.Component {
this.setState({limit});
}
+ getColumnHeaders() {
+ const columns = this.props.columns || [];
+ return [{id: 'label', label: this.props.label}].concat(columns);
+ }
+
renderHeaders() {
if (this.props.nodes && this.props.nodes.length > 0) {
- const columns = this.props.columns || [];
- const headers = [{id: 'label', label: this.props.label}].concat(columns);
+ const headers = this.getColumnHeaders();
+ const widths = getColumnsWidths(headers);
const defaultSortBy = getDefaultSortBy(this.props);
- // Beauty hack: adjust first column width if there are only few columns;
- // this assumes the other columns are narrow metric columns of 20% table width
- if (headers.length === 2) {
- headers[0].width = '66%';
- } else if (headers.length === 3) {
- headers[0].width = '50%';
- } else if (headers.length >= 3 && headers.length < 5) {
- headers[0].width = '33%';
- }
-
- //
- // More beauty hacking, ports and counts can only get so big, free up WS for other longer
- // fields like IPs!
- //
- headers.forEach(h => {
- h.width = COLUMN_WIDTHS[h.id];
- });
-
return (
- {headers.map(header => {
+ {headers.map((header, i) => {
const headerClasses = ['node-details-table-header', 'truncate'];
const onHeaderClick = ev => {
this.handleHeaderClick(ev, header.id);
@@ -144,8 +164,8 @@ export default class NodeDetailsTable extends React.Component {
// set header width in percent
const style = {};
- if (header.width) {
- style.width = header.width;
+ if (widths[i]) {
+ style.width = widths[i];
}
return (
@@ -183,14 +203,16 @@ export default class NodeDetailsTable extends React.Component {
React.cloneElement(child, { nodeOrder })
));
+ const className = classNames('node-details-table-wrapper-wrapper', this.props.className);
+
return (
-
+
{headers}
-
+
{nodes && nodes.map(node => (
diff --git a/client/app/scripts/components/nodes.js b/client/app/scripts/components/nodes.js
index 75e9459ab4..7080d831d9 100644
--- a/client/app/scripts/components/nodes.js
+++ b/client/app/scripts/components/nodes.js
@@ -7,7 +7,7 @@ import NodesError from '../charts/nodes-error';
import { isTopologyEmpty } from '../utils/topology-utils';
import { CANVAS_MARGINS } from '../constants/styles';
-const navbarHeight = 160;
+const navbarHeight = 168;
const marginTop = 0;
/**
@@ -75,6 +75,7 @@ class Nodes extends React.Component {
+
{children}
);
diff --git a/client/app/styles/main.less b/client/app/styles/main.less
index 89e3de049a..2cf157da76 100644
--- a/client/app/styles/main.less
+++ b/client/app/styles/main.less
@@ -273,7 +273,6 @@ h2 {
margin-bottom: 3px;
border: 1px solid transparent;
- background-color: #f7f7fa;
&-active, &:hover {
color: @text-color;
background-color: @background-darker-secondary-color;
@@ -1216,9 +1215,18 @@ h2 {
.sidebar {
position: fixed;
- bottom: 16px;
- left: 16px;
+ bottom: 12px;
+ left: 12px;
+ padding: 4px;
font-size: .7rem;
+ border-radius: 8px;
+ border: 1px solid transparent;
+}
+
+.sidebar-gridmode {
+ background-color: #e9e9f1;
+ border-color: @background-darker-color;
+ opacity: 0.9;
}
.search {
@@ -1505,13 +1513,9 @@ h2 {
.node-details-table-wrapper-wrapper {
flex: 1;
- overflow: scroll;
display: flex;
flex-direction: row;
- margin: 8px 16px;
width: 100%;
- // border: 1px solid @background-darker-color;
- padding-bottom: 36px;
.node-details-table-wrapper {
margin: 0;
@@ -1532,6 +1536,28 @@ h2 {
background-color: @background-darker-color;
}
}
+ }
+
+ .scroll-body {
+
+ table {
+ border-bottom: 1px solid #ccc;
+ }
+
+ thead, tbody tr {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ }
+ thead {
+ box-shadow: 0 4px 2px -2px rgba(0, 0, 0, 0.16);
+ border-bottom: 1px solid #aaa;
+ }
+
+ tbody {
+ display: block;
+ overflow-y: scroll;
+ }
}
}
|