зеркало из https://github.com/mozilla/treeherder.git
when viewing specific failure in IFV details, update graph (#7519)
This commit is contained in:
Родитель
4083943628
Коммит
94718b8448
|
@ -74,7 +74,7 @@ class IntermittentFailuresApp extends React.Component {
|
||||||
render={(props) => <BugDetailsView {...props} />}
|
render={(props) => <BugDetailsView {...props} />}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route
|
||||||
path={`${path}/bugdetails?startday=:startday&endday=:endday&tree=:tree&bug=bug`}
|
path={`${path}/bugdetails?startday=:startday&endday=:endday&tree=:tree&failurehash=:failurehash&bug=bug`}
|
||||||
render={(props) => <BugDetailsView {...props} />}
|
render={(props) => <BugDetailsView {...props} />}
|
||||||
/>
|
/>
|
||||||
<Redirect from={`${path}/`} to={`${path}/main`} />
|
<Redirect from={`${path}/`} to={`${path}/main`} />
|
||||||
|
|
|
@ -29,7 +29,9 @@ const BugDetailsView = (props) => {
|
||||||
initialParamsSet,
|
initialParamsSet,
|
||||||
startday,
|
startday,
|
||||||
endday,
|
endday,
|
||||||
|
failurehash,
|
||||||
updateState,
|
updateState,
|
||||||
|
updateHash,
|
||||||
bug,
|
bug,
|
||||||
summary,
|
summary,
|
||||||
errorMessages,
|
errorMessages,
|
||||||
|
@ -37,19 +39,24 @@ const BugDetailsView = (props) => {
|
||||||
tableFailureStatus,
|
tableFailureStatus,
|
||||||
graphFailureStatus,
|
graphFailureStatus,
|
||||||
uniqueLines,
|
uniqueLines,
|
||||||
|
uniqueFrequency,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const customFilter = ({ filter, onChange }) => {
|
const customFilter = ({ filter }) => {
|
||||||
if (!tableData || !uniqueLines) return;
|
if (!tableData || !uniqueLines) return;
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
onChange={(event) => onChange(event.target.value)}
|
onChange={(event) => updateHash(event.target.value)}
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
value={filter ? filter.value : 'all'}
|
value={filter ? filter.value : failurehash}
|
||||||
>
|
>
|
||||||
<option value="all">All</option>
|
<option value="all">All</option>
|
||||||
{uniqueLines.map((vals) => {
|
{uniqueLines.map((vals) => {
|
||||||
return <option value={vals[1]}>{vals[0]}</option>;
|
return (
|
||||||
|
<option key={vals[1]} value={vals[1]}>
|
||||||
|
{vals[0]}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</select>
|
</select>
|
||||||
);
|
);
|
||||||
|
@ -127,20 +134,6 @@ const BugDetailsView = (props) => {
|
||||||
{
|
{
|
||||||
Header: 'Log',
|
Header: 'Log',
|
||||||
accessor: 'job_id',
|
accessor: 'job_id',
|
||||||
filterMethod: (filter, row) => {
|
|
||||||
if (filter.value === 'all') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const trimmed = lineTrimmer(row._original.lines);
|
|
||||||
let filterValue = '';
|
|
||||||
const hashIndex = 1;
|
|
||||||
uniqueLines.forEach((uniqueLine) => {
|
|
||||||
if (trimmed === uniqueLine[0]) {
|
|
||||||
filterValue = uniqueLine[hashIndex];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return filterValue === filter.value;
|
|
||||||
},
|
|
||||||
Filter: ({ filter, onChange }) => customFilter({ filter, onChange }),
|
Filter: ({ filter, onChange }) => customFilter({ filter, onChange }),
|
||||||
Cell: (_props) => {
|
Cell: (_props) => {
|
||||||
const { value, original } = _props;
|
const { value, original } = _props;
|
||||||
|
@ -188,17 +181,45 @@ const BugDetailsView = (props) => {
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let gOneData = {};
|
||||||
let graphOneData = null;
|
let graphOneData = null;
|
||||||
let graphTwoData = null;
|
let graphTwoData = null;
|
||||||
|
let _tableData = null;
|
||||||
|
|
||||||
if (graphData.length > 0) {
|
if (graphData.length > 0) {
|
||||||
({ graphOneData, graphTwoData } = calculateMetrics(graphData));
|
({ graphOneData, graphTwoData } = calculateMetrics(graphData));
|
||||||
|
if (uniqueFrequency) {
|
||||||
|
gOneData = uniqueFrequency;
|
||||||
|
}
|
||||||
|
gOneData.all = graphOneData;
|
||||||
|
gOneData.all[0].count = tableData.length;
|
||||||
|
|
||||||
|
_tableData = tableData;
|
||||||
|
// here we Filter() the tableData.
|
||||||
|
// Since we use urlParams for failurehash, this synchronizes it.
|
||||||
|
if (failurehash !== 'all') {
|
||||||
|
const tData = [];
|
||||||
|
tableData.forEach((row) => {
|
||||||
|
const trimmed = lineTrimmer(row.lines);
|
||||||
|
let filterValue = '';
|
||||||
|
const hashIndex = 1;
|
||||||
|
uniqueLines.forEach((uniqueLine) => {
|
||||||
|
if (trimmed === uniqueLine[0]) {
|
||||||
|
filterValue = uniqueLine[hashIndex];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (filterValue === failurehash) {
|
||||||
|
tData.push(row);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_tableData = tData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout
|
<Layout
|
||||||
{...props}
|
{...props}
|
||||||
graphOneData={graphOneData}
|
graphOneData={gOneData}
|
||||||
graphTwoData={graphTwoData}
|
graphTwoData={graphTwoData}
|
||||||
header={
|
header={
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
|
@ -261,7 +282,10 @@ const BugDetailsView = (props) => {
|
||||||
<Row>
|
<Row>
|
||||||
<Col xs="12" className="mx-auto">
|
<Col xs="12" className="mx-auto">
|
||||||
<p className="text-secondary">
|
<p className="text-secondary">
|
||||||
{tableData.length} total failures
|
{failurehash in gOneData
|
||||||
|
? gOneData[failurehash][0].count
|
||||||
|
: 0}{' '}
|
||||||
|
total failures
|
||||||
</p>
|
</p>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
@ -272,9 +296,10 @@ const BugDetailsView = (props) => {
|
||||||
}
|
}
|
||||||
table={
|
table={
|
||||||
bug &&
|
bug &&
|
||||||
initialParamsSet && (
|
initialParamsSet &&
|
||||||
|
_tableData && (
|
||||||
<ReactTable
|
<ReactTable
|
||||||
data={tableData}
|
data={_tableData}
|
||||||
filterable
|
filterable
|
||||||
showPageSizeOptions
|
showPageSizeOptions
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
@ -295,18 +320,21 @@ BugDetailsView.propTypes = {
|
||||||
tree: PropTypes.string.isRequired,
|
tree: PropTypes.string.isRequired,
|
||||||
updateAppState: PropTypes.func,
|
updateAppState: PropTypes.func,
|
||||||
updateState: PropTypes.func.isRequired,
|
updateState: PropTypes.func.isRequired,
|
||||||
|
updateHash: PropTypes.func.isRequired,
|
||||||
startday: PropTypes.string.isRequired,
|
startday: PropTypes.string.isRequired,
|
||||||
|
failurehash: PropTypes.string.isRequired,
|
||||||
endday: PropTypes.string.isRequired,
|
endday: PropTypes.string.isRequired,
|
||||||
tableData: PropTypes.arrayOf(PropTypes.shape({})),
|
tableData: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
graphData: PropTypes.arrayOf(PropTypes.shape({})),
|
graphData: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
initialParamsSet: PropTypes.bool.isRequired,
|
initialParamsSet: PropTypes.bool.isRequired,
|
||||||
bug: PropTypes.number.isRequired,
|
bug: PropTypes.string.isRequired,
|
||||||
summary: PropTypes.string.isRequired,
|
summary: PropTypes.string.isRequired,
|
||||||
errorMessages: PropTypes.arrayOf(PropTypes.string),
|
errorMessages: PropTypes.arrayOf(PropTypes.string),
|
||||||
lastLocation: PropTypes.shape({}).isRequired,
|
lastLocation: PropTypes.shape({}).isRequired,
|
||||||
tableFailureStatus: PropTypes.string,
|
tableFailureStatus: PropTypes.string,
|
||||||
graphFailureStatus: PropTypes.string,
|
graphFailureStatus: PropTypes.string,
|
||||||
uniqueLines: PropTypes.arrayOf(PropTypes.array),
|
uniqueLines: PropTypes.arrayOf(PropTypes.array),
|
||||||
|
uniqueFrequency: PropTypes.shape({}),
|
||||||
};
|
};
|
||||||
|
|
||||||
BugDetailsView.defaultProps = {
|
BugDetailsView.defaultProps = {
|
||||||
|
@ -317,6 +345,7 @@ BugDetailsView.defaultProps = {
|
||||||
graphFailureStatus: null,
|
graphFailureStatus: null,
|
||||||
updateAppState: null,
|
updateAppState: null,
|
||||||
uniqueLines: [],
|
uniqueLines: [],
|
||||||
|
uniqueFrequency: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultState = {
|
const defaultState = {
|
||||||
|
|
|
@ -26,7 +26,8 @@ const Graph = ({ graphData, title, legendData }) => (
|
||||||
data={legendData}
|
data={legendData}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{graphData.length > 0 &&
|
{graphData &&
|
||||||
|
graphData.length > 0 &&
|
||||||
graphData.map((item) => (
|
graphData.map((item) => (
|
||||||
<VictoryLine
|
<VictoryLine
|
||||||
key={item}
|
key={item}
|
||||||
|
|
|
@ -25,7 +25,7 @@ export default class GraphsContainer extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { graphOneData, graphTwoData, children } = this.props;
|
const { graphOneData, graphTwoData, failurehash, children } = this.props;
|
||||||
const { showGraphTwo, showAlternateView } = this.state;
|
const { showGraphTwo, showAlternateView } = this.state;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -33,13 +33,24 @@ export default class GraphsContainer extends React.Component {
|
||||||
<Row className="pt-5">
|
<Row className="pt-5">
|
||||||
{showAlternateView ? (
|
{showAlternateView ? (
|
||||||
<GraphAlternateView
|
<GraphAlternateView
|
||||||
graphData={graphOneData}
|
graphData={graphOneData[failurehash]}
|
||||||
className="failure-per-count"
|
className="failure-per-count"
|
||||||
colNum={1}
|
colNum={1}
|
||||||
title="Failure Count Per Push"
|
title={
|
||||||
|
failurehash === 'all'
|
||||||
|
? 'Failure Count Per Push'
|
||||||
|
: 'Failure Count Per Day'
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Graph graphData={graphOneData} title="Failure Count per Push" />
|
<Graph
|
||||||
|
graphData={graphOneData[failurehash]}
|
||||||
|
title={
|
||||||
|
failurehash === 'all'
|
||||||
|
? 'Failure Count Per Push'
|
||||||
|
: 'Failure Count Per Day'
|
||||||
|
}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
|
@ -90,21 +101,19 @@ export default class GraphsContainer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
GraphsContainer.propTypes = {
|
GraphsContainer.propTypes = {
|
||||||
graphOneData: PropTypes.arrayOf(
|
graphOneData: PropTypes.shape({
|
||||||
PropTypes.shape({
|
hash: PropTypes.arrayOf(
|
||||||
data: PropTypes.arrayOf(PropTypes.shape({})),
|
PropTypes.shape({
|
||||||
color: PropTypes.string,
|
data: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
}),
|
color: PropTypes.string,
|
||||||
),
|
}),
|
||||||
|
),
|
||||||
|
}),
|
||||||
graphTwoData: PropTypes.arrayOf(
|
graphTwoData: PropTypes.arrayOf(
|
||||||
PropTypes.shape({
|
PropTypes.shape({
|
||||||
data: PropTypes.arrayOf(PropTypes.shape({})),
|
data: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
color: PropTypes.string,
|
color: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
PropTypes.shape({
|
|
||||||
data: PropTypes.arrayOf(PropTypes.shape({})),
|
|
||||||
color: PropTypes.string,
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
children: PropTypes.element.isRequired,
|
children: PropTypes.element.isRequired,
|
||||||
};
|
};
|
||||||
|
|
|
@ -21,8 +21,10 @@ const Layout = (props) => {
|
||||||
tableFailureStatus,
|
tableFailureStatus,
|
||||||
graphFailureStatus,
|
graphFailureStatus,
|
||||||
updateState,
|
updateState,
|
||||||
|
updateHash,
|
||||||
graphOneData,
|
graphOneData,
|
||||||
graphTwoData,
|
graphTwoData,
|
||||||
|
failurehash,
|
||||||
table,
|
table,
|
||||||
datePicker,
|
datePicker,
|
||||||
header,
|
header,
|
||||||
|
@ -36,7 +38,12 @@ const Layout = (props) => {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Container fluid className="my-5 max-width-default">
|
<Container fluid className="my-5 max-width-default">
|
||||||
<Navigation updateState={updateState} tree={tree} {...props} />
|
<Navigation
|
||||||
|
updateState={updateState}
|
||||||
|
updateHash={updateHash}
|
||||||
|
tree={tree}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
{(isFetchingGraphs || isFetchingTable) &&
|
{(isFetchingGraphs || isFetchingTable) &&
|
||||||
!(
|
!(
|
||||||
tableFailureStatus ||
|
tableFailureStatus ||
|
||||||
|
@ -60,6 +67,7 @@ const Layout = (props) => {
|
||||||
<GraphsContainer
|
<GraphsContainer
|
||||||
graphOneData={graphOneData}
|
graphOneData={graphOneData}
|
||||||
graphTwoData={graphTwoData}
|
graphTwoData={graphTwoData}
|
||||||
|
failurehash={failurehash}
|
||||||
>
|
>
|
||||||
{datePicker}
|
{datePicker}
|
||||||
</GraphsContainer>
|
</GraphsContainer>
|
||||||
|
@ -88,8 +96,8 @@ Layout.propTypes = {
|
||||||
datePicker: PropTypes.element.isRequired,
|
datePicker: PropTypes.element.isRequired,
|
||||||
header: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]),
|
header: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]),
|
||||||
table: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]),
|
table: PropTypes.oneOfType([PropTypes.shape({}), PropTypes.bool]),
|
||||||
graphOneData: PropTypes.arrayOf(PropTypes.shape({})),
|
|
||||||
graphTwoData: PropTypes.arrayOf(PropTypes.shape({})),
|
graphTwoData: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
|
failurehash: PropTypes.string,
|
||||||
tableData: PropTypes.arrayOf(PropTypes.shape({})),
|
tableData: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
graphData: PropTypes.oneOfType([
|
graphData: PropTypes.oneOfType([
|
||||||
PropTypes.arrayOf(PropTypes.shape({})),
|
PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
|
@ -105,7 +113,6 @@ Layout.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
Layout.defaultProps = {
|
Layout.defaultProps = {
|
||||||
graphOneData: null,
|
|
||||||
graphTwoData: null,
|
graphTwoData: null,
|
||||||
tableFailureStatus: null,
|
tableFailureStatus: null,
|
||||||
graphFailureStatus: null,
|
graphFailureStatus: null,
|
||||||
|
@ -113,6 +120,7 @@ Layout.defaultProps = {
|
||||||
isFetchingGraphs: null,
|
isFetchingGraphs: null,
|
||||||
tableData: null,
|
tableData: null,
|
||||||
graphData: null,
|
graphData: null,
|
||||||
|
failurehash: 'all',
|
||||||
tree: null,
|
tree: null,
|
||||||
table: null,
|
table: null,
|
||||||
header: null,
|
header: null,
|
||||||
|
|
|
@ -24,6 +24,7 @@ const MainView = (props) => {
|
||||||
initialParamsSet,
|
initialParamsSet,
|
||||||
startday,
|
startday,
|
||||||
endday,
|
endday,
|
||||||
|
failurehash,
|
||||||
updateState,
|
updateState,
|
||||||
tree,
|
tree,
|
||||||
location,
|
location,
|
||||||
|
@ -52,6 +53,7 @@ const MainView = (props) => {
|
||||||
tree={tree}
|
tree={tree}
|
||||||
startday={startday}
|
startday={startday}
|
||||||
endday={endday}
|
endday={endday}
|
||||||
|
failurehash={failurehash}
|
||||||
location={location}
|
location={location}
|
||||||
graphData={graphData}
|
graphData={graphData}
|
||||||
tableData={tableData}
|
tableData={tableData}
|
||||||
|
@ -103,6 +105,8 @@ const MainView = (props) => {
|
||||||
totalFailures,
|
totalFailures,
|
||||||
totalRuns,
|
totalRuns,
|
||||||
} = calculateMetrics(graphData));
|
} = calculateMetrics(graphData));
|
||||||
|
graphOneData = { all: graphOneData };
|
||||||
|
graphOneData.all[0].count = tableData.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getHeaderAriaLabel = (state, bug, data) => {
|
const getHeaderAriaLabel = (state, bug, data) => {
|
||||||
|
@ -190,6 +194,7 @@ MainView.propTypes = {
|
||||||
updateState: PropTypes.func.isRequired,
|
updateState: PropTypes.func.isRequired,
|
||||||
startday: PropTypes.string.isRequired,
|
startday: PropTypes.string.isRequired,
|
||||||
endday: PropTypes.string.isRequired,
|
endday: PropTypes.string.isRequired,
|
||||||
|
failurehash: PropTypes.string.isRequired,
|
||||||
tableData: PropTypes.arrayOf(PropTypes.shape({})),
|
tableData: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
graphData: PropTypes.arrayOf(PropTypes.shape({})),
|
graphData: PropTypes.arrayOf(PropTypes.shape({})),
|
||||||
initialParamsSet: PropTypes.bool.isRequired,
|
initialParamsSet: PropTypes.bool.isRequired,
|
||||||
|
@ -206,6 +211,7 @@ const defaultState = {
|
||||||
tree: 'all',
|
tree: 'all',
|
||||||
startday: ISODate(moment().utc().subtract(7, 'days')),
|
startday: ISODate(moment().utc().subtract(7, 'days')),
|
||||||
endday: ISODate(moment().utc()),
|
endday: ISODate(moment().utc()),
|
||||||
|
failurehash: 'all',
|
||||||
endpoint: bugsEndpoint,
|
endpoint: bugsEndpoint,
|
||||||
route: '/main',
|
route: '/main',
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import moment from 'moment';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
@ -11,7 +12,7 @@ import {
|
||||||
} from '../helpers/url';
|
} from '../helpers/url';
|
||||||
import { getData } from '../helpers/http';
|
import { getData } from '../helpers/http';
|
||||||
|
|
||||||
import { validateQueryParams, mergeData, formatBugs } from './helpers';
|
import { validateQueryParams, mergeData, formatBugs, ISODate } from './helpers';
|
||||||
|
|
||||||
const withView = (defaultState) => (WrappedComponent) => {
|
const withView = (defaultState) => (WrappedComponent) => {
|
||||||
class View extends React.Component {
|
class View extends React.Component {
|
||||||
|
@ -25,6 +26,7 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
tree: this.default.tree || null,
|
tree: this.default.tree || null,
|
||||||
startday: this.default.startday || null,
|
startday: this.default.startday || null,
|
||||||
endday: this.default.endday || null,
|
endday: this.default.endday || null,
|
||||||
|
failurehash: this.default.failurehash || 'all',
|
||||||
bug: this.default.id || null,
|
bug: this.default.id || null,
|
||||||
summary: this.default.summary || null,
|
summary: this.default.summary || null,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
|
@ -43,8 +45,8 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
|
|
||||||
setQueryParams = () => {
|
setQueryParams = () => {
|
||||||
const { location, history } = this.props;
|
const { location, history } = this.props;
|
||||||
const { startday, endday, tree, bug } = this.state;
|
const { startday, endday, tree, failurehash, bug } = this.state;
|
||||||
const params = { startday, endday, tree };
|
const params = { startday, endday, tree, failurehash };
|
||||||
|
|
||||||
if (bug) {
|
if (bug) {
|
||||||
params.bug = bug;
|
params.bug = bug;
|
||||||
|
@ -84,9 +86,9 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// trim off the timestamp and "TEST-UNEXPECTED-XXX | "
|
// trim off the timestamp and "TEST-UNEXPECTED-XXX | "
|
||||||
lineTrimmer = async (failureLines) => {
|
lineTrimmer = async (failureLines, pushTime) => {
|
||||||
if (failureLines === undefined) {
|
if (failureLines === undefined) {
|
||||||
return ['', ''];
|
return ['', '', pushTime];
|
||||||
}
|
}
|
||||||
if (typeof failureLines === 'string') {
|
if (typeof failureLines === 'string') {
|
||||||
failureLines = failureLines.split('\n');
|
failureLines = failureLines.split('\n');
|
||||||
|
@ -102,22 +104,68 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
});
|
});
|
||||||
const rv = trimmedLines.join('\n');
|
const rv = trimmedLines.join('\n');
|
||||||
return this.hashMessage(rv).then((hash) => {
|
return this.hashMessage(rv).then((hash) => {
|
||||||
return [rv, hash];
|
return [rv, hash, pushTime];
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
getUniqueLines = async (tableData) => {
|
getUniqueLines = async (tableData) => {
|
||||||
|
const { startday, endday } = this.state;
|
||||||
|
|
||||||
const uniqueLogKeys = [];
|
const uniqueLogKeys = [];
|
||||||
const uniqueLogHashes = [];
|
const uniqueLogHashes = [];
|
||||||
|
const uniqueFrequency = {};
|
||||||
|
|
||||||
const results = tableData.map((td) => this.lineTrimmer(td.lines));
|
const results = tableData.map((td) =>
|
||||||
|
this.lineTrimmer(td.lines, td.push_time),
|
||||||
|
);
|
||||||
for (const result of await Promise.all(results)) {
|
for (const result of await Promise.all(results)) {
|
||||||
if (uniqueLogKeys.indexOf(result[1]) === -1) {
|
const hash = result[1];
|
||||||
uniqueLogKeys.push(result[1]);
|
if (hash === '') {
|
||||||
uniqueLogHashes.push(result);
|
continue;
|
||||||
}
|
}
|
||||||
|
if (uniqueLogKeys.indexOf(hash) === -1) {
|
||||||
|
uniqueLogKeys.push(hash);
|
||||||
|
uniqueLogHashes.push([result[0], hash]);
|
||||||
|
|
||||||
|
uniqueFrequency[hash] = [
|
||||||
|
{ data: [], color: 'red', dates: {}, datemap: {}, count: 0 },
|
||||||
|
];
|
||||||
|
let start = ISODate(moment(startday).utc());
|
||||||
|
const end = ISODate(moment(endday).utc());
|
||||||
|
// create entry for each date in range so graph looks nice.
|
||||||
|
while (start <= end) {
|
||||||
|
const sdate = moment(start).format('MMM DD');
|
||||||
|
uniqueFrequency[hash][0].dates[sdate] = 0;
|
||||||
|
uniqueFrequency[hash][0].datemap[sdate] = start;
|
||||||
|
start = ISODate(moment(start).utc().add(1, 'days'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// store frequency data by date to use in graphs, etc.
|
||||||
|
const date = result[2].split(' ')[0];
|
||||||
|
const sdate = moment(date).format('MMM DD');
|
||||||
|
if (!(date in uniqueFrequency[hash][0].dates)) {
|
||||||
|
uniqueFrequency[hash][0].dates[sdate] = 0;
|
||||||
|
}
|
||||||
|
uniqueFrequency[hash][0].dates[sdate] += 1;
|
||||||
|
uniqueFrequency[hash][0].count += 1;
|
||||||
}
|
}
|
||||||
return uniqueLogHashes;
|
|
||||||
|
// convert data to a graph friendly format
|
||||||
|
uniqueLogKeys.forEach((hval) => {
|
||||||
|
const dates = Object.keys(uniqueFrequency[hval][0].dates);
|
||||||
|
dates.sort();
|
||||||
|
dates.forEach((date) => {
|
||||||
|
const counter = uniqueFrequency[hval][0].dates[date];
|
||||||
|
uniqueFrequency[hval][0].data.push({
|
||||||
|
date,
|
||||||
|
failurePerPush: counter,
|
||||||
|
x: uniqueFrequency[hval][0].datemap[date],
|
||||||
|
y: counter,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return [uniqueLogHashes, uniqueFrequency];
|
||||||
};
|
};
|
||||||
|
|
||||||
getTableData = async (url) => {
|
getTableData = async (url) => {
|
||||||
|
@ -137,7 +185,8 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
tableData: mergedData || data,
|
tableData: mergedData || data,
|
||||||
tableFailureStatus: failureStatus,
|
tableFailureStatus: failureStatus,
|
||||||
isFetchingTable: false,
|
isFetchingTable: false,
|
||||||
uniqueLines,
|
uniqueLines: uniqueLines[0],
|
||||||
|
uniqueFrequency: uniqueLines[1],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -179,8 +228,8 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
|
|
||||||
updateState = (updatedObj) => {
|
updateState = (updatedObj) => {
|
||||||
this.setState(updatedObj, () => {
|
this.setState(updatedObj, () => {
|
||||||
const { startday, endday, tree, bug } = this.state;
|
const { startday, endday, tree, failurehash, bug } = this.state;
|
||||||
const params = { startday, endday, tree };
|
const params = { startday, endday, tree, failurehash };
|
||||||
|
|
||||||
if (bug) {
|
if (bug) {
|
||||||
params.bug = bug;
|
params.bug = bug;
|
||||||
|
@ -195,6 +244,21 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
updateHash = (hashVal) => {
|
||||||
|
this.setState({ failurehash: hashVal }, () => {
|
||||||
|
const { startday, endday, tree, failurehash, bug } = this.state;
|
||||||
|
const params = { startday, endday, tree, failurehash };
|
||||||
|
|
||||||
|
if (bug) {
|
||||||
|
params.bug = bug;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update query params if dates or tree are updated
|
||||||
|
const queryString = createQueryParams(params);
|
||||||
|
updateQueryParams(queryString, this.props.history, this.props.location);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
updateData = (params, urlChanged = false) => {
|
updateData = (params, urlChanged = false) => {
|
||||||
const { mainGraphData, mainTableData } = this.props;
|
const { mainGraphData, mainTableData } = this.props;
|
||||||
|
|
||||||
|
@ -241,7 +305,13 @@ const withView = (defaultState) => (WrappedComponent) => {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const updateState = { updateState: this.updateState };
|
const updateState = { updateState: this.updateState };
|
||||||
const newProps = { ...this.props, ...this.state, ...updateState };
|
const updateHash = { updateHash: this.updateHash };
|
||||||
|
const newProps = {
|
||||||
|
...this.props,
|
||||||
|
...this.state,
|
||||||
|
...updateState,
|
||||||
|
...updateHash,
|
||||||
|
};
|
||||||
return <WrappedComponent {...newProps} />;
|
return <WrappedComponent {...newProps} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче