<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2015 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

// Define the name of the uncommitted model.
const NO_MODEL = 'untitled-model';

// This component handles the GUI header, in which the breadcrumb is
// displayed, including information about the current model and all other
// available models.
const HeaderBreadcrumb = React.createClass({
  propTypes: {
    acl: React.PropTypes.object.isRequired,
    appState: React.PropTypes.object.isRequired,
    changeState: React.PropTypes.func.isRequired,
    humanizeTimestamp: React.PropTypes.func.isRequired,
    listModelsWithInfo: React.PropTypes.func,
    loadingModel: React.PropTypes.bool,
    modelName: React.PropTypes.string,
    modelOwner: React.PropTypes.string,
    showEnvSwitcher: React.PropTypes.bool.isRequired,
    showProfile: React.PropTypes.func.isRequired,
    switchModel: React.PropTypes.func.isRequired,
    user: React.PropTypes.object
  },

  getDefaultProps: function() {
    return {
      loadingModel: false
    };
  },

  /**
    Returns the classes for the button based on the provided props.
    @method _generateClasses
    @returns {String} The collection of class names.
  */
  _generateClasses: function() {
    return classNames('header-breadcrumb', {
      'header-breadcrumb--loading-model': this.props.loadingModel
    });
  },

  /**
    Renders the markup for the Env Switcher if the showEnvSwitcher prop is
    truthy.

    @method _renderEnvSwitcher
  */
  _renderEnvSwitcher: function() {
    const props = this.props;
    const currentState = props.appState.current;
    if (
      !props.showEnvSwitcher ||
      currentState.profile ||
      currentState.root === 'account'
    ) {
      return null;
    }
    return (
      <li className="header-breadcrumb__list-item">
        <window.juju.components.EnvSwitcher
          acl={this.props.acl}
          user={this.props.user}
          changeState={this.props.changeState}
          environmentName={this.props.modelName}
          humanizeTimestamp={this.props.humanizeTimestamp}
          listModelsWithInfo={this.props.listModelsWithInfo}
          switchModel={this.props.switchModel}
        />
      </li>);
  },

  /**
    Handles clicks on the profile link. Does not navigate to the profile
    if we aren't showing the model switcher.

    @method _handleProfileClick
    @param {String} username The name of the profile.
    @param {Object} evt The click event.
  */
  _handleProfileClick: function(username, evt) {
    evt.preventDefault();
    if (!this.props.showEnvSwitcher) {
      // Nothing to be done: we are already in the profile view.
      return;
    }
    this.props.showProfile(username);
  },

  /**
    Generate the model owner link. If there is no model or if the owner is
    not available yet, fall back to showing the current logged in user.

    TODO frankban: this requires a better UX. We can no longer assume that
    the second part of the breadcrumb is the logged in user, and so we need a
    new element showing who currently you are.

    @method _generateOwnerLink
  */
  _generateOwnerLink: function() {
    const currentState = this.props.appState.current;
    if (currentState && currentState.profile) {
      return this._buildProfile(currentState.profile);
    }
    const modelOwner = this.props.modelOwner;
    const modelName = this.props.modelName;
    if (!modelOwner || !modelName || modelName === NO_MODEL) {
      // There are no models so just render the current user instead.
      return this._generateUserLink();
    }
    return this._buildProfile(modelOwner.split('@')[0]);
  },

  /**
    Generate the user link. If we aren't showing the model switcher then the
    link to the profile does not turn the users cursor to a pointer because
    we disable the profile functionality in that case.

    @method _generateUserLink
  */
  _generateUserLink: function() {
    const user = this.props.user;
    if (user) {
      return this._buildProfile(user.displayName);
    }
    return null;
  },

  /**
    Build a link for the given user name.

    @method _buildProfile
    @param {String} username The name of the profile.
  */
  _buildProfile: function(username) {
    const props = this.props;
    const linkClasses = classNames('header-breadcrumb--link', {
      'profile-disabled': !props.showEnvSwitcher
    });
    const onClick = this._handleProfileClick.bind(this, username);
    const profileUrl = props.appState.generatePath({profile: username});
    return (
      <li className="header-breadcrumb__list-item">
        <a className={linkClasses}
          onClick={onClick}
          href={profileUrl}
          title={username}>
          {username}
        </a>
      </li>
    );
  },

  render: function() {
    const props = this.props;
    const userItem = this._generateOwnerLink();
    const user = props.user;
    return (
      <div className={this._generateClasses()}>
        <div className="header-breadcrumb__loading">Loading model</div>
        <ul className="header-breadcrumb__list"
          // This attribute is required by uitests.
          data-username={user && user.displayName}>
          {userItem}
          {this._renderEnvSwitcher()}
        </ul>
      </div>
    );
  }

});

YUI.add('header-breadcrumb', function() {
  juju.components.HeaderBreadcrumb = HeaderBreadcrumb;
}, '0.1.0', {
  requires: [
    'env-switcher'
  ]
});<commit_msg>Update HeaderBreadcrumb to use es6 class.<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2015 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

// Define the name of the uncommitted model.
const NO_MODEL = 'untitled-model';

// This component handles the GUI header, in which the breadcrumb is
// displayed, including information about the current model and all other
// available models.
class HeaderBreadcrumb extends React.Component {
  /**
    Returns the classes for the button based on the provided props.
    @method _generateClasses
    @returns {String} The collection of class names.
  */
  _generateClasses() {
    return classNames('header-breadcrumb', {
      'header-breadcrumb--loading-model': this.props.loadingModel
    });
  }

  /**
    Renders the markup for the Env Switcher if the showEnvSwitcher prop is
    truthy.

    @method _renderEnvSwitcher
  */
  _renderEnvSwitcher() {
    const props = this.props;
    const currentState = props.appState.current;
    if (
      !props.showEnvSwitcher ||
      currentState.profile ||
      currentState.root === 'account'
    ) {
      return null;
    }
    return (
      <li className="header-breadcrumb__list-item">
        <window.juju.components.EnvSwitcher
          acl={this.props.acl}
          user={this.props.user}
          changeState={this.props.changeState}
          environmentName={this.props.modelName}
          humanizeTimestamp={this.props.humanizeTimestamp}
          listModelsWithInfo={this.props.listModelsWithInfo}
          switchModel={this.props.switchModel}
        />
      </li>);
  }

  /**
    Handles clicks on the profile link. Does not navigate to the profile
    if we aren't showing the model switcher.

    @method _handleProfileClick
    @param {String} username The name of the profile.
    @param {Object} evt The click event.
  */
  _handleProfileClick(username, evt) {
    evt.preventDefault();
    if (!this.props.showEnvSwitcher) {
      // Nothing to be done: we are already in the profile view.
      return;
    }
    this.props.showProfile(username);
  }

  /**
    Generate the model owner link. If there is no model or if the owner is
    not available yet, fall back to showing the current logged in user.

    TODO frankban: this requires a better UX. We can no longer assume that
    the second part of the breadcrumb is the logged in user, and so we need a
    new element showing who currently you are.

    @method _generateOwnerLink
  */
  _generateOwnerLink() {
    const currentState = this.props.appState.current;
    if (currentState && currentState.profile) {
      return this._buildProfile(currentState.profile);
    }
    const modelOwner = this.props.modelOwner;
    const modelName = this.props.modelName;
    if (!modelOwner || !modelName || modelName === NO_MODEL) {
      // There are no models so just render the current user instead.
      return this._generateUserLink();
    }
    return this._buildProfile(modelOwner.split('@')[0]);
  }

  /**
    Generate the user link. If we aren't showing the model switcher then the
    link to the profile does not turn the users cursor to a pointer because
    we disable the profile functionality in that case.

    @method _generateUserLink
  */
  _generateUserLink() {
    const user = this.props.user;
    if (user) {
      return this._buildProfile(user.displayName);
    }
    return null;
  }

  /**
    Build a link for the given user name.

    @method _buildProfile
    @param {String} username The name of the profile.
  */
  _buildProfile(username) {
    const props = this.props;
    const linkClasses = classNames('header-breadcrumb--link', {
      'profile-disabled': !props.showEnvSwitcher
    });
    const onClick = this._handleProfileClick.bind(this, username);
    const profileUrl = props.appState.generatePath({profile: username});
    return (
      <li className="header-breadcrumb__list-item">
        <a className={linkClasses}
          onClick={onClick}
          href={profileUrl}
          title={username}>
          {username}
        </a>
      </li>
    );
  }

  render() {
    const props = this.props;
    const userItem = this._generateOwnerLink();
    const user = props.user;
    return (
      <div className={this._generateClasses()}>
        <div className="header-breadcrumb__loading">Loading model</div>
        <ul className="header-breadcrumb__list"
          // This attribute is required by uitests.
          data-username={user && user.displayName}>
          {userItem}
          {this._renderEnvSwitcher()}
        </ul>
      </div>
    );
  }
};

HeaderBreadcrumb.propTypes = {
  acl: React.PropTypes.object.isRequired,
  appState: React.PropTypes.object.isRequired,
  changeState: React.PropTypes.func.isRequired,
  humanizeTimestamp: React.PropTypes.func.isRequired,
  listModelsWithInfo: React.PropTypes.func,
  loadingModel: React.PropTypes.bool,
  modelName: React.PropTypes.string,
  modelOwner: React.PropTypes.string,
  showEnvSwitcher: React.PropTypes.bool.isRequired,
  showProfile: React.PropTypes.func.isRequired,
  switchModel: React.PropTypes.func.isRequired,
  user: React.PropTypes.object
};

HeaderBreadcrumb.defaultProps = {
  loadingModel: false
};

YUI.add('header-breadcrumb', function() {
  juju.components.HeaderBreadcrumb = HeaderBreadcrumb;
}, '0.1.0', {
  requires: [
    'env-switcher'
  ]
});
{'fraction_non_alphanumeric': 0.09579859408206637, 'fraction_numerical': 0.001553048880170018, 'mean_word_length': 3.043291473892928, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, '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': '1893240', 'n_tokens_mistral': 3495, 'n_tokens_neox': 3464, 'n_words': 1085}