Issue #26 - Teams tab to show teams in your reporting chain

This commit is contained in:
Armen Zambrano G 2019-04-12 14:10:26 -04:00 коммит произвёл Armen Zambrano
Родитель 90c81d3229
Коммит 0f5c513170
7 изменённых файлов: 112 добавлений и 55 удалений

Просмотреть файл

@ -2,10 +2,40 @@
This is a Bugzilla dashboard that helps management determine Bugzilla components triaging status plus listing members of their reporting chain.
Only LDAP users are allowed to use this app.
Only LDAP users are allowed to use this app. You can do development locally without an LDAP account, however, the app will only
have fake org data. See the [Contribute](#contribute) section.
You can see the deployment in [here](http://bugzilla-management-dashboard.netlify.com/).
## Adding more teams
A team is a collection of components that can span various products and it is shown under the Teams tab.
You can add new teams and make them show in the Teams tab by making changes to the [config](https://github.com/mozilla/bugzilla-dashboard/blob/master/src/config.js) file.
To add a team you need to modify `TEAMS_CONFIG` and an entry similar to this:
```javascript
export const TEAMS_CONFIG = {
domCore: {
label: 'DOM Core',
owner: 'someone@mozilla.com',
product: ['Core'],
component: [
'DOM: Core & HTML', 'DOM: Events',
'Editor', 'HTML: Parser', 'Selection', 'Serializers',
'User events and focus handling',
],
},
```
Here's how to configure it:
* `product` and `component` are parameters passed to the Bugzilla queries.
* `owner` should match someone reporting to you.
* Use their Bugzilla email rather than their LDAP
* If the person does is not someone showing up on your Reportees tab it won't work
* `label` is the name of the team
## Generate data
Until we have a backend, we need to regenerate certain files to bring the app up-to-date.

Просмотреть файл

@ -16,7 +16,7 @@ const styles = ({
},
});
const sortByComponentName = (a, b) => a.label - b.label;
const sortByComponentName = (a, b) => a.label.localeCompare(b.label);
const BugzillaComponents = ({
classes, title, bugzillaComponents, onComponentDetails,

Просмотреть файл

@ -21,7 +21,7 @@ const styles = ({
},
});
const sortByPersonName = (a, b) => (a.cn <= b.cn ? -1 : 1);
const sortByPersonName = (a, b) => a.cn.localeCompare(b.cn);
const Reportees = ({
classes, ldapEmail, partialOrg, onPersonDetails,

Просмотреть файл

@ -18,7 +18,7 @@ const config = {
export const TEAMS_CONFIG = {
domCore: {
label: 'DOM Core',
owner: 'someone@mozilla.com',
owner: 'htsai@mozilla.com',
product: ['Core'],
component: [
'DOM: Core & HTML', 'DOM: Events',
@ -28,7 +28,7 @@ export const TEAMS_CONFIG = {
},
domFission: {
label: 'DOM Fission',
owner: 'manager@mozilla.com',
owner: 'nkochar@mozilla.com',
product: ['Core', 'Toolkit'],
component: [
'Document Navigation', 'XBL', 'XML', 'XPConnect', 'XSLT',
@ -36,7 +36,7 @@ export const TEAMS_CONFIG = {
},
workerStoreage: {
label: 'Worker and Storage',
owner: 'manager@mozilla.com',
owner: 'aoverholt@mozilla.com',
product: ['Core', 'Toolkit'],
component: [
'DOM: IndexedDB', 'DOM: Push Notifications', 'DOM: Quota Manager',

Просмотреть файл

@ -1,6 +1,7 @@
import React, { Component, Suspense } from 'react';
import { Switch } from 'react-router-dom';
import { withStyles } from '@material-ui/core/styles';
import Spinner from '@mozilla-frontend-infra/components/Spinner';
import PropsRoute from '../../components/PropsRoute';
import AuthContext from '../../components/auth/AuthContext';
import Header from '../../components/Header';
@ -13,8 +14,10 @@ const BugzillaComponents = React.lazy(() => import('../../components/BugzillaCom
const BugzillaComponentDetails = React.lazy(() => import('../../components/BugzillaComponentDetails'));
const PersonDetails = React.lazy(() => import('../../components/PersonDetails'));
const Reportees = React.lazy(() => import('../../components/Reportees'));
const Teams = React.lazy(() => import('../Teams'));
const DEFAULT_STATE = {
doneLoading: false,
bugzillaComponents: {},
partialOrg: undefined,
teamComponents: {},
@ -147,26 +150,27 @@ class MainContainer extends Component {
getBugzillaOwners(),
this.getReportees(userSession, ldapEmail),
]);
this.teamsData();
this.teamsData(partialOrg);
this.bugzillaComponents(bzOwners, partialOrg);
this.setState({ doneLoading: true });
}
async teamsData() {
const teamComponents = Object.assign({}, TEAMS_CONFIG);
// This will cause the teams to be displayed before having any metrics
this.setState({ teamComponents });
Object.entries(teamComponents).map(async ([teamKey, teamInfo]) => {
const team = {
teamKey,
...teamInfo,
metrics: {},
};
const { product, component } = teamInfo;
await Promise.all(Object.keys(BZ_QUERIES).map(async (metric) => {
team.metrics[metric] = await getBugsCountAndLink(product, component, metric);
}));
teamComponents[teamKey] = team;
this.setState({ teamComponents });
async teamsData(partialOrg) {
const teamComponents = {};
Object.entries(TEAMS_CONFIG).map(async ([teamKey, teamInfo]) => {
if (partialOrg[teamInfo.owner]) {
const team = {
teamKey,
...teamInfo,
metrics: {},
};
const { product, component } = teamInfo;
await Promise.all(Object.keys(BZ_QUERIES).map(async (metric) => {
team.metrics[metric] = await getBugsCountAndLink(product, component, metric);
}));
teamComponents[teamKey] = team;
this.setState({ teamComponents });
}
});
}
@ -211,6 +215,7 @@ class MainContainer extends Component {
render() {
const {
doneLoading,
componentDetails,
personDetails,
bugzillaComponents,
@ -269,12 +274,13 @@ class MainContainer extends Component {
)}
<PropsRoute
path="/teams"
component={BugzillaComponents}
component={Teams}
bugzillaComponents={Object.values(teamComponents)}
onComponentDetails={this.handleShowComponentDetails}
/>
</Switch>
</Suspense>
{!doneLoading && <Spinner loading /> }
</div>
</div>
);

21
src/views/Teams/index.jsx Normal file
Просмотреть файл

@ -0,0 +1,21 @@
import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import BugzillaComponents from '../../components/BugzillaComponents';
const styles = {
message: {
margin: '0 0 1rem 0',
},
};
const Teams = ({ classes, ...rest }) => (
<React.Fragment>
<div className={classes.message}>
<span>If you want to change what shows up in this page follow </span>
<a href="https://github.com/mozilla/bugzilla-dashboard#generate-data">these instructions</a>
</div>
<BugzillaComponents {...rest} />
</React.Fragment>
);
export default withStyles(styles)(Teams);

Просмотреть файл

@ -28,6 +28,37 @@ exports[`renders components 1`] = `
</tr>
</thead>
<tbody>
<tr>
<td>
<div
className="DrilldownIcon-svgWrapper-4"
name="Core::DOM: Core & HTML"
onClick={[Function]}
onKeyPress={[Function]}
role="button"
tabIndex="0"
>
<svg
aria-hidden="true"
className="MuiSvgIcon-root-6 DrilldownIcon-icon-5"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"
/>
<path
d="M0 0h24v24H0z"
fill="none"
/>
</svg>
</div>
</td>
<td>
Core::DOM: Core & HTML
</td>
</tr>
<tr>
<td>
<div
@ -90,37 +121,6 @@ exports[`renders components 1`] = `
Core::JavaScript Engine
</td>
</tr>
<tr>
<td>
<div
className="DrilldownIcon-svgWrapper-4"
name="Core::DOM: Core & HTML"
onClick={[Function]}
onKeyPress={[Function]}
role="button"
tabIndex="0"
>
<svg
aria-hidden="true"
className="MuiSvgIcon-root-6 DrilldownIcon-icon-5"
focusable="false"
role="presentation"
viewBox="0 0 24 24"
>
<path
d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"
/>
<path
d="M0 0h24v24H0z"
fill="none"
/>
</svg>
</div>
</td>
<td>
Core::DOM: Core & HTML
</td>
</tr>
<tr>
<td>
<div