ES6 Plato on Github
Report Home
Summary Display
components/Logbook/NewOrEditEventPanel.js
Maintainability
65.41
Lines of code
212
Difficulty
37.08
Estimated Errors
1.87
Function weight
By Complexity
By SLOC
import React from 'react'; import PropTypes from 'prop-types'; import { Panel, Label, Glyphicon, OverlayTrigger, Tooltip, Button } from 'react-bootstrap'; import EventFooter from './EventFooter'; import { EVENT_CATEGORY_COMMENT, ANNOTATION, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT, LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT, LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT } from '../../constants/EventTypes'; import { getContent } from '../../helpers/EventHelpers'; import _ from 'lodash'; import EventVersions from './EventVersions'; import TagsSelectorContainer from '../../containers/Logbook/Tags/TagsSelectorContainer'; import EditorWrapper from './EditorWrapper'; import ReactTimeAgo from 'react-time-ago'; import Moment from 'moment'; import JavascriptTimeAgo from 'javascript-time-ago' import en from 'javascript-time-ago/locale/en' JavascriptTimeAgo.locale(en); /** * React component which renders a Panel for creating of editing an event */ class NewOrEditEventPanel extends React.Component { constructor(props) { super(props); this.state = { isSaveButtonEnabled: false, //whether the editor contains some text or not isEditorContentValid: false, optionPanelDecollaped: false, selectedTags: [] // tags which are currently selected } this.isSaveButtonEnabled = this.isSaveButtonEnabled.bind(this); this.onCancelButtonClicked = this.onCancelButtonClicked.bind(this); this.onEventContentChanged = this.onEventContentChanged.bind(this); this.onSaveButtonClicked = this.onSaveButtonClicked.bind(this); this.onTagSelectionChanged = this.onTagSelectionChanged.bind(this); } render() { let { event, user, investigationId } = this.props; return <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}> <div style={{ flex: '0 0 33px' }}> <Panel bsStyle='primary' style={{ marginBottom: '0px' }}> <Panel.Heading style={{ padding: '5px 15px' }}> <b>{this.props.event ? "Edit" : "New comment"}</b> <div className="pull-right"> <AuthorAndTime event={event} /> </div> </Panel.Heading> </Panel> </div> <div style={{ flex: '2 2 70%' }}> <EditorWrapper event={event} investigationId={investigationId} onContentChanged={this.onEventContentChanged} user={user} /> </div> <div style={{ flex: '1 1 32px', padding: "5px 10px 0px 10px" }}> <div style={{ display: 'flex' }}> <div style={{ flex: '0 0 70px' }}> <h5 style={{ marginTop: '5px', marginBottom: '5px' }}> <Label style={{ margin: '0px 6px 0px 0px', paddingRight: '2px' }}> Tags </Label> <OverlayTrigger placement='top' overlay={<Tooltip id='tooltip'> <p> Manage tags </p> </Tooltip>}> <a href={"/investigation/" + this.props.investigationId + "/events/tagManager"} target="_blank"> <Glyphicon glyph='cog' /> </a> </OverlayTrigger> </h5> </div> <div style={{ flex: '1 1 100px' }}> <TagsSelectorContainer investigationId={this.props.investigationId} onChange={this.onTagSelectionChanged} tags={this.props.event ? this.props.event.tag : []} /> </div> </div> </div > <div style={{ flex: '0 0 37px' }}> <EventFooter isSaveButtonEnabled={this.isSaveButtonEnabled()} onCancelButtonClicked={() => this.onCancelButtonClicked()} onSaveButtonClicked={() => this.onSaveButtonClicked()} /> </div> </div > } /** * Function triggered when the tag selection has changed * @param {array} selectedTags tags currently selected by the user on the widget */ onTagSelectionChanged(selectedTags) { this.setState({ selectedTags: selectedTags }); } /** * Function triggered when the event content has changed */ onEventContentChanged() { let isEditorContentValid = false; if (this.props.event) { //editing an event let currentTextInEditionMode = localStorage.getItem(LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT + this.props.event._id) isEditorContentValid = (currentTextInEditionMode !== "" && currentTextInEditionMode !== getContent(this.props.event.content, 'plainText')); } else { //creating an event let currentTextInCreationMode = localStorage.getItem(LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT); isEditorContentValid = currentTextInCreationMode !== ""; } this.setState({ isEditorContentValid: isEditorContentValid }) } /** Enable or disable the save button */ isSaveButtonEnabled() { if (this.props.event) { //editing an event return (this.state.isEditorContentValid === true || !_.isEqual(this.props.event.tag.map(tag => tag._id).sort(), this.state.selectedTags.map(tag => tag._id).sort())) } else { //creating an event return (this.state.isEditorContentValid === true) } } /** * Callback function triggered when the user clicks on the cancel button */ onCancelButtonClicked() { if (this.props.event) { // edition of an event this.props.onCancelButtonClicked() } else { // creation of an event localStorage.removeItem('plainText'); localStorage.removeItem('HTMLText'); this.props.onCancelButtonClicked(); } } /** * Callback function triggered when the user click the save button while an event is being created or updated. */ onSaveButtonClicked() { let currentTagIds = this.state.selectedTags.map(tag => tag._id); if (this.props.event) { // edition of an event let { event, user } = this.props; this.props.onSaveButtonClicked({ _id: event._id, category: event.category, content: [ { format: 'plainText', text: localStorage.getItem(LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_PLAINTEXT_FORMAT + event._id) }, { format: 'html', text: localStorage.getItem(LOCALSTORAGE_KEY_EDITED_EVENT_CONTENT_IN_HTML_FORMAT + event._id) } ], creationDate: Date(), type: event.type, tag: currentTagIds, title: null, username: user.username, previousVersionEvent: event._id }); } else { // creation of an event this.props.onSaveButtonClicked({ category: EVENT_CATEGORY_COMMENT, content: [ { format: "plainText", text: localStorage.getItem(LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_PLAINTEXT_FORMAT) }, { format: "html", text: localStorage.getItem(LOCALSTORAGE_KEY_NEW_EVENT_CONTENT_IN_HTML_FORMAT) } ], creationDate: Date(), investigationId: this.props.investigationId, title: null, tag: currentTagIds, type: ANNOTATION, username: this.props.user.username, }) } } } /** Render author and time */ const AuthorAndTime = props => { if (props.event) { return <h5 style={{ marginTop: '0px', marginBottom: '0px' }}> <small style={{ color: 'white' }}> <em> @{props.event.username} - <ReactTimeAgo date={Moment(props.event.creationDate).toDate()} /> <OverlayTrigger trigger='click' placement='bottom' overlay={EventVersions(props.event)} rootClose={true} > <div style={{ display: 'inline-block' }}> <Button bsStyle='link' bsSize='xs'> <Glyphicon glyph='cog' style={{ color: 'white' }} /> </Button> </div> </OverlayTrigger> </em> </small> </h5> } return null; } NewOrEditEventPanel.propTypes = { /* event to edit. Null when a new event is being created. */ event: PropTypes.object, /* investigation identifier */ investigationId: PropTypes.string, /** Function triggered when the user clicks on the save button during event creation or edition*/ onSaveButtonClicked: PropTypes.func, /** Function triggered when the user hits the cancel button */ onCancelButtonClicked : PropTypes.func, /* User who is using this component */ user: PropTypes.object, } export default NewOrEditEventPanel;