Skip to content

Commit

Permalink
Merge pull request #4208 from broadinstitute/vlm-contact-option
Browse files Browse the repository at this point in the history
VLM configure contact
  • Loading branch information
hanars authored Jul 1, 2024
2 parents 38a58dc + 0c6a3d1 commit 8eff76b
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# _seqr_ Changes

## dev
* Add VLM contact for Projects (REQUIRES DB MIGRATION)

## 6/11/24
* Add "Partial Phenotype Contribution" functional tag (REQUIRES DB MIGRATION)
Expand Down
4 changes: 4 additions & 0 deletions seqr/fixtures/1kg_project.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"has_case_review": true,
"mme_primary_data_owner": "PI",
"mme_contact_url": "mailto:test@broadinstitute.org,matchmaker@broadinstitute.org",
"vlm_contact_email": "test@broadinstitute.org,vlm@broadinstitute.org",
"last_accessed_date": "2017-09-15T18:15:50.827Z"
}
},
Expand All @@ -41,6 +42,7 @@
"can_view_group": 3,
"is_mme_enabled": false,
"mme_primary_data_owner": "",
"vlm_contact_email": "vlm@broadinstitute.org",
"last_accessed_date": "2017-09-15T18:15:50.827Z"
}
},
Expand All @@ -63,6 +65,7 @@
"is_demo": true,
"mme_primary_data_owner": "",
"mme_contact_url": "mailto:seqr-test@gmail.com,test@broadinstitute.org",
"vlm_contact_email": "seqr-test@gmail.com,test@broadinstitute.org",
"last_accessed_date": "2017-09-15T18:15:50.827Z"
}
},
Expand All @@ -81,6 +84,7 @@
"last_accessed_date": "2017-09-15T18:15:50.827Z",
"consent_code": "H",
"genome_version": "38",
"vlm_contact_email": "vlm@broadinstitute.org",
"workspace_name": "anvil-non-analyst-project 1000 Genomes Demo",
"workspace_namespace": "ext-data"
}
Expand Down
29 changes: 29 additions & 0 deletions seqr/migrations/0068_project_vlm_contact_email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 3.2.23 on 2024-06-28 15:44

from django.db import migrations, models


def update_vlm_contact_email(apps, schema_editor):
Project = apps.get_model('seqr', 'Project')
db_alias = schema_editor.connection.alias

projects = Project.objects.using(db_alias).all()
for project in projects:
project.vlm_contact_email = project.mme_contact_url.replace('mailto:', '').replace('matchmaker', 'vlm')
Project.objects.using(db_alias).bulk_update(projects, ['vlm_contact_email'])


class Migration(migrations.Migration):

dependencies = [
('seqr', '0067_alter_variantfunctionaldata_functional_data_tag'),
]

operations = [
migrations.AddField(
model_name='project',
name='vlm_contact_email',
field=models.TextField(blank=True, default='vlm@broadinstitute.org', null=True),
),
migrations.RunPython(update_vlm_contact_email, reverse_code=migrations.RunPython.noop),
]
6 changes: 5 additions & 1 deletion seqr/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
from seqr.utils.xpos_utils import get_chrom_pos
from seqr.views.utils.terra_api_utils import anvil_enabled
from reference_data.models import GENOME_VERSION_GRCh37, GENOME_VERSION_CHOICES
from settings import MME_DEFAULT_CONTACT_NAME, MME_DEFAULT_CONTACT_HREF, MME_DEFAULT_CONTACT_INSTITUTION
from settings import MME_DEFAULT_CONTACT_NAME, MME_DEFAULT_CONTACT_HREF, MME_DEFAULT_CONTACT_INSTITUTION, \
VLM_DEFAULT_CONTACT_EMAIL

logger = SeqrLogger(__name__)

Expand Down Expand Up @@ -196,6 +197,8 @@ class Project(ModelWithGUID):
mme_contact_url = models.TextField(null=True, blank=True, default=MME_DEFAULT_CONTACT_HREF)
mme_contact_institution = models.TextField(null=True, blank=True, default=MME_DEFAULT_CONTACT_INSTITUTION)

vlm_contact_email = models.TextField(null=True, blank=True, default=VLM_DEFAULT_CONTACT_EMAIL)

has_case_review = models.BooleanField(default=False)
enable_hgmd = models.BooleanField(default=False)
all_user_demo = models.BooleanField(default=False)
Expand Down Expand Up @@ -261,6 +264,7 @@ class Meta:
'name', 'description', 'created_date', 'last_modified_date', 'genome_version', 'mme_contact_institution',
'last_accessed_date', 'is_mme_enabled', 'mme_primary_data_owner', 'mme_contact_url', 'guid', 'consent_code',
'workspace_namespace', 'workspace_name', 'has_case_review', 'enable_hgmd', 'is_demo', 'all_user_demo',
'vlm_contact_email',
]


Expand Down
1 change: 1 addition & 0 deletions seqr/views/apis/anvil_workspace_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ def create_project_from_workspace(request, namespace, name):
'workspace_name': name,
'mme_primary_data_owner': request.user.get_full_name(),
'mme_contact_url': 'mailto:{}'.format(request.user.email),
'vlm_contact_email': request.user.email,
}

project = create_model_from_json(Project, project_args, user=request.user)
Expand Down
29 changes: 21 additions & 8 deletions seqr/views/apis/anvil_workspace_api_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,14 +559,27 @@ def test_create_project_from_workspace(self):
self.assertEqual(response.status_code, 200)
project = Project.objects.get(workspace_namespace=TEST_WORKSPACE_NAMESPACE, workspace_name=TEST_NO_PROJECT_WORKSPACE_NAME)
response_json = response.json()
self.assertEqual(project.guid, response_json['projectGuid'])
self.assertListEqual(
[project.genome_version, project.description, project.workspace_namespace, project.workspace_name],
['38', 'A test project', TEST_WORKSPACE_NAMESPACE, TEST_NO_PROJECT_WORKSPACE_NAME])

self.assertListEqual(
[project.mme_contact_institution, project.mme_primary_data_owner, project.mme_contact_url],
['Broad Center for Mendelian Genomics', 'Test Manager User', 'mailto:test_user_manager@test.com'])
self.assertDictEqual({k: getattr(project, k) for k in project._meta.json_fields}, {
'guid': response_json['projectGuid'],
'name': TEST_NO_PROJECT_WORKSPACE_NAME,
'description': 'A test project',
'workspace_namespace': TEST_WORKSPACE_NAMESPACE,
'workspace_name': TEST_NO_PROJECT_WORKSPACE_NAME,
'has_case_review': False,
'enable_hgmd': False,
'is_demo': False,
'all_user_demo': False,
'consent_code': None,
'created_date': mock.ANY,
'last_modified_date': mock.ANY,
'last_accessed_date': mock.ANY,
'genome_version': '38',
'is_mme_enabled': True,
'mme_contact_institution': 'Broad Center for Mendelian Genomics',
'mme_primary_data_owner': 'Test Manager User',
'mme_contact_url': 'mailto:test_user_manager@test.com',
'vlm_contact_email': 'test_user_manager@test.com',
})

self._assert_valid_operation(project, test_add_data=False)

Expand Down
27 changes: 21 additions & 6 deletions seqr/views/apis/project_api_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,30 @@ def test_create_and_delete_project(self, mock_airtable_logger):

# check that project was created
new_project = Project.objects.get(name='new_project')
self.assertEqual(new_project.description, 'new project description')
self.assertEqual(new_project.genome_version, '38')
self.assertEqual(new_project.consent_code, 'H')
self.assertTrue(new_project.is_demo)
self.assertFalse(new_project.is_mme_enabled)
self.assertEqual(new_project.created_by, self.pm_user)
self.assertEqual(new_project.projectcategory_set.count(), 0)
expected_workspace_name = self.CREATE_PROJECT_JSON.get('workspaceName')
self.assertEqual(new_project.workspace_name, expected_workspace_name)
self.assertDictEqual({k: getattr(new_project, k) for k in new_project._meta.json_fields}, {
'guid': mock.ANY,
'name': 'new_project',
'description': 'new project description',
'workspace_namespace': self.CREATE_PROJECT_JSON.get('workspaceNamespace'),
'workspace_name': expected_workspace_name,
'has_case_review': False,
'enable_hgmd': False,
'is_demo': True,
'all_user_demo': False,
'consent_code': 'H',
'created_date': mock.ANY,
'last_modified_date': mock.ANY,
'last_accessed_date': mock.ANY,
'genome_version': '38',
'is_mme_enabled': False,
'mme_contact_institution': 'Broad Center for Mendelian Genomics',
'mme_primary_data_owner': 'Samantha Baxter',
'mme_contact_url': 'mailto:matchmaker@broadinstitute.org',
'vlm_contact_email': 'vlm@broadinstitute.org',
})
self._check_created_project_groups(new_project)

project_guid = new_project.guid
Expand Down
2 changes: 1 addition & 1 deletion seqr/views/utils/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ def _get_list_param(call, param):
'projectGuid', 'projectCategoryGuids', 'canEdit', 'name', 'description', 'createdDate', 'lastModifiedDate',
'lastAccessedDate', 'mmeContactUrl', 'genomeVersion', 'mmePrimaryDataOwner', 'mmeContactInstitution',
'isMmeEnabled', 'workspaceName', 'workspaceNamespace', 'hasCaseReview', 'enableHgmd', 'isDemo', 'allUserDemo',
'userIsCreator', 'consentCode', 'isAnalystProject',
'userIsCreator', 'consentCode', 'isAnalystProject', 'vlmContactEmail',
}

ANALYSIS_GROUP_FIELDS = {'analysisGroupGuid', 'description', 'name', 'projectGuid', 'familyGuids'}
Expand Down
2 changes: 2 additions & 0 deletions settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,8 @@
MME_DEFAULT_CONTACT_EMAIL = 'matchmaker@broadinstitute.org'
MME_DEFAULT_CONTACT_HREF = 'mailto:{}'.format(MME_DEFAULT_CONTACT_EMAIL)

VLM_DEFAULT_CONTACT_EMAIL = 'vlm@broadinstitute.org'

MME_CONFIG_DIR = os.environ.get('MME_CONFIG_DIR', '')
MME_NODES = {}
if MME_CONFIG_DIR:
Expand Down
45 changes: 43 additions & 2 deletions ui/shared/components/buttons/EditProjectButton.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { connect } from 'react-redux'
import PropTypes from 'prop-types'

import { updateProject } from 'redux/rootReducer'
import { BaseSemanticInput } from '../form/Inputs'
import { validators } from '../form/FormHelpers'
import UpdateButton from './UpdateButton'
import {
EDITABLE_PROJECT_FIELDS,
Expand All @@ -11,10 +13,49 @@ import {
MATCHMAKER_CONTACT_URL_FIELD,
} from '../../utils/constants'

const MATCHMAKER_PROJECT_FIELDS = [
const setBoolVal = onChange => data => onChange(data.checked ? null : 'vlm@broadinstitute.org')

const VlmContactInput = ({ value, onChange, ...props }) => ([
<BaseSemanticInput
{...props}
key="email"
inputType="Input"
label="Variant Matching Contact Email"
value={value}
onChange={onChange}
disabled={!value}
inline
width={9}
/>,
<BaseSemanticInput
{...props}
key="disable"
label="Disable Contact for Variant Matches"
inputType="Checkbox"
checked={!value}
onChange={setBoolVal(onChange)}
inline
width={7}
/>,
])

VlmContactInput.propTypes = {
value: PropTypes.string,
onChange: PropTypes.func,
}

const VLM_CONTACT_FIELD = {
name: 'vlmContactEmail',
parse: val => val || null,
format: val => val || '',
validate: value => (!value ? undefined : validators.requiredEmail(value)),
component: VlmContactInput,
}

const MATCHMAKER_PROJECT_FIELDS = [VLM_CONTACT_FIELD, ...[
{ ...MATCHMAKER_CONTACT_NAME_FIELD, name: 'mmePrimaryDataOwner' },
{ ...MATCHMAKER_CONTACT_URL_FIELD, name: 'mmeContactUrl' },
].map(({ label, ...field }) => ({ ...field, label: `Matchmaker ${label}` }))
].map(({ label, ...field }) => ({ ...field, label: `Matchmaker ${label}` }))]

// Field mapping based on whether project has matchmaker and user is a PM. Usage: FIELD_LOOKUP[isMmeEnabled][isPm]
const FIELD_LOOKUP = {
Expand Down

0 comments on commit 8eff76b

Please sign in to comment.