From 9858f99fe812a411e02205eee95fc7401c3a4563 Mon Sep 17 00:00:00 2001 From: Barak Argaman Date: Tue, 5 Sep 2017 00:46:24 +0300 Subject: [PATCH] full logs page - replace grid component --- monkey_island/cc/ui/package-lock.json | 42 ++++++ monkey_island/cc/ui/package.json | 6 +- monkey_island/cc/ui/src/components/Main.js | 1 + .../ui/src/components/pages/FullLogsPage.js | 138 +++--------------- monkey_island/cc/ui/src/styles/App.css | 50 ++++++- 5 files changed, 110 insertions(+), 127 deletions(-) diff --git a/monkey_island/cc/ui/package-lock.json b/monkey_island/cc/ui/package-lock.json index f7caf5e1a..90c1a1212 100644 --- a/monkey_island/cc/ui/package-lock.json +++ b/monkey_island/cc/ui/package-lock.json @@ -5525,6 +5525,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" }, + "lodash-es": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + }, "lodash._baseassign": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", @@ -7443,6 +7448,14 @@ "prop-types": "15.5.10" } }, + "react-data-components": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-data-components/-/react-data-components-1.1.1.tgz", + "integrity": "sha512-b6gq3tXSQ0hHTH1iNoBQODQw4Y5km5vCpUV4SK7TaS6RZt4TSXxL5vbqoMToccSnImSGZdrjvx1Sp2zju+LyxA==", + "requires": { + "lodash": "4.17.4" + } + }, "react-data-grid": { "version": "2.0.58", "resolved": "https://registry.npmjs.org/react-data-grid/-/react-data-grid-2.0.58.tgz", @@ -7572,6 +7585,19 @@ "warning": "3.0.0" } }, + "react-redux": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.6.tgz", + "integrity": "sha512-8taaaGu+J7PMJQDJrk/xiWEYQmdo3mkXw6wPr3K3LxvXis3Fymiq7c13S+Tpls/AyNUAsoONkU81AP0RA6y6Vw==", + "requires": { + "hoist-non-react-statics": "2.3.1", + "invariant": "2.2.2", + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "prop-types": "15.5.10" + } + }, "react-router": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/react-router/-/react-router-4.2.0.tgz", @@ -7752,6 +7778,17 @@ } } }, + "redux": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", + "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", + "requires": { + "lodash": "4.17.4", + "lodash-es": "4.17.4", + "loose-envify": "1.3.1", + "symbol-observable": "1.0.4" + } + }, "regenerate": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", @@ -8570,6 +8607,11 @@ "whet.extend": "0.9.9" } }, + "symbol-observable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.4.tgz", + "integrity": "sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=" + }, "table": { "version": "3.8.3", "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", diff --git a/monkey_island/cc/ui/package.json b/monkey_island/cc/ui/package.json index 11f7862e7..a7375ab3a 100644 --- a/monkey_island/cc/ui/package.json +++ b/monkey_island/cc/ui/package.json @@ -69,14 +69,16 @@ "react": "^15.6.1", "react-bootstrap": "^0.31.2", "react-copy-to-clipboard": "^5.0.0", + "react-data-components": "^1.1.1", "react-data-grid": "^2.0.58", "react-data-grid-addons": "^2.0.58", "react-dom": "^15.6.1", "react-fa": "^4.2.0", "react-graph-vis": "^0.1.3", "react-json-tree": "^0.10.9", - "react-json-view": "^1.12.1", "react-jsonschema-form": "^0.49.0", - "react-router-dom": "^4.2.2" + "react-redux": "^5.0.6", + "react-router-dom": "^4.2.2", + "redux": "^3.7.2" } } diff --git a/monkey_island/cc/ui/src/components/Main.js b/monkey_island/cc/ui/src/components/Main.js index f08875a60..11c7f1115 100644 --- a/monkey_island/cc/ui/src/components/Main.js +++ b/monkey_island/cc/ui/src/components/Main.js @@ -10,6 +10,7 @@ import MapPage from 'components/pages/MapPage'; import FullLogsPage from 'components/pages/FullLogsPage'; require('normalize.css/normalize.css'); +require('react-data-components/css/table-twbs.css'); require('styles/App.css'); let logoImage = require('../images/monkey-logo.png'); diff --git a/monkey_island/cc/ui/src/components/pages/FullLogsPage.js b/monkey_island/cc/ui/src/components/pages/FullLogsPage.js index cd6cef83c..837e12c1f 100644 --- a/monkey_island/cc/ui/src/components/pages/FullLogsPage.js +++ b/monkey_island/cc/ui/src/components/pages/FullLogsPage.js @@ -1,143 +1,45 @@ import React from 'react'; import {Col} from 'react-bootstrap'; -import ReactJson from 'react-json-view' import JSONTree from 'react-json-tree' -import ReactDataGrid, {Row} from 'react-data-grid'; -import {Icon} from "react-fa"; -const { Toolbar, Data: { Selectors } } = require('react-data-grid-addons'); +import {DataTable} from 'react-data-components'; -// Custom Formatter component -const JsonCellFormatter = React.createClass({ - render() { - return ( - - ); - } -}); +const renderJson = (val, row) => ; +const renderTime = (val, row) => val.split('.')[0]; -const RowRenderer = React.createClass({ - render() { - return ( - this.row = node } {...this.props}/> - ); - } - // height: '50px', - // - // onClick() { - // this.height = '200px'; - // }, - // - // render() { - // return ( - //
- // - // this.row = node } {...this.props}/> - //
- // ); - // } -}); +const columns = [ + { title: 'Type', prop: 'telem_type' }, + { title: 'Monkey ID', prop: 'monkey_guid' }, + { title: 'Time', prop: 'timestamp', render: renderTime}, + { title: 'More Info', prop: 'data', render: renderJson, width: '40%' } +]; class FullLogsPageComponent extends React.Component { constructor(props) { super(props); this.state = { - ...this.getInitialState() + data: [] }; } - getInitialState() { - this._columns = [ - { - key: 'telem_type', - name: 'Type', - width: 200, - filterable: true, - sortable: true - }, - { - key: 'monkey_guid', - name: 'Monkey ID', - filterable: true, - sortable: true - }, - { - key: 'timestamp', - name: 'Time', - filterable: true, - sortable: true - }, - { - key: 'data', - name: 'More Info', - formatter: JsonCellFormatter - } - ]; - - return { rows: [], filters: {}, sortColumn: null, sortDirection: null }; - } - - getRandomDate(start, end) { - return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime())).toLocaleDateString(); - } - - getRows() { - return Selectors.getRows(this.state); - } - - getSize() { - return this.getRows().length; - } - - rowGetter = (rowIdx) => { - const rows = this.getRows(); - return rows[rowIdx]; - }; - - handleGridSort = (sortColumn, sortDirection) => { - this.setState({ sortColumn: sortColumn, sortDirection: sortDirection }); - }; - - handleFilterChange = (filter) => { - let newFilters = Object.assign({}, this.state.filters); - if (filter.filterTerm) { - newFilters[filter.column.key] = filter; - } else { - delete newFilters[filter.column.key]; - } - - this.setState({ filters: newFilters }); - }; - - onClearFilters = () => { - this.setState({ filters: {} }); - }; - componentDidMount = () => { - this.dataGrid.setState({canFilter: true}, () => this.hideFilterButton()); fetch('/api/telemetry') .then(res => res.json()) - .then(res => this.setState({rows: res.objects})); + .then(res => this.setState({data: res.objects})); }; - hideFilterButton = () => document.getElementsByClassName('react-grid-Toolbar')[0].style.display = 'none'; - render() { return (

Full Logs

-
- { this.dataGrid = grid; }} - rowRenderer={RowRenderer} - rowHeight={50} - minHeight={500} - columns={this._columns} - toolbar={} - rowGetter={this.rowGetter} - rowsCount={this.getSize()} - onGridSort={this.handleGridSort} - onAddFilter={this.handleFilterChange} - onClearFilters={this.onClearFilters} /> +
+
); diff --git a/monkey_island/cc/ui/src/styles/App.css b/monkey_island/cc/ui/src/styles/App.css index fdb617c7a..64aeb0699 100644 --- a/monkey_island/cc/ui/src/styles/App.css +++ b/monkey_island/cc/ui/src/styles/App.css @@ -154,28 +154,32 @@ body { * Map Preview Pane */ -.preview.well { - padding: 1em; +.preview-pane { + background: #f5f5f5; + border-left: 1px solid #e8e8e8; + border-bottom: 3px solid #e8e8e8; + padding: 1.5em 1em; + border-radius: 8px; } -.preview h3 { +.preview-pane h3 { margin: 0; } -.preview h3 small { +.preview-pane h3 small { margin-top: 0.5em; display: block; } -.preview h3 .fa { +.preview-pane h3 .fa { margin-right: 5px; } -.preview h4 { +.preview-pane h4 { text-transform: uppercase; color: #999; font-size: 1em; margin-top: 0; } -.preview p, .preview .timeline { +.preview-pane p, .preview-pane .timeline { margin-left: 1em; } @@ -217,3 +221,35 @@ body { .timeline .bullet.bad { background: #d30d09; } + +/* + * Full Logs Page + */ + +.data-table-container > .container { + width: inherit; + padding: 0; +} + +.data-table-container > .container th , .data-table-container > .container td { + padding: 15px 8px; +} + +#search-field , #page-menu { + margin-left: 1em; + margin-bottom: 1em; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; + -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; +}