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,
+});