<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Plato - components/Event/DetailedEvent.js</title>

  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="">
  <meta name="author" content="">

  <!--[if lt IE 9]>
  <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
  <![endif]-->

  <link href="../../assets/css/vendor/morris.css" rel="stylesheet" type="text/css">
  <link href="../../assets/css/vendor/bootstrap.css" rel="stylesheet" type="text/css">
  <link href="../../assets/css/vendor/font-awesome.css" rel="stylesheet" type="text/css">
  <link href="../../assets/css/vendor/codemirror.css" rel="stylesheet" type="text/css">
  <link href="../../assets/css/plato.css" rel="stylesheet" type="text/css">
  <link href="../../assets/css/plato-file.css" rel="stylesheet" type="text/css">

</head>

<body>

<div class="navbar navbar-fixed-top">
  <div class="container">
    <a class="navbar-brand" href="https://github.com/the-simian/es6-plato">ES6 Plato on Github</a>
    <ul class="nav navbar-nav">
      <li>
        <a href="../../index.html">Report Home</a>
      </li>
      <li class="active">
        <a href="display.html">Summary Display</a>
      </li>
    </ul>
  </div>
</div>

<div class="jumbotron">
  <div class="container">
    <h1>components/Event/DetailedEvent.js</h1>
  </div>
</div>

<div class="container aggregate-stats">
  <div class="row">
    <div class="col-md-6">
      <h2 class="header">Maintainability <a href="http://blogs.msdn.com/b/codeanalysis/archive/2007/11/20/maintainability-index-range-and-meaning.aspx"><i class="icon icon-info-sign" rel="popover" data-placement="top" data-trigger="hover" data-content="A value between 0 and 100 that represents the relative ease of maintaining the code. A high value means better maintainability." data-original-title="Maintainability Index"  data-container="body"></i></a></h2>
      <p class="stat">63.97</p>
    </div>
    <div class="col-md-6">
      <h2 class="header">Lines of code <i class="icon icon-info-sign" rel="popover" data-placement="top" data-trigger="hover" data-content="Source Lines of Code / Logical Lines of Code" data-original-title="SLOC/LSLOC" data-container="body"></i></h2>
      <p class="stat">557</p>
    </div>
  </div>
  <div class="row historical">
    <div class="col-md-6">
      <p id="chart_historical_maint" class="chart"></p>
    </div>
    <div class="col-md-6">
      <p id="chart_historical_sloc" class="chart"></p>
    </div>
  </div>
  <div class="row">
    <div class="col-md-6">
      <h2 class="header">Difficulty  <a href="http://en.wikipedia.org/wiki/Halstead_complexity_measures"><i class="icon icon-info-sign" rel="popover" data-placement="top" data-trigger="hover" data-content="The difficulty measure is related to the difficulty of the program to write or understand." data-original-title="Difficulty" data-container="body"></i></a></h2>
      <p class="stat">55.89</p>
    </div>
    <div class="col-md-6">
      <h2 class="header">Estimated Errors  <a href="http://en.wikipedia.org/wiki/Halstead_complexity_measures"><i class="icon icon-info-sign" rel="popover" data-placement="top" data-trigger="hover" data-content="Halstead's delivered bugs is an estimate for the number of errors in the implementation." data-original-title="Delivered Bugs" data-container="body"></i></a></h2>
      <p class="stat">3.84</p>
    </div>
  </div>
</div>

<div class="container charts">
  <div class="row">
    <h2 class="header">Function weight</h2>
  </div>
  <div class="row">
    <div class="col-md-6">
      <h3 class="chart-header">By Complexity <a href="http://en.wikipedia.org/wiki/Cyclomatic_complexity"><i class="icon icon-info-sign" rel="popover" data-placement="top" data-trigger="hover" data-content="This metric counts the number of distinct paths through a block of code. Lower values are better." data-original-title="Cyclomatic Complexity" data-container="body"></i></a></h3>
      <div id="fn-by-complexity" class="stat"></div>
    </div>
    <div class="col-md-6">
      <h3 class="chart-header">By SLOC  <i class="icon icon-info-sign" rel="popover" data-placement="top" data-trigger="hover" data-content="Source Lines of Code / Logical Lines of Code" data-original-title="SLOC/LSLOC" data-container="body"></i></h3>
      <div id="fn-by-sloc" class="stat"></div>
    </div>
  </div>
</div>

<div class="container">
  <div class="row">
    <textarea id="file-source" class="col-md-12">import React from &#039;react&#039;;
import { Row, Col, OverlayTrigger, Tooltip, Popover, Button, Well, Label, FormControl, InputGroup, Glyphicon } from &#039;react-bootstrap&#039;;
import { getEventCreationDate, getEventHistoryCreationDate, getOriginalEvent, getPreviousVersionNumber, getEventIcon } from &#039;../../helpers/EventHelpers&#039;;

import EventFooter from &#039;./EventFooter&#039;;
import { ANNOTATION, NOTIFICATION, READ_MODE, DETAILED_EVENT_CONTEXT } from &#039;../../constants/EventTypes&#039;;
import PropTypes from &#039;prop-types&#039;;
import EventContentDisplayer from &#039;./EventContentDisplayer&#039;;
import Popup from &#039;reactjs-popup&#039;;
import Moment from &#039;moment&#039;;
import EventVersion from &#039;./EventVersion&#039;;
import _ from &#039;lodash&#039;;
import TagContainer from &#039;../../containers/TagContainer&#039;;


/**
 * A detailed event of the logbook.
 */
class DetailedEvent extends React.Component {
    constructor(props) {
        super(props);

        // Initialize state
        this.state = {
            isSaveButtonEnabled: false, // whether the event is valid ie can be saved
            isEditorContentValid: false
        };

        this.canEnableSaveButton = this.canEnableSaveButton.bind(this);
        this.onCancelButtonClicked = this.onCancelButtonClicked.bind(this);
        this.onSuccessfullyUpdated = this.onSuccessfullyUpdated.bind(this);
        this.setTitleInput = this.setTitleInput.bind(this);
        this.setTagContainer = this.setTagContainer.bind(this);
        this.updateEvent = this.updateEvent.bind(this);
    }

    render() {
        let { event, user } = this.props;

        if (event.type === ANNOTATION || event.type === NOTIFICATION) {
            return (
                &lt;div id=&#039;editionBox&#039; style={{ display: &#039;flex&#039; }} &gt;

                    {/* the left panel */}
                    &lt;div style={{ flexGrow: &#039;0&#039;, maxWidth: &#039;155px&#039; }}&gt;
                        &lt;div className=&#039;pull-right&#039; style={{ paddingRight: &#039;8px&#039; }}&gt;
                            {getEventIcon(event.category, &#039;20&#039;)}
                        &lt;/div&gt;

                        &lt;div style={{ paddingLeft: &#039;5px&#039; }} &gt;
                            &lt;div style={{ height: &#039;50px&#039; }} /&gt;

                            &lt;OverlayTrigger
                                placement=&#039;top&#039;
                                overlay={&lt;Tooltip id=&#039;tooltip&#039;&gt; &lt;p&gt; Manage tags &lt;/p&gt; &lt;/Tooltip&gt;}&gt;

                                &lt;a href={&#039;/investigation/&#039; + this.props.investigationId + &#039;/events/tagManager&#039;}
                                    target=&#039;_blank&#039;
                                    style={{ float: &#039;right&#039;, paddingRight: &#039;10px&#039;, color: &#039;#777&#039;, marginTop: &#039;2px&#039; }}&gt;
                                    &lt;Glyphicon glyph=&#039;cog&#039; /&gt;
                                &lt;/a&gt;
                            &lt;/OverlayTrigger&gt;

                            &lt;Label&gt; Tags &lt;/Label&gt;
                            &lt;div style={{ paddingTop: &#039;5px&#039;, marginRight: &#039;10px&#039; }}&gt;
                                &lt;TagContainer
                                    canEnableSaveButton={this.canEnableSaveButton}
                                    context={DETAILED_EVENT_CONTEXT}
                                    event={event}
                                    investigationId={this.props.investigationId}
                                    setTagContainer={this.setTagContainer}
                                /&gt;
                            &lt;/div&gt;

                            &lt;hr id=&#039;hrEvents&#039; /&gt;

                            &lt;Label&gt; Creation date &lt;/Label&gt;
                            &lt;OverlayTrigger
                                placement=&#039;right&#039;
                                overlay={
                                    &lt;Tooltip id=&#039;tooltip&#039;&gt;
                                        &lt;p&gt; Event created on {getEventHistoryCreationDate(getOriginalEvent(event))} &lt;/p&gt;
                                    &lt;/Tooltip&gt;
                                }&gt;
                                &lt;div&gt;
                                    &lt;div style={{ paddingTop: &#039;5px&#039;, paddingLeft: &#039;10px&#039;, color: &#039;#666666&#039; }}&gt;
                                        {getEventCreationDate(getOriginalEvent(event))}
                                    &lt;/div&gt;
                                &lt;/div&gt;
                            &lt;/OverlayTrigger&gt;

                            &lt;hr id=&#039;hrEvents&#039; /&gt;

                            &lt;CommentBy event={event} /&gt;

                            &lt;div style={{ position: &#039;relative&#039; }}&gt;
                                &lt;div &gt;
                                    &lt;OverlayTrigger
                                        trigger=&#039;click&#039;
                                        placement=&#039;top&#039;
                                        overlay={eventVersionsPopover(event)}
                                        rootClose={true}
                                    &gt;
                                        &lt;Label&gt;  History &lt;div className=&#039;arrow-down&#039; /&gt; &lt;/Label&gt;
                                    &lt;/OverlayTrigger&gt;
                                &lt;/div&gt;
                            &lt;/div&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                    &lt;div
                        style={{ flexGrow: &#039;1&#039; }}&gt;

                        {(event.type === ANNOTATION) ? &lt;AnnotationContent
                            canEnableSaveButton={this.canEnableSaveButton}
                            event={event}
                            investigationId={this.props.investigationId}
                            setTitleInput={this.setTitleInput}
                            user={user}
                        /&gt; : null}
                        {(event.type === NOTIFICATION) ? &lt;NotificationContent
                            canEnableSaveButton={this.canEnableSaveButton}
                            event={event}
                            investigationId={this.props.investigationId}
                            user={user}
                        /&gt; : null}

                        &lt;EventFooter
                            onCancelButtonClicked={this.onCancelButtonClicked}
                            onSaveButtonClicked={this.updateEvent}
                            isSaveButtonEnabled={this.state.isSaveButtonEnabled} /&gt;
                    &lt;/div&gt;
                &lt;/div &gt;);
        } else {
            console.log(&#039;[ERROR] Event (&#039; + event._id + &#039;) not shown because its type is not annotation and not notification. &#039;);
            return null;
        };
    }

    updateEvent() {
        let { investigationId, event, user } = this.props;

        // get tags
        let currentTagIds = this.tagContainer.state.selectedTags.map((tag) =&gt; tag._id);

        let updatedEvent = {
            _id: event._id,
            category: event.category,
            content: [
                {
                    format: &#039;plainText&#039;,
                    text: localStorage.getItem(&#039;plainText&#039;)
                },
                {
                    format: &#039;html&#039;,
                    text: localStorage.getItem(&#039;HTMLText&#039;)
                }
            ],
            creationDate: Date(),
            type: event.type,
            tags: currentTagIds,
            title: (this.inputTitle &amp;&amp; this.inputTitle.props) ? this.inputTitle.props.value : null,
            username: user.username,
            previousVersionEvent: event._id
        };
        this.props.updateEvent(updatedEvent, user.sessionId, investigationId, this.onSuccessfullyUpdated);
    }

    /** Callback executed when the event has been successfully updated on the server side*/
    onSuccessfullyUpdated(updatedEvent) {
        this.props.toggleMode(READ_MODE); //this makes sure the mode is changed in case the event is updated.
        this.props.onEventUpdated(updatedEvent);
    }

    /**
     * Callback function triggered when the user click the cancel button
     * @param {*} e the browser&#039;s event
    */
    onCancelButtonClicked(e) {
        e.stopPropagation();
        this.props.toggleMode(READ_MODE);
    }

    /**
    * Callback function called when the text of the editor changed from empty to something or vice versa
    * @param {object} change an object containing the properties:
    *   -1- hasText boolean which indicates whether the editor content has text or not; not null
    *   -2- currentTextEqualsOriginal, boolean, which indicates whether the current content is the same as the original content; not null
    */
    canEnableSaveButton(change) {
        let hasEventTitleChangedFromItsOriginalValue =
            this.inputTitle &amp;&amp;
            this.props.event &amp;&amp;
            this.inputTitle.props.value !== this.props.event.title;

        let hasEventTagsChangedFromItsOriginalValue =
            this.tagContainer &amp;&amp;
            this.props.event &amp;&amp;
            !(_.isEqual(this.tagContainer.state.selectedTags.map((tag) =&gt; tag._id), this.props.event.tag));

        if (hasEventTitleChangedFromItsOriginalValue || hasEventTagsChangedFromItsOriginalValue) {
            /* title is not the same as original. can save (even with no content) */
            if (this.state.isSaveButtonEnabled !== true) { this.setState({ isSaveButtonEnabled: true }); }
        } else {
            /* title is the same as original */
            if (change) {
                /* triggered from the editor */
                let hasText = null;
                let currentTextEqualsOriginal = null;
                if (&#039;hasText&#039; in change) { hasText = change.hasText; };
                if (&#039;currentTextEqualsOriginal&#039; in change) {
                    currentTextEqualsOriginal = change.currentTextEqualsOriginal;
                };
                if (!hasText) {
                    // there is no text in the editor
                    if (this.state.isEditorContentValid !== false) {
                        this.setState({
                            isEditorContentValid: false,
                            isSaveButtonEnabled: false
                        });
                    };
                } else {
                    // there is text in the editor
                    if (currentTextEqualsOriginal === undefined || currentTextEqualsOriginal === null) {
                        if (this.state.isEditorContentValid !== false) {
                            this.setState({
                                isEditorContentValid: false,
                                isSaveButtonEnabled: false
                            });
                        };
                    } else if (currentTextEqualsOriginal) {
                        // current text in the editor equals the original text
                        if (this.state.isEditorContentValid !== false) {
                            this.setState({
                                isEditorContentValid: false,
                                isSaveButtonEnabled: false
                            });
                        };
                    } else {
                        if (this.state.isEditorContentValid !== true) {
                            this.setState({
                                isEditorContentValid: true,
                                isSaveButtonEnabled: !hasEventTitleChangedFromItsOriginalValue
                            });
                        };
                    };
                }
            } else {
                if (!this.state.isEditorContentValid) {
                    /* Editor content is not valid. Can not save */
                    if (this.state.isSaveButtonEnabled !== false) { this.setState({ isSaveButtonEnabled: false }); }
                };
            };
        };
    }

    setTitleInput(element) {
        this.inputTitle = element;
    }

    setTagContainer(element) {
        this.tagContainer = element;
    }
}

DetailedEvent.propTypes = {
    /** the event object as received from the ICAT+ server */
    event: PropTypes.object.isRequired,
    /** the investigationId which the events belong to. */
    investigationId: PropTypes.string.isRequired,
    /**Callback function triggered when the user updated an existing event */
    onEventUpdated: PropTypes.func,
    /* Callback function used to change from one mode to the other READ_MODE vs EDIT_MODE*/
    toggleMode: PropTypes.func.isRequired,
    /** the user who is currently logged in */
    user: PropTypes.object.isRequired,
};

/**
* Render the popup which displays all event versions of the event
* @param {*} event the event under investigation
        */
function eventVersionsPopover(event) {
    let e = event;


    /* build the different lines representing the previous versions */
    let lines = [];
    while (e.previousVersionEvent != null) {
        if (lines.length === 0) {
            lines.push(&lt;EventVersionItem event={e} type=&#039;edition&#039; mostRecent={true} /&gt;);
        } else {
            lines.push(&lt;EventVersionItem event={e} type=&#039;edition&#039; mostRecent={false} /&gt;);
        };
        e = e.previousVersionEvent;
    }
    lines.push(&lt;EventVersionItem event={e} type=&#039;creation&#039; /&gt;);


    /* build the popover */
    return (&lt;Popover id=&#039;mypopover&#039;&gt;
        &lt;div&gt;
            &lt;p style={{ marginBottom: &#039;5px&#039; }}&gt; This log has {getPreviousVersionNumber(event) + 1} versions. &lt;/p&gt;
            &lt;hr style={{ marginTop: &#039;5px&#039; }} /&gt;
            {lines.map((item, index) =&gt; &lt;Popup
                key={index}
                trigger={&lt;div&gt; {item} &lt;/div&gt;}
                modal
                closeOnDocumentClick={false}
                contentStyle={{ width: &#039;90%&#039;, height: &#039;90%&#039; }}
            &gt;
                {close =&gt; (
                    &lt;div className=&#039;fullPage&#039;&gt;
                        &lt;a className=&#039;close&#039; onClick={close}&gt; &amp;times; &lt;/a&gt;
                        &lt;div className=&#039;content&#039;&gt;
                            &lt;EventVersion
                                event={item.props.event}
                                isLatestVersion={(index === 1) ? true : false}
                                isOriginalVersion={(index === lines.length - 1) ? true : false}
                            /&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                )}
            &lt;/Popup&gt;
            )}
            &lt;hr style={{ marginBottom: &#039;5px&#039; }} /&gt;

            &lt;Popup
                trigger={&lt;div style={{ display: &#039;inline&#039; }}&gt; &lt;Button bsStyle=&#039;link&#039;&gt; See all versions  &lt;/Button&gt; &lt;/div&gt;}
                modal
                closeOnDocumentClick={false}
                contentStyle={{ width: &#039;90%&#039;, height: &#039;90%&#039; }}
            &gt;
                {close =&gt; (
                    &lt;div className=&#039;fullPage&#039;&gt;
                        &lt;a className=&#039;close&#039; onClick={close}&gt; &amp;times; &lt;/a&gt;
                        &lt;div className=&#039;content&#039;&gt;
                            &lt;CompleteEventHistory event={event} /&gt;
                        &lt;/div&gt;
                    &lt;/div&gt;
                )}
            &lt;/Popup&gt;

        &lt;/div&gt;
    &lt;/Popover&gt;);
}

/**
 * React component which represents the content of an annotation
* @param {*} props the props passed to this component
        */
class AnnotationContent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            inputTitleValue: this.props.event.title || &#039;&#039;
        };

        this.onChangeInputValue = this.onChangeInputValue.bind(this);
    }

    onChangeInputValue(e) {
        this.setState({ inputTitleValue: e.target.value });
    }

    render() {
        let { event, investigationId, user } = this.props;

        if (event.type &amp;&amp; event.type === ANNOTATION) {
            return (
                &lt;div&gt;
                    &lt;EventContentDisplayer
                        content={event.content}
                        useRichTextEditor={true}
                        isEditionMode={true}
                        user={user}
                        investigationId={investigationId}
                        canEnableSaveButton={this.props.canEnableSaveButton}
                    /&gt;

                    &lt;div style={{ paddingTop: &#039;8px&#039; }}&gt;
                        &lt;InputGroup&gt;
                            &lt;InputGroup.Addon style={{ backgroundColor: &#039;transparent&#039;, border: &#039;none&#039; }}&gt; &lt;Label&gt; Title &lt;/Label&gt; &lt;/InputGroup.Addon&gt;
                            &lt;FormControl
                                type=&#039;text&#039;
                                value={this.state.inputTitleValue}
                                onChange={this.onChangeInputValue}
                                placeholder=&#039;Optional title here&#039;
                                ref={this.props.setTitleInput}
                            /&gt;
                        &lt;/InputGroup&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
            );
        };
    }

    componentDidUpdate() {
        this.props.canEnableSaveButton();
    }
}

AnnotationContent.propTypes = {
    /* the callback function which activates the save button */
    canEnableSaveButton: PropTypes.func.isRequired,
    /* The event to be shown */
    event: PropTypes.object.isRequired,
    /* the investigationId */
    investigationId: PropTypes.string.isRequired,
    /* the callback function which adds a ref to this */
    setTitleInput: PropTypes.func.isRequired,
    /* the user */
    user: PropTypes.object.isRequired
};

/**
 * React component which represents the content of an notification
* @param {*} props  the props passed to this component
        */
const NotificationContent = (props) =&gt; {
    let { event, investigationId, user } = props;

    let notificationMessage = getOriginalEvent(event);

    if (event.type &amp;&amp; event.type === NOTIFICATION) {
        let editorContent;
        if (getPreviousVersionNumber(event) === 0) {
            let fakeContent = [{ format: &#039;html&#039;, text: &#039;&lt;p&gt; &lt;/p&gt;&#039; }];
            editorContent = (&lt;EventContentDisplayer
                content={fakeContent}
                useRichTextEditor={true}
                isEditionMode={true}
                user={user}
                investigationId={investigationId}
                canEnableSaveButton={props.canEnableSaveButton}
            /&gt;);
        } else {
            editorContent = (&lt;EventContentDisplayer
                content={event.content}
                useRichTextEditor={true}
                isEditionMode={true}
                user={user}
                investigationId={investigationId}
                canEnableSaveButton={props.canEnableSaveButton}
            /&gt;);
        };

        return (
            &lt;div&gt;
                &lt;div style={{ marginLeft: &#039;10px&#039; }} &gt;
                    &lt;div id=&#039;divContainingHTMLNotificationInDocView&#039;&gt;
                        &lt;EventContentDisplayer
                            content={notificationMessage.content}
                            useRichTextEditor={false}
                            isEditionMode={false}
                        /&gt;
                    &lt;/div&gt;
                &lt;/div&gt;
                {editorContent}
            &lt;/div&gt;
        );
    };
};

NotificationContent.propTypes = {
    /* the callback function which activates the save button */
    canEnableSaveButton: PropTypes.func.isRequired,
    /* The event to be shown */
    event: PropTypes.object.isRequired,
    /* the investigationId */
    investigationId: PropTypes.string.isRequired,
    /* the user */
    user: PropTypes.object.isRequired
};

/**
 * React component which represents the commentBy part.
* @param {*} props
            */
const CommentBy = (props) =&gt; {
    let { event } = props;
    if (getPreviousVersionNumber(event) === 0) {
        return (
            &lt;div&gt;
                &lt;Label&gt; Created by &lt;/Label&gt;
                &lt;div style={{ paddingTop: &#039;5px&#039;, paddingLeft: &#039;10px&#039; }}&gt;
                    &lt;p style={{ color: &#039;#666666&#039; }}&gt; {props.event.username} &lt;/p&gt;
                &lt;/div&gt;
                &lt;hr id=&#039;hrEvents&#039; /&gt;
            &lt;/div&gt;
        );
    };
    if (getPreviousVersionNumber(event) !== 0) {
        return (
            &lt;div&gt;
                &lt;Label&gt; Commented by &lt;/Label&gt;
                &lt;div style={{ paddingTop: &#039;5px&#039;, paddingLeft: &#039;10px&#039; }}&gt;
                    &lt;p style={{ color: &#039;#666666&#039; }}&gt; {props.event.username} &lt;/p&gt;
                &lt;/div&gt;
                &lt;hr id=&#039;hrEvents&#039; /&gt;
            &lt;/div&gt;
        );
    };
    return null;
};

/**
 * React component which represents on item of the event history
* @param {*} props  the props passed to this component
                */
class EventVersionItem extends React.Component {
    render() {
        function buildTheDisplay(event, type, mostRecent) {
            return (
                &lt;Well bsSize=&#039;small&#039; style={{ marginBottom: &#039;5px&#039;, cursor: &#039;pointer&#039; }}&gt;
                    &lt;b&gt; {event.username} &lt;/b&gt;
                    {type === &#039;creation&#039; ? &#039;created on &#039; : &#039;&#039;}
                    {type === &#039;edition&#039; ? &#039;edited on &#039; : &#039;&#039;}
                    {Moment(event.creationDate).format(&#039;MMMM DD HH:mm&#039;)}
                    {mostRecent === true ? &#039; (most recent)&#039; : &#039;&#039;}
                    {event.machine ? &lt;span style={{ color: &#039;#777777&#039;, fontStyle: &#039;italic&#039; }}&gt; from {event.machine} &lt;/span&gt; : &#039;&#039;}
                &lt;/Well&gt;
            );
        };

        return (
            buildTheDisplay(this.props.event, this.props.type, this.props.mostRecent)
        );
    };
};

/**
 * React component which displays the complete event history
 */
const CompleteEventHistory = (props) =&gt; {
    let { event } = props;
    let eventVersions = [];

    /* first push the current event which is the latest version of the event*/
    //eventHistoryItems.push(&lt;EventListViewExpanded event={event} isFullPage={true} /&gt;)
    eventVersions.push(&lt;EventVersion event={event} isLatestVersion={true} /&gt;);
    /* then display the previous version of this event */
    while (event.previousVersionEvent != null) {
        event = event.previousVersionEvent;
        eventVersions.push(&lt;div class=&#039;margin-bottom-10&#039;&gt;
            &lt;Row&gt;
                &lt;Col xs={1}&gt; &lt;/Col&gt;
                &lt;Col xs={11}&gt;
                    &lt;EventVersion event={event} isOriginalVersion={event.previousVersionEvent === null ? true : false} /&gt;
                &lt;/Col&gt;
            &lt;/Row&gt;
        &lt;/div&gt;);
    };

    return eventVersions;
};

export default DetailedEvent;</textarea>
  </div>
</div>

<footer class="footer">
  <div class="container">
    <p>.</p>
  </div>
</footer>

<script type="text/html" id="complexity-popover-template">
  <div class="complexity-notice">
    Complexity : {{ complexity.cyclomatic }} <br>
    Length : {{ complexity.halstead.length }} <br>
    Difficulty : {{ complexity.halstead.difficulty.toFixed(2) }} <br>
    Est # bugs : {{ complexity.halstead.bugs.toFixed(2) }}<br>
  </div>
</script>

<script type="text/javascript" src="../../assets/scripts/bundles/core-bundle.js"></script>
<script type="text/javascript" src="../../assets/scripts/bundles/codemirror.js"></script>
<script type="text/javascript" src="../../assets/scripts/codemirror.markpopovertext.js"></script>
<script type="text/javascript" src="report.js"></script>
<script type="text/javascript" src="report.history.js"></script>
<script type="text/javascript" src="../../assets/scripts/plato-file.js"></script>
</body>
</html>
