Skip to content

Commit

Permalink
Merge pull request #374 from prabalsingh24/Entity-Revision-Table
Browse files Browse the repository at this point in the history
Entity revision table
  • Loading branch information
MonkeyDo authored Apr 6, 2020
2 parents 8267080 + eb8a2ad commit bf6c741
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 117 deletions.
3 changes: 3 additions & 0 deletions src/client/components/pages/editor-revision.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class EditorRevisionPage extends React.Component {
<div id="pageWithPagination">
<RevisionsTable
results={this.state.results}
showEntities={this.props.showEntities}
showRevisionEditor={this.props.showRevisionEditor}
showRevisionNote={this.props.showRevisionNote}
tableHeading={this.props.tableHeading}
Expand All @@ -65,6 +66,7 @@ EditorRevisionPage.propTypes = {
from: PropTypes.number,
nextEnabled: PropTypes.bool.isRequired,
results: PropTypes.array,
showEntities: PropTypes.bool,
showRevisionEditor: PropTypes.bool,
showRevisionNote: PropTypes.bool,
size: PropTypes.number,
Expand All @@ -73,6 +75,7 @@ EditorRevisionPage.propTypes = {
EditorRevisionPage.defaultProps = {
from: 0,
results: [],
showEntities: true,
showRevisionEditor: false,
showRevisionNote: true,
size: 20,
Expand Down
121 changes: 54 additions & 67 deletions src/client/components/pages/entity-revisions.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import * as bootstrap from 'react-bootstrap';
import * as utilsHelper from '../../helpers/utils';
import {genEntityIconHTMLElement, getEntityLabel, getEntityUrl} from '../../helpers/entity';
import PagerElement from './parts/pager';
import PropTypes from 'prop-types';
import React from 'react';
import RevisionsTable from './parts/revisions-table';


const {Col, ListGroup, ListGroupItem, Row} = bootstrap;
const {formatDate, isWithinDayFromNow} = utilsHelper;

/**
* The class is derived from the React Component base class and
* renders the 'Entity RevisionsPage' page.
Expand All @@ -38,8 +36,18 @@ class EntityRevisions extends React.Component {
*/
constructor(props) {
super(props);
this.state = {
results: this.props.revisions
};

// React does not autobind non-React class methods
this.renderHeader = this.renderHeader.bind(this);
this.renderRevision = this.renderRevision.bind(this);
this.searchResultsCallback = this.searchResultsCallback.bind(this);
this.paginationUrl = './revisions/revisions?';
}

searchResultsCallback(newResults) {
this.setState({results: newResults});
}

/**
Expand All @@ -49,62 +57,20 @@ class EntityRevisions extends React.Component {
*/
renderHeader() {
const {entity} = this.props;

return (
<Row>
<Col md={12}>
<h1>
{entity.defaultAlias &&
`${entity.defaultAlias.name} `
}
{entity.disambiguation &&
<small>
{`(${entity.disambiguation.comment})`}
</small>
}
</h1>
<hr/>
</Col>
</Row>
<div>
Revision History
<h3>
for&nbsp;
<a href={getEntityUrl(entity)} >
{genEntityIconHTMLElement(entity.type)}
{getEntityLabel(entity)}
</a>
</h3>
</div>
);
}

/**
* Renders the data related to Revision such as 'author' and 'date'.
* It also displays the first revison note which is a summary of the changes
* made in the revision.
* @param {object} revision - The revision to be represented by the
* rendered component.
* @returns {ReactElement} a HTML document which is a part of the Revision
* page
*/
renderRevision(revision) {
const createdDate = new Date(revision.revision.createdAt);
const dateLabel =
formatDate(createdDate, isWithinDayFromNow(createdDate));
const header = (
<h4 className="list-group-item-heading">
<small className="pull-right">
{`${revision.revision.author.name}, ${dateLabel}`}
</small>
{`r${revision.id}`}
</h4>
);

return (
<ListGroupItem
href={`/revision/${revision.id}`}
key={`${revision.revision.author.id}${revision.id}`}
>
{header}
{revision.revision.notes.length > 0 &&
<p className="list-group-item-text">
{revision.revision.notes[0].content}
</p>
}
</ListGroupItem>
);
}

/**
* Renders the EntityRevisions page, which is a list of all the revisions
Expand All @@ -113,15 +79,23 @@ class EntityRevisions extends React.Component {
* @returns {ReactElement} a HTML document which displays the Revision page
*/
render() {
const {revisions} = this.props;

return (
<div>
{this.renderHeader()}
<h2>Revision History</h2>
<ListGroup>
{revisions.map(this.renderRevision)}
</ListGroup>
<div id="pageWithPagination">
<RevisionsTable
results={this.state.results}
showEntities={this.props.showEntities}
showRevisionEditor={this.props.showRevisionEditor}
showRevisionNote={this.props.showRevisionNote}
tableHeading={this.renderHeader()}
/>
<PagerElement
from={this.props.from}
nextEnabled={this.props.nextEnabled}
paginationUrl={this.paginationUrl}
results={this.state.results}
searchResultsCallback={this.searchResultsCallback}
size={this.props.size}
/>
</div>
);
}
Expand All @@ -132,7 +106,20 @@ EntityRevisions.propTypes = {
defaultAlias: PropTypes.object,
disambiguation: PropTypes.object
}).isRequired,
revisions: PropTypes.array.isRequired
from: PropTypes.number,
nextEnabled: PropTypes.bool.isRequired,
revisions: PropTypes.array.isRequired,
showEntities: PropTypes.bool,
showRevisionEditor: PropTypes.bool,
showRevisionNote: PropTypes.bool,
size: PropTypes.number
};
EntityRevisions.defaultProps = {
from: 0,
showEntities: false,
showRevisionEditor: false,
showRevisionNote: false,
size: 20
};

export default EntityRevisions;
7 changes: 5 additions & 2 deletions src/client/components/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,15 @@ class IndexPage extends React.Component {
<div>
<RevisionsTable
results={this.props.recent}
showEntities={this.props.showEntities}
showRevisionEditor={this.props.showRevisionEditor}
/>
<div className="text-center">
<Button
bsStyle="primary"
href="/revisions"
>
See all revisions
See all revisions
</Button>
</div>
</div>
Expand Down Expand Up @@ -233,7 +234,7 @@ class IndexPage extends React.Component {
Register!
</Button>
</div>
</React.Fragment>
</React.Fragment>
);
}

Expand All @@ -252,11 +253,13 @@ IndexPage.propTypes = {
disableSignUp: PropTypes.bool,
isLoggedIn: PropTypes.bool.isRequired,
recent: PropTypes.array.isRequired,
showEntities: PropTypes.bool,
showRevisionEditor: PropTypes.bool

};
IndexPage.defaultProps = {
disableSignUp: false,
showEntities: true,
showRevisionEditor: true
};

Expand Down
34 changes: 21 additions & 13 deletions src/client/components/pages/parts/revisions-table.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const {formatDate} = utilsHelper;


function RevisionsTable(props) {
const {results, showRevisionNote, showRevisionEditor, tableHeading} = props;
const {results, showEntities, showRevisionNote, showRevisionEditor, tableHeading} = props;

const tableCssClasses = 'table table-striped';
return (
Expand All @@ -47,7 +47,10 @@ function RevisionsTable(props) {
<thead>
<tr>
<th className="col-sm-2">Revision ID</th>
<th className="col-sm-5">Modified entities</th>
{
showEntities ?
<th className="col-sm-5">Modified entities</th> : null
}
{
showRevisionEditor ?
<th className="col-sm-3">User</th> : null
Expand All @@ -69,16 +72,19 @@ function RevisionsTable(props) {
{revision.revisionId}
</a>
</td>
<td>
{revision.entities.map(entity => (
<div key={`${revision.revisionId}-${entity.bbid}`}>
<a href={getEntityUrl(entity)} >
{genEntityIconHTMLElement(entity.type)}
{getEntityLabel(entity)}
</a>
</div>
))}
</td>
{
showEntities ?
<td>
{revision.entities.map(entity => (
<div key={`${revision.revisionId}-${entity.bbid}`}>
<a href={getEntityUrl(entity)} >
{genEntityIconHTMLElement(entity.type)}
{getEntityLabel(entity)}
</a>
</div>
))}
</td> : null
}
{
showRevisionEditor ?
<td>
Expand Down Expand Up @@ -125,11 +131,13 @@ function RevisionsTable(props) {

RevisionsTable.propTypes = {
results: PropTypes.array.isRequired,
showEntities: PropTypes.bool,
showRevisionEditor: PropTypes.bool,
showRevisionNote: PropTypes.bool,
tableHeading: PropTypes.string
tableHeading: PropTypes.node
};
RevisionsTable.defaultProps = {
showEntities: false,
showRevisionEditor: false,
showRevisionNote: false,
tableHeading: 'Recent Activity'
Expand Down
3 changes: 3 additions & 0 deletions src/client/components/pages/revisions.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class RevisionsPage extends React.Component {
<div id="pageWithPagination">
<RevisionsTable
results={this.state.results}
showEntities={this.props.showEntities}
showRevisionEditor={this.props.showRevisionEditor}
/>
<PagerElement
Expand All @@ -64,12 +65,14 @@ RevisionsPage.propTypes = {
from: PropTypes.number,
nextEnabled: PropTypes.bool.isRequired,
results: PropTypes.array,
showEntities: PropTypes.bool,
showRevisionEditor: PropTypes.bool,
size: PropTypes.number
};
RevisionsPage.defaultProps = {
from: 0,
results: [],
showEntities: true,
showRevisionEditor: true,
size: 20
};
Expand Down
3 changes: 2 additions & 1 deletion src/client/controllers/entity/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

import {
extractChildProps,
extractEntityProps,
extractLayoutProps
} from '../../helpers/props';
Expand Down Expand Up @@ -55,7 +56,7 @@ if (page === 'revisions') {
<Layout {...extractLayoutProps(props)}>
<EntityRevisions
entity={props.entity}
revisions={props.revisions}
{...extractChildProps(props)}
/>
</Layout>
</AppContainer>
Expand Down
35 changes: 35 additions & 0 deletions src/server/helpers/revisions.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export async function getOrderedRevisions(from, size, orm) {

/* Massage the revisions to match the expected format */
const formattedRevisions = revisionsJSON.map(rev => {
delete rev.authorId;
const {author: editor, id: revisionId, ...otherProps} = rev;
return {editor, entities: [], revisionId, ...otherProps};
});
Expand Down Expand Up @@ -157,10 +158,44 @@ export async function getOrderedRevisionForEditorPage(from, size, req) {
});
const revisionsJSON = revisions.toJSON();
const formattedRevisions = revisionsJSON.map(rev => {
delete rev.authorId;
const {author: editor, id: revisionId, ...otherProps} = rev;
return {editor, entities: [], revisionId, ...otherProps};
});

const orderedRevisions = await getAssociatedEntityRevisions(formattedRevisions, req.app.locals.orm);
return orderedRevisions;
}

export async function getOrderedRevisionsForEntityPage(from, size, RevisionModel, req) {
const revisions = await new RevisionModel()
.query((qb) => {
qb.where('bbid', req.params.bbid);
qb.join('bookbrainz.revision', `${RevisionModel.prototype.tableName}.id`, '=', 'bookbrainz.revision.id');
qb.orderBy('revision.created_at', 'DESC');
}).fetchPage({
limit: size,
offset: from,
withRelated: [
'revision.author',
{
'revision.notes'(q) {
q.orderBy('note.posted_at');
}
},
'revision.notes.author'
]
});

const revisionsJSON = revisions ? revisions.toJSON() : [];
const orderedRevisions = revisionsJSON.map(rev => {
const {revision} = rev;
const editor = revision.author;
const revisionId = revision.id;
delete revision.author;
delete revision.authorId;
delete revision.id;
return {editor, revisionId, ...revision};
});
return orderedRevisions;
}
Loading

0 comments on commit bf6c741

Please sign in to comment.