зеркало из https://github.com/mozilla/treeherder.git
191 строка
6.2 KiB
JavaScript
191 строка
6.2 KiB
JavaScript
import React from 'react';
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { updateQueryParams, validateQueryParams, getData, mergeData, formatBugs } from './helpers';
|
|
import { graphsEndpoint, parseQueryParams, createQueryParams, createApiUrl,
|
|
bugzillaBugsApi } from '../helpers/url';
|
|
|
|
const withView = defaultState => WrappedComponent =>
|
|
class View extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.updateData = this.updateData.bind(this);
|
|
this.setQueryParams = this.setQueryParams.bind(this);
|
|
this.checkQueryValidation = this.checkQueryValidation.bind(this);
|
|
this.getTableData = this.getTableData.bind(this);
|
|
this.getGraphData = this.getGraphData.bind(this);
|
|
this.updateState = this.updateState.bind(this);
|
|
this.getBugDetails = this.getBugDetails.bind(this);
|
|
|
|
this.default = (this.props.location.state || defaultState);
|
|
this.state = {
|
|
errorMessages: [],
|
|
initialParamsSet: false,
|
|
tree: (this.default.tree || null),
|
|
startday: (this.default.startday || null),
|
|
endday: (this.default.endday || null),
|
|
bug: (this.default.id || null),
|
|
summary: (this.default.summary || null),
|
|
tableData: {},
|
|
tableFailureStatus: null,
|
|
isFetchingTable: false,
|
|
graphData: [],
|
|
graphFailureStatus: null,
|
|
isFetchingGraphs: false,
|
|
page: 0,
|
|
pageSize: 20,
|
|
lastLocation: (this.default.location || null),
|
|
};
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.setQueryParams();
|
|
}
|
|
|
|
componentDidUpdate(prevProps) {
|
|
const { location } = this.props;
|
|
// update all data if the user edits dates, tree or bug via the query params
|
|
if (prevProps.location.search !== location.search) {
|
|
this.checkQueryValidation(parseQueryParams(location.search), this.state.initialParamsSet);
|
|
}
|
|
}
|
|
|
|
setQueryParams() {
|
|
const { location, history } = this.props;
|
|
const { startday, endday, tree, bug } = this.state;
|
|
const params = { startday, endday, tree };
|
|
|
|
if (bug) {
|
|
params.bug = bug;
|
|
}
|
|
|
|
if (location.search !== '' && !location.state) {
|
|
// update data based on the params or show error if params are missing
|
|
this.checkQueryValidation(parseQueryParams(location.search));
|
|
} else {
|
|
// if the query params are not specified for mainview, set params based on default state
|
|
if (location.search === '') {
|
|
const queryString = createQueryParams(params);
|
|
updateQueryParams(defaultState.route, queryString, history, location);
|
|
}
|
|
|
|
this.setState({ initialParamsSet: true });
|
|
this.getGraphData(createApiUrl(graphsEndpoint, params));
|
|
}
|
|
}
|
|
|
|
async getBugDetails(url) {
|
|
const { data, failureStatus } = await getData(url);
|
|
if (!failureStatus && data.bugs.length === 1) {
|
|
this.setState({ summary: data.bugs[0].summary });
|
|
}
|
|
}
|
|
|
|
async getTableData(url) {
|
|
this.setState({ tableFailureStatus: null, isFetchingTable: true });
|
|
const { data, failureStatus } = await getData(url);
|
|
|
|
if (defaultState.route === '/main' && !failureStatus && data.results.length) {
|
|
const bugs_list = formatBugs(data.results);
|
|
const bugzillaUrl = bugzillaBugsApi('bug', {
|
|
include_fields: 'id,status,summary,whiteboard',
|
|
id: bugs_list,
|
|
});
|
|
const bugzillaData = await getData(bugzillaUrl);
|
|
const results = mergeData(data.results, bugzillaData.data.bugs);
|
|
data.results = results;
|
|
}
|
|
|
|
this.setState({ tableData: data, tableFailureStatus: failureStatus, isFetchingTable: false });
|
|
}
|
|
|
|
async getGraphData(url) {
|
|
this.setState({ graphFailureStatus: null, isFetchingGraphs: true });
|
|
const { data, failureStatus } = await getData(url);
|
|
this.setState({ graphData: data, graphFailureStatus: failureStatus, isFetchingGraphs: false });
|
|
}
|
|
|
|
updateState(updatedObj, updateTable = false) {
|
|
this.setState(updatedObj, () => {
|
|
const { startday, endday, tree, page, pageSize, bug } = this.state;
|
|
const params = { startday, endday, tree, page, page_size: pageSize };
|
|
|
|
if (bug) {
|
|
params.bug = bug;
|
|
}
|
|
|
|
if (!updateTable) {
|
|
this.getGraphData(createApiUrl(graphsEndpoint, params));
|
|
}
|
|
this.getTableData(createApiUrl(defaultState.endpoint, params));
|
|
|
|
// update query params if dates or tree are updated
|
|
const queryString = createQueryParams(params);
|
|
updateQueryParams(defaultState.route, queryString, this.props.history, this.props.location);
|
|
});
|
|
}
|
|
|
|
updateData(params, urlChanged = false) {
|
|
const { mainGraphData } = this.props;
|
|
|
|
if (mainGraphData && !urlChanged) {
|
|
this.setState({ graphData: mainGraphData });
|
|
} else {
|
|
this.getGraphData(createApiUrl(graphsEndpoint, params));
|
|
}
|
|
|
|
// the table library fetches data directly when its component mounts and in response
|
|
// to a user selecting pagesize or page; this condition will prevent duplicate requests
|
|
// when this component mounts and when the table mounts.
|
|
if (urlChanged) {
|
|
this.getTableData(createApiUrl(defaultState.endpoint, params));
|
|
}
|
|
|
|
if (params.bug && Object.keys(this.state.tableData).length) {
|
|
this.getBugDetails(bugzillaBugsApi('bug', { include_fields: 'summary', id: params.bug }));
|
|
}
|
|
}
|
|
|
|
checkQueryValidation(params, urlChanged = false) {
|
|
const { errorMessages, initialParamsSet, summary } = this.state;
|
|
const messages = validateQueryParams(params, defaultState.route === '/bugdetails');
|
|
const updates = {};
|
|
|
|
if (messages.length > 0) {
|
|
this.setState({ errorMessages: messages });
|
|
} else {
|
|
if (errorMessages.length) {
|
|
updates.errorMessages = [];
|
|
}
|
|
if (!initialParamsSet) {
|
|
updates.initialParamsSet = true;
|
|
}
|
|
if (summary) {
|
|
// reset summary
|
|
updates.summary = null;
|
|
}
|
|
|
|
this.setState({ ...updates, ...params });
|
|
this.updateData(params, urlChanged);
|
|
}
|
|
}
|
|
|
|
render() {
|
|
const updateState = { updateState: this.updateState };
|
|
const newProps = { ...this.props, ...this.state, ...updateState };
|
|
return (
|
|
<WrappedComponent {...newProps} />
|
|
);
|
|
}
|
|
};
|
|
|
|
withView.propTypes = {
|
|
history: PropTypes.shape({}).isRequired,
|
|
location: PropTypes.shape({
|
|
search: PropTypes.string,
|
|
}).isRequired,
|
|
};
|
|
|
|
export default withView;
|