<commit_before>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { createSelector } from 'reselect';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Button } from 'react-bootstrap';

import { FullWidthRow } from '../../../helperComponents';
import { Form } from '../formHelpers';
import JSAlgoAndDSForm from './JSAlgoAndDSForm.jsx';
import SectionHeader from './SectionHeader.jsx';
import { projectsSelector } from '../../../entities';
import { claimCert, updateUserBackend } from '../redux';
import {
  fetchChallenges,
  userSelector,
  hardGoTo,
  createErrorObservable
} from '../../../redux';
import {
  buildUserProjectsMap,
  jsProjectSuperBlock
} from '../utils/buildUserProjectsMap';

const mapStateToProps = createSelector(
  userSelector,
  projectsSelector,
  (
    {
      challengeMap,
      isRespWebDesignCert,
      is2018DataVisCert,
      isFrontEndLibsCert,
      isJsAlgoDataStructCert,
      isApisMicroservicesCert,
      isInfosecQaCert,
      isFrontEndCert,
      isBackEndCert,
      isDataVisCert,
      username
    },
    projects
  ) => ({
    allProjects: projects,
    legacyProjects: projects.filter(p => p.superBlock.includes('legacy')),
    modernProjects: projects.filter(p => !p.superBlock.includes('legacy')),
    userProjects: projects
      .map(block => buildUserProjectsMap(block, challengeMap))
      .reduce((projects, current) => ({
        ...projects,
        ...current
      }), {}),
    blockNameIsCertMap: {
      'Applied Responsive Web Design Projects': isRespWebDesignCert,
      /* eslint-disable max-len */
      'JavaScript Algorithms and Data Structures Projects': isJsAlgoDataStructCert,
      /* eslint-enable max-len */
      'Front End Libraries Projects': isFrontEndLibsCert,
      'Data Visualization Projects': is2018DataVisCert,
      'API and Microservice Projects': isApisMicroservicesCert,
      'Information Security and Quality Assurance Projects': isInfosecQaCert,
      'Legacy Front End Projects': isFrontEndCert,
      'Legacy Back End Projects': isBackEndCert,
      'Legacy Data Visualization Projects': isDataVisCert
    },
    username
  })
);

function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    claimCert,
    createError: createErrorObservable,
    fetchChallenges,
    hardGoTo,
    updateUserBackend
  }, dispatch);
}

const projectsTypes = PropTypes.arrayOf(
  PropTypes.shape({
    projectBlockName: PropTypes.string,
    challenges: PropTypes.arrayOf(
      PropTypes.shape({
        dashedName: PropTypes.string,
        id: PropTypes.string,
        title: PropTypes.string
      })
    )
  }),
);

const propTypes = {
  allProjects: projectsTypes,
  blockNameIsCertMap: PropTypes.objectOf(PropTypes.bool),
  claimCert: PropTypes.func.isRequired,
  createError: PropTypes.func.isRequired,
  fetchChallenges: PropTypes.func.isRequired,
  hardGoTo: PropTypes.func.isRequired,
  legacyProjects: projectsTypes,
  modernProjects: projectsTypes,
  superBlock: PropTypes.string,
  updateUserBackend: PropTypes.func.isRequired,
  userProjects: PropTypes.objectOf(
    PropTypes.objectOf(PropTypes.oneOfType(
      [
        PropTypes.string,
        PropTypes.object
      ]
    ))
  ),
  username: PropTypes.string
};

class CertificationSettings extends PureComponent {
  constructor(props) {
    super(props);

    this.buildProjectForms = this.buildProjectForms.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  componentDidMount() {
    const { modernProjects } = this.props;
    if (!modernProjects.length) {
      this.props.fetchChallenges();
    }
  }

  buildProjectForms({
    projectBlockName,
    challenges,
    superBlock
  }) {
    const {
      blockNameIsCertMap,
      claimCert,
      hardGoTo,
      userProjects,
      username
    } = this.props;
    const isCertClaimed = blockNameIsCertMap[projectBlockName];
    const challengeTitles = challenges
      .map(challenge => challenge.title || 'Unknown Challenge');
    if (superBlock === jsProjectSuperBlock) {
      return (
        <JSAlgoAndDSForm
          challenges={ challengeTitles }
          claimCert={ claimCert }
          hardGoTo={ hardGoTo }
          isCertClaimed={ isCertClaimed }
          jsProjects={ userProjects[superBlock] }
          key={ superBlock }
          projectBlockName={ projectBlockName }
          superBlock={ superBlock }
          username={ username }
        />
      );
    }
    const options = challengeTitles
      .reduce((options, current) => {
        options.types[current] = 'url';
        return options;
      }, { types: {} });

    options.types.id = 'hidden';
    options.placeholder = false;

    const userValues = userProjects[superBlock] || {};

    if (!userValues.id) {
      userValues.id = superBlock;
    }

    const initialValues = challengeTitles
      .reduce((accu, current) => ({
        ...accu,
        [current]: ''
      }), {});

    const completedProjects = _.values(userValues)
      .filter(Boolean)
      .filter(_.isString)
      // minus 1 to account for the id
      .length - 1;

    const fullForm = completedProjects === challengeTitles.length;
    return (
      <FullWidthRow key={superBlock}>
        <h3 className='project-heading'>{ projectBlockName }</h3>
        <Form
          buttonText={ fullForm ? 'Claim Certificate' : 'Save Progress' }
          enableSubmit={ fullForm }
          formFields={ challengeTitles.concat([ 'id' ]) }
          hideButton={isCertClaimed}
          id={ superBlock }
          initialValues={{
            ...initialValues,
            ...userValues
          }}
          options={ options }
          submit={ this.handleSubmit }
        />
        {
          isCertClaimed ?
            <Button
              block={ true }
              bsSize='lg'
              bsStyle='primary'
              href={ `/certificates/${username}/${superBlock}`}
              >
              Show Certificate
            </Button> :
            null
        }
        <hr />
      </FullWidthRow>
    );
  }

  handleSubmit(values) {
    const { id } = values;
    const { allProjects } = this.props;
    let project = _.find(allProjects, { superBlock: id });
    if (!project) {
      // the submitted projects do not belong to current/legacy certificates
      return this.props.createError(
        new Error(<commit_msg>fix(showCert): Target _blank the link for Show Cert<commit_after>import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import { createSelector } from 'reselect';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Button } from 'react-bootstrap';

import { FullWidthRow } from '../../../helperComponents';
import { Form } from '../formHelpers';
import JSAlgoAndDSForm from './JSAlgoAndDSForm.jsx';
import SectionHeader from './SectionHeader.jsx';
import { projectsSelector } from '../../../entities';
import { claimCert, updateUserBackend } from '../redux';
import {
  fetchChallenges,
  userSelector,
  hardGoTo,
  createErrorObservable
} from '../../../redux';
import {
  buildUserProjectsMap,
  jsProjectSuperBlock
} from '../utils/buildUserProjectsMap';

const mapStateToProps = createSelector(
  userSelector,
  projectsSelector,
  (
    {
      challengeMap,
      isRespWebDesignCert,
      is2018DataVisCert,
      isFrontEndLibsCert,
      isJsAlgoDataStructCert,
      isApisMicroservicesCert,
      isInfosecQaCert,
      isFrontEndCert,
      isBackEndCert,
      isDataVisCert,
      username
    },
    projects
  ) => ({
    allProjects: projects,
    legacyProjects: projects.filter(p => p.superBlock.includes('legacy')),
    modernProjects: projects.filter(p => !p.superBlock.includes('legacy')),
    userProjects: projects
      .map(block => buildUserProjectsMap(block, challengeMap))
      .reduce((projects, current) => ({
        ...projects,
        ...current
      }), {}),
    blockNameIsCertMap: {
      'Applied Responsive Web Design Projects': isRespWebDesignCert,
      /* eslint-disable max-len */
      'JavaScript Algorithms and Data Structures Projects': isJsAlgoDataStructCert,
      /* eslint-enable max-len */
      'Front End Libraries Projects': isFrontEndLibsCert,
      'Data Visualization Projects': is2018DataVisCert,
      'API and Microservice Projects': isApisMicroservicesCert,
      'Information Security and Quality Assurance Projects': isInfosecQaCert,
      'Legacy Front End Projects': isFrontEndCert,
      'Legacy Back End Projects': isBackEndCert,
      'Legacy Data Visualization Projects': isDataVisCert
    },
    username
  })
);

function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    claimCert,
    createError: createErrorObservable,
    fetchChallenges,
    hardGoTo,
    updateUserBackend
  }, dispatch);
}

const projectsTypes = PropTypes.arrayOf(
  PropTypes.shape({
    projectBlockName: PropTypes.string,
    challenges: PropTypes.arrayOf(
      PropTypes.shape({
        dashedName: PropTypes.string,
        id: PropTypes.string,
        title: PropTypes.string
      })
    )
  }),
);

const propTypes = {
  allProjects: projectsTypes,
  blockNameIsCertMap: PropTypes.objectOf(PropTypes.bool),
  claimCert: PropTypes.func.isRequired,
  createError: PropTypes.func.isRequired,
  fetchChallenges: PropTypes.func.isRequired,
  hardGoTo: PropTypes.func.isRequired,
  legacyProjects: projectsTypes,
  modernProjects: projectsTypes,
  superBlock: PropTypes.string,
  updateUserBackend: PropTypes.func.isRequired,
  userProjects: PropTypes.objectOf(
    PropTypes.objectOf(PropTypes.oneOfType(
      [
        PropTypes.string,
        PropTypes.object
      ]
    ))
  ),
  username: PropTypes.string
};

class CertificationSettings extends PureComponent {
  constructor(props) {
    super(props);

    this.buildProjectForms = this.buildProjectForms.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  componentDidMount() {
    const { modernProjects } = this.props;
    if (!modernProjects.length) {
      this.props.fetchChallenges();
    }
  }

  buildProjectForms({
    projectBlockName,
    challenges,
    superBlock
  }) {
    const {
      blockNameIsCertMap,
      claimCert,
      hardGoTo,
      userProjects,
      username
    } = this.props;
    const isCertClaimed = blockNameIsCertMap[projectBlockName];
    const challengeTitles = challenges
      .map(challenge => challenge.title || 'Unknown Challenge');
    if (superBlock === jsProjectSuperBlock) {
      return (
        <JSAlgoAndDSForm
          challenges={ challengeTitles }
          claimCert={ claimCert }
          hardGoTo={ hardGoTo }
          isCertClaimed={ isCertClaimed }
          jsProjects={ userProjects[superBlock] }
          key={ superBlock }
          projectBlockName={ projectBlockName }
          superBlock={ superBlock }
          username={ username }
        />
      );
    }
    const options = challengeTitles
      .reduce((options, current) => {
        options.types[current] = 'url';
        return options;
      }, { types: {} });

    options.types.id = 'hidden';
    options.placeholder = false;

    const userValues = userProjects[superBlock] || {};

    if (!userValues.id) {
      userValues.id = superBlock;
    }

    const initialValues = challengeTitles
      .reduce((accu, current) => ({
        ...accu,
        [current]: ''
      }), {});

    const completedProjects = _.values(userValues)
      .filter(Boolean)
      .filter(_.isString)
      // minus 1 to account for the id
      .length - 1;

    const fullForm = completedProjects === challengeTitles.length;
    return (
      <FullWidthRow key={superBlock}>
        <h3 className='project-heading'>{ projectBlockName }</h3>
        <Form
          buttonText={ fullForm ? 'Claim Certificate' : 'Save Progress' }
          enableSubmit={ fullForm }
          formFields={ challengeTitles.concat([ 'id' ]) }
          hideButton={isCertClaimed}
          id={ superBlock }
          initialValues={{
            ...initialValues,
            ...userValues
          }}
          options={ options }
          submit={ this.handleSubmit }
        />
        {
          isCertClaimed ?
            <Button
              block={ true }
              bsSize='lg'
              bsStyle='primary'
              href={ `/certificates/${username}/${superBlock}`}
              target='_blank'
              >
              Show Certificate
            </Button> :
            null
        }
        <hr />
      </FullWidthRow>
    );
  }

  handleSubmit(values) {
    const { id } = values;
    const { allProjects } = this.props;
    let project = _.find(allProjects, { superBlock: id });
    if (!project) {
      // the submitted projects do not belong to current/legacy certificates
      return this.props.createError(
        new Error(
{'fraction_non_alphanumeric': 0.11150524367674275, 'fraction_numerical': 0.001850709438618137, 'mean_word_length': 2.615556175076666, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 37, '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': '6885201', 'n_tokens_mistral': 3728, 'n_tokens_neox': 3700, 'n_words': 779}