diff --git a/frontend/components/loaders/Timer/Timer.jsx b/frontend/components/loaders/Timer/Timer.jsx index dbec7b94c2..3a0e6f9afe 100644 --- a/frontend/components/loaders/Timer/Timer.jsx +++ b/frontend/components/loaders/Timer/Timer.jsx @@ -29,6 +29,10 @@ class Timer extends Component { } } + componentWillUnmount () { + this.pause(); + } + play = () => { const { interval, update } = this; diff --git a/frontend/components/queries/QueryResultsTable/QueryResultsRow.jsx b/frontend/components/queries/QueryResultsTable/QueryResultsRow.jsx new file mode 100644 index 0000000000..9bc28b5fe3 --- /dev/null +++ b/frontend/components/queries/QueryResultsTable/QueryResultsRow.jsx @@ -0,0 +1,33 @@ +import React, { Component, PropTypes } from 'react'; +import { isEqual, omit, values } from 'lodash'; + +import queryResultInterface from 'interfaces/query_result'; + +class QueryResultsRow extends Component { + static propTypes = { + index: PropTypes.number.isRequired, + queryResult: queryResultInterface.isRequired, + }; + + shouldComponentUpdate (nextProps) { + return !isEqual(this.props.queryResult, nextProps.queryResult); + } + + render () { + const { index, queryResult } = this.props; + const { hostname } = queryResult; + const queryAttrs = omit(queryResult, ['hostname']); + const queryAttrValues = values(queryAttrs); + + return ( + + {hostname} + {queryAttrValues.map((attribute, i) => { + return {attribute}; + })} + + ); + } +} + +export default QueryResultsRow; diff --git a/frontend/components/queries/QueryResultsTable/QueryResultsTable.jsx b/frontend/components/queries/QueryResultsTable/QueryResultsTable.jsx index 586be7dbf8..0aba59b4be 100644 --- a/frontend/components/queries/QueryResultsTable/QueryResultsTable.jsx +++ b/frontend/components/queries/QueryResultsTable/QueryResultsTable.jsx @@ -1,12 +1,13 @@ import React, { Component } from 'react'; import classnames from 'classnames'; -import { get, keys, omit, values } from 'lodash'; +import { get, keys, omit } from 'lodash'; import campaignInterface from 'interfaces/campaign'; import filterArrayByHash from 'utilities/filter_array_by_hash'; import Icon from 'components/icons/Icon'; import InputField from 'components/forms/fields/InputField'; import ProgressBar from 'components/loaders/ProgressBar'; +import QueryResultsRow from 'components/queries/QueryResultsTable/QueryResultsRow'; const baseClass = 'query-results-table'; @@ -104,17 +105,13 @@ class QueryResultsTable extends Component { const { resultsFilter } = this.state; const filteredQueryResults = filterArrayByHash(queryResults, resultsFilter); - return filteredQueryResults.map((row, index) => { - const queryAttrs = omit(row, ['hostname']); - const queryResult = values(queryAttrs); - + return filteredQueryResults.map((queryResult, index) => { return ( - - {row.hostname} - {queryResult.map((attribute, i) => { - return {attribute}; - })} - + ); }); } diff --git a/frontend/interfaces/query_result.js b/frontend/interfaces/query_result.js new file mode 100644 index 0000000000..459477d1e5 --- /dev/null +++ b/frontend/interfaces/query_result.js @@ -0,0 +1,29 @@ +import { PropTypes } from 'react'; + +export default PropTypes.shape({ + cmdline: PropTypes.string, + cwd: PropTypes.string, + egid: PropTypes.string, + euid: PropTypes.string, + gid: PropTypes.string, + hostname: PropTypes.string, + name: PropTypes.string, + nice: PropTypes.string, + on_disk: PropTypes.string, + parent: PropTypes.string, + path: PropTypes.string, + pgroup: PropTypes.string, + pid: PropTypes.string, + resident_size: PropTypes.string, + root: PropTypes.string, + sgid: PropTypes.string, + start_time: PropTypes.string, + state: PropTypes.string, + suid: PropTypes.string, + system_time: PropTypes.string, + threads: PropTypes.string, + total_size: PropTypes.string, + uid: PropTypes.string, + user_time: PropTypes.string, + wired_size: PropTypes.string, +});