From 6cadc733d2d04ec3b4e9397384e632012d4da221 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 23 Feb 2024 16:09:28 -0500 Subject: [PATCH 01/10] refactor: switch DataUseAgreements to JSX --- .../dar_application/DataUseAgreements.js | 118 ++++++++---------- 1 file changed, 49 insertions(+), 69 deletions(-) diff --git a/src/pages/dar_application/DataUseAgreements.js b/src/pages/dar_application/DataUseAgreements.js index 8d6d4f6e1..6b1cca28c 100644 --- a/src/pages/dar_application/DataUseAgreements.js +++ b/src/pages/dar_application/DataUseAgreements.js @@ -1,5 +1,4 @@ - -import { a, div, h2, h3, span, li, ol, p } from 'react-hyperscript-helpers'; +import React from 'react'; import {isNil} from 'lodash/fp'; import BroadLibraryCardAgreementLink from '../../assets/Library_Card_Agreement_2023_ApplicationVersion.pdf'; import NhgriLibraryCardAgreementLink from '../../assets/NIH_Library_Card_Agreement_11_17_22_version.pdf'; @@ -18,78 +17,59 @@ export default function DataUseAgreements(props) { } = props; return ( - div({ - className: 'dar-step-card' - }, [ - - h2({}, ['Data Use Agreements']), - - div({ className: 'form-group' }, [ - h3({}, [ - 'DUOS Library Card Data Access Agreement and Attestation' - ]), - - p({ - className: 'data-use-paragraph', - }, [ - 'Under the National Institutes of Health (NIH) Genomic Data Sharing Policy, the Genomic Data User Code of Conduct sets forth principles for responsible management and use of large-scale genomic data and associated phenotypic data accessed through controlled access to NIH-designated data repositories (e.g., the database of Genotypes and Phenotypes (dbGaP), repositories established as NIH Trusted Partners). Failure to abide by any term within this Code of Conduct may result in revocation of approved access to datasets obtained through these repositories. Investigators who are approved to access data agree to:' - ]), - - ol({ className: 'data-use-list' }, [ - li({}, ['Use datasets solely in connection with the research project described in the approved Data Access Request for each dataset; ']), - li({}, ['Make no attempt to identify or contact individual participants or groups from whom data were collected, or generate information that could allow participants’ identities to be readily ascertained, without appropriate approvals from the submitting institutions;']), - li({}, ['Maintain the confidentiality of the data and not distribute them to any entity or individual beyond those specified in the approved Data Access Request;']), - li({}, ['Adhere to the NIH Security Best Practices for Controlled-Access Data Subject to the NIH Genomic Data Sharing Policy and ensure that only approved users can gain access to data files;']), - li({}, ['Acknowledge the Intellectual Property terms as specified in the Library Card Agreement; ']), - li({}, ['Provide appropriate acknowledgement in any dissemination of research findings including the investigator(s) who generated the data, the funding source, accession numbers of the dataset, and the data repository from which the data were accessed; and,']), - li({}, [ - 'Report any inadvertent data release, breach of data security, or other data management incidents in accordance with the terms specified in the ', a({target: '_blank', href: BroadLibraryCardAgreementLink}, ['Library Card Agreement']), ' and ', a({target: '_blank', href: ModelDucLink}, ['NIH Data Use Certification.'])]), - ]) - ]), +
+

Data Use Agreements

- h3({}, [ - 'By submitting this data access request, you agree to all terms in the agreement(s) listed below.' - ]), +
+

DUOS Library Card Data Access Agreement and Attestation

- div({ className: 'flex flex-row', style: { justifyContent: 'flex-start', }, }, [ - div({}, [ - a({ target: '_blank', href: BroadLibraryCardAgreementLink, className: 'button button-white', style: { marginRight: '2rem', }, }, [ - span({className: 'glyphicon glyphicon-download'}), - ' Broad Library Card Agreement' - ]) - ]), - div({}, [ - a({ target: '_blank', href: NhgriLibraryCardAgreementLink, className: 'button button-white' }, [ - span({className: 'glyphicon glyphicon-download'}), - ' NHGRI Library Card Agreement' - ]) - ]) - ]), +

+ Under the National Institutes of Health (NIH) Genomic Data Sharing Policy, the Genomic Data User Code of Conduct sets forth principles for responsible management and use of large-scale genomic data and associated phenotypic data accessed through controlled access to NIH-designated data repositories (e.g., the database of Genotypes and Phenotypes (dbGaP), repositories established as NIH Trusted Partners). Failure to abide by any term within this Code of Conduct may result in revocation of approved access to datasets obtained through these repositories. Investigators who are approved to access data agree to: +

+
    +
  1. Use datasets solely in connection with the research project described in the approved Data Access Request for each dataset;
  2. +
  3. Make no attempt to identify or contact individual participants or groups from whom data were collected, or generate information that could allow participants’ identities to be readily ascertained, without appropriate approvals from the submitting institutions;
  4. +
  5. Maintain the confidentiality of the data and not distribute them to any entity or individual beyond those specified in the approved Data Access Request;
  6. +
  7. Adhere to the NIH Security Best Practices for Controlled-Access Data Subject to the NIH Genomic Data Sharing Policy and ensure that only approved users can gain access to data files;
  8. +
  9. Acknowledge the Intellectual Property terms as specified in the Library Card Agreement;
  10. +
  11. Provide appropriate acknowledgement in any dissemination of research findings including the investigator(s) who generated the data, the funding source, accession numbers of the dataset, and the data repository from which the data were accessed; and,
  12. +
  13. Report any inadvertent data release, breach of data security, or other data management incidents in accordance with the terms specified in the Library Card Agreement and NIH Data Use Certification.
  14. +
+
- div({ className: 'flex flex-row', style: { justifyContent: 'around', paddingTop: '4rem' } }, [ - div({ className: 'flex flex-row', style: { justifyContent: 'flex-start' }, }, [ - a({ - id: 'btn_attest', isRendered: isNil(darCode), onClick: () => attest(), - className: 'button button-blue', - disabled: isAttested, - style: { - marginRight: '2rem', - } - }, ['Attest']), - a({ - id: 'btn_saveDar', isRendered: isNil(darCode), onClick: () => save(), - className: 'button button-white', - disabled: isAttested, - }, ['Save']), +

By submitting this data access request, you agree to all terms in the agreement(s) listed below.

- ]), - a({ - id: 'btn_cancelAttest', isRendered: isNil(darCode) && isAttested, onClick: () => cancelAttest(), - style: { 'float': 'right' }, className: 'button button-white', - }, ['Cancel']), - ]) +
+
+ + + {' '} + Broad Library Card Agreement + +
+
+ + + {' '} + NHGRI Library Card Agreement + +
+
- ]) +
+
+ {isNil(darCode) && + Attest + } + {isNil(darCode) && + Save + } +
+ {isNil(darCode) && isAttested && + Cancel + } +
+
); } From d859062e1d8bcf3048934cfefd175f44aebc57f6 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 10:30:53 -0500 Subject: [PATCH 02/10] refactor: switch TranslatedDulModal to JSX --- src/components/modals/TranslatedDulModal.js | 53 +++++++++++---------- src/pages/DatasetCatalog.js | 1 - 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/components/modals/TranslatedDulModal.js b/src/components/modals/TranslatedDulModal.js index cdd81d437..dd2990920 100644 --- a/src/components/modals/TranslatedDulModal.js +++ b/src/components/modals/TranslatedDulModal.js @@ -1,10 +1,10 @@ -import {li, ul, span} from 'react-hyperscript-helpers'; +import React from 'react'; import { BaseModal } from '../BaseModal'; import { useState, useEffect } from 'react'; import isEmpty from 'lodash/fp/isEmpty'; import {DataUseTranslation} from '../../libs/dataUseTranslation'; -const MODAL_ID = 'translatedDul'; +const MODAL_ID = 'translatedDulModal'; const listStyle = { listStyle: 'none' @@ -13,53 +13,56 @@ const listStyle = { //NOTE: li partial can be used in components that only need the list async function GenerateUseRestrictionStatements(dataUse) { if (!dataUse || isEmpty(dataUse)) { - return [li({ - className: 'translated restriction', - key: 'restriction-none' - }, ['None'])]; + return ( +
  • + None +
  • + ); } const translations = await DataUseTranslation.translateDataUseRestrictions(dataUse); return translations.map((restriction) => { - return li({ - className: 'translated-restriction', - key: `${restriction.code}-statement`, - }, [span({ style: { fontWeight: 'bold' } }, [restriction.code, ': ']), restriction.description]); + return ( +
  • + {restriction.code}: + {restriction.description} +
  • + ); }); } export default function TranslatedDulModal(props) { - const OKHandler = () => { - props.onOKRequest(MODAL_ID); - }; + const { showModal, onCloseRequest, dataUse } = props; + + const [translatedDulList, setTranslatedDulList] = useState([]); const closeHandler = () => { - props.onCloseRequest(MODAL_ID); + onCloseRequest(MODAL_ID); }; - const [translatedDULList, setTranslatedDULList] = useState(GenerateUseRestrictionStatements(props.dataUse || [])); - useEffect(() => { - const getTranslatedDULList = async() => { - const list = await GenerateUseRestrictionStatements(props.dataUse || []); - setTranslatedDULList(list); + const getTranslatedDulList = async () => { + const dulList = await GenerateUseRestrictionStatements(dataUse || []); + setTranslatedDulList(dulList); }; - getTranslatedDULList(); - }, [props.dataUse]); + getTranslatedDulList(); + }, [dataUse]); return ( BaseModal({ - id: 'translatedDulModal', - showModal: props.showModal, + id: MODAL_ID, + showModal: showModal, onRequestClose: closeHandler, color: 'dataset', type: 'informative', iconSize: 'none', title: 'Data Use Terms', - action: { label: 'Close', handler: OKHandler } + action: { label: 'Close', handler: closeHandler } }, [ - ul({style: listStyle, id: 'txt_translatedRestrictions', className: 'row no-margin translated-restriction'}, translatedDULList), + ]) ); } diff --git a/src/pages/DatasetCatalog.js b/src/pages/DatasetCatalog.js index cab59aa68..d524c1e80 100644 --- a/src/pages/DatasetCatalog.js +++ b/src/pages/DatasetCatalog.js @@ -773,7 +773,6 @@ export default function DatasetCatalog(props) { isRendered: showTranslatedDULModal, showModal: showTranslatedDULModal, dataUse: dataUse, - onOKRequest: () => setShowTranslatedDULModal(false), onCloseRequest: () => setShowTranslatedDULModal(false) }), From 6211723511f588716adf587c2d6efcaf43806fa3 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 10:50:07 -0500 Subject: [PATCH 03/10] refactor: switch CollaboratorList to JSX --- .../collaborator/CollaboratorList.js | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/src/pages/dar_application/collaborator/CollaboratorList.js b/src/pages/dar_application/collaborator/CollaboratorList.js index be4855d73..1d337d9ad 100644 --- a/src/pages/dar_application/collaborator/CollaboratorList.js +++ b/src/pages/dar_application/collaborator/CollaboratorList.js @@ -1,7 +1,7 @@ +import React from 'react'; import CollaboratorForm from './CollaboratorForm'; import CollaboratorRow from './CollaboratorRow'; import { useState, useEffect} from 'react'; -import { button, div, h } from 'react-hyperscript-helpers'; import './collaborator.css'; import { isNil } from 'lodash'; @@ -68,59 +68,62 @@ export default function CollaboratorList(props) { setDeleteBoolArray((new Array(props.collaborators.length).fill(false))); }, [props.collaborators, props.deleteBoolArray]); - const ListItems = div({className: 'form-group row no-margin'}, [ - collaborators - .map((collaborator, index) => { - return h(CollaboratorRow, { - index: index, - saveCollaborator: (newCollaborator) => saveCollaborator(index, newCollaborator), - deleteCollaborator: () => deleteCollaborator(index), - updateEditState: (bool) => updateEditState(index, bool), - toggleDeleteBool: (bool) => toggleDeleteBool(index, bool), - collaborator, - collaboratorLabel, - showApproval, - editMode: editState[index], - key: collaborator?.uuid, - validation: !isNil(validation) ? validation[index] || {} : {}, - onCollaboratorValidationChange, - deleteMode: deleteBoolArray[index] - }); - }) - ]); + const ListItems = ( +
    + {collaborators.map((collaborator, index) => ( + saveCollaborator(index, newCollaborator)} + deleteCollaborator={() => deleteCollaborator(index)} + updateEditState={(bool) => updateEditState(index, bool)} + toggleDeleteBool={(bool) => toggleDeleteBool(index, bool)} + collaborator={collaborator} + collaboratorLabel={collaboratorLabel} + showApproval={showApproval} + editMode={editState[index]} + key={collaborator?.uuid} + validation={!isNil(validation) ? validation[index] || {} : {}} + onCollaboratorValidationChange={onCollaboratorValidationChange} + deleteMode={deleteBoolArray[index]} + /> + ))} +
    + ); return ( - div({className: 'collaborator-list-component'}, [ - div({className: 'row no-margin'}, [ - button({ - id: `add-${collaboratorKey}-btn`, - type: 'button', // default button element type inside a form is "submit". - className: 'button button-white', - style: { +
    +
    + {!showNewForm && } + {showNewForm && ( + saveCollaborator(collaborators.length, newCollaborator)} + updateEditState={(bool) => setShowNewForm(bool)} + collaboratorLabel={collaboratorLabel} + showApproval={showApproval} + editMode={true} + validation={!isNil(validation) ? validation[collaborators.length] || {} : {}} + onCollaboratorValidationChange={onCollaboratorValidationChange} + /> + )} +
    + {ListItems} +
    ); } From 66170c75140ccec29805966b0463649947db89ff Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 10:58:53 -0500 Subject: [PATCH 04/10] refactor: switch CollaboratorSummary to JSX --- .../collaborator/CollaboratorSummary.js | 159 +++++++----------- 1 file changed, 63 insertions(+), 96 deletions(-) diff --git a/src/pages/dar_application/collaborator/CollaboratorSummary.js b/src/pages/dar_application/collaborator/CollaboratorSummary.js index dd176f5a9..6af156da5 100644 --- a/src/pages/dar_application/collaborator/CollaboratorSummary.js +++ b/src/pages/dar_application/collaborator/CollaboratorSummary.js @@ -1,5 +1,4 @@ import React from 'react'; -import { a, h, div, span } from 'react-hyperscript-helpers'; import { useState } from 'react'; import DeleteCollaboratorModal from './DeleteCollaboratorModal'; @@ -14,101 +13,69 @@ export const CollaboratorSummary = (props) => { setShowDeleteCollaboratorModal(false); }; - return div({}, [ - div({}, [ - ]), - div( { - id: index+'_summary', - className: 'collaborator-summary-card', - }, [ - div({ - id: index+'_name', - style: { - flex: '1 1 100%', - marginRight: '1.5rem', - } - }, [ - span(collaborator.name), - ]), - - div({ - id: index+'_title', - style: { - flex: '1 1 100%', - marginRight: '1.5rem', - } - }, [ - span(collaborator.title), - ]), - - div({ - id: index+'_eraCommonsId', - style: { - flex: '1 1 100%', - marginRight: '1.5rem', - } - }, [ - span(collaborator.eraCommonsId), - ]), - - div({ - id: index+'_email', - style: { - flex: '1 1 100%', - } - }, [ - span(collaborator.email), - ]), - // Edit Button - div({ - className: 'collaborator-summary-edit-delete-buttons', - isRendered: !props.deleteMode, - }, [ - a({ - id: index+'_editCollaborator', - style: { marginLeft: 10, marginRight: 10 }, - onClick: () => { - props.updateEditState(true); - }, - }, [ - span({ - className: 'glyphicon glyphicon-pencil caret-margin collaborator-edit-icon', 'aria-hidden': 'true', - 'data-tip': 'Edit dataset', 'data-for': 'tip_edit' - }), - span({ - style: { - marginLeft: '1rem', - } - }), - ]), - // Delete Button - a({ - id: index+'_deleteMember', - style: { marginLeft: 10 }, - onClick: () => { setShowDeleteCollaboratorModal(true), props.toggleDeleteBool(false); }, - }, [ - span({ - className: 'glyphicon glyphicon-trash collaborator-delete-icon', - 'aria-hidden': 'true', 'data-tip': 'Delete dataset', 'data-for': 'tip_delete' - }), - span({ - style: { - marginLeft: '1rem', - } - }), - ]), - // Delete Modal - h(DeleteCollaboratorModal, { - showDelete: showDeleteCollaboratorModal, - closeDelete: closeDelete, - header: 'Delete Entry', - title:
    Are you sure you want to delete {collaborator.name}?
    , - message:
    This action is permanent and cannot be undone.
    , - onConfirm: () => props.deleteCollaborator(), - }) - ]), - ]), - ]); + return ( +
    +
    +
    +
    + {collaborator.name} +
    +
    + {collaborator.title} +
    +
    + {collaborator.eraCommonsId} +
    +
    + {collaborator.email} +
    + {/* Edit Button */} + {!props.deleteMode &&
    + { + props.updateEditState(true); + }} + > + + + + {/* Delete Button */} + { + setShowDeleteCollaboratorModal(true); + props.toggleDeleteBool(false); + }} + > + + + + {/* Delete Modal */} + Are you sure you want to delete {collaborator.name}?
    } + message={
    This action is permanent and cannot be undone.
    } + onConfirm={() => props.deleteCollaborator()} + /> +
    } +
    + + ); }; export default CollaboratorSummary; From 5db455ca97424ad38591a933888bcd49cf1b7f2b Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 11:20:53 -0500 Subject: [PATCH 05/10] refactor: switch SearchSelectOrText to JSX --- src/components/SearchSelectOrText.js | 98 +++++++++++++--------------- 1 file changed, 47 insertions(+), 51 deletions(-) diff --git a/src/components/SearchSelectOrText.js b/src/components/SearchSelectOrText.js index 5831658ec..103fdf9cf 100644 --- a/src/components/SearchSelectOrText.js +++ b/src/components/SearchSelectOrText.js @@ -1,5 +1,5 @@ +import React from 'react'; import { useState, useEffect, useRef } from 'react'; -import {div, input, span, a, ul, li } from 'react-hyperscript-helpers'; import {isEqual} from 'lodash'; import {find} from 'lodash/fp'; @@ -68,57 +68,53 @@ export const SearchSelectOrText = (props) => { return ( - div({ className: 'dropdown select-dropdown', id, name: label }, [ - a({ - className: `btn select-btn btn-secondary dropdown-toggle ${errored ? 'errored' : ''}`, - role: 'button', - id: 'dropdownMenuLink', - 'data-toggle': 'dropdown', - 'aria-haspopup': true, - 'aria-expanded': false, - onClick: onOpen, - disabled - }, [ - div({ - style: { width: '100%' } - }, [ - span([currentDisplay]), - span({ className: 'caret select-caret caret-margin', style: { right: '2%' } }) - ]) - ]), - div({ - className: 'dropdown-menu select-dropdown-menu', - onBlur: () => { - selectManual(searchTerms.current.value); - onBlur && onBlur(); - } - }, [ - input({ - type: 'text', - placeholder: searchPlaceholder ? searchPlaceholder : 'Search...', - className: 'search-bar', - onChange:() => handleSearch(searchTerms), - onKeyDown: (e) => { - if (e.key == 'Enter') { +
    + +
    { + selectManual(searchTerms.current.value); + onBlur && onBlur(); + }}> + handleSearch(searchTerms)} + onKeyDown={(e) => { + if (e.key === 'Enter') { selectManual(searchTerms.current.value); } - }, - ref: searchTerms - }), - div({ - className: 'dropdown-divider' - }), - ul({ style: { paddingLeft: 0 } }, filteredList.map(item => { - return li({ - className: item.key === currentSelection - ? 'dropdown-item select-dropdown-item active' - : 'dropdown-item select-dropdown-item', - onMouseUp: () => { - select(item.key); - }, - }, [item.displayText]); - })) - ]) - ]) + }} + ref={searchTerms} + /> +
    +
      + {filteredList.map(item => ( +
    • { + select(item.key); + }} + key={item.key} + > + {item.displayText} +
    • + ))} +
    +
    +
    ); }; From bbbfc8d7f28f6cc688e34002fbf25ddf4ef4a0df Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 11:29:48 -0500 Subject: [PATCH 06/10] refactor: switch DucAddendum to JSX --- src/pages/dar_application/DucAddendum.js | 87 +++++++++++------------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/src/pages/dar_application/DucAddendum.js b/src/pages/dar_application/DucAddendum.js index 535e38437..72d6c828e 100644 --- a/src/pages/dar_application/DucAddendum.js +++ b/src/pages/dar_application/DucAddendum.js @@ -1,5 +1,5 @@ +import React from 'react'; import { useState, useEffect, Fragment } from 'react'; -import { a, div, h2, h3, h } from 'react-hyperscript-helpers'; import { Styles } from '../../libs/theme'; import SimpleTable from '../../components/SimpleTable'; import './dar_application.css'; @@ -150,32 +150,36 @@ export default function DucAddendum(props) { ]; }); - return [ - h(Fragment, {}, [ - h(SimpleTable, { - isLoading: isLoading, - columnHeaders: columnHeaderData(headerConfig), - rowData: [], - styles: headerStyles - }), - ]), - h(Fragment, {}, [ - h(SimpleTable, { - isLoading: false, - columnHeaders: columnHeaderData(columnConfig), - rowData: datasetData, - styles: columnStyles - }), - ]), - ]; + return ( + <> + + + + + + + + ); }); - tableChunks.push(div({ - style: { - borderTop: '1px solid black', - borderWidth: '1px 0 0 0', - }, - }, [])); + tableChunks.push( +
    + ); const fullTable = flatten(tableChunks); setDucAddendumTable(fullTable); @@ -186,27 +190,16 @@ export default function DucAddendum(props) { }, [buildDucAddendumTable]); return ( - div({ - className: 'dar-step-card' - }, [ - h2({}, ['Addendum']), - h3({ style: { marginBottom: '2rem' } }, ['Please review the datasets you requested grouped by their data use terms below, and click "Submit" below to send your data access request to the DAC(s).']), - - div({ className: 'table-container' }, ducAddendumTable), - - div({ className: 'flex flex-row', style: { justifyContent: 'flex-start', paddingTop: '4rem' }, }, [ - a({ - id: 'btn_openSubmitModal', onClick: () => doSubmit(), - className: 'button button-blue', - style: { - marginRight: '2rem', - } - }, ['Submit']), - a({ - id: 'btn_save', onClick: () => save(), - className: 'button button-white', - }, ['Save']), - ]), - ]) +
    +

    Addendum

    +

    Please review the datasets you requested grouped by their data use terms below, and click "Submit" below to send your data access request to the DAC(s).

    + +
    {ducAddendumTable}
    + + +
    ); } From 920a132d18ed5b2b82f5401e005d2fd7f515e6de Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 12:22:02 -0500 Subject: [PATCH 07/10] refactor: switch DatasetUpdate to JSX --- src/components/data_update/DatasetUpdate.js | 509 ++++++++++---------- 1 file changed, 251 insertions(+), 258 deletions(-) diff --git a/src/components/data_update/DatasetUpdate.js b/src/components/data_update/DatasetUpdate.js index d589e376f..04b028668 100644 --- a/src/components/data_update/DatasetUpdate.js +++ b/src/components/data_update/DatasetUpdate.js @@ -1,7 +1,6 @@ +import React from 'react'; import { useCallback, useState, useEffect } from 'react'; -import { button, h, h2, div } from 'react-hyperscript-helpers'; -import { find, isArray, isNil } from 'lodash/fp'; - +import { find, isNil } from 'lodash/fp'; import { FormFieldTypes, FormField, FormValidators } from '../forms/forms'; import { DAC, DAR, DataSet } from '../../libs/ajax'; import { Notifications } from '../../libs/utils'; @@ -133,261 +132,255 @@ export const DatasetUpdate = (props) => { } }, [prefillFormData, dataset, formData]); - return h(div, { - className: 'data-update-section', - }, [ - h2('1. Dataset Information'), - h(FormField, { - id: 'datasetName', - title: 'Dataset Name', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.datasetName, - onChange: ({ value }) => { - formData.properties.datasetName = value; - } - }), - h(FormField, { - id: 'description', - title: 'Dataset Description', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.description, - onChange: ({ value }) => { - formData.properties.description = value; - } - }), - h(FormField, { - id: 'dataDepositor', - title: 'Data Custodian', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.dataDepositor, - onChange: ({ value }) => { - formData.properties.dataDepositor = value; - } - }), - h(FormField, { - id: 'principalInvestigator', - title: 'Principal Investigator (PI)', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.principalInvestigator, - onChange: ({ value }) => { - formData.properties.principalInvestigator = value; - } - }), - h(FormField, { - id: 'dbGap', - title: 'Dataset Repository URL', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.dbGap, - onChange: ({ value }) => { - formData.properties.dbGap = value; - } - }), - h(FormField, { - id: 'dataType', - title: 'Data Type', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.dataType, - onChange: ({ value }) => { - formData.properties.dataType = value; - } - }), - h(FormField, { - id: 'species', - title: 'Species', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.species, - onChange: ({ value }) => { - formData.properties.species = value; - } - }), - h(FormField, { - id: 'phenotype', - title: 'Phenotype/Indication', - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.phenotype, - onChange: ({ value }) => { - formData.properties.phenotype = value; - } - }), - h(FormField, { - id: 'nrParticipants', - title: '# of Participants', - type: FormFieldTypes.NUMBER, - validators: [FormValidators.REQUIRED], - defaultValue: formData.properties.nrParticipants, - onChange: ({ value }) => { - formData.properties.nrParticipants = value; - } - }), - h(FormField, { - id: 'dac', - title: 'Data Access Committee', - validators: [FormValidators.REQUIRED], - type: FormFieldTypes.SELECT, - selectOptions: dacOptions(formData.dac.dacs), - defaultValue: [ - { displayText: formData.dac.name, dacId: formData.dac.dacId }, - ], - disabled: true, - }), - h2('2. Data Use Terms'), - // readonly primary - div({}, [ - h(FormField, { - title: 'Primary Data Use Terms*', - description: 'Please select one of the following data use permissions for your dataset', - type: FormFieldTypes.RADIOBUTTON, - id: 'generalUse', - toggleText: 'General Research Use', - value: 'generalUse', - defaultValue: formData.dataUse.generalUse === true ? 'generalUse' : undefined, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.RADIOBUTTON, - id: 'hmbResearch', - toggleText: 'Health/Medical/Biomedical Research Use', - value: 'hmbResearch', - defaultValue: formData.dataUse.hmbResearch === true ? 'hmbResearch' : undefined, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.RADIOBUTTON, - id: 'diseaseRestrictions', - toggleText: 'Disease-Specific Research Use', - value: 'diseaseRestrictions', - defaultValue: isArray(formData.dataUse.diseaseRestrictions) && formData.dataUse.diseaseRestrictions.length > 0 ? 'diseaseRestrictions' : undefined, - disabled: true, - }), - div({ - style: { - marginBottom: '1.0rem' - } - }, [ - h(FormField, { - type: FormFieldTypes.SELECT, - isMulti: true, - isCreatable: true, - optionsAreString: true, - isAsync: true, - id: 'diseaseRestrictionsText', - validators: [FormValidators.REQUIRED], - placeholder: 'none', - loadOptions: searchOntologies, - defaultValue: formData.dataUse.diseaseLabels, - disabled: true, - }), - ]), - h(FormField, { - type: FormFieldTypes.RADIOBUTTON, - id: 'otherPrimary', - toggleText: 'Other', - value: 'otherPrimary', - defaultValue: formData.dataUse.otherRestrictions ? 'otherPrimary' : undefined, - disabled: true, - }), - h(FormField, { - id: 'otherPrimaryText', - validators: [FormValidators.REQUIRED], - placeholder: 'none', - defaultValue: formData.dataUse.other, - disabled: true, - }), - ]), - // secondary - div({}, [ - h(FormField, { - title: 'Secondary Data Use Terms', - description: 'Please select all applicable data use parameters.', - type: FormFieldTypes.CHECKBOX, - id: 'methodsResearch', - toggleText: 'No methods development or validation studies (NMDS)', - defaultValue: formData.dataUse.methodsResearch === true, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'geneticStudiesOnly', - toggleText: 'Genetic studies only (GSO)', - defaultValue: formData.dataUse.geneticStudiesOnly === true, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'publicationResults', - toggleText: 'Publication Required (PUB)', - defaultValue: formData.dataUse.publicationResults === true, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'collaboratorRequired', - toggleText: 'Collaboration Required (COL)', - defaultValue: formData.dataUse.collaboratorRequired === true, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'ethicsApprovalRequired', - name: 'ethicsApprovalRequired', - toggleText: 'Ethics Approval Required (IRB)', - defaultValue: formData.dataUse.ethicsApprovalRequired === true, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'geographicalRestrictions', - toggleText: 'Geographic Restriction (GS-)', - defaultValue: formData.dataUse.geographicalRestrictions === 'Yes', - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'publicationMoratorium', - toggleText: 'Publication Moratorium (MOR)', - defaultValue: formData.dataUse.publicationMoratorium === 'true', - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'nonCommercialUse', - toggleText: 'Non-profit Use Only (NPU)', - defaultValue: formData.dataUse.commercialUse === false, - disabled: true, - }), - h(FormField, { - type: FormFieldTypes.CHECKBOX, - id: 'otherSecondary', - toggleText: 'Other', - defaultValue: formData.dataUse.hasSecondaryOther, - disabled: true, - }), - h(FormField, { - id: 'otherSecondaryText', - validators: [FormValidators.REQUIRED], - placeholder: 'Please specify', - defaultValue: formData.dataUse.secondaryOther, - disabled: true, - }), - ]), - h2('3. NIH Certification'), - div({ style: { display: 'flex', flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'flex-end', marginRight: '30px' } }, [ - h(FormField, { - type: FormFieldTypes.FILE, - title: 'NIH Institutional Certification', - description: 'If an Institutional Certification for this dataset exists, please upload it here', - id: 'nihInstitutionalCertificationFile', - placeholder: 'default.txt', - }), - ]), - div({ className: 'flex flex-row', style: { justifyContent: 'flex-end', marginTop: '2rem', marginBottom: '2rem' } }, [ - button({ - className: 'button button-white', - type: 'submit', - onClick: submitForm, - }, 'Submit'), - ]), - ]); + return ( +
    +

    1. Dataset Information

    + { + formData.properties.datasetName = value; + }} + /> + { + formData.properties.description = value; + }} + /> + { + formData.properties.dataDepositor = value; + }} + /> + { + formData.properties.principalInvestigator = value; + }} + /> + { + formData.properties.dbGap = value; + }} + /> + { + formData.properties.dataType = value; + }} + /> + { + formData.properties.species = value; + }} + /> + { + formData.properties.phenotype = value; + }} + /> + { + formData.properties.nrParticipants = value; + }} + /> + +

    2. Data Use Terms

    + {/* readonly primary */} +
    + + + 0 ? 'diseaseRestrictions' : undefined} + disabled={true} + /> +
    + +
    + + +
    + {/* secondary */} +
    + + + + + + + + + + +
    +

    3. NIH Certification

    +
    + +
    +
    + +
    +
    + ); }; export default DatasetUpdate; From 1ab7f1519d444afeedd8307940450b7510eaa513 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 12:40:29 -0500 Subject: [PATCH 08/10] refactor: switch ds_study_information to JSX --- .../data_submission/ds_study_information.js | 370 +++++++++--------- 1 file changed, 177 insertions(+), 193 deletions(-) diff --git a/src/pages/data_submission/ds_study_information.js b/src/pages/data_submission/ds_study_information.js index 4d1d0ec0f..52234f406 100644 --- a/src/pages/data_submission/ds_study_information.js +++ b/src/pages/data_submission/ds_study_information.js @@ -1,5 +1,5 @@ +import React from 'react'; import { useState, useEffect } from 'react'; -import { h, h2, div } from 'react-hyperscript-helpers'; import { isEmpty } from 'lodash/fp'; import { Notifications } from '../../libs/utils'; @@ -38,196 +38,180 @@ export default function DataSubmissionStudyInformation(props) { init(); }, [onChange]); - return h(div, { - className: 'data-submitter-section', - }, [ - h2('Study Information'), - h(FormField, { - id: 'studyName', - title: 'Study Name', - validators: studyEditMode ? undefined : [FormValidators.REQUIRED], - validation: validation.studyName, - onChange, - onValidationChange, - defaultValue: studyEditMode ? formData?.studyName : undefined, - disabled: studyEditMode, - }), - h(FormField, { - id: 'studyType', - title: 'Study Type', - type: FormFieldTypes.SELECT, - selectOptions: [ - 'Observational', 'Interventional', 'Descriptive', - 'Analytical', 'Prospective', 'Retrospective', - 'Case report', 'Case series', 'Cross-sectional', - 'Cohort study' - ], - isCreatable: true, - validation: validation.studyType, - selectConfig: {}, - defaultValue: studyEditMode ? formData?.studyType : undefined, - onChange, - onValidationChange - }), - h(FormField, { - type: FormFieldTypes.TEXTAREA, - rows: 6, - id: 'studyDescription', - title: 'Study Description', - placeholder: 'Description', - defaultValue: studyEditMode ? formData?.studyDescription : undefined, - validators: [FormValidators.REQUIRED], - validation: validation.studyDescription, - onChange, - onValidationChange - }), - h(FormField, { - id: 'dataTypes', - title: 'Data Types', - placeholder: 'Type', - validators: [FormValidators.REQUIRED], - type: FormFieldTypes.SELECT, - isCreatable: true, - isMulti: true, - optionsAreString: true, - // The top properties were extracted from the prod database and deduplicated using the query: - // SELECT property_value, COUNT(*) FROM dataset_property WHERE property_key = 2 GROUP BY property_value ORDER BY COUNT(*) DESC; - selectOptions: [ - 'CITE-seq', - 'Hybrid Capture', - 'RNA-Seq', - 'scRNA-Seq', - 'Spatial Transcriptomics', - 'snRNA-Seq', - 'Whole Genome (WGS)', - 'Whole Exome (WES)', - ], - defaultValue: studyEditMode ? formData?.dataTypes : undefined, - validation: validation.dataTypes, - onChange, - onValidationChange - }), - h(FormField, { - id: 'phenotypeIndication', - title: 'Phenotype/Indication Studied', - defaultValue: studyEditMode ? formData?.phenotypeIndication : undefined, - validation: validation.phenotypeIndication, - onChange, - onValidationChange - }), - h(FormField, { - id: 'species', - title: 'Species', - defaultValue: studyEditMode ? formData?.species : undefined, - validation: validation.species, - onChange, - onValidationChange - }), - h(FormField, { - id: 'piName', - title: 'Principal Investigator Name', - defaultValue: studyEditMode ? formData?.piName : undefined, - validators: [FormValidators.REQUIRED], - validation: validation.piName, - onChange, - onValidationChange - }), - h(FormField, { - isRendered: !isEmpty(user), - id: 'dataSubmitterName', - title: 'Data Submitter Name ', - description: `The individual completing this form will be saved with the study.`, - defaultValue: studyEditMode ? formData?.dataSubmitterName : user?.displayName, - validation: validation.dataSubmitterName, - disabled: true, - onChange, - onValidationChange - }), - h(FormField, { - isRendered: !isEmpty(user), - id: 'dataSubmitterEmail', - title: 'Data Submitter Email', - defaultValue: studyEditMode ? formData?.dataSubmitterEmail : user?.email, - validation: validation.dataSubmitterEmail, - disabled: true, - onChange, - onValidationChange - }), - h(FormField, { - id: 'dataCustodianEmail', - title: 'Data Custodian Email', - description: `Insert the email for any individual with the - authority to add/remove users access to this study’s datasets.`, - type: FormFieldTypes.SELECT, - validators: [ - FormValidators.EMAIL - ], - selectOptions: [], - isCreatable: true, - isMulti: true, - optionsAreString: true, - selectConfig: { - components: { - DropdownIndicator: null, - Menu: () => null, - }, - }, - placeholder: 'Add one or more emails', - defaultValue: studyEditMode ? formData?.dataCustodianEmail : undefined, - validation: validation.dataCustodianEmail, - onChange, - onValidationChange - }), - div({ - style: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'space-between', - }, - }, [ - - h(FormField, { - id: 'alternativeDataSharingPlanTargetDeliveryDate', - style: { - width: '45%', - }, - title: 'Target Delivery Date', - placeholder: 'Please enter date (YYYY-MM-DD)', - defaultValue: studyEditMode ? formData?.alternativeDataSharingPlanTargetDeliveryDate : initialFormData?.alternativeDataSharingPlanTargetDeliveryDate, - validators: [FormValidators.DATE], - onChange, - validation: validation.alternativeDataSharingPlanTargetDeliveryDate, - onValidationChange, - }), - h(FormField, { - id: 'alternativeDataSharingPlanTargetPublicReleaseDate', - style: { - width: '45%', - }, - title: 'Target Public Release Date', - placeholder: 'Please enter date (YYYY-MM-DD)', - defaultValue: studyEditMode ? formData?.alternativeDataSharingPlanTargetPublicReleaseDate : initialFormData?.alternativeDataSharingPlanTargetPublicReleaseDate, - validators: [FormValidators.DATE], - onChange, - validation: validation.alternativeDataSharingPlanTargetPublicReleaseDate, - onValidationChange, - }), - ]), - h(FormField, { - id: 'publicVisibility', - title: 'Public Visibility', - validators: [FormValidators.REQUIRED], - type: FormFieldTypes.RADIOGROUP, - description: 'Please select one of the following data use permissions for your dataset', - name: 'publicVisibility', - options: [ - { name: true, text: 'Yes, I want my dataset info to be visible and available for requests' }, - { name: false, text: 'No, I do not want my dataset info to be visible and available for requests' } - ], - defaultValue: studyEditMode ? formData?.publicVisibility : undefined, - onChange, - validation: validation.publicVisibility, - onValidationChange - }), - ]); + return ( +
    +

    Study Information

    + + + + + + + + {!isEmpty(user) && } + {!isEmpty(user) && } + null, + }, + }} + placeholder="Add one or more emails" + defaultValue={studyEditMode ? formData?.dataCustodianEmail : undefined} + validation={validation.dataCustodianEmail} + onChange={onChange} + onValidationChange={onValidationChange} + /> +
    + + +
    + +
    + ); } From 92b377cd088cd926902dbaf61b6fe40bcfbf42f6 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Mon, 26 Feb 2024 13:42:46 -0500 Subject: [PATCH 09/10] refactor: switch ConsentTextGenerator to JSX --- src/pages/ConsentTextGenerator.js | 407 ++++++++++++++---------------- 1 file changed, 187 insertions(+), 220 deletions(-) diff --git a/src/pages/ConsentTextGenerator.js b/src/pages/ConsentTextGenerator.js index 606c912d3..34ff6b01e 100644 --- a/src/pages/ConsentTextGenerator.js +++ b/src/pages/ConsentTextGenerator.js @@ -1,5 +1,5 @@ +import React from 'react'; import {Styles} from '../libs/theme'; -import {a, br, button, div, h, input, label, span, textarea} from 'react-hyperscript-helpers'; import {RadioButton} from '../components/RadioButton'; import AsyncSelect from 'react-select/async'; import {isNil, isEmpty, head} from 'lodash/fp'; @@ -61,227 +61,194 @@ export default function ConsentTextGenerator() { }; return ( - div({style: {...Styles.PAGE, color: '#1f3b50' }}, [ - div({style: {...Styles.TITLE, marginTop: '3.5rem'}}, [ - 'Consent Text Generator' - ]), - div({style: {...Styles.SMALL, marginTop: '1rem'}}, [ - 'This tool is made publicly available by the DUOS team for anyone' + - ' interested in leveraging standardized data sharing language in their' + - ' consent forms. The tool leverages the Global Alliance for Genomics ' + - 'and Health’s (GA4GH) companion standards of the ', - a({href: 'https://github.com/EBISPOT/DUO' , target:'_blank', rel:'noopener noreferrer' - }, ['Data Use Ontology (DUO)']), - ' and ', - a({href: 'https://drive.google.com/file/d/102_I0_phOGs9YSmPx7It9CSt1sHFJ87C/view', target: '_blank', rel: 'noreferrer noopener' - }, ['Machine Readable Consent Guidance (MRCG)']), - '. The DUO is a structured vocabulary describing permitted data uses and ' + - 'the MRCG is a suggested representation of those uses in consent form language. ' + - 'This tool enables users to easily define what types of data use they would ' + - 'like permitted in their consent forms and then suggests corresponding text ' + - 'for the consent form below, based on the MRCG.' - ]), - div({className: 'form-group', style: {marginTop: '1rem'}}, [ - label({style: Styles.MEDIUM}, [ - '1. Permitted data uses', br(), - span({style: Styles.MEDIUM_DESCRIPTION}, ['Determine what type of secondary use is permitted for you study\'s data.']), - ]), - div({}, [ - RadioButton({ - value: 'general', - defaultChecked: general, - onClick: () => { +
    +
    + Consent Text Generator +
    +
    + This tool is made publicly available by the DUOS team for anyone interested in leveraging standardized data sharing language in their consent forms. The tool leverages the Global Alliance for Genomics and Health's (GA4GH) companion standards of the + {' '} + + Data Use Ontology (DUO) + + {' '}and{' '} + + Machine Readable Consent Guidance (MRCG) + + . The DUO is a structured vocabulary describing permitted data uses and the MRCG is a suggested representation of those uses in consent form language. This tool enables users to easily define what types of data use they would like permitted in their consent forms and then suggests corresponding text for the consent form below, based on the MRCG. +
    +
    + +
    + { setGeneral(true), setHmb(false), setDiseases(false), setOther(false), setOntologies([]), clearOtherTextBox(); - }, - label: 'General Research Use (GRU): ', - description: 'use is permitted for any research purpose', - style: { fontFamily: 'Montserrat', color: '#1f3b50'} - }), - - RadioButton({ - value: 'hmb', - defaultChecked: hmb, - onClick: () => { + }} + label="General Research Use (GRU): " + description="use is permitted for any research purpose" + style={{ fontFamily: 'Montserrat', color: '#1f3b50' }} + /> + { setHmb(true), setGeneral(false), setDiseases(false), setOther(false), setOntologies([]), clearOtherTextBox(); - }, - label: 'Health/Medical/Biomedical Use (HMB): ', - description: 'use is permitted for any health, medical, or biomedical purpose', - style: { fontFamily: 'Montserrat', color: '#1f3b50'} - }), - - RadioButton({ - value: 'diseases', - defaultChecked: diseases, - onClick: () => { + }} + label="Health/Medical/Biomedical Use (HMB): " + description="use is permitted for any health, medical, or biomedical purpose" + style={{ fontFamily: 'Montserrat', color: '#1f3b50' }} + /> + { setDiseases(true), setHmb(false), setGeneral(false), setOther(false), clearOtherTextBox(); - }, - label: 'Disease-related studies (DS): ', - description: 'use is permitted for research on the specified disease', - style: { fontFamily: 'Montserrat', color: '#1f3b50'} - }), - - div({ - style: {buttonStyle, marginBottom: '10px', cursor: diseases ? 'pointer' : 'not-allowed'}, - }, [ - h(AsyncSelect, { - isDisabled: !diseases, - isMulti: true, - loadOptions: (query, callback) => searchOntologies(query, callback), - onChange: (option) => option ? setOntologies(option) : setOntologies, - value: ontologies, - placeholder: 'Please enter one or more diseases', - classNamePrefix: 'select', - }), - ]), - - RadioButton({ - value: 'other', - defaultChecked: other, - onClick: () => { - setOther(true), setHmb(false), setDiseases(false), setGeneral(false), setOntologies([]); - }, - label: 'Other Use: ', - description: 'permitted research use is defined as follows: ', - style: { fontFamily: 'Montserrat', color: '#1f3b50'} - }), - - textarea({ - className: 'form-control', - onBlur: (e) => setOtherText(e.target.value), - maxLength: '512', - rows: '2', - required: other, - disabled: !other, - id: 'other_text', - placeholder: 'Please specify if selected (max. 512 characters)', - }), - ]), - ]), - - div({className: 'form-group', style: {marginTop: '2rem'}}, [ - label({style: {...Styles.MEDIUM, marginBottom: '5px'}}, [ - '2. Additional constraints', br(), - span({style: Styles.MEDIUM_DESCRIPTION}, ['If necessary, choose any additional terms on your study\'s data to govern its use.']), - ]), - - div({}, [ - div({className: 'checkbox'}, [ - input({ - checked: nmds, - onChange: (e) => setNmds(e.target.checked), - id: 'checkNMDS', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkNMDS', - }, ['No methods development or validation studies (NMDS)']), - ]), - - div({className: 'checkbox'}, [ - input({ - checked: gso, - onChange: (e) => setGso(e.target.checked), - id: 'checkGSO', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkGSO', - }, ['Genetic Studies Only (GSO)']), - ]), - - div({className: 'checkbox'}, [ - input({ - checked: pub, - onChange: (e) => setPub(e.target.checked), - id: 'checkPUB', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkPUB', - }, ['Publication Required (PUB)']), - ]), - - div({className: 'checkbox'}, [ - input({ - checked: col, - onChange: (e) => setCol(e.target.checked), - id: 'checkCOL', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkCOL', - }, ['Collaboration Required (COL)']), - ]), - - div({className: 'checkbox'}, [ - input({ - checked: irb, - onChange: (e) => setIrb(e.target.checked), - id: 'checkIRB', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkIRB', - }, ['Ethics Approval Required (IRB)']), - ]), - - div({className: 'checkbox'}, [ - input({ - checked: gs, - onChange: (e) => setGs(e.target.checked), - id: 'checkGS', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkGS', - }, ['Geographic Restriction (GS-)']), - ]), - - div({className: 'checkbox'}, [ - input({ - checked: npu, - onChange: (e) => setNpu(e.target.checked), - id: 'checkNPU', - type: 'checkbox', - }), - label({ - style: labelStyle, - className: 'regular-checkbox', - htmlFor: 'checkNPU', - }, ['Non-Profit Use Only (NPU)']), - ]) - ]) - ]), - - button({ - style: {...Styles.TABLE.TABLE_TEXT_BUTTON, marginBottom: '2rem'}, - className: 'button', - onClick: () => generate(), - }, ['Generate']), - - textarea({ - defaultValue: sdsl, - className: 'form-control', - rows: '12', - required: false, - readOnly: true, - style: {backgroundColor: '#fff'} - }), - - div({style: {marginBottom: '2rem'}}) - - ]) + }} + label="Disease-related studies (DS): " + description="use is permitted for research on the specified disease" + style={{ fontFamily: 'Montserrat', color: '#1f3b50' }} + /> +
    +
    + searchOntologies(query, callback)} + onChange={(option) => (option ? setOntologies(option) : setOntologies)} + value={ontologies} + placeholder="Please enter one or more diseases" + classNamePrefix="select" + /> +
    + { + setOther(true), setHmb(false), setDiseases(false), setGeneral(false), setOntologies([]); + }} + label="Other Use: " + description="permitted research use is defined as follows: " + style={{ fontFamily: 'Montserrat', color: '#1f3b50' }} + /> +