210 lines
5.8 KiB
JavaScript
210 lines
5.8 KiB
JavaScript
import React from 'react';
|
|
import { connect } from 'react-redux';
|
|
import { getRepos, getUser, getRepoLanguages, nextPage, setSortValue } from '../../actions';
|
|
import { ToggleButton, Button } from './Buttons';
|
|
|
|
class GithubRepos extends React.Component {
|
|
|
|
perPage = 5;
|
|
sortOptions = [
|
|
// text: displayed text, value: value used for sorting
|
|
{text: "Created Date", value: "created_at"},
|
|
{text: "Last Pushed", value: "pushed_at"},
|
|
{text: "Name", value: "name"},
|
|
{text: "Number of Forks", value: "forks"},
|
|
{text: "Size", value: "size"},
|
|
{text: "Last Updated", value: "updated_at"},
|
|
];
|
|
|
|
componentDidMount() {
|
|
|
|
document.title = "Github Repos";
|
|
|
|
if (!this.props.repos) {
|
|
|
|
this.props.getUser(this.props.username); // Receive the repos at start
|
|
this.props.getRepos(this.props.username); // Receive the repos at start
|
|
|
|
}
|
|
|
|
}
|
|
|
|
renderLanguages(name) {
|
|
this.props.getRepoLanguages(this.props.username, name);
|
|
|
|
// Given that we've already received the repo's languages
|
|
if (this.props.repoLanguages && this.props.repoLanguages[name]) {
|
|
|
|
// Create a bubble for each language
|
|
return Object.keys(this.props.repoLanguages[name]).map(language=>{
|
|
|
|
return <div className="language" key={language}>{language}</div>; // Language bubble JSX
|
|
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
roundUp(num) {
|
|
return num%1 === 0? num : num-(num%1)+1
|
|
}
|
|
|
|
objArrayBubbleSort(arr, value) {
|
|
/**
|
|
* arrayBubbleSort
|
|
*/
|
|
let unsorted;
|
|
let tmp;
|
|
|
|
do {
|
|
unsorted = false;
|
|
|
|
for (let i = 0; i < arr.length-1; i++) {
|
|
if (
|
|
(value.asc && arr[i][value.value] > arr[i+1][value.value]) // Ascending
|
|
|| (!value.asc && arr[i][value.value] < arr[i+1][value.value]) // Descending
|
|
) {
|
|
tmp = arr[i+1];
|
|
arr[i+1] = arr[i];
|
|
arr[i] = tmp;
|
|
|
|
unsorted = true;
|
|
}
|
|
}
|
|
|
|
|
|
} while (unsorted);
|
|
|
|
return arr;
|
|
|
|
}
|
|
|
|
renderRepos() {
|
|
|
|
if (this.props.repos) { // If the repos have been received
|
|
|
|
if (this.props.repos.length > 0) {
|
|
// Render each repo
|
|
let repos = this.props.single ? [this.props.repos[0]] : this.props.repos
|
|
|
|
let pages = this.roundUp(repos.length/this.perPage);
|
|
|
|
let sortedRepos = this.objArrayBubbleSort([...repos], this.props.sortedValue);
|
|
|
|
const render = sortedRepos.slice(0, this.props.page*this.perPage).map((repo) =>{
|
|
let updated = (new Date (repo.updated_at)).toLocaleString();
|
|
let created = (new Date (repo.created_at)).toLocaleString();
|
|
|
|
return (
|
|
<div className="repo" key={repo.id}>
|
|
|
|
<a href={repo.html_url} target="_blank" rel="noreferrer" className="title">{repo.name}</a>
|
|
|
|
<div className="content">
|
|
<p className="description">{repo.description ? repo.description : "No Description"}</p>
|
|
|
|
{
|
|
repo.homepage ? // If the repo has a homepage, render a button
|
|
<a href={repo.homepage} target="_blank" rel="noreferrer" className="website"> Project Website </a>:
|
|
""
|
|
}
|
|
</div>
|
|
|
|
<div className="languages">
|
|
Languages:
|
|
|
|
{
|
|
this.renderLanguages(repo.name) // Render each language for the repo
|
|
}
|
|
</div>
|
|
<div className="time">
|
|
Last Updated: {updated}
|
|
</div>
|
|
<div className="time">
|
|
Created: {created}
|
|
</div>
|
|
</div>
|
|
|
|
);
|
|
});
|
|
|
|
return (
|
|
<div className="repo-list">
|
|
<div className="sort-menu">
|
|
<div className="select-menu">
|
|
<p>Sort By: </p>
|
|
<select className="dropdown-list" onChange={v=>{
|
|
this.props.setSortValue({
|
|
...this.props.sortedValue,
|
|
value: v.target.value
|
|
});
|
|
}}>
|
|
{
|
|
this.sortOptions.map(option=>{
|
|
return (
|
|
<option
|
|
value={option.value}
|
|
key={option.value}
|
|
selected={option.value === this.props.sortedValue.value}
|
|
>
|
|
{option.text}
|
|
</option>);
|
|
})
|
|
}
|
|
</select>
|
|
</div>
|
|
 
|
|
<ToggleButton defVal={false} clickAction={(val)=>{
|
|
console.warn(val);
|
|
this.props.setSortValue({
|
|
...this.props.sortedValue,
|
|
asc: val
|
|
});
|
|
}} />
|
|
</div>
|
|
|
|
{render}
|
|
|
|
{this.props.page < pages ?
|
|
<Button className="mar-la mar-ra" onClick={()=>this.props.nextPage()}>Load More ({this.props.page}/{pages})</Button>
|
|
: ""
|
|
}
|
|
</div>
|
|
); // display the repo list with the rendered repos
|
|
|
|
} else {
|
|
|
|
return <div className="loading">User doesn't have any repositories</div>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Return nothing if repos haven't been received
|
|
|
|
return <div className="loading"> Loading Repositories... </div>; // Return nothing if repos haven't been collected
|
|
}
|
|
|
|
render = () => {
|
|
return (<div>{this.renderRepos()}</div>);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
const mapStateToProps = (state) => {
|
|
return {
|
|
repos: state.github.repos,
|
|
repoLanguages: state.github.repoLanguages,
|
|
page: state.github.page,
|
|
sortedValue: state.github.sortedValue
|
|
};
|
|
}
|
|
|
|
export default connect(mapStateToProps, {
|
|
getRepos,
|
|
getRepoLanguages,
|
|
getUser,
|
|
nextPage,
|
|
setSortValue
|
|
})(GithubRepos); |