<commit_before>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2016  Loki Education (Social Enterprise)

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

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY 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/>.
*/
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';

import { ArrayOfMessages as ArrayOfMessagesPropType } from '../prop-types/messages';

import ApiClient from '../api/client';
import { API_HOST } from '../config';
import { defaultSelector } from '../selectors';
import { ActionsTrigger } from '../triggers';
import { Link } from 'react-router';

import {
  Page,
  PageMain,
  PageBody,
  PageContent
} from '../components/page';
import Footer from '../components/footer';
import Header from '../components/header';
import Messages from '../components/messages';

const SuccessMessage = () => (
  <div>
    You have successfully changed your password. Please proceed into our <Link className="link" to="/auth">login form </Link>.
  </div>
);

class PasswordForm extends React.Component {
  static propTypes = {
    messages: ArrayOfMessagesPropType,
    onSubmit: PropTypes.func
  };

  static defaultProps = {
    onSubmit: () => {}
  };

  constructor(props) {
    super(props);

    this.state = {
      errors: {
        password: null,
        password_repeat: null
      }
    };
  }

  _validatePassword = () => {
    const errors = this.state.errors;
    const password = this.form.password;

    if (password.value.length < 8) {
      errors.password = 'Password must be at least 8 characters';
    } else {
      errors.password = null;
    }

    this.setState({ errors });
  };

  _validatePasswordRepeat = () => {
    const errors = this.state.errors;
    const { password, password_repeat } = this.form;

    if (password_repeat.value.length > 0 && password.value !== password_repeat.value) {
      errors.password_repeat = 'Passwords do not match';
    } else {
      errors.password_repeat = null;
    }

    this.setState({ errors });
  };

  render() {
    const errors = this.state.errors;

    return (
      <form action="" className="password-form" method="post" ref={c => this.form = c} onSubmit={this.props.onSubmit}>
        <div className="layout__row">
          <div className="form__row">
            <label className="label label-block label-space" htmlFor="newPassword">New Password</label>
            <input
              className="input input-block"
              id="newPassword"
              name="password"
              required="required"
              type="password"
              onChange={this._validatePassword}
            />
            {errors.password && <div className="validation_error">{errors.password}</div>}

            <label className="label label-block label-space" htmlFor="newPasswordRepeat">Repeat</label>
            <input
              className="input input-block"
              id="newPasswordRepeat"
              name="password_repeat"
              required="required"
              type="password"
              onChange={this._validatePasswordRepeat}
            />
            {errors.password_repeat && <div className="validation_error">{errors.password_repeat}</div>}
          </div>
        </div>
        <div className="layout__row layout layout-align_vertical layout-align_justify">
          <button className="button button-wide button-green" type="submit">Submit</button>
        </div>
      </form>
    );
  }
}


class Form extends React.Component {
  static propTypes = {
    messages: ArrayOfMessagesPropType.isRequired
  };

  submitHandler = (event) => {
    event.preventDefault();

    const form = event.target;

    const client = new ApiClient(API_HOST);
    const triggers = new ActionsTrigger(client, this.props.dispatch);

    triggers.newPassword(this.props.routeParams.hash, form.password.value, form.password_repeat.value);
  };

  render() {
    const {
      messages,
      is_logged_in
    } = this.props;

    let content = <PasswordForm onSubmit={this.submitHandler} />;

    if (this.props.ui.submitNewPassword) {
      content = <SuccessMessage />;
    }

    const client = new ApiClient(API_HOST);
    const triggers = new ActionsTrigger(client, this.props.dispatch);

    return (
      <div>
        <Helmet title="Set New Password for " />
        <Header is_logged_in={is_logged_in} />

        <Page className="page__container-no_sidebar">
          <PageMain>
            <PageBody>
              <PageContent>
                <div className="area">
                  <Messages messages={messages} removeMessage={triggers.removeMessage} />
                  <div className="area__body layout-align_start">
                    <div className="box box-middle">
                      <header className="box__title">Set new password</header>
                      <div className="box__body">
                        {content}
                      </div>
                    </div>
                  </div>
                </div>
              </PageContent>
            </PageBody>
          </PageMain>
        </Page>

        <Footer />
      </div>
    );
  }
}

export default connect(defaultSelector)(Form);<commit_msg>Create selector for PasswordFormPage component<commit_after>/*
 This file is a part of libertysoil.org website
 Copyright (C) 2016  Loki Education (Social Enterprise)

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

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY 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/>.
*/
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import Helmet from 'react-helmet';

import { ArrayOfMessages as ArrayOfMessagesPropType } from '../prop-types/messages';

import ApiClient from '../api/client';
import { API_HOST } from '../config';
import { createSelector } from '../selectors';
import { ActionsTrigger } from '../triggers';
import { Link } from 'react-router';

import {
  Page,
  PageMain,
  PageBody,
  PageContent
} from '../components/page';
import Footer from '../components/footer';
import Header from '../components/header';
import Messages from '../components/messages';

const SuccessMessage = () => (
  <div>
    You have successfully changed your password. Please proceed into our <Link className="link" to="/auth">login form </Link>.
  </div>
);

class PasswordForm extends React.Component {
  static propTypes = {
    messages: ArrayOfMessagesPropType,
    onSubmit: PropTypes.func
  };

  static defaultProps = {
    onSubmit: () => {}
  };

  constructor(props) {
    super(props);

    this.state = {
      errors: {
        password: null,
        password_repeat: null
      }
    };
  }

  _validatePassword = () => {
    const errors = this.state.errors;
    const password = this.form.password;

    if (password.value.length < 8) {
      errors.password = 'Password must be at least <PASSWORD>';
    } else {
      errors.password = null;
    }

    this.setState({ errors });
  };

  _validatePasswordRepeat = () => {
    const errors = this.state.errors;
    const { password, password_repeat } = this.form;

    if (password_repeat.value.length > 0 && password.value !== password_repeat.value) {
      errors.password_repeat = 'Passwords do not match';
    } else {
      errors.password_repeat = null;
    }

    this.setState({ errors });
  };

  render() {
    const errors = this.state.errors;

    return (
      <form action="" className="password-form" method="post" ref={c => this.form = c} onSubmit={this.props.onSubmit}>
        <div className="layout__row">
          <div className="form__row">
            <label className="label label-block label-space" htmlFor="newPassword">New Password</label>
            <input
              className="input input-block"
              id="newPassword"
              name="password"
              required="required"
              type="password"
              onChange={this._validatePassword}
            />
            {errors.password && <div className="validation_error">{errors.password}</div>}

            <label className="label label-block label-space" htmlFor="newPasswordRepeat">Repeat</label>
            <input
              className="input input-block"
              id="newPasswordRepeat"
              name="password_repeat"
              required="required"
              type="password"
              onChange={this._validatePasswordRepeat}
            />
            {errors.password_repeat && <div className="validation_error">{errors.password_repeat}</div>}
          </div>
        </div>
        <div className="layout__row layout layout-align_vertical layout-align_justify">
          <button className="button button-wide button-green" type="submit">Submit</button>
        </div>
      </form>
    );
  }
}


class PasswordPage extends React.Component {
  static propTypes = {
    messages: ArrayOfMessagesPropType.isRequired
  };

  submitHandler = (event) => {
    event.preventDefault();

    const form = event.target;

    const client = new ApiClient(API_HOST);
    const triggers = new ActionsTrigger(client, this.props.dispatch);

    triggers.newPassword(this.props.routeParams.hash, form.password.value, form.password_repeat.value);
  };

  render() {
    const {
      messages,
      is_logged_in,
      ui
    } = this.props;

    const messages_js = messages.toJS(); // FIXME #662

    let content = <PasswordForm onSubmit={this.submitHandler} />;

    if (ui.get('submitNewPassword')) {
      content = <SuccessMessage />;
    }

    const client = new ApiClient(API_HOST);
    const triggers = new ActionsTrigger(client, this.props.dispatch);

    return (
      <div>
        <Helmet title="Set New Password for " />
        <Header is_logged_in={is_logged_in} />

        <Page className="page__container-no_sidebar">
          <PageMain>
            <PageBody>
              <PageContent>
                <div className="area">
                  <Messages messages={messages_js} removeMessage={triggers.removeMessage} />
                  <div className="area__body layout-align_start">
                    <div className="box box-middle">
                      <header className="box__title">Set new password</header>
                      <div className="box__body">
                        {content}
                      </div>
                    </div>
                  </div>
                </div>
              </PageContent>
            </PageBody>
          </PageMain>
        </Page>

        <Footer />
      </div>
    );
  }
}

const selector = createSelector(
  state => !!state.getIn(['current_user', 'id']),
  state => state.get('messages'),
  state => state.get('ui'),
  (is_logged_in, messages, ui) => ({
    is_logged_in,
    messages,
    ui
  })
);

export default connect(selector)(PasswordPage);
{'fraction_non_alphanumeric': 0.11645910467855941, 'fraction_numerical': 0.0015146415348367553, 'mean_word_length': 2.458963911525029, 'pattern_counts': {'":': 0, '<': 108, '<?xml version=': 0, '>': 124, 'https://': 0, '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': '7026717', 'n_tokens_mistral': 3232, 'n_tokens_neox': 3136, 'n_words': 862}