Skip to content
This repository has been archived by the owner on May 10, 2023. It is now read-only.

feat: show rejected sentences (fixes #159) #219

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ dist
.env
docker-compose.prod.yml
.ignored_files
.vscode
.vscode
.DS_Store
4 changes: 4 additions & 0 deletions shared/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,10 @@ export default class DB {
return this.sentences.vote(language, validated, invalidated);
}

async getAllRejectedByUsername(languages, username) {
return this.sentences.getAllRejectedByUsername(languages, username);
}

async getLanguageInfoForMe(language) {
try {
const [ submitted, validated ] = await Promise.all([
Expand Down
22 changes: 21 additions & 1 deletion shared/db/collections/sentences-meta.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,34 @@ export default class SentencesMeta {
return result.data;
}

getAllRejectedByUsername(languages, username) {
const rejectedSentences = {};

const promises = languages.map((language) => this.getAllUnapprovedByUsername(language, username));

return Promise.all(promises)
.then((unapprovedPerLanguage) => {
return unapprovedPerLanguage.reduce((rejectedSentences, unapproved, index) => {
if (unapproved) {
// we can use the index here, as Promise.all guarantees that its
// resolved values will be in the same order
rejectedSentences[languages[index]] = unapproved;
}

return rejectedSentences;
}, {});
});
}

async getAllUnapprovedByUsername(language, username) {
const collection = await this.getCollection(language);
const filters = {
username,
approved: false,
};
const result = await collection.listRecords({ filters });
return result.data;
const unapprovedSentencesWithoutDetail = result.data.map((record) => record.sentence);
return unapprovedSentencesWithoutDetail;
}

async getAllByUsername(language, username) {
Expand Down
6 changes: 6 additions & 0 deletions web/css/root.css
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,10 @@ form button {
font-size: 80%;
font-weight: 800;
width: 40%;
}

.no-bullets {
list-style: none;
margin-left: 0;
padding-left: 0;
}
3 changes: 3 additions & 0 deletions web/src/components/app.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Home from '../containers/home';
import HowTo from './pages/how-to';
import Login from '../containers/login';
import Profile from '../containers/profile';
import Rejected from '../containers/rejected';
import Add from '../containers/add';
import Review from '../containers/review';

Expand All @@ -35,6 +36,8 @@ export default class App extends React.Component {
path="/review" component={Review} />
<PrivateRoute authed={this.props.authed}
path="/review/:language" component={Review} />
<PrivateRoute authed={this.props.authed}
path="/rejected" component={Rejected} />
<Route render={() => (
<Redirect
to={{
Expand Down
1 change: 1 addition & 0 deletions web/src/components/header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const Header = (props) => {
<NavLink to="/how-to" exact>How-to</NavLink>
<NavLink to="/add" exact key="add">Add</NavLink>
<NavLink to="/review" key="review">Review</NavLink>
<NavLink to="/rejected" key="rejected">Rejected Sentences</NavLink>
{ props.authed ? (
<NavLink to="/profile" exact key="profile">Profile</NavLink>
) : (
Expand Down
60 changes: 60 additions & 0 deletions web/src/components/pages/rejected.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import React from 'react';

import WebDB from '../../web-db';

export default class Rejected extends React.Component {
constructor() {
super();
this.state = {
loading: true,
rejectedSentences: {},
};
}

async loadRejected() {
if (!this.props.languages || this.props.languages.length < 1) {
return;
}

const db = new WebDB(this.props.username, this.props.password);
const rejectedSentences = await db.getAllRejectedByUsername(this.props.languages, this.props.username);
this.setState({
rejectedSentences,
loading: false,
});
}

componentDidMount() {
this.loadRejected();
}

render() {
const { rejectedSentences, loading } = this.state;

return (
<>
<h1>Your rejected sentences</h1>

{ loading && (
<p>Loading rejected sentences..</p>
)}

{ !loading && Object.keys(rejectedSentences).length === 0 && (
<p>No rejected sentences found!</p>
)}

{ Object.keys(rejectedSentences).map((language) => (
<section>
<h2 key={language}>{language}</h2>

<ul className="no-bullets">
{ rejectedSentences[language].map((sentence) => (
<li key={sentence}>{sentence}</li>
))}
</ul>
</section>
))}
</>
);
}
}
2 changes: 1 addition & 1 deletion web/src/components/review-form.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ export default class ReviewForm extends React.Component {
</section>
)) }

<section class="review-footer">
<section className="review-footer">
<section id="confirm-buttons" className="divCenter">
{ this.state.pendingSentences ?
<SpinnerButton></SpinnerButton> :
Expand Down
13 changes: 13 additions & 0 deletions web/src/containers/rejected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { connect } from 'react-redux';

import Rejected from '../components/pages/rejected';

function mapStateToProps(state) {
return {
username: state.username,
password: state.password,
languages: state.languages,
};
}

export default connect(mapStateToProps)(Rejected);