mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-17 09:23:48 +00:00
dashboard, cmd: minor UI fix, include commit hash
This commit is contained in:
parent
011ab3665a
commit
24880501bb
9 changed files with 93 additions and 145 deletions
|
|
@ -158,7 +158,7 @@ func makeFullNode(ctx *cli.Context) *node.Node {
|
||||||
utils.RegisterEthService(stack, &cfg.Eth)
|
utils.RegisterEthService(stack, &cfg.Eth)
|
||||||
|
|
||||||
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
|
if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
|
||||||
utils.RegisterDashboardService(stack, &cfg.Dashboard)
|
utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
|
||||||
}
|
}
|
||||||
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
|
// Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
|
||||||
shhEnabled := enableWhisper(ctx)
|
shhEnabled := enableWhisper(ctx)
|
||||||
|
|
|
||||||
|
|
@ -1103,9 +1103,9 @@ func RegisterEthService(stack *node.Node, cfg *eth.Config) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegisterDashboardService adds a dashboard to the stack.
|
// RegisterDashboardService adds a dashboard to the stack.
|
||||||
func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config) {
|
func RegisterDashboardService(stack *node.Node, cfg *dashboard.Config, commit string) {
|
||||||
stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
return dashboard.New(cfg)
|
return dashboard.New(cfg, commit)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26819,37 +26819,28 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
|
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
|
||||||
Constructor;
|
Constructor;
|
||||||
};
|
};
|
||||||
}(), _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(obj) {
|
}(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _Header = __webpack_require__(459), _Header2 = _interopRequireDefault(_Header), _Body = __webpack_require__(489), _Body2 = _interopRequireDefault(_Body), _Footer = __webpack_require__(805), _Footer2 = _interopRequireDefault(_Footer), _Common = __webpack_require__(77), deepUpdate = function deepUpdate(prev, update, updater) {
|
||||||
return typeof obj;
|
if (void 0 === update) return prev;
|
||||||
} : function(obj) {
|
if ("function" == typeof updater) return updater(prev, update);
|
||||||
return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
|
var updated = {};
|
||||||
}, _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _Header = __webpack_require__(459), _Header2 = _interopRequireDefault(_Header), _Body = __webpack_require__(489), _Body2 = _interopRequireDefault(_Body), _Footer = __webpack_require__(805), _Footer2 = _interopRequireDefault(_Footer), _Common = __webpack_require__(77), deepCopy = function deepCopy(prev) {
|
|
||||||
var copied = Array.isArray(prev) ? [] : {};
|
|
||||||
return Object.keys(prev).forEach(function(key) {
|
return Object.keys(prev).forEach(function(key) {
|
||||||
var c = prev[key];
|
updated[key] = deepUpdate(prev[key], update[key], updater[key]);
|
||||||
copied[key] = "object" === (void 0 === c ? "undefined" : _typeof(c)) ? deepCopy(c) : c;
|
|
||||||
}), copied;
|
|
||||||
}, deepUpdate = function deepUpdate(prev, update, handler) {
|
|
||||||
if (void 0 === update) return deepCopy(prev);
|
|
||||||
if ("function" == typeof handler) return handler(prev, update);
|
|
||||||
var updated = Array.isArray(prev) ? [] : {};
|
|
||||||
return Object.keys(prev).forEach(function(key) {
|
|
||||||
void 0 === update[key] ? updated[key] = deepCopy(prev[key]) : updated[key] = deepUpdate(prev[key], update[key], handler[key]);
|
|
||||||
}), updated;
|
}), updated;
|
||||||
}, shouldUpdate = function shouldUpdate(msg, handler) {
|
}, shouldUpdate = function shouldUpdate(msg, updater) {
|
||||||
var su = {};
|
var su = {};
|
||||||
return Object.keys(msg).forEach(function(key) {
|
return Object.keys(msg).forEach(function(key) {
|
||||||
su[key] = "object" !== _typeof(msg[key]) || "function" == typeof handler[key] || shouldUpdate(msg[key], handler[key]);
|
su[key] = "function" == typeof updater[key] || shouldUpdate(msg[key], updater[key]);
|
||||||
}), su;
|
}), su;
|
||||||
}, appender200 = function(limit) {
|
}, appender = function(limit) {
|
||||||
return function(prev, update) {
|
return function(prev, update) {
|
||||||
return [].concat(_toConsumableArray(prev), _toConsumableArray(update)).slice(-limit);
|
return [].concat(_toConsumableArray(prev), _toConsumableArray(update)).slice(-limit);
|
||||||
};
|
};
|
||||||
}(200), replacer = function(prev, update) {
|
}, replacer = function(prev, update) {
|
||||||
return update;
|
return update;
|
||||||
}, defaultContent = {
|
}, defaultContent = {
|
||||||
general: {
|
general: {
|
||||||
version: "-"
|
version: "-",
|
||||||
|
gitCommit: "-"
|
||||||
},
|
},
|
||||||
home: {
|
home: {
|
||||||
memory: [],
|
memory: [],
|
||||||
|
|
@ -26862,20 +26853,21 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
logs: {
|
logs: {
|
||||||
log: []
|
log: []
|
||||||
}
|
}
|
||||||
}, handlers = {
|
}, updaters = {
|
||||||
general: {
|
general: {
|
||||||
version: replacer
|
version: replacer,
|
||||||
|
gitCommit: replacer
|
||||||
},
|
},
|
||||||
home: {
|
home: {
|
||||||
memory: appender200,
|
memory: appender(200),
|
||||||
traffic: appender200
|
traffic: appender(200)
|
||||||
},
|
},
|
||||||
chain: null,
|
chain: null,
|
||||||
txpool: null,
|
txpool: null,
|
||||||
network: null,
|
network: null,
|
||||||
system: null,
|
system: null,
|
||||||
logs: {
|
logs: {
|
||||||
log: appender200
|
log: appender(200)
|
||||||
}
|
}
|
||||||
}, styles = function(theme) {
|
}, styles = function(theme) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -26902,15 +26894,16 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
});
|
});
|
||||||
}, server.onmessage = function(event) {
|
}, server.onmessage = function(event) {
|
||||||
var msg = JSON.parse(event.data);
|
var msg = JSON.parse(event.data);
|
||||||
msg && _this.update(msg);
|
if (!msg) return void console.error("Incoming message is " + msg);
|
||||||
|
console.log(msg), _this.update(msg);
|
||||||
}, server.onclose = function() {
|
}, server.onclose = function() {
|
||||||
setTimeout(_this.reconnect, 3e3);
|
setTimeout(_this.reconnect, 3e3);
|
||||||
};
|
};
|
||||||
}, _this.update = function(msg) {
|
}, _this.update = function(msg) {
|
||||||
_this.setState(function(prevState) {
|
_this.setState(function(prevState) {
|
||||||
return {
|
return {
|
||||||
content: deepUpdate(prevState.content, msg, handlers),
|
content: deepUpdate(prevState.content, msg, updaters),
|
||||||
shouldUpdate: shouldUpdate(msg, handlers)
|
shouldUpdate: shouldUpdate(msg, updaters)
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}, _this.changeContent = function(newActive) {
|
}, _this.changeContent = function(newActive) {
|
||||||
|
|
@ -38146,13 +38139,7 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
Object.defineProperty(exports, "__esModule", {
|
Object.defineProperty(exports, "__esModule", {
|
||||||
value: !0
|
value: !0
|
||||||
});
|
});
|
||||||
var _extends = Object.assign || function(target) {
|
var _createClass = function() {
|
||||||
for (var i = 1; i < arguments.length; i++) {
|
|
||||||
var source = arguments[i];
|
|
||||||
for (var key in source) Object.prototype.hasOwnProperty.call(source, key) && (target[key] = source[key]);
|
|
||||||
}
|
|
||||||
return target;
|
|
||||||
}, _createClass = function() {
|
|
||||||
function defineProperties(target, props) {
|
function defineProperties(target, props) {
|
||||||
for (var i = 0; i < props.length; i++) {
|
for (var i = 0; i < props.length; i++) {
|
||||||
var descriptor = props[i];
|
var descriptor = props[i];
|
||||||
|
|
@ -38164,13 +38151,9 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
|
return protoProps && defineProperties(Constructor.prototype, protoProps), staticProps && defineProperties(Constructor, staticProps),
|
||||||
Constructor;
|
Constructor;
|
||||||
};
|
};
|
||||||
}(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _AppBar = __webpack_require__(235), _AppBar2 = _interopRequireDefault(_AppBar), _Toolbar = __webpack_require__(236), _Toolbar2 = _interopRequireDefault(_Toolbar), _Transition = __webpack_require__(76), _Transition2 = _interopRequireDefault(_Transition), _IconButton = __webpack_require__(237), _IconButton2 = _interopRequireDefault(_IconButton), _Typography = __webpack_require__(158), _Typography2 = _interopRequireDefault(_Typography), _ChevronLeft = __webpack_require__(244), _ChevronLeft2 = _interopRequireDefault(_ChevronLeft), _Common = __webpack_require__(77), arrowDefault = {
|
}(), _react = __webpack_require__(0), _react2 = _interopRequireDefault(_react), _withStyles = __webpack_require__(10), _withStyles2 = _interopRequireDefault(_withStyles), _AppBar = __webpack_require__(235), _AppBar2 = _interopRequireDefault(_AppBar), _Toolbar = __webpack_require__(236), _Toolbar2 = _interopRequireDefault(_Toolbar), _Transition = __webpack_require__(76), _IconButton = (_interopRequireDefault(_Transition),
|
||||||
transition: "transform " + _Common.DURATION + "ms"
|
__webpack_require__(237)), _Typography = (_interopRequireDefault(_IconButton), __webpack_require__(158)), _Typography2 = _interopRequireDefault(_Typography), _ChevronLeft = __webpack_require__(244), _Common = (_interopRequireDefault(_ChevronLeft),
|
||||||
}, arrowTransition = {
|
__webpack_require__(77)), styles = (_Common.DURATION, function(theme) {
|
||||||
entered: {
|
|
||||||
transform: "rotate(180deg)"
|
|
||||||
}
|
|
||||||
}, styles = function(theme) {
|
|
||||||
return {
|
return {
|
||||||
header: {
|
header: {
|
||||||
backgroundColor: theme.palette.background.appBar,
|
backgroundColor: theme.palette.background.appBar,
|
||||||
|
|
@ -38185,21 +38168,9 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
paddingLeft: theme.spacing.unit
|
paddingLeft: theme.spacing.unit
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, Footer = function(_Component) {
|
}), Footer = function(_Component) {
|
||||||
function Footer() {
|
function Footer() {
|
||||||
var _ref, _temp, _this, _ret;
|
return _classCallCheck(this, Footer), _possibleConstructorReturn(this, (Footer.__proto__ || Object.getPrototypeOf(Footer)).apply(this, arguments));
|
||||||
_classCallCheck(this, Footer);
|
|
||||||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) args[_key] = arguments[_key];
|
|
||||||
return _temp = _this = _possibleConstructorReturn(this, (_ref = Footer.__proto__ || Object.getPrototypeOf(Footer)).call.apply(_ref, [ this ].concat(args))),
|
|
||||||
_this.changeSideBar = function() {
|
|
||||||
_this.props.opened ? _this.props.closeSideBar() : _this.props.openSideBar();
|
|
||||||
}, _this.arrowButton = function(transitionState) {
|
|
||||||
return _react2.default.createElement(_IconButton2.default, {
|
|
||||||
onClick: _this.changeSideBar
|
|
||||||
}, _react2.default.createElement(_ChevronLeft2.default, {
|
|
||||||
style: _extends({}, arrowDefault, arrowTransition[transitionState])
|
|
||||||
}));
|
|
||||||
}, _ret = _temp, _possibleConstructorReturn(_this, _ret);
|
|
||||||
}
|
}
|
||||||
return _inherits(Footer, _Component), _createClass(Footer, [ {
|
return _inherits(Footer, _Component), _createClass(Footer, [ {
|
||||||
key: "shouldComponentUpdate",
|
key: "shouldComponentUpdate",
|
||||||
|
|
@ -38209,24 +38180,21 @@ var _bundleJs = []byte((((((((((`!function(modules) {
|
||||||
}, {
|
}, {
|
||||||
key: "render",
|
key: "render",
|
||||||
value: function() {
|
value: function() {
|
||||||
var _props = this.props, classes = _props.classes, opened = _props.opened;
|
var classes = this.props.classes;
|
||||||
return _react2.default.createElement(_AppBar2.default, {
|
return _react2.default.createElement(_AppBar2.default, {
|
||||||
position: "static",
|
position: "static",
|
||||||
className: classes.header
|
className: classes.header
|
||||||
}, _react2.default.createElement(_Toolbar2.default, {
|
}, _react2.default.createElement(_Toolbar2.default, {
|
||||||
className: classes.toolbar
|
className: classes.toolbar
|
||||||
}, _react2.default.createElement(_Transition2.default, {
|
}, _react2.default.createElement(_Typography2.default, {
|
||||||
mountOnEnter: !0,
|
|
||||||
in: opened,
|
|
||||||
timeout: {
|
|
||||||
enter: _Common.DURATION
|
|
||||||
}
|
|
||||||
}, this.arrowButton), _react2.default.createElement(_Typography2.default, {
|
|
||||||
type: "title",
|
type: "title",
|
||||||
color: "inherit",
|
color: "inherit",
|
||||||
noWrap: !0,
|
|
||||||
className: classes.mainText
|
className: classes.mainText
|
||||||
}, this.props.general.version)));
|
}, this.props.general.version), _react2.default.createElement(_Typography2.default, {
|
||||||
|
type: "title",
|
||||||
|
color: "inherit",
|
||||||
|
className: classes.mainText
|
||||||
|
}, this.props.general.gitCommit)));
|
||||||
}
|
}
|
||||||
} ]), Footer;
|
} ]), Footer;
|
||||||
}(_react.Component);
|
}(_react.Component);
|
||||||
|
|
|
||||||
|
|
@ -26,22 +26,8 @@ import Footer from './Footer';
|
||||||
import {MENU} from './Common';
|
import {MENU} from './Common';
|
||||||
import type {Content} from '../types/content';
|
import type {Content} from '../types/content';
|
||||||
|
|
||||||
// deepCopy retrieves a copy of the given object, copying recursively in all depth.
|
|
||||||
// It is used at the state update, because React doesn't handle the object nesting well.
|
|
||||||
// References are prohibited, since the state needs to be immutable.
|
|
||||||
// NOTE: maybe there is better solution.
|
|
||||||
const deepCopy = (prev: mixed) => {
|
|
||||||
const copied = Array.isArray(prev) ? [] : {};
|
|
||||||
Object.keys(prev).forEach((key) => {
|
|
||||||
const c: mixed = prev[key]
|
|
||||||
copied[key] = typeof c === 'object' ? deepCopy(c) : c;
|
|
||||||
});
|
|
||||||
|
|
||||||
return copied;
|
|
||||||
};
|
|
||||||
|
|
||||||
// deepUpdate updates an object corresponding to the given update data, which has
|
// deepUpdate updates an object corresponding to the given update data, which has
|
||||||
// the shape of the same structure as the original object. handler also has the same
|
// the shape of the same structure as the original object. updater also has the same
|
||||||
// structure, except that it contains functions where the original data needs to be
|
// structure, except that it contains functions where the original data needs to be
|
||||||
// updated. These functions are used to handle the update.
|
// updated. These functions are used to handle the update.
|
||||||
//
|
//
|
||||||
|
|
@ -49,41 +35,41 @@ const deepCopy = (prev: mixed) => {
|
||||||
// the generalization of the message handling. The only necessary thing is to set a
|
// the generalization of the message handling. The only necessary thing is to set a
|
||||||
// handler function for every path of the state in order to maximize the flexibility
|
// handler function for every path of the state in order to maximize the flexibility
|
||||||
// of the update.
|
// of the update.
|
||||||
const deepUpdate = (prev: mixed, update: mixed, handler: mixed) => {
|
const deepUpdate = (prev: Object, update: Object, updater: Object) => {
|
||||||
if (typeof update === 'undefined') {
|
if (typeof update === 'undefined') {
|
||||||
return deepCopy(prev);
|
// TODO (kurkomisi): originally this was deep copy, investigate it.
|
||||||
|
return prev;
|
||||||
}
|
}
|
||||||
if (typeof handler === 'function') {
|
if (typeof updater === 'function') {
|
||||||
return handler(prev, update);
|
return updater(prev, update);
|
||||||
}
|
}
|
||||||
const updated = Array.isArray(prev) ? [] : {};
|
const updated = {};
|
||||||
Object.keys(prev).forEach((key) => {
|
Object.keys(prev).forEach((key) => {
|
||||||
if (typeof update[key] === 'undefined') {
|
updated[key] = deepUpdate(prev[key], update[key], updater[key]);
|
||||||
updated[key] = deepCopy(prev[key]);
|
|
||||||
} else {
|
|
||||||
updated[key] = deepUpdate(prev[key], update[key], handler[key]);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
};
|
};
|
||||||
|
|
||||||
// shouldUpdate retrieves the structure of a message. It is used to prevent unnecessary render
|
// shouldUpdate returns the structure of a message. It is used to prevent unnecessary render
|
||||||
// method triggerings. In the affected component's shouldComponentUpdate method it can be checked
|
// method triggerings. In the affected component's shouldComponentUpdate method it can be checked
|
||||||
// whether the involved data was changed or not by checking the message structure.
|
// whether the involved data was changed or not by checking the message structure.
|
||||||
const shouldUpdate = (msg: mixed, handler: mixed) => {
|
//
|
||||||
|
// We could return the message itself too, but it's safer not to give access to it.
|
||||||
|
const shouldUpdate = (msg: Object, updater: Object) => {
|
||||||
const su = {};
|
const su = {};
|
||||||
|
console.log(msg);
|
||||||
Object.keys(msg).forEach((key) => {
|
Object.keys(msg).forEach((key) => {
|
||||||
su[key] = typeof msg[key] === 'object' && typeof handler[key] !== 'function' ? shouldUpdate(msg[key], handler[key]) : true;
|
su[key] = typeof updater[key] !== 'function' ? shouldUpdate(msg[key], updater[key]) : true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return su;
|
return su;
|
||||||
};
|
};
|
||||||
|
|
||||||
// appender is a state update generalization function, which appends the update data
|
// appender is a state update generalization function, which appends the update data
|
||||||
// to the existing data. limit defines the maximum allowed size of the created array.
|
// to the existing data. limit defines the maximum allowed size of the created array.
|
||||||
const appender = <T>(limit: number) => (prev: Array<T>, update: Array<T>) => [...prev, ...update].slice(-limit);
|
const appender = <T>(limit: number) => (prev: Array<T>, update: Array<T>) => [...prev, ...update].slice(-limit);
|
||||||
// appender200 is an appender function with limit 200.
|
|
||||||
const appender200 = appender(200);
|
|
||||||
// replacer is a state update generalization function, which replaces the original data.
|
// replacer is a state update generalization function, which replaces the original data.
|
||||||
const replacer = <T>(prev: T, update: T) => update;
|
const replacer = <T>(prev: T, update: T) => update;
|
||||||
|
|
||||||
|
|
@ -91,6 +77,7 @@ const replacer = <T>(prev: T, update: T) => update;
|
||||||
const defaultContent: Content = {
|
const defaultContent: Content = {
|
||||||
general: {
|
general: {
|
||||||
version: '-',
|
version: '-',
|
||||||
|
gitCommit: '-',
|
||||||
},
|
},
|
||||||
home: {
|
home: {
|
||||||
memory: [],
|
memory: [],
|
||||||
|
|
@ -104,25 +91,28 @@ const defaultContent: Content = {
|
||||||
log: [],
|
log: [],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// handlers contains the state update generalization functions for each path of the state.
|
|
||||||
|
// updaters contains the state update generalization functions for each path of the state.
|
||||||
// TODO (kurkomisi): Define a tricky type which embraces the content and the handlers.
|
// TODO (kurkomisi): Define a tricky type which embraces the content and the handlers.
|
||||||
const handlers = {
|
const updaters = {
|
||||||
general: {
|
general: {
|
||||||
version: replacer,
|
version: replacer,
|
||||||
|
gitCommit: replacer,
|
||||||
},
|
},
|
||||||
home: {
|
home: {
|
||||||
memory: appender200,
|
memory: appender(200),
|
||||||
traffic: appender200,
|
traffic: appender(200),
|
||||||
},
|
},
|
||||||
chain: null,
|
chain: null,
|
||||||
txpool: null,
|
txpool: null,
|
||||||
network: null,
|
network: null,
|
||||||
system: null,
|
system: null,
|
||||||
logs: {
|
logs: {
|
||||||
log: appender200,
|
log: appender(200),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// styles retrieves the styles for the Dashboard component.
|
|
||||||
|
// styles returns the styles for the Dashboard component.
|
||||||
const styles = theme => ({
|
const styles = theme => ({
|
||||||
dashboard: {
|
dashboard: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
|
@ -134,15 +124,18 @@ const styles = theme => ({
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
classes: Object,
|
classes: Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
active: string, // active menu
|
active: string, // active menu
|
||||||
sideBar: boolean, // true if the sidebar is opened
|
sideBar: boolean, // true if the sidebar is opened
|
||||||
content: Content, // the visualized data
|
content: Content, // the visualized data
|
||||||
shouldUpdate: Object // labels for the components, which need to rerender based on the incoming message
|
shouldUpdate: Object // labels for the components, which need to rerender based on the incoming message
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dashboard is the main component, which renders the whole page, makes connection with the server and
|
// Dashboard is the main component, which renders the whole page, makes connection with the server and
|
||||||
// listens for messages. When there is an incoming message, updates the page's content correspondingly.
|
// listens for messages. When there is an incoming message, updates the page's content correspondingly.
|
||||||
class Dashboard extends Component<Props, State> {
|
class Dashboard extends Component<Props, State> {
|
||||||
|
|
@ -171,6 +164,7 @@ class Dashboard extends Component<Props, State> {
|
||||||
server.onmessage = (event) => {
|
server.onmessage = (event) => {
|
||||||
const msg: $Shape<Content> = JSON.parse(event.data);
|
const msg: $Shape<Content> = JSON.parse(event.data);
|
||||||
if (!msg) {
|
if (!msg) {
|
||||||
|
console.error(`Incoming message is ${msg}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.update(msg);
|
this.update(msg);
|
||||||
|
|
@ -183,8 +177,8 @@ class Dashboard extends Component<Props, State> {
|
||||||
// update updates the content corresponding to the incoming message.
|
// update updates the content corresponding to the incoming message.
|
||||||
update = (msg: $Shape<Content>) => {
|
update = (msg: $Shape<Content>) => {
|
||||||
this.setState(prevState => ({
|
this.setState(prevState => ({
|
||||||
content: deepUpdate(prevState.content, msg, handlers),
|
content: deepUpdate(prevState.content, msg, updaters),
|
||||||
shouldUpdate: shouldUpdate(msg, handlers),
|
shouldUpdate: shouldUpdate(msg, updaters),
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,9 +53,6 @@ const styles = theme => ({
|
||||||
});
|
});
|
||||||
export type Props = {
|
export type Props = {
|
||||||
classes: Object,
|
classes: Object,
|
||||||
opened: boolean,
|
|
||||||
openSideBar: () => {},
|
|
||||||
closeSideBar: () => {},
|
|
||||||
};
|
};
|
||||||
// TODO (kurkomisi): If the structure is appropriate, make an abstraction of the common parts with the Header.
|
// TODO (kurkomisi): If the structure is appropriate, make an abstraction of the common parts with the Header.
|
||||||
// Footer renders the header of the dashboard.
|
// Footer renders the header of the dashboard.
|
||||||
|
|
@ -64,39 +61,18 @@ class Footer extends Component<Props> {
|
||||||
return typeof nextProps.shouldUpdate.logs !== 'undefined';
|
return typeof nextProps.shouldUpdate.logs !== 'undefined';
|
||||||
}
|
}
|
||||||
|
|
||||||
// changeSideBar opens or closes the sidebar corresponding to the previous state.
|
|
||||||
changeSideBar = () => {
|
|
||||||
if (this.props.opened) {
|
|
||||||
this.props.closeSideBar();
|
|
||||||
} else {
|
|
||||||
this.props.openSideBar();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// arrowButton is connected to the sidebar; changes its state.
|
|
||||||
arrowButton = (transitionState: string) => (
|
|
||||||
<IconButton onClick={this.changeSideBar}>
|
|
||||||
<ChevronLeftIcon
|
|
||||||
style={{
|
|
||||||
...arrowDefault,
|
|
||||||
...arrowTransition[transitionState],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
);
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {classes, opened} = this.props; // The classes property is injected by withStyles().
|
const {classes} = this.props; // The classes property is injected by withStyles().
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AppBar position="static" className={classes.header}>
|
<AppBar position="static" className={classes.header}>
|
||||||
<Toolbar className={classes.toolbar}>
|
<Toolbar className={classes.toolbar}>
|
||||||
<Transition mountOnEnter in={opened} timeout={{enter: DURATION}}>
|
<Typography type="title" color="inherit" className={classes.mainText}>
|
||||||
{this.arrowButton}
|
|
||||||
</Transition>
|
|
||||||
<Typography type="title" color="inherit" noWrap className={classes.mainText}>
|
|
||||||
{this.props.general.version}
|
{this.props.general.version}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography type="title" color="inherit" className={classes.mainText}>
|
||||||
|
{this.props.general.gitCommit}
|
||||||
|
</Typography>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export type Content = {
|
||||||
|
|
||||||
export type General = {
|
export type General = {
|
||||||
version: string,
|
version: string,
|
||||||
|
gitCommit: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Home = {
|
export type Home = {
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ type Dashboard struct {
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
conns map[uint32]*client // Currently live websocket connections
|
conns map[uint32]*client // Currently live websocket connections
|
||||||
charts *HomeMessage
|
charts *HomeMessage
|
||||||
|
gitCommit string
|
||||||
lock sync.RWMutex // Lock protecting the dashboard's internals
|
lock sync.RWMutex // Lock protecting the dashboard's internals
|
||||||
|
|
||||||
quit chan chan error // Channel used for graceful exit
|
quit chan chan error // Channel used for graceful exit
|
||||||
|
|
@ -69,7 +70,7 @@ type client struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new dashboard instance with the given configuration.
|
// New creates a new dashboard instance with the given configuration.
|
||||||
func New(config *Config) (*Dashboard, error) {
|
func New(config *Config, gitCommit string) (*Dashboard, error) {
|
||||||
return &Dashboard{
|
return &Dashboard{
|
||||||
conns: make(map[uint32]*client),
|
conns: make(map[uint32]*client),
|
||||||
config: config,
|
config: config,
|
||||||
|
|
@ -78,6 +79,7 @@ func New(config *Config) (*Dashboard, error) {
|
||||||
Memory: ChartEntries{},
|
Memory: ChartEntries{},
|
||||||
Traffic: ChartEntries{},
|
Traffic: ChartEntries{},
|
||||||
},
|
},
|
||||||
|
gitCommit: gitCommit,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,10 +203,16 @@ func (db *Dashboard) apiHandler(conn *websocket.Conn) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
versionMeta := ""
|
||||||
|
if len(params.VersionMeta) > 0 {
|
||||||
|
versionMeta = fmt.Sprintf(" (%s)", params.VersionMeta)
|
||||||
|
}
|
||||||
// Send the past data.
|
// Send the past data.
|
||||||
client.msg <- Message{
|
client.msg <- Message{
|
||||||
General: &GeneralMessage{
|
General: &GeneralMessage{
|
||||||
Version: params.Version,
|
Version: fmt.Sprintf("Geth v%d.%d.%d%s", params.VersionMajor, params.VersionMinor, params.VersionPatch, versionMeta),
|
||||||
|
GitCommit: fmt.Sprintf("Commit %s", db.gitCommit),
|
||||||
},
|
},
|
||||||
Home: &HomeMessage{
|
Home: &HomeMessage{
|
||||||
Memory: db.charts.Memory,
|
Memory: db.charts.Memory,
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ type Message struct {
|
||||||
|
|
||||||
type GeneralMessage struct {
|
type GeneralMessage struct {
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
|
GitCommit string `json:"gitCommit,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type HomeMessage struct {
|
type HomeMessage struct {
|
||||||
|
|
|
||||||
BIN
geth
Executable file
BIN
geth
Executable file
Binary file not shown.
Loading…
Reference in a new issue