Tidy up initial basic leaderboard
This commit is contained in:
parent
a2393a019a
commit
c4ffdf4db9
@ -6,8 +6,9 @@ async function getLeaders(number_limit: number, time_limit: number) {
|
|||||||
number_limit = Math.min(number_limit, max_limit);
|
number_limit = Math.min(number_limit, max_limit);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
let leaders;
|
||||||
if(time_limit > 0){
|
if(time_limit > 0){
|
||||||
return await db.manyOrNone(
|
leaders = await db.manyOrNone(
|
||||||
`SELECT count(log_id) as number_edits, username
|
`SELECT count(log_id) as number_edits, username
|
||||||
FROM logs, users
|
FROM logs, users
|
||||||
WHERE logs.user_id = users.user_id
|
WHERE logs.user_id = users.user_id
|
||||||
@ -19,7 +20,7 @@ async function getLeaders(number_limit: number, time_limit: number) {
|
|||||||
LIMIT $2`, [time_limit, number_limit]
|
LIMIT $2`, [time_limit, number_limit]
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return await db.manyOrNone(
|
leaders = await db.manyOrNone(
|
||||||
`SELECT count(log_id) as number_edits, username
|
`SELECT count(log_id) as number_edits, username
|
||||||
FROM logs, users
|
FROM logs, users
|
||||||
WHERE logs.user_id = users.user_id
|
WHERE logs.user_id = users.user_id
|
||||||
@ -30,6 +31,9 @@ async function getLeaders(number_limit: number, time_limit: number) {
|
|||||||
LIMIT $1`, [number_limit]
|
LIMIT $1`, [number_limit]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return leaders.map(d => {
|
||||||
|
return {username: d.username, number_edits: Number(d.number_edits)};
|
||||||
|
})
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return [];
|
return [];
|
||||||
|
@ -58,6 +58,8 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<nav className={this.state.collapseMenu ? 'collapse navbar-collapse' : 'navbar-collapse'}>
|
<nav className={this.state.collapseMenu ? 'collapse navbar-collapse' : 'navbar-collapse'}>
|
||||||
|
<Categories mode='view' />
|
||||||
|
<hr />
|
||||||
<ul className="navbar-nav flex-column">
|
<ul className="navbar-nav flex-column">
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink to="/view/categories" className="nav-link" onClick={this.handleNavigate}>
|
<NavLink to="/view/categories" className="nav-link" onClick={this.handleNavigate}>
|
||||||
@ -133,8 +135,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr />
|
<hr />
|
||||||
<Categories mode='view' />
|
|
||||||
<hr />
|
|
||||||
<ul className="navbar-nav flex-column">
|
<ul className="navbar-nav flex-column">
|
||||||
<li className="nav-item">
|
<li className="nav-item">
|
||||||
<NavLink to="/contact.html" className="nav-link" onClick={this.handleNavigate}>
|
<NavLink to="/contact.html" className="nav-link" onClick={this.handleNavigate}>
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
table {
|
|
||||||
table-layout: fixed;
|
|
||||||
width: 60%;
|
|
||||||
margin-left: 20%;
|
|
||||||
margin-right: 20%;
|
|
||||||
border: 1px solid black;
|
|
||||||
}
|
|
||||||
|
|
||||||
table th, td {
|
|
||||||
border: 1px solid black;
|
|
||||||
text-align: left;
|
|
||||||
padding-left: 1%;
|
|
||||||
}
|
|
||||||
|
|
||||||
table tr:nth-child(odd) {
|
|
||||||
background: #f6f8fa;
|
|
||||||
}
|
|
||||||
|
|
||||||
table tr:nth-child(1) {
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
#title {
|
|
||||||
text-align: center;
|
|
||||||
padding-bottom: 1%;
|
|
||||||
}
|
|
||||||
|
|
||||||
#radiogroup {
|
|
||||||
padding: 1%;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type="radio"] {
|
|
||||||
margin: 0 2px 0 10px;
|
|
||||||
}
|
|
@ -1,25 +1,23 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import './leaderboard.css';
|
|
||||||
|
|
||||||
interface Leader {
|
interface Leader {
|
||||||
number_edits: string;
|
number_edits: number;
|
||||||
username: string;
|
username: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface LeaderboardProps {
|
interface LeaderboardProps {}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
interface LeaderboardState {
|
interface LeaderboardState {
|
||||||
leaders: Leader[];
|
leaders: Leader[];
|
||||||
fetching: boolean;
|
fetching: boolean;
|
||||||
|
|
||||||
//We need to track the state of the radio buttons to ensure their current state is shown correctly when the view is (re)rendered
|
//We need to track the state of the radio buttons to ensure their current state is shown correctly when the view is (re)rendered
|
||||||
number_limit: number;
|
number_limit: number;
|
||||||
time_limit: number;
|
time_limit: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class LeaderboardPage extends Component<LeaderboardProps, LeaderboardState> {
|
class LeaderboardPage extends Component<LeaderboardProps, LeaderboardState> {
|
||||||
@ -42,29 +40,23 @@ class LeaderboardPage extends Component<LeaderboardProps, LeaderboardState> {
|
|||||||
if(e.target.name == 'number_limit'){
|
if(e.target.name == 'number_limit'){
|
||||||
this.getLeaders(e.target.value, this.state.time_limit);
|
this.getLeaders(e.target.value, this.state.time_limit);
|
||||||
this.setState({number_limit: e.target.value});
|
this.setState({number_limit: e.target.value});
|
||||||
}else {
|
} else {
|
||||||
this.getLeaders(this.state.number_limit, e.target.value);
|
this.getLeaders(this.state.number_limit, e.target.value);
|
||||||
this.setState({time_limit: e.target.value});
|
this.setState({time_limit: e.target.value});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.getLeaders(this.state.number_limit, this.state.time_limit);
|
this.getLeaders(this.state.number_limit, this.state.time_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLeaders(number_limit: number, time_limit: number) {
|
||||||
componentWillUnmount() {}
|
|
||||||
|
|
||||||
|
|
||||||
getLeaders(number_limit, time_limit) {
|
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
fetching: true
|
fetching: true
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch(
|
fetch(
|
||||||
'/api/leaderboard/leaders?number_limit=' + number_limit + '&time_limit='+time_limit
|
`/api/leaderboard/leaders?number_limit=${number_limit}&time_limit=${time_limit}`
|
||||||
).then(
|
).then(
|
||||||
(res) => res.json()
|
(res) => res.json()
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
@ -100,9 +92,9 @@ class LeaderboardPage extends Component<LeaderboardProps, LeaderboardState> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<tr key={username}>
|
<tr key={username}>
|
||||||
<td>{i+1}</td>
|
<th scope="row">{i+1}</th>
|
||||||
<td>{username}</td>
|
<td>{username}</td>
|
||||||
<td>{number_edits}</td>
|
<td>{number_edits.toLocaleString()}</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -110,35 +102,92 @@ class LeaderboardPage extends Component<LeaderboardProps, LeaderboardState> {
|
|||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return(
|
return (
|
||||||
<div>
|
<article>
|
||||||
<form id="radiogroup">
|
<section className="main-col">
|
||||||
<div id="number-radiogroup" >
|
<h1 className="h2">Leaderboard</h1>
|
||||||
<p>Select number of users to be displayed: <br/>
|
<form>
|
||||||
<input type="radio" name="number_limit" value="10" onChange={this.handleChange} checked={10 == this.state.number_limit} />10
|
<label>Select number of users to be displayed</label>
|
||||||
<input type="radio" name="number_limit" value="100" onChange={this.handleChange} checked={100 == this.state.number_limit} />100
|
<div className="form-group">
|
||||||
</p>
|
<div className="form-check-inline">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="number_limit"
|
||||||
|
id="number_10"
|
||||||
|
className="form-check-input"
|
||||||
|
value="10"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
checked={10 == this.state.number_limit}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="number_10">10</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-check-inline">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="number_limit"
|
||||||
|
id="number_100"
|
||||||
|
className="form-check-input"
|
||||||
|
value="100"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
checked={100 == this.state.number_limit}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="number_100">100</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<label>Select time period</label>
|
||||||
|
<div className="form-group">
|
||||||
|
<div className="form-check-inline">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="time_limit"
|
||||||
|
id="time_all"
|
||||||
|
className="form-check-input"
|
||||||
|
value="-1"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
checked={-1 == this.state.time_limit}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="time_all">All time</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-check-inline">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="time_limit"
|
||||||
|
id="time_7"
|
||||||
|
className="form-check-input"
|
||||||
|
value="7"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
checked={7 == this.state.time_limit}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="time_7">Last 7 days</label>
|
||||||
|
</div>
|
||||||
|
<div className="form-check-inline">
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
name="time_limit"
|
||||||
|
id="time_30"
|
||||||
|
className="form-check-input"
|
||||||
|
value="30"
|
||||||
|
onChange={this.handleChange}
|
||||||
|
checked={30 == this.state.time_limit}
|
||||||
|
/>
|
||||||
|
<label className="form-check-label" htmlFor="time_30">Last 30 days</label>
|
||||||
</div>
|
</div>
|
||||||
<div id="time-radiogroup" >
|
|
||||||
<p>Select time period: <br/>
|
|
||||||
<input type="radio" name="time_limit" value="-1" onChange={this.handleChange} checked={-1 == this.state.time_limit} /> All time
|
|
||||||
<input type="radio" name="time_limit" value="7" onChange={this.handleChange} checked={7 == this.state.time_limit} /> Last 7 days
|
|
||||||
<input type="radio" name="time_limit" value="30" onChange={this.handleChange} checked={30 == this.state.time_limit} /> Last 30 days
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<h1 id='title'>Leader Board</h1>
|
<table className="table table-striped">
|
||||||
<table id='leaderboard'>
|
<thead>
|
||||||
<tbody>
|
|
||||||
<tr>
|
<tr>
|
||||||
<th>Rank</th>
|
<th scope="col">#</th>
|
||||||
<th>Username</th>
|
<th scope="col">Username</th>
|
||||||
<th>Contributions</th>
|
<th scope="col">Contributions</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{this.renderTableData()}
|
{this.renderTableData()}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</section>
|
||||||
|
</article>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,4 +195,3 @@ class LeaderboardPage extends Component<LeaderboardProps, LeaderboardState> {
|
|||||||
|
|
||||||
|
|
||||||
export default LeaderboardPage;
|
export default LeaderboardPage;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user