<commit_before>import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import classnames from 'classnames';
import SideNavContainer from 'src/side_nav';
import {
  publishNotification as publishNotificationAction,
  dismissNotification as dismissNotificationAction,
  dismissAllNotifications as dismissAllNotificationsAction,
} from 'src/shared/actions/notifications';

const App = React.createClass({
  propTypes: {
    children: PropTypes.node.isRequired,
    location: PropTypes.shape({
      pathname: PropTypes.string,
    }),
    params: PropTypes.shape({
      sourceID: PropTypes.string.isRequired,
      base64ExplorerID: PropTypes.string,
    }).isRequired,
    publishNotification: PropTypes.func.isRequired,
    dismissNotification: PropTypes.func.isRequired,
    dismissAllNotifications: PropTypes.func.isRequired,
    notifications: PropTypes.shape({
      success: PropTypes.string,
      error: PropTypes.string,
      warning: PropTypes.string,
    }),
  },

  handleNotification({type, text}) {
    const validTypes = ['error', 'success'];
    if (!validTypes.includes(type) || text === undefined) {
      console.error("handleNotification must have a valid type and text"); // eslint-disable-line no-console
    }
    this.props.publishNotification(type, text);
  },

  handleDismissNotification(type) {
    this.props.dismissNotification(type);
  },

  componentWillReceiveProps(nextProps) {
    if (nextProps.location.pathname !== this.props.location.pathname) {
      this.props.dismissAllNotifications();
    }
  },

  render() {
    const {sourceID, base64ExplorerID} = this.props.params;

    return (
      <div className="enterprise-wrapper--flex">
        <SideNavContainer sourceID={sourceID} explorationID={base64ExplorerID} addFlashMessage={this.handleNotification} currentLocation={this.props.location.pathname} />
        <div className="page-wrapper">
          {this.renderNotifications()}
          {this.props.children && React.cloneElement(this.props.children, {
            addFlashMessage: this.handleNotification,
          })}
        </div>
      </div>
    );
  },

  renderNotifications() {
    const {success, error} = this.props.notifications;
    if (!success && !error) {
      return null;
    }
    return (
      <div className="flash-messages">
        {this.renderNotification('success', success)}
        {this.renderNotification('error', error)}
      </div>
    );
  },

  renderNotification(type, message) {
    if (!message) {
      return null;
    }
    const cls = classnames('alert', {
      'alert-danger': type === 'error',
      'alert-success': type === 'success',
    });
    return (
      <div className={cls} role="alert">
        {message}{this.renderDismiss(type)}
      </div>
    );
  },

  renderDismiss(type) {<commit_msg>Allow for warning messages to be published<commit_after>import React, {PropTypes} from 'react';
import {connect} from 'react-redux';
import classnames from 'classnames';
import SideNavContainer from 'src/side_nav';
import {
  publishNotification as publishNotificationAction,
  dismissNotification as dismissNotificationAction,
  dismissAllNotifications as dismissAllNotificationsAction,
} from 'src/shared/actions/notifications';

const App = React.createClass({
  propTypes: {
    children: PropTypes.node.isRequired,
    location: PropTypes.shape({
      pathname: PropTypes.string,
    }),
    params: PropTypes.shape({
      sourceID: PropTypes.string.isRequired,
      base64ExplorerID: PropTypes.string,
    }).isRequired,
    publishNotification: PropTypes.func.isRequired,
    dismissNotification: PropTypes.func.isRequired,
    dismissAllNotifications: PropTypes.func.isRequired,
    notifications: PropTypes.shape({
      success: PropTypes.string,
      error: PropTypes.string,
      warning: PropTypes.string,
    }),
  },

  handleNotification({type, text}) {
    const validTypes = ['error', 'success', 'warning'];
    if (!validTypes.includes(type) || text === undefined) {
      console.error("handleNotification must have a valid type and text"); // eslint-disable-line no-console
    }
    this.props.publishNotification(type, text);
  },

  handleDismissNotification(type) {
    this.props.dismissNotification(type);
  },

  componentWillReceiveProps(nextProps) {
    if (nextProps.location.pathname !== this.props.location.pathname) {
      this.props.dismissAllNotifications();
    }
  },

  render() {
    const {sourceID, base64ExplorerID} = this.props.params;

    return (
      <div className="enterprise-wrapper--flex">
        <SideNavContainer sourceID={sourceID} explorationID={base64ExplorerID} addFlashMessage={this.handleNotification} currentLocation={this.props.location.pathname} />
        <div className="page-wrapper">
          {this.renderNotifications()}
          {this.props.children && React.cloneElement(this.props.children, {
            addFlashMessage: this.handleNotification,
          })}
        </div>
      </div>
    );
  },

  renderNotifications() {
    const {success, error, warning} = this.props.notifications;
    if (!success && !error && !warning) {
      return null;
    }
    return (
      <div className="flash-messages">
        {this.renderNotification('success', success)}
        {this.renderNotification('error', error)}
        {this.renderNotification('warning', warning)}
      </div>
    );
  },

  renderNotification(type, message) {
    if (!message) {
      return null;
    }
    const cls = classnames('alert', {
      'alert-danger': type === 'error',
      'alert-success': type === 'success',
      'alert-warning': type === 'warning',
    });
    return (
      <div className={cls} role="alert">
        {message}{this.renderDismiss(type)}
      </div>
    );
  },

  renderDismiss(type) {
{'fraction_non_alphanumeric': 0.13090720938254571, 'fraction_numerical': 0.002069679199724043, 'mean_word_length': 3.4098859315589354, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2302515', 'n_tokens_mistral': 1635, 'n_tokens_neox': 1622, 'n_words': 316}