<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';

import EntityTypeHeader from '../entity-editor/EntityTypeHeader';
import ConfirmUserAction from './ConfirmUserAction';
import InviteUser from './InviteUser';
import User from './User';
import * as api from '../../utilities/api';
import { showNotification } from '../../actions/notification';

require('../entity-editor/EntityTypeHeader.scss');
require('./Users.scss');

function UserList({
  currentUserEmail, getUserActions, invitationMode, onChange, users,
}) {
  return (
    <table>
      <tbody>
        <tr>
          {!invitationMode && (
            <th />
          )}
          {!invitationMode && (
            <th><FormattedMessage id="first_name" /></th>
          )}
          {!invitationMode && (
            <th><FormattedMessage id="last_name" /></th>
          )}
          <th><FormattedMessage id="email" /></th>
          {!invitationMode && (
            <th>
              <FormattedMessage id="role" />
            </th>
          )}
          <th>
            <FormattedMessage id="actions" />
          </th>
        </tr>
        {users.map(({
          admin, email, id, firstName, lastName,
        }) => (
          <User
            getUserActions={getUserActions}
            key={id}
            onChange={onChange}
            invitationMode={invitationMode}
            user={{
              currentUser: email === currentUserEmail,
              admin,
              email,
              id,
              firstName,
              lastName,
            }}
          />
        ))}
      </tbody>
    </table>
  );
}

UserList.propTypes = {
  currentUserEmail: PropTypes.string.isRequired,
  getUserActions: PropTypes.func.isRequired,
  invitationMode: PropTypes.bool,
  onChange: PropTypes.func.isRequired,
  users: PropTypes.array.isRequired,
};

UserList.defaultProps = {
  invitationMode: false,
};

function compareByRoleAndNames(a, b) {
  if (a.admin < b.admin) {
    return 1;
  }
  if (a.admin > b.admin) {
    return -1;
  }
  if (a.firstName.toLowerCase() > b.firstName.toLowerCase()) {
    return 1;
  }
  if (a.firstName.toLowerCase() < b.firstName.toLowerCase()) {
    return -1;
  }
  if (a.lastName.toLowerCase() > b.lastName.toLowerCase()) {
    return 1;
  }
  if (a.lastName.toLowerCase() < b.lastName.toLowerCase()) {
    return -1;
  }
  return 0;
}

class Users extends Component {
  constructor(props) {
    super(props);
    this.state = {
      userAction: {
        action: '',
        user: {
          email: '', id: '', firstName: '', lastName: '',
        },
      },
      invitationMode: false,
      invitations: [],
      isActionModalVisible: false,
      isInviteModalVisible: false,
      users: [],
    };
    this.getUserActions = this.getUserActions.bind(this);
    this.getUserActionButtons = this.getUserActionButtons.bind(this);
    this.getInvitations = this.getInvitations.bind(this);<commit_msg>[#2304] Sort fn now handles non existing keys<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { FormattedMessage } from 'react-intl';

import EntityTypeHeader from '../entity-editor/EntityTypeHeader';
import ConfirmUserAction from './ConfirmUserAction';
import InviteUser from './InviteUser';
import User from './User';
import * as api from '../../utilities/api';
import { showNotification } from '../../actions/notification';

require('../entity-editor/EntityTypeHeader.scss');
require('./Users.scss');

function UserList({
  currentUserEmail, getUserActions, invitationMode, onChange, users,
}) {
  return (
    <table>
      <tbody>
        <tr>
          {!invitationMode && (
            <th />
          )}
          {!invitationMode && (
            <th><FormattedMessage id="first_name" /></th>
          )}
          {!invitationMode && (
            <th><FormattedMessage id="last_name" /></th>
          )}
          <th><FormattedMessage id="email" /></th>
          {!invitationMode && (
            <th>
              <FormattedMessage id="role" />
            </th>
          )}
          <th>
            <FormattedMessage id="actions" />
          </th>
        </tr>
        {users.map(({
          admin, email, id, firstName, lastName,
        }) => (
          <User
            getUserActions={getUserActions}
            key={id}
            onChange={onChange}
            invitationMode={invitationMode}
            user={{
              currentUser: email === currentUserEmail,
              admin,
              email,
              id,
              firstName,
              lastName,
            }}
          />
        ))}
      </tbody>
    </table>
  );
}

UserList.propTypes = {
  currentUserEmail: PropTypes.string.isRequired,
  getUserActions: PropTypes.func.isRequired,
  invitationMode: PropTypes.bool,
  onChange: PropTypes.func.isRequired,
  users: PropTypes.array.isRequired,
};

UserList.defaultProps = {
  invitationMode: false,
};

function compareByRoleAndNames(a, b) {
  const aFirstName = a.firstName && a.firstName.toLowerCase();
  const aLastName = a.lastName && a.lastName.toLowerCase();
  const bFirstName = b.firstName && b.firstName.toLowerCase();
  const bLastName = b.lastName && b.lastName.toLowerCase();

  if (a.admin < b.admin) {
    return 1;
  }
  if (a.admin > b.admin) {
    return -1;
  }
  if (aFirstName > bFirstName) {
    return 1;
  }
  if (aFirstName < bFirstName) {
    return -1;
  }
  if (aLastName > bLastName) {
    return 1;
  }
  if (aLastName < bLastName) {
    return -1;
  }
  return 0;
}

class Users extends Component {
  constructor(props) {
    super(props);
    this.state = {
      userAction: {
        action: '',
        user: {
          email: '', id: '', firstName: '', lastName: '',
        },
      },
      invitationMode: false,
      invitations: [],
      isActionModalVisible: false,
      isInviteModalVisible: false,
      users: [],
    };
    this.getUserActions = this.getUserActions.bind(this);
    this.getUserActionButtons = this.getUserActionButtons.bind(this);
    this.getInvitations = this.getInvitations.bind(this);
{'fraction_non_alphanumeric': 0.14144474565460055, 'fraction_numerical': 0.00287035560516664, 'mean_word_length': 2.1628845184064547, 'pattern_counts': {'":': 0, '<': 55, '<?xml version=': 0, '>': 57, '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': '5920656', 'n_tokens_mistral': 1867, 'n_tokens_neox': 1900, 'n_words': 376}