Merge pull request #8 from RandellDawson/feat/report-improvements

Feature: Added Pareto Report and Tabs Navigation
This commit is contained in:
Randell Dawson
2018-11-24 01:27:54 -08:00
committed by mrugesh mohapatra
parent e8aa30162a
commit e31396931e
5 changed files with 15090 additions and 9 deletions

14974
dashboard-client/app/app/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,10 @@
import React, { Component } from 'react';
import styled from 'styled-components';
import Tabs from './components/Tabs';
import Input from './components/Input';
import Results from './components/Results';
import Pareto from './components/Pareto';
const Container = styled.div`
display: flex;
@ -12,14 +14,19 @@ const Container = styled.div`
padding: 15px;
border-radius: 4px;
box-shadow: 0 0 4px 0 #777;
`;
class App extends Component {
state = {
number: '',
foundPRs: []
foundPRs: [],
pareto: [],
view: 'search'
};
clearObj = { number: '', foundPRs: [] };
inputRef = React.createRef();
handleInputEvent = (event) => {
@ -37,7 +44,6 @@ class App extends Component {
handleButtonClick = () => {
const { number } = this.state;
this.searchPRs(number);
}
@ -56,19 +62,25 @@ class App extends Component {
}
})
.catch(() => {
this.setState((prevState) => ({ number: '', foundPRs: [] }));
this.setState((prevState) => (this.clearObj));
});
}
render() {
const { handleButtonClick, handleInputEvent, inputRef, state } = this;
const { number, foundPRs } = state;
handleViewChange = ( { target: { id } }) => {
const view = id.replace('tabs-', '');
this.setState((prevState) => ({ ...this.clearObj, view }));
}
render() {
const { handleButtonClick, handleViewChange, handleInputEvent, inputRef, state } = this;
const { number, foundPRs, view } = state;
return (
<Container>
<Tabs view={view} onViewChange={handleViewChange}/>
<Input ref={inputRef} value={number} onInputEvent={handleInputEvent} />
<button onClick={handleButtonClick}>Search</button>
<Results foundPRs={foundPRs} />
{ view === 'search' && <Results foundPRs={foundPRs} /> }
{ view === 'reports' && <Pareto /> }
</Container>
);
}

View File

@ -0,0 +1,63 @@
import React from 'react';
import styled from 'styled-components';
const Result = styled.div`
word-wrap: break-word;
margin: 10px 0;
&:nth-child(odd) {
background: #eee;
}
`;
class Pareto extends React.Component {
state = {
data: []
};
componentDidMount() {
fetch(`https://pr-relations.glitch.me/pareto`)
.then((response) => response.json())
.then(({ ok, pareto }) => {
if (ok) {
if (!pareto.length) {
pareto.push({ filename: 'Nothing to show in Pareto Report', count: 0, prs: [] });
}
this.setState((prevState) => ({ data: pareto }));
}
})
.catch(() => {
const pareto = [{ filename: 'Nothing to show in Pareto Report', count: 0, prs: [] }];
this.setState((prevState) => ({ data: pareto }));
});
}
render() {
const { data } = this.state;
const elements = data.map((entry) => {
const { filename, count, prs } = entry;
const prsList = prs.reduce((html, { number, username }) => {
const prUrl = `https://github.com/freeCodeCamp/freeCodeCamp/pull/${number}`;
return html += `
<a href=${prUrl} rel="noopener noreferrer" target="_blank">#${number} <span>${username}</span></a>, `;
}, '');
return (
<Result key={filename}>
{filename}<br />
<details>
<summary># of PRs: {count}</summary>
<div dangerouslySetInnerHTML={{__html: prsList}} />
</details>
</Result>
);
});
return (
<div>
{elements}
</div>
);
}
}
export default Pareto;

View File

@ -0,0 +1,32 @@
import React from 'react';
import styled from 'styled-components';
const Container = styled.div`
display: flex;
justify-content: center;
height: 40px;
`;
const Tab = styled.div`
background: ${({ active }) => active ? 'blue' : 'white'};
color: ${({ active }) => active ? 'white' : 'blue'};
font-size: 18px;
padding: 5px;
border: 2px solid blue;
&:hover {
cursor: pointer;
background: blue;
color: white;
}
`;
const Tabs = ({ view, onViewChange }) => {
return (
<Container>
<Tab id="tabs-search" onClick={onViewChange} active={view === 'search'}>Search</Tab>
<Tab id="tabs-reports" onClick={onViewChange} active={view === 'reports'}>Reports</Tab>
</Container>
);
};
export default Tabs;

View File

@ -6,7 +6,7 @@ body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
/* height: 100vh; */
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",