UNPKG

horizon-devtools

Version:
314 lines (272 loc) 10.9 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.createDevTools = createDevTools; var _react = require('react'); var _react2 = _interopRequireDefault(_react); var _reactJsonTree = require('react-json-tree'); var _reactJsonTree2 = _interopRequireDefault(_reactJsonTree); var _reactDock = require('react-dock'); var _reactDock2 = _interopRequireDefault(_reactDock); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } // This should be replaced with Horizon 2's `query.toString()` method var ast2string = function ast2string(ast, live) { // All queries except `find` are an array, so we normalize `find` here to be an array if (ast.find) ast.find = [ast.find]; return ['find', 'find_all', 'above', 'below', 'order', 'limit'].reduce(function (res, key) { return res + (!ast[key] ? '' : '.' + key + '(' + JSON.stringify(ast[key][0]).replace(/[\[\]\"\{\}]/g, '') + ')'); }, (live === 'watch' ? '🔄 ' : '') + ast.collection); }; var positions = ['left', 'top', 'right', 'bottom']; var nextPosition = function nextPosition(c) { return positions[(positions.indexOf(c) + 1) % 4]; }; var theme = { base00: '#1B2B34', base01: '#EC5F67', base03: '#99C794', base06: '#FAC863', base05: '#6699CC', base04: '#C594C5', base02: '#5FB3B3', base07: '#A7ADBA', base08: '#4F5B66', base09: '#EC5F67', base0A: '#99C794', base0B: '#FAC863', base0D: '#6699CC', base0C: '#C594C5', base0E: '#5FB3B3', base0F: '#D8DEE9' }; function instrument(horizon) { var observ = { queries: {}, update: function update() { return null; } }; Object.getPrototypeOf(Object.getPrototypeOf(horizon('users'))).fetch = new Proxy(Object.getPrototypeOf(Object.getPrototypeOf(horizon('users'))).fetch, { apply: function apply(_fetch, thisArg) { return _fetch.bind(thisArg)().map(function (c) { observ.queries[ast2string(thisArg._query, 'fetch')] = c; observ.update(); return c; }); } }); Object.getPrototypeOf(Object.getPrototypeOf(horizon('users'))).watch = new Proxy(Object.getPrototypeOf(Object.getPrototypeOf(horizon('users'))).watch, { apply: function apply(_watch, thisArg, args) { return _watch.bind(thisArg).apply(undefined, _toConsumableArray(args)).map(function (c) { observ.queries[ast2string(thisArg._query, 'watch')] = c; observ.update(); return c; }); } }); return observ; } var Button = function Button(_ref) { var onClick = _ref.onClick; var children = _ref.children; return _react2.default.createElement( 'span', { onClick: onClick, style: { flexGrow: '1', cursor: 'pointer', textAlign: 'center', color: theme.base07, backgroundColor: theme.base08, borderRadius: '3px', margin: '5px', padding: '5px 0', textDecoration: 'underline' } }, children ); }; var ButtonTabs = function ButtonTabs(_ref2) { var _onClick = _ref2.onClick; return _react2.default.createElement( 'div', { style: { display: 'flex' } }, _react2.default.createElement( Button, { onClick: function onClick() { return _onClick('query'); } }, 'Query' ), _react2.default.createElement( Button, { onClick: function onClick() { return _onClick('user'); } }, 'User' ) ); }; var Logo = function Logo() { return _react2.default.createElement( 'span', null, _react2.default.createElement('img', { src: 'http://horizon.io/images/horizon-logo.png', style: { maxWidth: '200px', width: '50%' } }), _react2.default.createElement( 'span', { style: { color: '#5e5e5e' } }, '[DEV TOOLS]' ) ); }; var QueryView = function QueryView(_ref3) { var queries = _ref3.queries; return _react2.default.createElement(_reactJsonTree2.default, { data: queries, theme: theme, invertTheme: false, hideRoot: true }); }; var UserView = function UserView(_ref4) { var user = _ref4.user; return user === null ? _react2.default.createElement( 'div', { style: { color: theme.base01, margin: '.5em' } }, 'No user exists' ) : _react2.default.createElement(_reactJsonTree2.default, { data: user, theme: theme, invertTheme: false, hideRoot: true }); }; function createDevTools(horizon) { var devtools = instrument(horizon); if (typeof window !== 'undefined') window.devtools = devtools; return function (_Component) { _inherits(HzDevTools, _Component); function HzDevTools(props) { _classCallCheck(this, HzDevTools); var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(HzDevTools).call(this, props)); _this.handleKeyDown = _this.handleKeyDown.bind(_this); _this.handleQueryTextUpdate = _this.handleQueryTextUpdate.bind(_this); _this.shouldRunQuery = _this.shouldRunQuery.bind(_this); _this.state = { visible: props.defaultVisible || true, position: props.defaultPosition || 'right', queries: devtools.queries, user: {}, queryText: '', queryTextError: false, currentTab: 'query' }; return _this; } _createClass(HzDevTools, [{ key: 'componentDidMount', value: function componentDidMount() { var _this2 = this; if (typeof window !== 'undefined') window.addEventListener('keydown', this.handleKeyDown); horizon.currentUser().watch().subscribe(function (user) { _this2.setState({ user: user }); }, function () { _this2.setState({ user: null }); }); devtools.update = function () { _this2.setState({ queries: devtools.queries }); }; } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { if (typeof window !== 'undefined') window.removeEventListener('keydown', this.handleKeyDown); devtools.update = function () { return null; }; } }, { key: 'handleKeyDown', value: function handleKeyDown(e) { var char = String.fromCharCode(e.keyCode || e.which); if (char.toUpperCase() === 'Q' && e.ctrlKey) this.setState({ visible: !this.state.visible }); if (char.toUpperCase() === 'W' && e.ctrlKey) this.setState({ position: nextPosition(this.state.position) }); } }, { key: 'handleQueryTextUpdate', value: function handleQueryTextUpdate(e) { this.setState({ queryText: e.target.value, queryTextError: false }); } }, { key: 'shouldRunQuery', value: function shouldRunQuery(e) { if (e.keyCode === 13 && e.ctrlKey) { this.setState({ queryText: '' }); this.runQuery(this.state.queryText); return false; } } }, { key: 'runQuery', value: function runQuery(query) { try { var q = eval(query); if (q.fetch) { q = q.fetch(); } if (q.subscribe) { q = q.subscribe(); } this.setState({ queries: devtools.queries }); } catch (e) { this.setState({ queryTextError: true, queryText: e }); } } }, { key: 'render', value: function render() { var _this3 = this; return _react2.default.createElement( _reactDock2.default, { position: this.state.position, isVisible: this.state.visible, dimMode: 'none' }, _react2.default.createElement( 'pre', { style: { padding: '10px', width: 'calc(100% - 20px)', height: '90%', margin: 0, backgroundColor: theme.base00 } }, _react2.default.createElement(Logo, null), _react2.default.createElement('hr', { style: { borderStyle: 'solid', color: '#5e5e5e' } }), _react2.default.createElement(ButtonTabs, { onClick: function onClick(currentTab) { return _this3.setState({ currentTab: currentTab }); } }), _react2.default.createElement( 'div', { style: { overflow: 'auto', height: '100%' } }, this.state.currentTab === 'query' ? _react2.default.createElement(QueryView, { queries: this.state.queries }) : this.state.currentTab === 'user' ? _react2.default.createElement(UserView, { user: this.state.user }) : null ) ), _react2.default.createElement('textarea', { onChange: this.handleQueryTextUpdate, value: this.state.queryText, onKeyUp: this.shouldRunQuery, placeholder: 'Write a query using `horizon`. Run with ^ + Enter.', style: { color: this.state.queryTextError ? 'red' : undefined, padding: '5px', position: 'absolute', bottom: '0', width: '97.2%', resize: 'none', height: '10%', fontSize: '12pt', fontFamily: 'monospace' } }) ); } }]); return HzDevTools; }(_react.Component); }