Skip to content

Commit

Permalink
Merge branch 'master' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
MonkeyDo committed Jun 15, 2020
2 parents 02aba1a + 81e6ee4 commit ad2b129
Show file tree
Hide file tree
Showing 21 changed files with 364 additions and 37 deletions.
67 changes: 67 additions & 0 deletions src/client/components/pages/entities/annotation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (C) 2020 Nicolas Pelletier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import {Button, Col, Collapse, Row} from 'react-bootstrap';
import PropTypes from 'prop-types';
import React from 'react';
import {formatDate} from '../../../helpers/utils';


class EntityAnnotation extends React.Component {
constructor(props) {
super(props);

this.state = {
open: false
};
}

handleToggleCollapse = () => {
this.setState(prevState => ({open: !prevState.open}));
};

render() {
const {annotation} = this.props.entity;
if (!annotation || !annotation.content) {
return null;
}
const lastModifiedDate = new Date(annotation.lastRevision.createdAt);
return (
<Row>
<Col md={12}>
<h2>Annotation</h2>
<Collapse in={this.state.open}>
<p className="annotation-content">{annotation.content}</p>
</Collapse>
<Button bsStyle="link" onClick={this.handleToggleCollapse}>
Show {this.state.open ? 'less' : 'more…'}
</Button>
<p className="text-muted">Last modified: <span title={formatDate(lastModifiedDate, true)}>{formatDate(lastModifiedDate)}</span>
<span className="small"> (revision <a href={`/revision/${annotation.lastRevisionId}`}>#{annotation.lastRevisionId}</a>)</span>
</p>
</Col>
</Row>
);
}
}
EntityAnnotation.displayName = 'EntityAnnotation';
EntityAnnotation.propTypes = {
entity: PropTypes.object.isRequired
};

export default EntityAnnotation;
2 changes: 2 additions & 0 deletions src/client/components/pages/entities/author.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';

import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
import EntityLinks from './links';
Expand Down Expand Up @@ -121,6 +122,7 @@ function AuthorDisplayPage({entity, identifierTypes}) {
<AuthorAttributes author={entity}/>
</Col>
</Row>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
<EntityLinks
Expand Down
3 changes: 2 additions & 1 deletion src/client/components/pages/entities/edition-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';

import EditionTable from './edition-table';
import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
import EntityLinks from './links';
Expand Down Expand Up @@ -79,6 +79,7 @@ function EditionGroupDisplayPage({entity, identifierTypes}) {
<EditionGroupAttributes editionGroup={entity}/>
</Col>
</Row>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
<EditionTable editions={entity.editions} entity={entity}/>
Expand Down
3 changes: 2 additions & 1 deletion src/client/components/pages/entities/edition.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';

import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
import EntityLinks from './links';
Expand Down Expand Up @@ -139,6 +139,7 @@ function EditionDisplayPage({entity, identifierTypes}) {
{editionGroupSection}
</Col>
</Row>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
<WorksTable
Expand Down
3 changes: 2 additions & 1 deletion src/client/components/pages/entities/publisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@

import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';

import EditionTable from './edition-table';
import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
import EntityLinks from './links';
Expand Down Expand Up @@ -97,6 +97,7 @@ function PublisherDisplayPage({entity, identifierTypes}) {
<PublisherAttributes publisher={entity}/>
</Col>
</Row>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
<EditionTable editions={entity.editions} entity={entity}/>
Expand Down
2 changes: 2 additions & 0 deletions src/client/components/pages/entities/work.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as bootstrap from 'react-bootstrap';
import * as entityHelper from '../../../helpers/entity';

import EditionTable from './edition-table';
import EntityAnnotation from './annotation';
import EntityFooter from './footer';
import EntityImage from './image';
import EntityLinks from './links';
Expand Down Expand Up @@ -91,6 +92,7 @@ function WorkDisplayPage({entity, identifierTypes}) {
<WorkAttributes work={entity}/>
</Col>
</Row>
<EntityAnnotation entity={entity}/>
{!entity.deleted &&
<React.Fragment>
<EditionTable
Expand Down
45 changes: 45 additions & 0 deletions src/client/entity-editor/annotation-section/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2020 Nicolas Pelletier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

// @flow

export const UPDATE_ANNOTATION = 'UPDATE_ANNOTATION';

export type Action = {
type: string,
payload?: mixed,
metadata?: {
debounce?: string
}
};

/**
* Produces an action indicating that the annotation for the editing form
* should be updated with the provided value. The action is marked to be
* debounced by the keystroke debouncer defined for redux-debounce.
*
* @param {string} value - The new value to be used for the revision note.
* @returns {Action} The resulting UPDATE_ANNOTATION action.
*/
export function debounceUpdateAnnotation(value: string): Action {
return {
meta: {debounce: 'keystroke'},
type: UPDATE_ANNOTATION,
value
};
}
99 changes: 99 additions & 0 deletions src/client/entity-editor/annotation-section/annotation-section.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (C) 2020 Nicolas Pelletier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import {Col, Row} from 'react-bootstrap';
import {convertMapToObject, formatDate} from '../../helpers/utils';

import CustomInput from '../../input';
import PropTypes from 'prop-types';
import React from 'react';
import {connect} from 'react-redux';
import {debounceUpdateAnnotation} from './actions';

/**
* Container component. The AnnotationSection component contains a
* field for entering or modifying annotations for this entity.
*
* @param {Object} props - The properties passed to the component.
* @param {Object} props.annotation - The annotation object containing
* its content and lastRevision info
* @param {Function} props.onAnnotationChange - A function to be called when the
* annotation is changed.
* @returns {ReactElement} React element containing the rendered
* AnnotationSection.
*/
function AnnotationSection({
annotation,
onAnnotationChange
}) {
const annotationLabel = (
<span>
Annotation
<span className="text-muted"> (optional)</span>
</span>
);

return (
<div>
<h2>
Annotation
</h2>
<Row>
<Col md={6} mdOffset={3}>
<CustomInput
defaultValue={annotation.content}
label={annotationLabel}
rows="4"
tooltipText="Additional freeform data that does not fit in the above form"
type="textarea"
onChange={onAnnotationChange}
/>
{
annotation && annotation.lastRevision &&
<p className="small text-muted">Last modified: {formatDate(new Date(annotation.lastRevision.createdAt))}</p>
}
<p className="help-block">
Annotations allow you to enter freeform data that does not otherwise fit in the above form.
<b> Do not submit any copyrighted text here.</b> The contents will be made available to the public under <a href="https://musicbrainz.org/doc/About/Data_License">open licenses</a>.
</p>
</Col>
</Row>
</div>
);
}
AnnotationSection.displayName = 'AnnotationSection';
AnnotationSection.propTypes = {
annotation: PropTypes.object.isRequired,
onAnnotationChange: PropTypes.func.isRequired
};

function mapStateToProps(rootState) {
return {
annotation: convertMapToObject(rootState.get('annotationSection'))
};
}


function mapDispatchToProps(dispatch) {
return {
onAnnotationChange: (event) =>
dispatch(debounceUpdateAnnotation(event.target.value))
};
}

export default connect(mapStateToProps, mapDispatchToProps)(AnnotationSection);
35 changes: 35 additions & 0 deletions src/client/entity-editor/annotation-section/reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) 2020 Nicolas Pelletier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

import Immutable from 'immutable';
import {UPDATE_ANNOTATION} from './actions';


function reducer(
state = Immutable.Map({content: ''}),
action
) {
switch (action.type) {
case UPDATE_ANNOTATION:
return state.set('content', action.value);
// no default
}
return state;
}

export default reducer;
7 changes: 5 additions & 2 deletions src/client/entity-editor/entity-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import * as React from 'react';
import AliasEditor from './alias-editor/alias-editor';
import AnnotationSection from './annotation-section/annotation-section';
import ButtonBar from './button-bar/button-bar';
import IdentifierEditor from './identifier-editor/identifier-editor';
import NameSection from './name-section/name-section';
Expand All @@ -30,12 +31,13 @@ import {connect} from 'react-redux';


type OwnProps = {
children: React.Element<any>
children: React.Element<any>,
heading: string
};

type StateProps = {
aliasEditorVisible: boolean,
identifierEditorVisible: boolean
identifierEditorVisible: boolean,
};

type Props = StateProps & OwnProps;
Expand Down Expand Up @@ -79,6 +81,7 @@ const EntityEditor = (props: Props) => {
)
}
<IdentifierEditor show={identifierEditorVisible} {...props}/>
<AnnotationSection {...props}/>
</Panel.Body>
<Panel.Footer>
<SubmissionSection {...props}/>
Expand Down
2 changes: 2 additions & 0 deletions src/client/entity-editor/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import PublisherSectionMerge from './publisher-section/publisher-section-merge';
import WorkSection from './work-section/work-section';
import WorkSectionMerge from './work-section/work-section-merge';
import aliasEditorReducer from './alias-editor/reducer';
import annotationSectionReducer from './annotation-section/reducer';
import authorSectionReducer from './author-section/reducer';
import buttonBarReducer from './button-bar/reducer';
import {combineReducers} from 'redux-immutable';
Expand Down Expand Up @@ -119,6 +120,7 @@ export function createRootReducer(entityType: string) {

return combineReducers({
aliasEditor: aliasEditorReducer,
annotationSection: annotationSectionReducer,
buttonBar: buttonBarReducer,
[entityReducerKey]: entityReducer,
identifierEditor: identifierEditorReducer,
Expand Down
Loading

0 comments on commit ad2b129

Please sign in to comment.