<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Plato - helpers/EventHelpers.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>helpers/EventHelpers.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">66.34</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">225</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">31.31</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">1.22</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 Moment from &#039;moment&#039;
import _ from &#039;lodash&#039;
import { Glyphicon } from &#039;react-bootstrap&#039;
import { ANNOTATION, NOTIFICATION, EVENT_CATEGORY_COMMANDLINE, EVENT_CATEGORY_COMMENT, EVENT_CATEGORY_ERROR, EVENT_CATEGORY_INFO, EVENT_CATEGORY_DEBUG } from &#039;../constants/EventTypes&#039;;

//sets global constants
export const COLLAPSED_MODE = &quot;collapsedState&quot;
export const EXPANDED_VIEW_MODE = &quot;expandedViewingState&quot;
export const EDITION_MODE = &quot;expandedEditingState&quot;
export const HISTORY_MODE = &quot;viewingHistoryState&quot;

/**
 * Get the visual representation of the event&#039;s category. Ban cicle Glyph provided when there is no category
 * @param {*} category the event category
 * @param {string} size the size in px of the icon, 25 by default
 */
export function getEventIcon(category, size) {
    let iconSize;
    if (size) {
        iconSize = size + &quot;px&quot;;
    } else {
        iconSize = &quot;25px&quot;;
    }
    if (category) {
        if (category.toLowerCase() === EVENT_CATEGORY_COMMENT) {
            return (&lt;img src=&#039;/comment.png&#039; width={iconSize} alt=&#039;comment.png&#039; /&gt;)
        } else if (category.toLowerCase() === EVENT_CATEGORY_COMMANDLINE) {
            return &lt;Glyphicon glyph=&#039;expand&#039; style={{ fontSize: iconSize, position: &#039;static&#039; }} /&gt;
        } else if (category.toLowerCase() === EVENT_CATEGORY_ERROR) {
            return &lt;Glyphicon glyph=&#039;alert&#039; style={{ fontSize: iconSize, color: &#039;#d03436&#039;, position: &#039;static&#039; }} /&gt;
        } else if (category.toLowerCase() === EVENT_CATEGORY_INFO) {
            return &lt;Glyphicon glyph=&#039;info-sign&#039; style={{ fontSize: iconSize, color: &#039;#3366CC&#039;, position: &#039;static&#039; }} /&gt;
        } else if (category.toLowerCase() === EVENT_CATEGORY_DEBUG) {
            return &lt;Glyphicon glyph=&#039;exclamation-sign&#039; style={{ fontSize: iconSize, color: &#039;gray&#039;, position: &#039;static&#039; }} /&gt;
        }
    }
    // no category was found
    return &lt;Glyphicon glyph=&#039;ban-circle&#039; style={{ fontSize: iconSize }} /&gt;
}

/**
 * A helper function which returns the formatted date the event was created
 * @param {event} event the investigated event
 * @returns {string} the date in the format HH:mm 
*/
export function getEventCreationDate(event) {
    return (Moment(event.creationDate).format(&quot;HH:mm:ss&quot;))
}

/**
 * Get the formatted event creation date for an event history
 * @param {event} event the event to retrieve the creation date from
 * @returns {String} the formatted date under the from  MMM DD YYYY HH:mm a
 */
export function getEventHistoryCreationDate(event) {
    return Moment(event.creationDate).format(&quot;MMM DD YYYY HH:mm:ss&quot;)
}

/**
 * Get the original event which the provided event has modified. This original event is the more nested event inside the provided event.
 * @param {event} event the event which has modified the original event.
 * @return {event} the original event. If there is no original event (ie the provided event is the original event) returns itself.
 */
export function getOriginalEvent(event) {
    let e = event;
    if (e) {
        while (e.previousVersionEvent) {
            e = e.previousVersionEvent;
        }
        return e;
    }
    return null;
}

/**
 * Get the original username for the given event.
 * @param {*} event the event under investigation
 * @returns {string} the original username, null if not found
 */
export function getOriginalUsername(event) {
    let originalEvent = getOriginalEvent(event);
    return originalEvent.username ? originalEvent.username : null;
}

/**
 * Get the number of previous version an given event has.
 * @param {event} event the event which is investigated
 * @returns {number} the number of previous event version which exists
 */
export function getPreviousVersionNumber(event) {
    let e = event;
    if (e) {
        let previousVersionNumber = 0;
        while (e.previousVersionEvent) {
            previousVersionNumber += 1;
            e = e.previousVersionEvent;
        }
        return previousVersionNumber;
    }
    return 0;
}

/**
 * Get the text from a given event content
 * @param {array} content 
 * @param {string} format the requested format (&#039;plainText&#039;, &#039;html&#039;s )
 * @returns {string} the text of content. Null if not found.
 */
export function getContent(content, format) {
    if (content) {
        for (let item of content) {
            if (item.format) {
                if (item.format === format) {
                    if (item.text) {
                        return item.text;
                    }
                }
            }
        }
    }
    return null;
}

/**
* Gets the content of the event as an html string.
* @param {array} the event content, not null
* @returns {string} If the HTML format exists, returns the content in HTML format. If not, returns the plainText formatted content surrounded by &lt;p&gt; &lt;/p&gt;. Null if no format exist. 
*/
export function getContentAsHTML(content) {
    let HTMLText = getContent(content, &#039;html&#039;);
    if (HTMLText) { return HTMLText; }
    else {
        let plainText = getContent(content, &#039;plainText&#039;);
        if (plainText) { return &quot;&lt;p&gt;&quot; + plainText + &quot;&lt;/p&gt;&quot; }
    }
    return null;
}

/**
 * Get the last comment of an event
 * @param {*} event 
 * @returns {array} the content of the comment in all different formats available
 */
export function getLastCommentContent(event) {
    if (event) {
        if (event.type) {
            if (event.type === ANNOTATION) {
                return event.content;
            } else if (event.type === NOTIFICATION) {
                let nbPreviousVersion = getPreviousVersionNumber(event);
                if (nbPreviousVersion &gt; 0) {
                    return event.content
                }
            }
        }
    }
    return null;
}

/**
 * Converts images to thumbnails
 * @param {String} html text containing an HTML node possibly including &lt;img/&gt; elements
 * @returns {String} text containing the same HTML node as the input where each img element as been modified to make the image look like a thumbnail 
 */
export function convertImagesToThumbnails(html) {
    if (html) {
        return html.replace(new RegExp(&#039;img src&#039;, &#039;g&#039;), &#039;img style=&quot;height:200px;width:auto;cursor:zoom-in;&quot; src&#039;);
    }
};

/**
    * Get the first letters of the event content. 
    * @param {array} content the event content
    * @param {integer} nbCharacterToDisplay the number of characters to be returned
    * @returns {string} the portion of plain text composed of the nbCharacterToDisplay first characters
    */
export function getFirstLettersofContent(content, nbCharacterToDisplay) {
    let text = getContent(content, &#039;plainText&#039;);
    if (text) {
        if (nbCharacterToDisplay) {
            if (text.length &gt; nbCharacterToDisplay) {
                return text.slice(0, nbCharacterToDisplay) + &quot; ...&quot;
            } else {
                return text.slice(0, nbCharacterToDisplay)
            }
        } else {
            return text.slice(0, 10) + &quot; ...&quot;
        }
    }

    return &#039;&#039;
}

/**
 * HTTP error parser. THis is meant to handle HTTP error such as 400, 403, 404 creating a general error message for these types of errors.
 * @param {*} error HTTP error
 * @returns {String} Error message
 */
export function parseHTTPError(error) {
    if (error) {
        if (error.response) {
            if (error.response.status === 403) {
                return &#039;You do not have the permission to access this resource.&#039;
            }
        }
    }
    return &#039;An error has occured.&#039;
}

/**
 * Get the sorting order
 * @param {object} sortingFilter sorting filter. Example: { creationDate: 1 }
 * @returns {number} the sorting order (1 or -1) for the field the events are sorted by. 1 =&gt; ascending; -1 =&gt; descending; -1 if not properly setup
 */
export function getSortingOrder(sortingFilter) {
    if (sortingFilter) {
        let sortingOrder = sortingFilter[Object.keys(sortingFilter)[0]];

        if (sortingOrder === 1 || sortingOrder === -1) {
            return sortingOrder;
        }
        return -1;
    }
}</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>
