<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Header, Icon, Popup, Label, Grid } from 'semantic-ui-react'
import styled from 'styled-components'

import { getIndividualsByGuid, getSortedIndividualsByFamily, getUser } from 'redux/selectors'
import DeleteButton from 'shared/components/buttons/DeleteButton'
import UpdateButton from 'shared/components/buttons/UpdateButton'
import { BooleanCheckbox, BaseSemanticInput } from 'shared/components/form/Inputs'
import { SubmissionGeneVariants, Phenotypes } from 'shared/components/panel/MatchmakerPanel'
import BaseFieldView from 'shared/components/panel/view-fields/BaseFieldView'
import TextFieldView from 'shared/components/panel/view-fields/TextFieldView'
import { Alleles } from 'shared/components/panel/variants/VariantIndividuals'
import SortableTable, { SelectableTableFormInput } from 'shared/components/table/SortableTable'
import DataLoader from 'shared/components/DataLoader'
import { HorizontalSpacer, VerticalSpacer } from 'shared/components/Spacers'
import { ButtonLink, ColoredLabel } from 'shared/components/StyledComponents'
import { AFFECTED } from 'shared/utils/constants'
import { camelcaseToTitlecase } from 'shared/utils/stringUtils'

import {
  loadMmeMatches, updateMmeSubmission, updateMmeSubmissionStatus, sendMmeContactEmail, updateMmeContactNotes,
} from '../reducers'
import {
  getMatchmakerMatchesLoading,
  getIndividualTaggedVariants,
  getDefaultMmeSubmissionByIndividual,
  getMmeResultsByIndividual,
  getMmeDefaultContactEmail,
  getMatchmakerContactNotes,
} from '../selectors'

const BreakWordLink = styled.a`
  word-break: break-all;
`

const MatchContainer = styled.div`
  word-break: break-all;
`

const PATIENT_CORE_FIELDS = ['id', 'contact', 'features', 'genomicFeatures']

const MATCH_STATUS_EDIT_FIELDS = [
  { name: 'weContacted', label: 'We Contacted Host', component: BooleanCheckbox, inline: true },
  { name: 'hostContacted', label: 'Host Contacted Us', component: BooleanCheckbox, inline: true },
  { name: 'flagForAnalysis', label: 'Flag for Analysis', component: BooleanCheckbox, inline: true },
  { name: 'deemedIrrelevant', label: 'Deemed Irrelevant', component: BooleanCheckbox, inline: true },
  { name: 'comments', label: 'Comments', component: BaseSemanticInput, inputType: 'TextArea', rows: 5 },
]

const variantSummary = variant => (
  <span>
    {variant.chrom}:{variant.pos}
    {variant.alt && <span> {variant.ref} <Icon fitted name="angle right" /> {variant.alt}</span>}
  </span>
)

const GENOTYPE_FIELDS = [
  { name: 'geneSymbol', content: 'Gene', width: 2 },
  { name: 'xpos', content: 'Variant', width: 3, format: val => variantSummary(val) },
  { name: 'numAlt', content: 'Genotype', width: 2, format: val => <Alleles variant={val} numAlt={val.numAlt} /> },
  {
    name: 'tags',
    content: 'Tags',
    width: 8,
    format: val => val.tags.map(tag =>
      <ColoredLabel key={tag.tagGuid}size="small" color={tag.color} horizontal content={tag.name} />,
    ),
  },
]

const BaseEditGenotypesTable = ({ savedVariants, value, onChange }) =>
  <SelectableTableFormInput
    idField="variantId"
    defaultSortColumn="xpos"
    columns={GENOTYPE_FIELDS}
    data={savedVariants}
    value={value}
    onChange={newValue => onChange(savedVariants.filter(variant => newValue[variant.variantId]))}
  />

BaseEditGenotypesTable.propTypes = {
  savedVariants: PropTypes.array,
  value: PropTypes.object,
  onChange: PropTypes.func,
}

const mapGenotypesStateToProps = (state, ownProps) => {
  const individualGuid = ownProps.meta.form.split('_-_')[0]
  return {
    savedVariants: getIndividualTaggedVariants(state, { individualGuid }),
  }
}

const EditGenotypesTable = connect(mapGenotypesStateToProps)(BaseEditGenotypesTable)

const PHENOTYPE_FIELDS = [
  { name: 'id', content: 'HPO ID', width: 3 },
  { name: 'label', content: 'Description', width: 9 },
  {
    name: 'observed',
    content: 'Observed?',
    width: 3,
    textAlign: 'center',
    format: val =>
      <Icon name={val.observed === 'yes' ? 'check' : 'remove'} color={val.observed === 'yes' ? 'green' : 'red'} />,
  },
]

const BaseEditPhenotypesTable = ({ individual, value, onChange }) =>
  <SelectableTableFormInput
    idField="id"
    defaultSortColumn="label"
    columns={PHENOTYPE_FIELDS}
    data={individual.phenotipsData.features}
    value={value}
    onChange={newValue => onChange(individual.phenotipsData.features.filter(feature => newValue[feature.id]))}
  />

BaseEditPhenotypesTable.propTypes = {
  individual: PropTypes.object,
  value: PropTypes.object,
  onChange: PropTypes.func,
}

const mapPhenotypeStateToProps = (state, ownProps) => ({
  individual: getIndividualsByGuid(state)[ownProps.meta.form.split('_-_')[0]],
})

const EditPhenotypesTable = connect(mapPhenotypeStateToProps)(BaseEditPhenotypesTable)

const MAILTO_CONTACT_URL_REGEX = /^mailto:[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}(,\s*[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{1,4})*$/i
const CONTACT_URL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}(,\s*[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{1,4})*$/i
const SUBMISSION_EDIT_FIELDS = [
  { name: 'patient.contact.name', label: 'Contact Name' },
  {
    name: 'patient.contact.href',
    label: 'Contact URL',
    parse: val => `mailto:${val}`,
    format: val => val.replace('mailto:', ''),
    validate: val => (MAILTO_CONTACT_URL_REGEX.test(val) ? undefined : 'Invalid contact url'),
  },
  {
    name: 'geneVariants',
    component: EditGenotypesTable,<commit_msg>fix mme submission when no phenotips<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Header, Icon, Popup, Label, Grid } from 'semantic-ui-react'
import styled from 'styled-components'

import { getIndividualsByGuid, getSortedIndividualsByFamily, getUser } from 'redux/selectors'
import DeleteButton from 'shared/components/buttons/DeleteButton'
import UpdateButton from 'shared/components/buttons/UpdateButton'
import { BooleanCheckbox, BaseSemanticInput } from 'shared/components/form/Inputs'
import { SubmissionGeneVariants, Phenotypes } from 'shared/components/panel/MatchmakerPanel'
import BaseFieldView from 'shared/components/panel/view-fields/BaseFieldView'
import TextFieldView from 'shared/components/panel/view-fields/TextFieldView'
import { Alleles } from 'shared/components/panel/variants/VariantIndividuals'
import SortableTable, { SelectableTableFormInput } from 'shared/components/table/SortableTable'
import DataLoader from 'shared/components/DataLoader'
import { HorizontalSpacer, VerticalSpacer } from 'shared/components/Spacers'
import { ButtonLink, ColoredLabel } from 'shared/components/StyledComponents'
import { AFFECTED } from 'shared/utils/constants'
import { camelcaseToTitlecase } from 'shared/utils/stringUtils'

import {
  loadMmeMatches, updateMmeSubmission, updateMmeSubmissionStatus, sendMmeContactEmail, updateMmeContactNotes,
} from '../reducers'
import {
  getMatchmakerMatchesLoading,
  getIndividualTaggedVariants,
  getDefaultMmeSubmissionByIndividual,
  getMmeResultsByIndividual,
  getMmeDefaultContactEmail,
  getMatchmakerContactNotes,
} from '../selectors'

const BreakWordLink = styled.a`
  word-break: break-all;
`

const MatchContainer = styled.div`
  word-break: break-all;
`

const PATIENT_CORE_FIELDS = ['id', 'contact', 'features', 'genomicFeatures']

const MATCH_STATUS_EDIT_FIELDS = [
  { name: 'weContacted', label: 'We Contacted Host', component: BooleanCheckbox, inline: true },
  { name: 'hostContacted', label: 'Host Contacted Us', component: BooleanCheckbox, inline: true },
  { name: 'flagForAnalysis', label: 'Flag for Analysis', component: BooleanCheckbox, inline: true },
  { name: 'deemedIrrelevant', label: 'Deemed Irrelevant', component: BooleanCheckbox, inline: true },
  { name: 'comments', label: 'Comments', component: BaseSemanticInput, inputType: 'TextArea', rows: 5 },
]

const variantSummary = variant => (
  <span>
    {variant.chrom}:{variant.pos}
    {variant.alt && <span> {variant.ref} <Icon fitted name="angle right" /> {variant.alt}</span>}
  </span>
)

const GENOTYPE_FIELDS = [
  { name: 'geneSymbol', content: 'Gene', width: 2 },
  { name: 'xpos', content: 'Variant', width: 3, format: val => variantSummary(val) },
  { name: 'numAlt', content: 'Genotype', width: 2, format: val => <Alleles variant={val} numAlt={val.numAlt} /> },
  {
    name: 'tags',
    content: 'Tags',
    width: 8,
    format: val => val.tags.map(tag =>
      <ColoredLabel key={tag.tagGuid}size="small" color={tag.color} horizontal content={tag.name} />,
    ),
  },
]

const BaseEditGenotypesTable = ({ savedVariants, value, onChange }) =>
  <SelectableTableFormInput
    idField="variantId"
    defaultSortColumn="xpos"
    columns={GENOTYPE_FIELDS}
    data={savedVariants}
    value={value}
    onChange={newValue => onChange(savedVariants.filter(variant => newValue[variant.variantId]))}
  />

BaseEditGenotypesTable.propTypes = {
  savedVariants: PropTypes.array,
  value: PropTypes.object,
  onChange: PropTypes.func,
}

const mapGenotypesStateToProps = (state, ownProps) => {
  const individualGuid = ownProps.meta.form.split('_-_')[0]
  return {
    savedVariants: getIndividualTaggedVariants(state, { individualGuid }),
  }
}

const EditGenotypesTable = connect(mapGenotypesStateToProps)(BaseEditGenotypesTable)

const PHENOTYPE_FIELDS = [
  { name: 'id', content: 'HPO ID', width: 3 },
  { name: 'label', content: 'Description', width: 9 },
  {
    name: 'observed',
    content: 'Observed?',
    width: 3,
    textAlign: 'center',
    format: val =>
      <Icon name={val.observed === 'yes' ? 'check' : 'remove'} color={val.observed === 'yes' ? 'green' : 'red'} />,
  },
]

const BaseEditPhenotypesTable = ({ individual, value, onChange }) =>
  <SelectableTableFormInput
    idField="id"
    defaultSortColumn="label"
    columns={PHENOTYPE_FIELDS}
    data={(individual.phenotipsData || {}).features}
    value={value}
    onChange={newValue => onChange(individual.phenotipsData.features.filter(feature => newValue[feature.id]))}
  />

BaseEditPhenotypesTable.propTypes = {
  individual: PropTypes.object,
  value: PropTypes.object,
  onChange: PropTypes.func,
}

const mapPhenotypeStateToProps = (state, ownProps) => ({
  individual: getIndividualsByGuid(state)[ownProps.meta.form.split('_-_')[0]],
})

const EditPhenotypesTable = connect(mapPhenotypeStateToProps)(BaseEditPhenotypesTable)

const MAILTO_CONTACT_URL_REGEX = /^mailto:[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}(,\s*[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{1,4})*$/i
const CONTACT_URL_REGEX = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}(,\s*[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{1,4})*$/i
const SUBMISSION_EDIT_FIELDS = [
  { name: 'patient.contact.name', label: 'Contact Name' },
  {
    name: 'patient.contact.href',
    label: 'Contact URL',
    parse: val => `mailto:${val}`,
    format: val => val.replace('mailto:', ''),
    validate: val => (MAILTO_CONTACT_URL_REGEX.test(val) ? undefined : 'Invalid contact url'),
  },
  {
    name: 'geneVariants',
    component: EditGenotypesTable,
{'fraction_non_alphanumeric': 0.15218758422423861, 'fraction_numerical': 0.006109064774054443, 'mean_word_length': 5.177580466148724, 'pattern_counts': {'":': 0, '<': 23, '<?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': '2878673', 'n_tokens_mistral': 3772, 'n_tokens_neox': 3687, 'n_words': 727}