More Bugzilla metadata
The Bugzilla queries are based on what the various DOM teams use: https://wiki.mozilla.org/Platform/DOM_Bug_Triage Hide details button until making use of the feature.
This commit is contained in:
Родитель
3485ae5207
Коммит
3db1e3ea78
|
@ -3,30 +3,46 @@ import PropTypes from 'prop-types';
|
|||
import { withStyles } from '@material-ui/core/styles';
|
||||
|
||||
const styles = ({
|
||||
root: {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
flex: '1',
|
||||
margin: '0 1rem 0 0',
|
||||
metric: {
|
||||
textAlign: 'center',
|
||||
},
|
||||
componentText: {
|
||||
margin: '0 1rem 0 0',
|
||||
button: {
|
||||
display: 'none',
|
||||
},
|
||||
});
|
||||
|
||||
const linkToQuery = (key, metrics, alt) => (
|
||||
<a href={metrics[key].link} alt={alt}>{metrics[key].count}</a>
|
||||
const linkToQuery = (key, metrics) => (
|
||||
<a href={metrics[key].link}>{metrics[key].count}</a>
|
||||
);
|
||||
|
||||
const BugzillaComponentSummary = ({
|
||||
classes, product, component, metrics,
|
||||
classes, product, component, metrics, onComponentDrilldown,
|
||||
}) => (
|
||||
<div className={classes.root}>
|
||||
<span className={classes.componentText}>{`${product}::${component}`}</span>
|
||||
{metrics.untriaged
|
||||
&& linkToQuery('untriaged', metrics, 'Number of untriaged bugs')
|
||||
}
|
||||
</div>
|
||||
<tr>
|
||||
<td>{`${product}::${component}`}</td>
|
||||
{Object.keys(metrics).map(metric => (
|
||||
metrics[metric] && (
|
||||
<td key={metric} className={classes.metric}>
|
||||
{linkToQuery(metric, metrics)}
|
||||
</td>
|
||||
)
|
||||
))}
|
||||
{onComponentDrilldown && (
|
||||
<td>
|
||||
<button
|
||||
className={classes.button}
|
||||
name={`${product}::${component}`}
|
||||
value={{ product, component }}
|
||||
product={product}
|
||||
component={component}
|
||||
onClick={onComponentDrilldown}
|
||||
type="button"
|
||||
>
|
||||
Details
|
||||
</button>
|
||||
</td>
|
||||
)}
|
||||
</tr>
|
||||
);
|
||||
|
||||
BugzillaComponentSummary.propTypes = {
|
||||
|
@ -34,10 +50,12 @@ BugzillaComponentSummary.propTypes = {
|
|||
product: PropTypes.string.isRequired,
|
||||
component: PropTypes.string.isRequired,
|
||||
metrics: PropTypes.shape({}),
|
||||
onComponentDrilldown: PropTypes.func,
|
||||
};
|
||||
|
||||
BugzillaComponentSummary.defaultProps = {
|
||||
metrics: {},
|
||||
onComponentDrilldown: undefined,
|
||||
};
|
||||
|
||||
export default withStyles(styles)(BugzillaComponentSummary);
|
||||
|
|
|
@ -3,10 +3,14 @@ import PropTypes from 'prop-types';
|
|||
import { withStyles } from '@material-ui/core/styles';
|
||||
import BugzillaComponentSummary from '../BugzillaComponentSummary';
|
||||
import Reportees from '../Reportees';
|
||||
import METRICS from '../../utils/bugzilla/metrics';
|
||||
|
||||
const styles = ({
|
||||
content: {
|
||||
display: 'flex',
|
||||
},
|
||||
header: {
|
||||
margin: '0.5rem 0 0.5rem 0',
|
||||
margin: '0.5rem 0 0 0',
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -22,38 +26,33 @@ const MainView = ({
|
|||
classes, ldapEmail, partialOrg, bugzillaComponents, onComponentDrilldown,
|
||||
}) => (
|
||||
<div key={ldapEmail}>
|
||||
<h3 className={classes.header}>{partialOrg[ldapEmail].cn}</h3>
|
||||
<div style={{ display: 'flex' }}>
|
||||
<h2 className={classes.header}>{partialOrg[ldapEmail].cn}</h2>
|
||||
<div className={classes.content}>
|
||||
<Reportees ldapEmail={ldapEmail} partialOrg={partialOrg} />
|
||||
{Object.values(bugzillaComponents).length > 0 && (
|
||||
<div>
|
||||
<h4 className={classes.header}>Components</h4>
|
||||
{Object.values(bugzillaComponents)
|
||||
.sort(sortByComponentName)
|
||||
.map(({ component, product, metrics }) => (
|
||||
<div
|
||||
key={`${product}::${component}`}
|
||||
style={{ display: 'flex', justifyContent: 'space-between' }}
|
||||
>
|
||||
<h3 className={classes.header}>Components</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
{Object.values(METRICS).map(({ label }) => <th key={label}>{label}</th>)}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{Object.values(bugzillaComponents)
|
||||
.sort(sortByComponentName)
|
||||
.map(({ component, product, metrics }) => (
|
||||
<BugzillaComponentSummary
|
||||
key={`${product}::${component}`}
|
||||
product={product}
|
||||
component={component}
|
||||
metrics={metrics}
|
||||
onComponentDrilldown={onComponentDrilldown}
|
||||
/>
|
||||
{onComponentDrilldown && (
|
||||
<button
|
||||
name={`${product}::${component}`}
|
||||
value={{ product, component }}
|
||||
product={product}
|
||||
component={component}
|
||||
onClick={onComponentDrilldown}
|
||||
type="button"
|
||||
>
|
||||
Details
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -3,6 +3,9 @@ import PropTypes from 'prop-types';
|
|||
import { withStyles } from '@material-ui/core/styles';
|
||||
|
||||
const styles = ({
|
||||
root: {
|
||||
margin: '0 0.5rem 0 0',
|
||||
},
|
||||
header: {
|
||||
margin: '0.5rem 0 0.5rem 0',
|
||||
},
|
||||
|
@ -11,7 +14,7 @@ const styles = ({
|
|||
const sortByPersonName = (a, b) => (a.cn <= b.cn ? -1 : 1);
|
||||
|
||||
const Reportees = ({ classes, ldapEmail, partialOrg }) => (
|
||||
<div>
|
||||
<div className={classes.root}>
|
||||
<h4 className={classes.header}>Reportees</h4>
|
||||
{Object.values(partialOrg)
|
||||
.filter(({ cn }) => cn !== ldapEmail)
|
||||
|
|
|
@ -5,6 +5,7 @@ import BugzillaComponentDetails from '../../components/BugzillaComponentDetails'
|
|||
import getAllReportees from '../../utils/getAllReportees';
|
||||
import getBugzillaOwners from '../../utils/getBugzillaOwners';
|
||||
import getBugsCountAndLink from '../../utils/bugzilla/getBugsCountAndLink';
|
||||
import METRICS from '../../utils/bugzilla/metrics';
|
||||
|
||||
class MainContainer extends Component {
|
||||
state = {
|
||||
|
@ -74,14 +75,10 @@ class MainContainer extends Component {
|
|||
// Let's fetch the metrics for each component
|
||||
Object.values(bugzillaComponents)
|
||||
.map(async ({ product, component }) => {
|
||||
const metric = 'untriaged';
|
||||
const { count, link } = await getBugsCountAndLink(product, component, metric);
|
||||
bugzillaComponents[`${product}::${component}`].metrics = {
|
||||
[metric]: {
|
||||
count,
|
||||
link,
|
||||
},
|
||||
};
|
||||
const { metrics } = bugzillaComponents[`${product}::${component}`];
|
||||
await Promise.all(Object.keys(METRICS).map(async (metric) => {
|
||||
metrics[metric] = await getBugsCountAndLink(product, component, metric);
|
||||
}));
|
||||
this.setState({ bugzillaComponents });
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
import { stringify } from 'query-string';
|
||||
import fetchJson from '../fetchJson';
|
||||
import settings from './settings';
|
||||
import queryBugzilla from './queryBugzilla';
|
||||
import METRICS from './metrics';
|
||||
|
||||
const queryBugzilla = async queryParameters => (
|
||||
fetchJson(`${settings.BZ_HOST}/rest/bug?${queryParameters}`));
|
||||
|
||||
const getBugzillaComponentLink = queryParameters => (
|
||||
`${settings.BZ_HOST}/buglist.cgi?${stringify(queryParameters)}`);
|
||||
|
||||
|
@ -14,11 +11,11 @@ const getBugsCountAndLink = async (product, component, metric) => {
|
|||
const baseParams = {
|
||||
product,
|
||||
component,
|
||||
...METRICS[metric],
|
||||
...METRICS[metric].parameters,
|
||||
};
|
||||
const link = getBugzillaComponentLink(baseParams);
|
||||
const { bug_count = 0 } = await queryBugzilla(
|
||||
stringify({ ...baseParams, count_only: 1 }),
|
||||
{ ...baseParams, count_only: 1 },
|
||||
);
|
||||
return { count: bug_count, link };
|
||||
};
|
||||
|
|
|
@ -3,10 +3,30 @@
|
|||
/* eslint-disable no-multi-spaces */
|
||||
const METRICS = {
|
||||
untriaged: {
|
||||
f1: 'bug_severity', o1: 'notequals', v1: 'enhancement',
|
||||
f2: 'keywords', o2: 'notsubstring', v2: 'meta',
|
||||
f3: 'resolution', o3: 'isempty',
|
||||
limit: 0,
|
||||
label: 'Untriaged',
|
||||
parameters: {
|
||||
chfield: '[Bug creation]', chfieldfrom: '2018-06-01', chfieldto: 'Now',
|
||||
priority: '--',
|
||||
resolution: '---',
|
||||
f1: 'flagtypes.name', o1: 'notsubstring', v1: 'needinfo',
|
||||
},
|
||||
},
|
||||
needinfo: {
|
||||
label: 'Needinfo',
|
||||
parameters: {
|
||||
chfield: '[Bug creation]', chfieldfrom: '2018-06-01', chfieldto: 'Now',
|
||||
priority: '--',
|
||||
resolution: '---',
|
||||
f1: 'flagtypes.name', o1: 'substring', v1: 'needinfo',
|
||||
},
|
||||
},
|
||||
P1: {
|
||||
label: 'P1s',
|
||||
parameters: {
|
||||
chfield: '[Bug creation]', chfieldfrom: '2018-06-01', chfieldto: 'Now',
|
||||
priority: 'P1',
|
||||
resolution: '---',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import { stringify } from 'query-string';
|
||||
import fetchJson from '../fetchJson';
|
||||
import settings from './settings';
|
||||
|
||||
const TRANSFORM_FIELD = {
|
||||
chfieldfrom: 'creation_time',
|
||||
};
|
||||
|
||||
const advancedSearchToRestApi = parameters => (
|
||||
Object.keys(parameters).reduce((result, key) => {
|
||||
const newResult = Object.assign({}, result);
|
||||
const newKey = TRANSFORM_FIELD[key] || key;
|
||||
newResult[newKey] = parameters[key];
|
||||
return newResult;
|
||||
}, {})
|
||||
);
|
||||
|
||||
const generateBugzillaRestApiUrl = (queryParameters) => {
|
||||
const transformedParameters = advancedSearchToRestApi(queryParameters);
|
||||
const query = stringify({ ...transformedParameters });
|
||||
return `${settings.BZ_HOST}/rest/bug?${query}`;
|
||||
};
|
||||
|
||||
const queryBugzilla = async queryParameters => (
|
||||
fetchJson(generateBugzillaRestApiUrl(queryParameters)));
|
||||
|
||||
export default queryBugzilla;
|
|
@ -1,11 +0,0 @@
|
|||
/* eslint-disable indent */
|
||||
/* eslint-disable object-property-newline */
|
||||
/* eslint-disable no-multi-spaces */
|
||||
const untriagedParameters = () => ({
|
||||
f1: 'bug_severity', o1: 'notequals', v1: 'enhancement',
|
||||
f2: 'keywords', o2: 'notsubstring', v2: 'meta',
|
||||
f3: 'resolution', o3: 'isempty',
|
||||
limit: 0,
|
||||
});
|
||||
|
||||
export default untriagedParameters;
|
|
@ -2,21 +2,19 @@
|
|||
|
||||
exports[`renders Manager who has reportees 1`] = `
|
||||
<div>
|
||||
<h3
|
||||
className="MainView-header-1"
|
||||
<h2
|
||||
className="MainView-header-2"
|
||||
>
|
||||
Manager
|
||||
</h3>
|
||||
</h2>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
}
|
||||
}
|
||||
className="MainView-content-1"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className="Reportees-root-3"
|
||||
>
|
||||
<h4
|
||||
className="Reportees-header-2"
|
||||
className="Reportees-header-4"
|
||||
>
|
||||
Reportees
|
||||
</h4>
|
||||
|
@ -32,89 +30,58 @@ exports[`renders Manager who has reportees 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4
|
||||
className="MainView-header-1"
|
||||
<h3
|
||||
className="MainView-header-2"
|
||||
>
|
||||
Components
|
||||
</h4>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Core::DOM: Core & HTML
|
||||
</span>
|
||||
<a
|
||||
alt="Number of untriaged bugs"
|
||||
href="https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta"
|
||||
>
|
||||
944
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Core::DOM: IndexedDB
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Core::JavaScript Engine
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Toolkit::Async Tooling
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<th>
|
||||
Untriaged
|
||||
</th>
|
||||
<th>
|
||||
Needinfo
|
||||
</th>
|
||||
<th>
|
||||
P1s
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Core::DOM: Core & HTML
|
||||
</td>
|
||||
<td
|
||||
className="BugzillaComponentSummary-metric-5"
|
||||
>
|
||||
<a
|
||||
href="https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta"
|
||||
>
|
||||
944
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Core::DOM: IndexedDB
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Core::JavaScript Engine
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Toolkit::Async Tooling
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -122,21 +89,19 @@ exports[`renders Manager who has reportees 1`] = `
|
|||
|
||||
exports[`renders Someone with no reportees 1`] = `
|
||||
<div>
|
||||
<h3
|
||||
className="MainView-header-1"
|
||||
<h2
|
||||
className="MainView-header-2"
|
||||
>
|
||||
Someone
|
||||
</h3>
|
||||
</h2>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
}
|
||||
}
|
||||
className="MainView-content-1"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className="Reportees-root-3"
|
||||
>
|
||||
<h4
|
||||
className="Reportees-header-2"
|
||||
className="Reportees-header-4"
|
||||
>
|
||||
Reportees
|
||||
</h4>
|
||||
|
@ -152,89 +117,58 @@ exports[`renders Someone with no reportees 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h4
|
||||
className="MainView-header-1"
|
||||
<h3
|
||||
className="MainView-header-2"
|
||||
>
|
||||
Components
|
||||
</h4>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Core::DOM: Core & HTML
|
||||
</span>
|
||||
<a
|
||||
alt="Number of untriaged bugs"
|
||||
href="https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta"
|
||||
>
|
||||
944
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Core::DOM: IndexedDB
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Core::JavaScript Engine
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"display": "flex",
|
||||
"justifyContent": "space-between",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="BugzillaComponentSummary-root-3"
|
||||
>
|
||||
<span
|
||||
className="BugzillaComponentSummary-componentText-4"
|
||||
>
|
||||
Toolkit::Async Tooling
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th />
|
||||
<th>
|
||||
Untriaged
|
||||
</th>
|
||||
<th>
|
||||
Needinfo
|
||||
</th>
|
||||
<th>
|
||||
P1s
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
Core::DOM: Core & HTML
|
||||
</td>
|
||||
<td
|
||||
className="BugzillaComponentSummary-metric-5"
|
||||
>
|
||||
<a
|
||||
href="https://bugzilla.mozilla.org/buglist.cgi?component=DOM%3A%20Core%20%26%20HTML&f1=bug_severity&f2=keywords&f3=resolution&limit=0&o1=notequals&o2=notsubstring&o3=isempty&product=Core&v1=enhancement&v2=meta"
|
||||
>
|
||||
944
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Core::DOM: IndexedDB
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Core::JavaScript Engine
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Toolkit::Async Tooling
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Загрузка…
Ссылка в новой задаче