From 776cdc1752b0948c13e16d6e1a3ae81b6d88c4ce Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 13:56:54 -0500 Subject: [PATCH 01/15] refactor: switch SearchBox to JSX --- src/components/SearchBox.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/components/SearchBox.js b/src/components/SearchBox.js index eb2bd8295..d372ec14f 100644 --- a/src/components/SearchBox.js +++ b/src/components/SearchBox.js @@ -1,6 +1,5 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { input } from 'react-hyperscript-helpers'; import ReactTooltip from 'react-tooltip'; import './SearchBox.css'; @@ -28,12 +27,12 @@ export class SearchBox extends Component { render() { return ( - input({ - type: 'text', - placeholder: 'Enter search terms', - onChange: this.changeHandler, - ref: this.myRef, - style: { + ); } } From e73536765498c96c370bae940306337fca14ad79 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Thu, 29 Feb 2024 17:18:18 -0500 Subject: [PATCH 02/15] refactor: switch Status to JSX --- src/Routes.js | 5 ++--- src/pages/Status.js | 33 ++++++++++++++++++--------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/Routes.js b/src/Routes.js index 5cc2baa60..71f8319ba 100644 --- a/src/Routes.js +++ b/src/Routes.js @@ -1,4 +1,3 @@ -import {mergeAll} from 'lodash/fp'; import React from 'react'; import {Route, Switch} from 'react-router-dom'; import AuthenticatedRoute from './components/AuthenticatedRoute'; @@ -21,7 +20,7 @@ import SigningOfficialDarRequests from './pages/signing_official_console/Signing import SigningOfficialDataSubmitters from './pages/signing_official_console/SigningOfficialDataSubmitters'; import Translator from './pages/Translator'; import NIHPilotInfo from './pages/NIHPilotInfo'; -import {Status} from './pages/Status'; +import Status from './pages/Status'; import BackgroundSignIn from './pages/BackgroundSignIn'; import ConsentTextGenerator from './pages/ConsentTextGenerator'; import AdminManageInstitutions from './pages/AdminManageInstitutions'; @@ -49,7 +48,7 @@ const Routes = (props) => ( } /> } /> - Status(mergeAll([routeProps, props]))} /> + } /> diff --git a/src/pages/Status.js b/src/pages/Status.js index b8ffa53a7..7b1c9c1d9 100644 --- a/src/pages/Status.js +++ b/src/pages/Status.js @@ -1,12 +1,12 @@ +import React from 'react'; import { getOr, isNil, map, uniq } from 'lodash/fp'; -import React, { Component } from 'react'; -import { a, div, h2, hh, hr, li, pre, ul } from 'react-hyperscript-helpers'; +import { Component } from 'react'; import CheckboxMarkedCircleOutline from 'react-material-icon-svg/dist/CheckboxMarkedCircleOutline'; import DiameterVariant from 'react-material-icon-svg/dist/DiameterVariant'; import { getApiUrl, getOntologyUrl } from '../libs/ajax'; -export const Status = hh(class Status extends Component { +class Status extends Component { constructor(props) { super(props); @@ -50,17 +50,20 @@ export const Status = hh(class Status extends Component { const ontologyHealthy = this.isOntologyHealthy(this.state.ontologyStatus) ? healthyState : unhealthyState; return ( - div({ style: { margin: '2rem' } }, [ - ul({ style: { marginTop: '2rem', listStyle: 'none', fontSize: 'x-large' } }, [ - li({}, [a({ href: '#consent' }, 'Consent'), ' ', consentHealthy]), - li({}, [a({ href: '#ontology' }, 'Ontology'), ' ', ontologyHealthy]) - ]), - hr(), - h2({}, [a({ id: 'consent' }, ['Consent Status'])]), - pre({}, [JSON.stringify(this.state.consentStatus, null, 4)]), - h2({}, [a({ id: 'ontology' }, ['Ontology Status'])]), - pre({}, [JSON.stringify(this.state.ontologyStatus, null, 4)]) - ])); +
+ +
+

Consent Status

+
{JSON.stringify(this.state.consentStatus, null, 4)}
+

Ontology Status

+
{JSON.stringify(this.state.ontologyStatus, null, 4)}
+
+ ); } -}); +}; + +export default Status; From 62ee0375b5449af8a3398823bf4d5ba8c4028167 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 09:19:05 -0500 Subject: [PATCH 03/15] refactor: switch ManageUsersTableCellData to JSX --- .../ManageUsersTableCellData.js | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/components/manage_users_table/ManageUsersTableCellData.js b/src/components/manage_users_table/ManageUsersTableCellData.js index a02da112a..3c85cc16f 100644 --- a/src/components/manage_users_table/ManageUsersTableCellData.js +++ b/src/components/manage_users_table/ManageUsersTableCellData.js @@ -1,5 +1,5 @@ +import React from 'react'; import {isNil, isEmpty, map, sortedUniq} from 'lodash'; -import {h, div} from 'react-hyperscript-helpers'; import {styles} from './ManageUsersTable'; import {Link} from 'react-router-dom'; import ReactTooltip from 'react-tooltip'; @@ -8,25 +8,27 @@ import voca from 'voca'; export function usernameCellData({displayName, userId, label= 'user-name'}) { return { // clicking on username lets you edit user - data: div({}, [ - h(Link, { - to: `/admin_edit_user/${userId}`, - 'data-for': `tip_${userId}_edit`, - 'data-tip': `Edit ${displayName}` - }, [ - displayName - ]), - h(ReactTooltip, { - id: `tip_${userId}_edit`, - place: 'right', - effect: 'solid', - multiline: true, - className: 'tooltip-wrapper' - }) - ]), + data: ( +
+ + {displayName} + + +
+ ), value: displayName, id: userId, - style : { + style: { color: '#354052', fontSize: styles.fontSize.username, paddingRight: '2%' From 3d6a86b67c84c77f9bc8207e367722d648968a44 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 10:06:09 -0500 Subject: [PATCH 04/15] refactor: switch ManageDacTableCellData to JSX --- .../ManageDacTableCellData.js | 70 ++++++++++--------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/src/components/manage_dac_table/ManageDacTableCellData.js b/src/components/manage_dac_table/ManageDacTableCellData.js index 7413860ff..1f1515fff 100644 --- a/src/components/manage_dac_table/ManageDacTableCellData.js +++ b/src/components/manage_dac_table/ManageDacTableCellData.js @@ -1,6 +1,6 @@ +import React from 'react'; import {isNil, isEmpty} from 'lodash/fp'; import {styles} from './ManageDacTable'; -import {a, label, h, div} from 'react-hyperscript-helpers'; import TableIconButton from '../../components/TableIconButton'; import {Styles} from '../../libs/theme'; import {Delete, Edit} from '@mui/icons-material'; @@ -33,14 +33,17 @@ export function descriptionCellData({description = '- -', dacId, label= 'dac-des } -export function datasetsCellData({dac, viewDatasets}) { +export function datasetsCellData({dac, viewDatasets, label='dac-datasets'}) { return { - data: a({ - id: dac.dacId + '_dacDatasets', - name: 'dacDatasets', - className: '', - onClick: () => viewDatasets(dac) - }, [`View Datasets`]), + data: ( + viewDatasets(dac)} + > + View Datasets + + ), id: dac.dacId, style : { color: '#354052', @@ -55,26 +58,27 @@ export function actionsCellData({dac, editDac, deleteDac, userRole}) { const isAdmin = (userRole === 'Admin'); const deleteDisabled = (!isNil(dac.datasets) && !isEmpty(dac.datasets)); - const actions = [ - h(TableIconButton, { - key: 'edit-dac-icon', - dataTip: 'Edit DAC', - onClick: () => editDac(dac), - icon: Edit, - style: Object.assign({}, Styles.TABLE.TABLE_ICON_BUTTON), - hoverStyle: Object.assign({}, Styles.TABLE.TABLE_BUTTON_ICON_HOVER) - }), - h(TableIconButton, { - key: 'delete-dac-icon', - dataTip: (deleteDisabled?'All datasets assigned to this DAC must be reassigned before this can be deleted' :'Delete DAC'), - disabled: deleteDisabled, - isRendered: isAdmin, - onClick: () => deleteDac(dac), - icon: Delete, - style: Object.assign({}, Styles.TABLE.TABLE_ICON_BUTTON), - hoverStyle: Object.assign({}, Styles.TABLE.TABLE_BUTTON_ICON_HOVER) - }) - ]; + const actions = ( + <> + editDac(dac)} + icon={Edit} + style={Object.assign({}, Styles.TABLE.TABLE_ICON_BUTTON)} + hoverStyle={Object.assign({}, Styles.TABLE.TABLE_BUTTON_ICON_HOVER)} + /> + {isAdmin && deleteDac(dac)} + icon={Delete} + style={Object.assign({}, Styles.TABLE.TABLE_ICON_BUTTON)} + hoverStyle={Object.assign({}, Styles.TABLE.TABLE_BUTTON_ICON_HOVER)} + />} + + ); return { isComponent: true, @@ -84,11 +88,11 @@ export function actionsCellData({dac, editDac, deleteDac, userRole}) { fontSize: styles.fontSize.actions }, label: 'table-actions', - data: div({ - style: { - display: 'flex', - } - }, actions) + data: ( +
+ {actions} +
+ ) }; } From 7b92528d7588fe2b9721f0c5d7d80a04809d8ceb Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 10:50:14 -0500 Subject: [PATCH 05/15] refactor: switch SimpleTable to JSX --- src/components/SimpleTable.js | 175 ++++++++++++++++++++-------------- 1 file changed, 103 insertions(+), 72 deletions(-) diff --git a/src/components/SimpleTable.js b/src/components/SimpleTable.js index 1416dc5b5..20054f206 100644 --- a/src/components/SimpleTable.js +++ b/src/components/SimpleTable.js @@ -1,5 +1,5 @@ +import React from 'react'; import { isNil } from 'lodash/fp'; -import { div, h } from 'react-hyperscript-helpers'; import { Styles } from '../libs/theme'; import ReactTooltip from 'react-tooltip'; import { ArrowDropUp, ArrowDropDown } from '@mui/icons-material'; @@ -8,58 +8,74 @@ import loadingImage from '../images/loading-indicator.svg'; // Renders spinning circle while table loading const TableLoading = () => { - return div({className: 'table-loading-placeholder'}, - [ - h(SpinnerComponent, { - show: true, - name: 'loadingSpinner', - loadingImage - }, []) - ] + return ( +
+ +
); }; //Simple cell text display -const SimpleTextCell = ({ text, style, keyProp }) => { +const SimpleTextCell = ({ text, style }) => { text = isNil(text) ? '- -' : text; - return div({ style, role: 'cell', key: keyProp }, [text]); + return ( +
+ {text} +
+ ); }; //Simple cell text that carries onClick functionality -const OnClickTextCell = ({ text, style, onClick, keyProp }) => { +const OnClickTextCell = ({ text, style, onClick }) => { text = isNil(text) ? '- -' : text; - return div({ style, onClick, role: 'cell', key: keyProp }, [text]); + return ( +
+ {text} +
+ ); }; //Column component that renders the column row based on column headers const ColumnRow = ({columnHeaders, baseStyle, columnStyle, sort, onSort}) => { const rowStyle = Object.assign({}, baseStyle, columnStyle); - return div({style: rowStyle, key: 'column-row-container', role:'row'}, columnHeaders.map((header, colIndex) => { - const {cellStyle, label} = header; - //style here pertains to styling for individual cells - //should be used to set dimensions of specific columns - return div({style: cellStyle, key: `column-row-${label}`, className: 'column-header'}, [ - header.sortable && onSort - ? div({ - style: Styles.TABLE.HEADER_SORT, - key: 'data_id_cell', - className: 'cell-sort', - onClick: () => { - onSort({ - colIndex: colIndex, - dir: sort.colIndex === colIndex ? sort.dir * -1 : 1 - }); - } - }, [ - label, - div({className: 'sort-container'}, [ - h(ArrowDropUp, { className: `sort-icon sort-icon-up ${sort.colIndex === colIndex && sort.dir === -1 ? 'active' : ''}` }), - h(ArrowDropDown, { className: `sort-icon sort-icon-down ${sort.colIndex === colIndex && sort.dir === 1 ? 'active': ''}` }) - ]) - ]) - : label - ]); - })); + return ( +
+ {columnHeaders.map((header, colIndex) => { + const { cellStyle, label } = header; + //style here pertains to styling for individual cells + //should be used to set dimensions of specific columns + return ( +
+ {header.sortable && onSort ? ( +
{ + onSort({ + colIndex: colIndex, + dir: sort.colIndex === colIndex ? sort.dir * -1 : 1 + }); + }} + > + {label} +
+ + +
+
+ ) : ( + label + )} +
+ ); + })} +
+ ); }; //Row component that renders out rows for each element in the provided data collection @@ -67,26 +83,37 @@ const DataRows = ({rowData, baseStyle, columnHeaders, rowWrapper = ({renderedRow return rowData.map((row, index) => { const id = rowData[index][0].id; const mapKey = id || `noId-index-${index}`; - const renderedRow = div({style: Object.assign({borderTop: '1px solid #f3f6f7'}, baseStyle), key: `row-data-${mapKey}`, role: 'row', className: `row-data-${index}`}, - row.map(({data, style, onClick, isComponent, id, label}, cellIndex) => { - let output; - //columnHeaders determine width of the columns, - //therefore extract width from columnHeader and apply to cell style - const columnWidthStyle = columnHeaders[cellIndex].cellStyle; - const appliedStyle = Object.assign({}, style, columnWidthStyle); - //assume component is in hyperscript format - //wrap component in dive with columnWidth applied - if (isComponent) { - output = div({role: 'cell', style: columnWidthStyle, key: `${!isNil(data) && !isNil(data.key) ? data.key : 'component-' + index + '-' + cellIndex}-container`}, [data]); - //if there is no onClick function, render as simple cell - } else if (isNil(onClick)) { - output = h(SimpleTextCell, { text: data, style: appliedStyle, keyProp: `filtered-list-${id}-${label}`, cellIndex }); - } else { - //otherwise render as on click cell - output = h(OnClickTextCell, { text: data, style: appliedStyle, onClick: () => onClick(index), keyProp: `filtered-list-${id}-${label}`, cellIndex }); - } - return output; - })); + const renderedRow = ( +
+ {row.map(({data, style, onClick, isComponent, id, label}, cellIndex) => { + let output; + //columnHeaders determine width of the columns, + //therefore extract width from columnHeader and apply to cell style + const columnWidthStyle = columnHeaders[cellIndex].cellStyle; + const appliedStyle = Object.assign({}, style, columnWidthStyle); + //assume component is in hyperscript format + //wrap component in dive with columnWidth applied + if (isComponent) { + output = ( +
+ {data} +
+ ); + //if there is no onClick function, render as simple cell + } else if (isNil(onClick)) { + output = ( + + ); + } else { + //otherwise render as on click cell + output = ( + onClick(index)} key={`filtered-list-${id}-${label}`} cellIndex={cellIndex} /> + ); + } + return output; + })} +
+ ); return rowWrapper({renderedRow, rowData: row}); }); @@ -112,17 +139,21 @@ export default function SimpleTable(props) { } = props; const {baseStyle, columnStyle, containerOverride} = styles; - const columnRow = h(ColumnRow, {key: 'column-row-container', columnHeaders, baseStyle, columnStyle, sort, onSort}); - const tableTemplate = [columnRow, h(DataRows, {rowData, baseStyle, columnHeaders, rowWrapper, key: 'table-data-rows'})]; - const output = isLoading ? h(TableLoading, {}) : tableTemplate; - return div([ - div({className: 'table-data', style: containerOverride || Styles.TABLE.CONTAINER, role: 'table'}, - [output, isNil(paginationBar) ? div() : paginationBar]), - h(ReactTooltip, { - place: 'left', - effect: 'solid', - multiline: true, - className: 'tooltip-wrapper' - }) - ]); + const columnRow = ; + const tableTemplate = [ columnRow, ]; + const output = isLoading ? : tableTemplate; + return ( +
+
+ {output} + {isNil(paginationBar) ?
: paginationBar} +
+ +
+ ); } From 934bde71bb9d2e2ebb40fa71cd0296b37de7f0ce Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 11:06:16 -0500 Subject: [PATCH 06/15] refactor: switch InstitutionTable to JSX --- src/components/TableSkeletonLoader.js | 2 +- .../institution_table/InstitutionTable.js | 138 +++++++++--------- 2 files changed, 66 insertions(+), 74 deletions(-) diff --git a/src/components/TableSkeletonLoader.js b/src/components/TableSkeletonLoader.js index 984196c38..24d0f1ec9 100644 --- a/src/components/TableSkeletonLoader.js +++ b/src/components/TableSkeletonLoader.js @@ -30,7 +30,7 @@ export default function TableSkeletonLoader(props) { template.push(rowTemplate); start++; } - template.push(
); + template.push(
); return template; }; diff --git a/src/components/institution_table/InstitutionTable.js b/src/components/institution_table/InstitutionTable.js index 2411b4275..8c287e4c1 100644 --- a/src/components/institution_table/InstitutionTable.js +++ b/src/components/institution_table/InstitutionTable.js @@ -1,32 +1,36 @@ -import { isEmpty, isNil, assign } from 'lodash/fp'; +import React from 'react'; +import { isEmpty, isNil } from 'lodash/fp'; import { useState, useEffect } from 'react'; -import { div, h, a , span } from 'react-hyperscript-helpers'; import { Styles } from '../../libs/theme'; import ReactTooltip from 'react-tooltip'; import PaginationBar from '../PaginationBar'; import AddInstitutionModal from '../modals/AddInstitutionModal'; -export const tableHeaderTemplate = [ - div({style: Styles.TABLE.ID_CELL}, ['ID']), - div({style: Styles.TABLE.INSTITUTION_CELL}, ['Institution']), - div({style: Styles.TABLE.INSTITUTION_CELL}, ['Signing Officials']), - div({style: Styles.TABLE.DATA_ID_CELL}, ['Create User']), - div({style: Styles.TABLE.SUBMISSION_DATE_CELL}, ['Create Date']), - div({style: Styles.TABLE.DATA_ID_CELL}, ['Update User']), - div({style: Styles.TABLE.SUBMISSION_DATE_CELL}, ['Update Date']), -]; +export const tableHeaderTemplate = ( + <> +
ID
+
Institution
+
Signing Officials
+
Create User
+
Create Date
+
Update User
+
Update Date
+ +); const loadingMarginOverwrite = {margin: '1rem 2%'}; -export const tableRowLoadingTemplate = [ - div({style: assign(Styles.TABLE.ID_CELL, loadingMarginOverwrite), className: 'text-placeholder'}), - div({style: assign(Styles.TABLE.INSTITUTION_CELL, loadingMarginOverwrite), className: 'text-placeholder'}), - div({style: assign(Styles.TABLE.INSTITUTION_CELL, loadingMarginOverwrite), className: 'text-placeholder'}), - div({style: assign(Styles.TABLE.DATA_ID_CELL, loadingMarginOverwrite), className: 'text-placeholder'}), - div({style: assign(Styles.TABLE.SUBMISSION_DATE_CELL, loadingMarginOverwrite), className: 'text-placeholder'}), - div({style: assign(Styles.TABLE.DATA_ID_CELL, loadingMarginOverwrite), className: 'text-placeholder'}), - div({style: assign(Styles.TABLE.SUBMISSION_DATE_CELL, loadingMarginOverwrite), className: 'text-placeholder'}) -]; +export const tableRowLoadingTemplate = ( + <> +
+
+
+
+
+
+
+ +); const calcPageCount = (tableSize, filteredList) => { if(isEmpty(filteredList)) { @@ -70,64 +74,52 @@ export default function InstitutionTable(props) { }; return ( - div({className: 'institution-table-component'}, [ - div({style: Styles.TABLE.CONTAINER}, [ - div({style: Styles.TABLE.HEADER_ROW}, tableHeaderTemplate), - filteredList.slice((currentPage - 1) * tableSize, (currentPage * tableSize)).map((inst, index) => { +
+
+
+ {tableHeaderTemplate} +
+ {filteredList.slice((currentPage - 1) * tableSize, (currentPage * tableSize)).map((inst, index) => { let signingOfficialsList = []; if (!isNil(inst.signingOfficials)) { inst.signingOfficials.forEach((user) => { - signingOfficialsList.push(span({style: {display: 'block'}}, `${user.displayName} (${user.email})`)); + signingOfficialsList.push( + + {user.displayName} ({user.email}) + + ); }); } const borderStyle = index > 0 ? {borderTop: '1px solid rgba(109,110,112,0.2)'} : {}; - return div({style: Object.assign({}, borderStyle, Styles.TABLE.RECORD_ROW), key: `${inst.id}-${index}`}, [ - div({ - style: Object.assign({}, Styles.TABLE.ID_CELL), - }, [inst.id]), - div({ - style: Object.assign({}, Styles.TABLE.INSTITUTION_CELL) - }, [ - a({ style: { - overflow: 'hidden', - whiteSpace: 'nowrap', - textOverflow: 'ellipsis'}, - onClick: () => { openUpdateModal(inst.id); } - }, [inst.name]) - ]), - div({ - style: Object.assign({}, {...Styles.TABLE.INSTITUTION_CELL, display: 'block'}) - }, signingOfficialsList), - div({ - style: Object.assign({}, Styles.TABLE.DATA_ID_CELL) - }, [inst.createUser ? inst.createUser.displayName : '']), - div({ - style: Object.assign({}, Styles.TABLE.SUBMISSION_DATE_CELL) - }, [inst.createDate]), - div({ - style: Object.assign({}, Styles.TABLE.DATA_ID_CELL) - }, [inst.updateUser ? inst.updateUser.displayName : '']), - div({ - style: Object.assign({}, Styles.TABLE.SUBMISSION_DATE_CELL) - }, [inst.updateDate]), - ]); - }), - h(PaginationBar, {pageCount, currentPage, tableSize, goToPage, changeTableSize}) - ]), - h(AddInstitutionModal, { - isRendered: showUpdateInstitutionModal, - showModal: showUpdateInstitutionModal, - institutionId: institutionId, - closeModal: closeUpdateModal, - onOKRequest: onUpdateSave, - onCloseRequest: closeUpdateModal - }), - h(ReactTooltip, { - place: 'left', - effect: 'solid', - multiline: true, - className: 'tooltip-wrapper' - }) - ]) + return ( +
+
{inst.id}
+ +
{signingOfficialsList}
+
{inst.createUser ? inst.createUser.displayName : ''}
+
{inst.createDate}
+
{inst.updateUser ? inst.updateUser.displayName : ''}
+
{inst.updateDate}
+
+ ); + })} + +
+ {showUpdateInstitutionModal && } + +
); } From 11d362acd0a5d15cfa5b0957a6c63f0c6961c237 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 11:40:03 -0500 Subject: [PATCH 07/15] refactor: switch AddInstitutionModal to JSX --- src/components/modals/AddInstitutionModal.js | 91 +++++++++++--------- 1 file changed, 52 insertions(+), 39 deletions(-) diff --git a/src/components/modals/AddInstitutionModal.js b/src/components/modals/AddInstitutionModal.js index 1aff31035..28d215d78 100644 --- a/src/components/modals/AddInstitutionModal.js +++ b/src/components/modals/AddInstitutionModal.js @@ -1,5 +1,5 @@ +import React from 'react'; import { useState, useRef, useEffect } from 'react'; -import {div, form, label, input } from 'react-hyperscript-helpers'; import { Alert } from '../Alert'; import { Institution } from '../../libs/ajax'; import { BaseModal } from '../BaseModal'; @@ -105,44 +105,57 @@ const AddInstitutionModal = (props) => { onOKRequest(result); }; - return BaseModal({ - id: 'addInstitutionModal', - showModal: showModal, - disableOkBtn: !validForm, - onRequestClose: closeHandler, - imgSrc: mode === 'Add' ? addInstitutionIcon : editInstitutionIcon, - color: 'common', - title: mode === 'Add' ? 'Add Institution' : 'Edit Institution', - description: mode === 'Add' ? 'Add a new Institution in the system' : 'Edit an Institution in the system', - action: { label: mode === 'Add' ? 'Add' : 'Save', handler: OKHandler } - }, - [ - form({ isRendered: !isLoading, className: 'form-horizontal css-form', name: 'userForm', encType: 'multipart/form-data', onChange: formChange }, [ - div({ className: 'form-group first-form-group' }, [ - label({ id: 'lbl_institution_name', className: 'col-lg-3 col-md-3 col-sm-3 col-xs-4 control-label common-color' }, ['Institution Name']), - div({ className: 'col-lg-9 col-md-9 col-sm-9 col-xs-8' }, [ - input({ - type: 'text', - name: 'name', - id: 'txt_name', - className: 'form-control col-lg-12', - placeholder: 'Institution name', - required: true, - autoFocus: true, - value: institutionName, - onChange: changeHandler('name'), - ref: nameRef - }) - ]), - div({ isRendered: institutionNameValid === false && submitted === true }, [ - Alert({ - id: 'institutionNameInvalid', type: 'danger', title: 'Field required!', - description: 'Please provide a name for the institution.' - }) - ]) - ]), - ]) - ]); + return ( + + {!isLoading &&
+
+ +
+ +
+ {institutionNameValid === false && submitted === true && ( + + )} +
+
} +
+ ); }; export default AddInstitutionModal; From d23ae68a84b9a7917010796fd15386b13bef4d76 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 12:53:28 -0500 Subject: [PATCH 08/15] refactor: switch NIHAdministrativeInformation to JSX --- .../NIHAdministrativeInformation.js | 276 +++++++++--------- 1 file changed, 139 insertions(+), 137 deletions(-) diff --git a/src/pages/data_submission/NIHAdministrativeInformation.js b/src/pages/data_submission/NIHAdministrativeInformation.js index 2c290163b..9a81a32df 100644 --- a/src/pages/data_submission/NIHAdministrativeInformation.js +++ b/src/pages/data_submission/NIHAdministrativeInformation.js @@ -1,4 +1,4 @@ -import {div, h, h2} from 'react-hyperscript-helpers'; +import React from 'react'; import { FormFieldTypes, FormField, FormValidators } from '../../components/forms/forms'; import { nihInstitutions } from './nih_institutions'; import { isEmpty, isNil } from 'lodash/fp'; @@ -28,142 +28,144 @@ export const NIHAdministrativeInformation = (props) => { }; }; - return div({ - isRendered: - (studyEditMode ? - ['yes_nhgri_yes_phs_id', 'yes_nhgri_no_phs_id', 'no_nhgri_yes_anvil'].includes(formData.nihAnvilUse) - : [YES_NHGRI_YES_PHS_ID, YES_NHGRI_NO_PHS_ID, NO_NHGRI_YES_ANVIL].includes(formData.nihAnvilUse)), - className: 'data-submitter-section', - }, [ - h2('NIH Administrative Information'), - h(FormField, { - id: 'piInstitution', - title: 'Principal Investigator Institution', - isRendered: !isEmpty(institutions), - validators: studyEditMode ? undefined : [FormValidators.REQUIRED], - type: FormFieldTypes.SELECT, - selectOptions: institutions.map((inst) => { return { displayText: inst.name, id: inst.id };}), - isCreatable: false, - selectConfig: {}, - onChange: ({key, value, isValid}) => { - onChange({key, value: value?.id, isValid}); - }, - defaultValue:!isNil(formData.piInstitution) ? findInstitutionSelectOption(formData.piInstitution) : null, - validation: validation.piInstitution, - onValidationChange, - }), - h(FormField, { - id: 'nihGrantContractNumber', - title: 'NIH Grant or Contract Number', - validators: studyEditMode ? undefined : [FormValidators.REQUIRED], - onChange, - defaultValue: formData?.nihGrantContractNumber, - validation: validation.nihGrantContractNumber, - onValidationChange, - }), - h(FormField, { - id: 'nihICsSupportingStudy', - title: 'NIH ICs Supporting the Study', - placeholder: 'Institute/Center Name', - onChange, - type: FormFieldTypes.SELECT, - isMulti: true, - defaultValue: formData?.nihICsSupportingStudy, - selectOptions: nihInstitutions, - validation: validation.nihICsSupportingStudy, - onValidationChange, - }), - h(FormField, { - id: 'nihProgramOfficerName', - title: 'NIH Program Officer Name', - onChange, - placeholder: 'Officer Name', - defaultValue: formData?.nihProgramOfficerName, - validation: validation.nihProgramOfficerName, - onValidationChange, - }), - h(FormField, { - id: 'nihInstitutionCenterSubmission', - title: 'NIH Institute/Center for Submission', - placeholder: 'Institute/Center Name', - onChange, - type: FormFieldTypes.SELECT, - defaultValue: formData?.nihInstitutionCenterSubmission, - selectOptions: nihInstitutions, - validation: validation.nihInstitutionCenterSubmission, - onValidationChange, - }), - h(FormField, { - id: 'nihGenomicProgramAdministratorName', - title: 'NIH Genomic Program Administrator Name', - defaultValue: formData?.nihGenomicProgramAdministratorName, - onChange, - validation: validation.nihGenomicProgramAdministratorName, - onValidationChange, - }), - h(FormField, { - id: 'multiCenterStudy', - title: 'Is this a multi-center study?', - type: FormFieldTypes.YESNORADIOGROUP, - defaultValue: formData?.multiCenterStudy, - onChange: ({key, value}) => { - setShowMultiCenterStudy(value); - onChange({key, value}); - }, - validation: validation.multiCenterStudy, - onValidationChange, - }), - h(FormField, { - id: 'collaboratingSites', - isRendered: showMultiCenterStudy, - title: 'What are the collaborating sites?', - type: FormFieldTypes.SELECT, - selectOptions: [], - isCreatable: true, - isMulti: true, - optionsAreString: true, - selectConfig: { - components: { - DropdownIndicator: null, - Menu: () => null, - }, - }, - placeholder: 'List site and hit enter here...', - defaultValue: formData?.collaboratingSites, - onChange, - validation: validation.collaboratingSites, - onValidationChange, - }), - h(FormField, { - id: 'controlledAccessRequiredForGenomicSummaryResultsGSR', - title: 'Is controlled access required for genomic summary results (GSR)?', - defaultValue: formData?.controlledAccessRequiredForGenomicSummaryResultsGSR, - type: FormFieldTypes.YESNORADIOGROUP, - onChange: ({key, value}) => { - setShowGSRRequiredExplanation(value); - onChange({key, value}); - onChange({ - key: 'controlledAccessRequiredForGenomicSummaryResultsGSRRequiredExplanation', - value: (value ? gsrRequiredExplanation : undefined), - }); - }, - validation: validation.controlledAccessRequiredForGenomicSummaryResultsGSR, - onValidationChange, - }), - h(FormField, { - id: 'controlledAccessRequiredForGenomicSummaryResultsGSRRequiredExplanation', - title: 'If yes, explain why controlled access is needed for GSR.', - isRendered: showGSRRequiredExplanation, - defaultValue: gsrRequiredExplanation, - validators: studyEditMode ? undefined : [FormValidators.REQUIRED], - onChange: ({key, value}) => { - setGSRRequiredExplanation(value); - onChange({key, value}); - }, - validation: validation.controlledAccessRequiredForGenomicSummaryResultsGSRNotRequiredExplanation, - onValidationChange, - }), - ]); + const isRendered = studyEditMode ? + ['yes_nhgri_yes_phs_id', 'yes_nhgri_no_phs_id', 'no_nhgri_yes_anvil'].includes(formData.nihAnvilUse) + : [YES_NHGRI_YES_PHS_ID, YES_NHGRI_NO_PHS_ID, NO_NHGRI_YES_ANVIL].includes(formData.nihAnvilUse); + + return ( + <> + {isRendered &&
+

NIH Administrative Information

+ ({displayText: inst.name, id: inst.id }))} + isCreatable={false} + selectConfig={{}} + onChange={({ key, value, isValid }) => { + onChange({ key, value: value?.id, isValid }); + }} + defaultValue={!isNil(formData.piInstitution) ? findInstitutionSelectOption(formData.piInstitution) : null} + validation={validation.piInstitution} + onValidationChange={onValidationChange} + /> + + + + + + { + setShowMultiCenterStudy(value); + onChange({ key, value }); + }} + validation={validation.multiCenterStudy} + onValidationChange={onValidationChange} + /> + null, + }, + }} + placeholder="List site and hit enter here..." + defaultValue={formData?.collaboratingSites} + onChange={onChange} + validation={validation.collaboratingSites} + onValidationChange={onValidationChange} + /> + { + setShowGSRRequiredExplanation(value); + onChange({ key, value }); + onChange({ + key: 'controlledAccessRequiredForGenomicSummaryResultsGSRRequiredExplanation', + value: value ? gsrRequiredExplanation : undefined, + }); + }} + validation={validation.controlledAccessRequiredForGenomicSummaryResultsGSR} + onValidationChange={onValidationChange} + /> + { + setGSRRequiredExplanation(value); + onChange({ key, value }); + }} + validation={validation.controlledAccessRequiredForGenomicSummaryResultsGSRNotRequiredExplanation} + onValidationChange={onValidationChange} + /> +
} + + ); }; export default NIHAdministrativeInformation; \ No newline at end of file From af10529aed6b4b77f1e03239ae166fcf60d0cc3a Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 13:15:59 -0500 Subject: [PATCH 09/15] refactor: switch AdminManageInstitutions to JSX --- src/pages/AdminManageInstitutions.js | 106 +++++++++++++-------------- 1 file changed, 50 insertions(+), 56 deletions(-) diff --git a/src/pages/AdminManageInstitutions.js b/src/pages/AdminManageInstitutions.js index 5e0d9045c..9d73aa715 100644 --- a/src/pages/AdminManageInstitutions.js +++ b/src/pages/AdminManageInstitutions.js @@ -1,5 +1,5 @@ +import React from 'react'; import { useState, useEffect } from 'react'; -import { div, h, img, a, span } from 'react-hyperscript-helpers'; import { Institution } from '../libs/ajax'; import { Styles} from '../libs/theme'; import { Notifications } from '../libs/utils'; @@ -83,60 +83,54 @@ export default function AdminManageInstitutions(props) { }; return ( - div({style: Styles.PAGE}, [ - div({ style: {display: 'flex', justifyContent: 'space-between'}}, [ - div({className: 'left-header-section', style: Styles.LEFT_HEADER_SECTION}, [ - div({style: Styles.ICON_CONTAINER}, [ - img({ - id: 'lock-icon', - src: manageInstitutionsIcon, - style: Styles.HEADER_IMG - }) - ]), - div({style: Styles.HEADER_CONTAINER}, [ - div({style: Styles.TITLE}, ['Manage Institutions']), - div({style: Styles.SMALL}, ['Select and manage Institutions']) - ]), - ]), - h(SearchBar, {handleSearchChange, currentPage, - style: { - width: '60%', - margin: '0 3% 0 0', - }, - button: div([ - a({ - id: 'btn_addInstitution', - className: 'btn-primary btn-add common-background', - style: { - marginTop: '30%', - display: 'block', - lineHeight: 0.6, - }, - onClick: addInstitution - }, [ - span({}, ['Add Institution']), - ]), - ]), - }) - ]), - h(InstitutionTable, { - filteredList, - history: props.history, - currentPage, - setCurrentPage, - tableSize, - setTableSize, - isRendered: !isLoading, - onUpdateSave: modalSave - }), - h(DarTableSkeletonLoader, {isRendered: isLoading, tableHeaderTemplate, tableRowLoadingTemplate}), - h(AddInstitutionModal, { - isRendered: showAddInstitutionModal, - showModal: showAddInstitutionModal, - closeModal: closeAddInstitutionModal, - onOKRequest: modalSave, - onCloseRequest: closeAddInstitutionModal - }), - ]) +
+
+
+
+ +
+
+
Manage Institutions
+
Select and manage Institutions
+
+
+ + + Add Institution + +
+ } + /> +
+ {!isLoading && } + {isLoading && } + {showAddInstitutionModal && } +
); } From 34f9e9a1e17dda72a3d485f2df12797e0a8a10da Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 13:44:00 -0500 Subject: [PATCH 10/15] style: address eslint nits --- src/components/SimpleTable.js | 2 +- src/components/dac_dataset_table/DACDatasetApprovalStatus.js | 2 +- src/components/dac_dataset_table/DACDatasetTableCellData.js | 2 +- src/pages/dar_application/ResearcherInfo.js | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/SimpleTable.js b/src/components/SimpleTable.js index 20054f206..5b15d2ca6 100644 --- a/src/components/SimpleTable.js +++ b/src/components/SimpleTable.js @@ -140,7 +140,7 @@ export default function SimpleTable(props) { const {baseStyle, columnStyle, containerOverride} = styles; const columnRow = ; - const tableTemplate = [ columnRow, ]; + const tableTemplate = [columnRow, ]; const output = isLoading ? : tableTemplate; return (
diff --git a/src/components/dac_dataset_table/DACDatasetApprovalStatus.js b/src/components/dac_dataset_table/DACDatasetApprovalStatus.js index cfed9efcd..b93d9ed8a 100644 --- a/src/components/dac_dataset_table/DACDatasetApprovalStatus.js +++ b/src/components/dac_dataset_table/DACDatasetApprovalStatus.js @@ -33,7 +33,7 @@ export default function DACDatasetApprovalStatus(props) { } catch { Notifications.showError({text: `Error deleting dataset '${name}'`}); } - } + }; const updateApprovalStatus = async (approvalState) => { const updatedDataset = await DAC.updateApprovalStatus(dataset.dacId, dataset.dataSetId, approvalState); diff --git a/src/components/dac_dataset_table/DACDatasetTableCellData.js b/src/components/dac_dataset_table/DACDatasetTableCellData.js index c50477013..0dbbadfd9 100644 --- a/src/components/dac_dataset_table/DACDatasetTableCellData.js +++ b/src/components/dac_dataset_table/DACDatasetTableCellData.js @@ -44,7 +44,7 @@ export function datasetNameCellData({dataset, label = 'datasetNameCellData'}) { export function dataCustodianCellData({dataset, label = 'dataCustodianCellData'}) { // Newer datasets have a list of data custodian emails. // Older datasets may or may not have a data depositor - const displayValue = firstNonEmptyPropertyValue(dataset, [ 'Data Custodian Email', 'Data Depositor', 'dataCustodianEmail' ]); + const displayValue = firstNonEmptyPropertyValue(dataset, ['Data Custodian Email', 'Data Depositor', 'dataCustodianEmail']); return { data:
{displayValue}
, value: displayValue, diff --git a/src/pages/dar_application/ResearcherInfo.js b/src/pages/dar_application/ResearcherInfo.js index 4fd859308..06e6f1893 100644 --- a/src/pages/dar_application/ResearcherInfo.js +++ b/src/pages/dar_application/ResearcherInfo.js @@ -61,7 +61,7 @@ export default function ResearcherInfo(props) { !readOnlyMode && Alert({ id: 'profileSubmitted', type: 'danger', - title: span({ className: 'errored' }, [ + title: span({ className: 'errored' }, [ `You must submit `, profileLink, ` and obtain a `, libraryCardLink, ` from your Signing official before you can submit a Data Access Request.` ]) From 6edd3de6f5b50fe214e5a964289779ebf716216f Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 14:41:26 -0500 Subject: [PATCH 11/15] refactor: switch ManageDac to JSX --- src/pages/manage_dac/ManageDac.js | 170 ++++++++++++++---------------- 1 file changed, 77 insertions(+), 93 deletions(-) diff --git a/src/pages/manage_dac/ManageDac.js b/src/pages/manage_dac/ManageDac.js index 8039e9131..d703150e4 100644 --- a/src/pages/manage_dac/ManageDac.js +++ b/src/pages/manage_dac/ManageDac.js @@ -1,6 +1,6 @@ +import React from 'react'; import ManageDacTable from '../../components/manage_dac_table/ManageDacTable'; import {useState, useEffect, useCallback} from 'react'; -import {div, h, img, a, span} from 'react-hyperscript-helpers'; import { Styles } from '../../libs/theme'; import lockIcon from '../../images/lock-icon.png'; import {DAC} from '../../libs/ajax'; @@ -116,98 +116,82 @@ export const ManageDac = function ManageDac() { setSelectedDatasets([]); }; - return div({ style: Styles.PAGE }, [ - div({ style: { display: 'flex', justifyContent: 'space-between', width: '112%', marginLeft: '-6%', padding: '0 2.5%' } }, [ - div( - { className: 'left-header-section', style: Styles.LEFT_HEADER_SECTION }, - [ - div({ style: Styles.ICON_CONTAINER }, [ - img({ - id: 'lock-icon', - src: lockIcon, - style: Styles.HEADER_IMG, - }), - ]), - div({ style: Styles.HEADER_CONTAINER }, [ - div({ style: { - fontFamily: 'Montserrat', - fontWeight: 600, - fontSize: '2.8rem' - } }, [ - `Manage Data Access Committee`, - ]), - div( - { - style: { - fontFamily: 'Montserrat', - fontSize: '1.6rem' - }, - }, - ['Create and manage Data Access Commitee'] - ), - ]), - ] - ), - div({className: 'right-header-section'}, [ - a({ - id: 'btn_addDAC', - className: 'col-md-12 btn-primary btn-add common-background', - style: { - marginTop: '30%', - display: 'flex' - }, - onClick: addDac - }, [ - span({}, ['Add DAC']) - ]) - ]) - - ]), - h(ManageDacTable, { - isLoading, - dacs, - userRole, - setShowDacModal, - setShowDatasetsModal, - setShowMembersModal, - setShowConfirmationModal, - setIsEditMode, - setSelectedDac, - setSelectedDatasets - }), - h(ConfirmationModal, { - showConfirmation: showConfirmationModal, - closeConfirmation: closeConfirmation, - title: 'Delete DAC?', - message: 'Are you sure you want to delete this Data Access Committee?', - header: selectedDac.name, - onConfirm: () => handleDeleteDac(), - }), - DacMembersModal({ - isRendered: showMembersModal, - showModal: showMembersModal, - onOKRequest: closeViewMembersModal, - onCloseRequest: closeViewMembersModal, - dac: selectedDac - }), - DacDatasetsModal({ - isRendered: showDatasetsModal, - showModal: showDatasetsModal, - onOKRequest: closeViewDatasetsModal, - onCloseRequest: closeViewDatasetsModal, - dac: selectedDac, - datasets: selectedDatasets - }), - AddDacModal({ - isRendered: showDacModal, - showModal: showDacModal, - isEditMode: isEditMode, - onOKRequest: okAddDacModal, - onCloseRequest: closeAddDacModal, - dac: selectedDac, - userRole: userRole - }), - ]); + return ( +
+
+
+
+ +
+
+
+ Manage Data Access Committee +
+
+ Create and manage Data Access Committee +
+
+
+ +
+ + + {showMembersModal && ( + + )} + {showDatasetsModal && ( + + )} + {showDacModal && ( + + )} +
+ ); }; export default ManageDac; \ No newline at end of file From dc6b68464718d7afd6ae34628d4f7a7835b5169f Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 15:23:28 -0500 Subject: [PATCH 12/15] refactor: switch DarCollectionTableCellData to JSX --- .../DarCollectionTableCellData.js | 52 ++++++++++--------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/src/components/dar_collection_table/DarCollectionTableCellData.js b/src/components/dar_collection_table/DarCollectionTableCellData.js index 598bb5c3a..98dae429e 100644 --- a/src/components/dar_collection_table/DarCollectionTableCellData.js +++ b/src/components/dar_collection_table/DarCollectionTableCellData.js @@ -1,6 +1,6 @@ +import React from 'react'; import {includes, isEmpty, isNil, toLower, uniq} from 'lodash/fp'; import {formatDate} from '../../libs/utils'; -import {h, div} from 'react-hyperscript-helpers'; import { ExpandMore, ExpandLess } from '@mui/icons-material'; import {styles} from './DarCollectionTable'; import Actions from './Actions'; @@ -34,7 +34,7 @@ export function darCodeCellData({darCode = '- -', darCollectionId, collectionIsE switch (consoleType) { case consoleTypes.ADMIN: - darCodeData = h(DarCollectionAdminReviewLink, { darCollectionId, darCode }); + darCodeData = ; break; case consoleTypes.CHAIR: case consoleTypes.MEMBER: @@ -45,23 +45,21 @@ export function darCodeCellData({darCode = '- -', darCollectionId, collectionIsE darCodeData = darCode; } + const ExpandComponent = collectionIsExpanded ? ExpandLess : ExpandMore; + return { - data: div({ - style: { - display: 'flex', - alignItems: 'center', - } - }, [ - h((collectionIsExpanded ? ExpandLess : ExpandMore), { - id: `${darCollectionId}_dropdown`, - className: `sort-icon dar-expand-dropdown-arrow ${collectionIsExpanded ? 'sort-icon-up' : 'sort-icon-down'}`, - isRendered: toLower(status) !== 'draft', - onClick: () => { - updateCollectionIsExpanded(!collectionIsExpanded); - }, - }), - darCodeData, - ]), + data: ( +
+ {toLower(status) !== 'draft' && { + updateCollectionIsExpanded(!collectionIsExpanded); + }} + />} + {darCodeData} +
+ ), value: darCode, id: darCollectionId, style: { @@ -80,7 +78,7 @@ const dacLinkToCollection = (darCode, status = '', darCollectionId) => { `/dar_collection/${darCollectionId}` : `/dar_vote_review/${darCollectionId}`; - return h(Link, { to: path }, [darCode]); + return {darCode}; }; export function DacCellData({dacNames, darCollectionId, label = 'dacNames'}) { @@ -165,12 +163,16 @@ export function statusCellData({status = '- -', darCollectionId, label = 'status export function consoleActionsCellData({collection, reviewCollection, goToVote, showConfirmationModal, consoleType, resumeCollection, actions, status}) { let actionComponent; - actionComponent = h(Actions, { - collection, consoleType, - showConfirmationModal, goToVote, - reviewCollection, resumeCollection, - actions, status - }); + actionComponent = ; return { isComponent: true, From 33b9d0bfaa5f3c5a880f123ea4072e2f521d7f03 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 15:24:00 -0500 Subject: [PATCH 13/15] fix: ensure unique key for each row --- src/components/SimpleTable.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/SimpleTable.js b/src/components/SimpleTable.js index 5b15d2ca6..4719263c9 100644 --- a/src/components/SimpleTable.js +++ b/src/components/SimpleTable.js @@ -102,12 +102,12 @@ const DataRows = ({rowData, baseStyle, columnHeaders, rowWrapper = ({renderedRow //if there is no onClick function, render as simple cell } else if (isNil(onClick)) { output = ( - + ); } else { //otherwise render as on click cell output = ( - onClick(index)} key={`filtered-list-${id}-${label}`} cellIndex={cellIndex} /> + onClick(index)} key={`filtered-list-click-${id}-${label}-${cellIndex}`} /> ); } return output; From 166fa175973b973e1528e71a9c318115ae10269c Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 15:40:40 -0500 Subject: [PATCH 14/15] refactor: switch DatasetsRequestedPanel to JSX --- .../datasets_requested.spec.js | 164 +++++++++--------- .../DatasetsRequestedPanel.js | 67 ++++--- 2 files changed, 122 insertions(+), 109 deletions(-) diff --git a/cypress/component/MultiDatasetVoteTab/datasets_requested.spec.js b/cypress/component/MultiDatasetVoteTab/datasets_requested.spec.js index a1f07e6e4..b8608c13f 100644 --- a/cypress/component/MultiDatasetVoteTab/datasets_requested.spec.js +++ b/cypress/component/MultiDatasetVoteTab/datasets_requested.spec.js @@ -29,8 +29,8 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1, 2, 3, 4, 5, 6, 7]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 0); - cy.get('[datacy=dataset-count]').should('contain.text', '(0)'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 0); + cy.get('[data-cy=dataset-count]').should('contain.text', '(0)'); }); it('Renders no dataset information if bucketDatasets is null', function () { @@ -39,8 +39,8 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1, 2, 3, 4, 5, 6, 7]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 0); - cy.get('[datacy=dataset-count]').should('contain.text', '(0)'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 0); + cy.get('[data-cy=dataset-count]').should('contain.text', '(0)'); }); it('Renders no dataset information if dacDatasetIds is empty', function () { @@ -50,8 +50,8 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 0); - cy.get('[datacy=dataset-count]').should('contain.text', '(0)'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 0); + cy.get('[data-cy=dataset-count]').should('contain.text', '(0)'); }); it('Renders no dataset information if dacDatasetIds is null', function () { @@ -60,8 +60,8 @@ describe('DatasetsRequestedPanel - Tests', function () { bucketDatasets={bucketDatasets} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 0); - cy.get('[datacy=dataset-count]').should('contain.text', '(0)'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 0); + cy.get('[data-cy=dataset-count]').should('contain.text', '(0)'); }); it('Renders no dataset information if there are no matches between bucket datasets and DAC dataset ids', function () { @@ -71,8 +71,8 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[8, 9, 10]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 0); - cy.get('[datacy=dataset-count]').should('contain.text', '(0)'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 0); + cy.get('[data-cy=dataset-count]').should('contain.text', '(0)'); }); it('Renders less than five datasets without an expansion link', function () { @@ -82,15 +82,15 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1, 3, 9, 10]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 2); - cy.get('[datacy=dataset-count]').should('contain.text', '(2)'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 2); + cy.get('[data-cy=dataset-count]').should('contain.text', '(2)'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-1'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 1'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-3'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 3'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-1'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 1'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-3'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 3'); - cy.get('[datacy=collapse-expand-link]').should('not.exist'); + cy.get('[data-cy=collapse-expand-link]').should('not.exist'); }); it('Renders five datasets without an expansion link', function () { @@ -100,21 +100,21 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1, 2, 3, 4, 5]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 5); - cy.get('[datacy=dataset-count]').should('contain.text', '(5)'); - - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-1'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 1'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-2'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 2'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-3'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 3'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-4'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 4'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-5'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 5'); - - cy.get('[datacy=collapse-expand-link]').should('not.exist'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 5); + cy.get('[data-cy=dataset-count]').should('contain.text', '(5)'); + + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-1'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 1'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-2'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 2'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-3'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 3'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-4'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 4'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-5'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 5'); + + cy.get('[data-cy=collapse-expand-link]').should('not.exist'); }); it('Renders more than five datasets with an expansion link', function () { @@ -124,26 +124,26 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1, 2, 3, 4, 5, 6, 7]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 5); - cy.get('[datacy=dataset-count]').should('contain.text', '(7)'); - - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-1'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 1'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-2'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 2'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-3'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 3'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-4'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 4'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-5'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 5'); - - cy.get('[datacy=dataset-list]').should('not.contain.text', 'DUOS-6'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'Dataset 6'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'DUOS-7'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'Dataset 7'); - - cy.get('[datacy=collapse-expand-link]').should('contain.text', '+ View 2 more'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 5); + cy.get('[data-cy=dataset-count]').should('contain.text', '(7)'); + + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-1'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 1'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-2'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 2'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-3'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 3'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-4'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 4'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-5'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 5'); + + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'DUOS-6'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'Dataset 6'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'DUOS-7'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'Dataset 7'); + + cy.get('[data-cy=collapse-expand-link]').should('contain.text', '+ View 2 more'); }); it('Shows more or less datasets when link is clicked', function () { @@ -153,28 +153,28 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1, 2, 3, 4, 5, 6, 7]} /> ); - cy.get('[datacy=dataset-list]').children().should('have.length', 5); - cy.get('[datacy=dataset-count]').should('contain.text', '(7)'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'DUOS-6'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'Dataset 6'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'DUOS-7'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'Dataset 7'); - - cy.get('[datacy=collapse-expand-link]').should('contain.text', '+ View 2 more'); - cy.get('[datacy=collapse-expand-link]').click(); - - cy.get('[datacy=dataset-list]').children().should('have.length', 7); - cy.get('[datacy=dataset-count]').should('contain.text', '(7)'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-6'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 6'); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-7'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 7'); - - cy.get('[datacy=collapse-expand-link]').should('contain.text', '- View 2 less'); - cy.get('[datacy=collapse-expand-link]').click(); - - cy.get('[datacy=dataset-list]').children().should('have.length', 5); - cy.get('[datacy=collapse-expand-link]').should('contain.text', '+ View 2 more'); + cy.get('[data-cy=dataset-list]').children().should('have.length', 5); + cy.get('[data-cy=dataset-count]').should('contain.text', '(7)'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'DUOS-6'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'Dataset 6'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'DUOS-7'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'Dataset 7'); + + cy.get('[data-cy=collapse-expand-link]').should('contain.text', '+ View 2 more'); + cy.get('[data-cy=collapse-expand-link]').click(); + + cy.get('[data-cy=dataset-list]').children().should('have.length', 7); + cy.get('[data-cy=dataset-count]').should('contain.text', '(7)'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-6'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 6'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-7'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 7'); + + cy.get('[data-cy=collapse-expand-link]').should('contain.text', '- View 2 less'); + cy.get('[data-cy=collapse-expand-link]').click(); + + cy.get('[data-cy=dataset-list]').children().should('have.length', 5); + cy.get('[data-cy=collapse-expand-link]').should('contain.text', '+ View 2 more'); }); it('Renders filler dataset identifier if attribute is null', function () { @@ -189,9 +189,9 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1]} /> ); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'DUOS-1'); - cy.get('[datacy=dataset-list]').should('contain.text', '- -'); - cy.get('[datacy=dataset-list]').should('contain.text', 'Dataset 1'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'DUOS-1'); + cy.get('[data-cy=dataset-list]').should('contain.text', '- -'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'Dataset 1'); }); it('Renders filler dataset name if attribute is null', function () { @@ -206,9 +206,9 @@ describe('DatasetsRequestedPanel - Tests', function () { dacDatasetIds={[1]} /> ); - cy.get('[datacy=dataset-list]').should('contain.text', 'DUOS-1'); - cy.get('[datacy=dataset-list]').should('not.contain.text', 'Dataset 1'); - cy.get('[datacy=dataset-list]').should('contain.text', '- -'); + cy.get('[data-cy=dataset-list]').should('contain.text', 'DUOS-1'); + cy.get('[data-cy=dataset-list]').should('not.contain.text', 'Dataset 1'); + cy.get('[data-cy=dataset-list]').should('contain.text', '- -'); }); it('Renders skeleton text when loading', function () { @@ -221,7 +221,7 @@ describe('DatasetsRequestedPanel - Tests', function () { ); cy.get('.text-placeholder').should('exist'); - cy.get('[datacy=dataset-list]').should('not.exist'); + cy.get('[data-cy=dataset-list]').should('not.exist'); }); it('shows all datasets if the viewing on the admin page', () => { @@ -234,6 +234,6 @@ describe('DatasetsRequestedPanel - Tests', function () { /> ); cy.get('.dataset-list-item').should('have.length', 5); - cy.get('[datacy=collapse-expand-link]').contains('View 2 more'); + cy.get('[data-cy=collapse-expand-link]').contains('View 2 more'); }); }); diff --git a/src/components/collection_voting_slab/DatasetsRequestedPanel.js b/src/components/collection_voting_slab/DatasetsRequestedPanel.js index 065e26fc2..f2356ab11 100644 --- a/src/components/collection_voting_slab/DatasetsRequestedPanel.js +++ b/src/components/collection_voting_slab/DatasetsRequestedPanel.js @@ -1,4 +1,4 @@ -import {a, div, h, span} from 'react-hyperscript-helpers'; +import React from 'react'; import {useEffect, useState} from 'react'; import {isNil, filter, includes, map} from 'lodash/fp'; @@ -71,27 +71,33 @@ export default function DatasetsRequestedPanel(props) { }; const SectionHeading = () => { - return div({style: styles.heading}, [ - 'Datasets Requested', - span({ - style: styles.datasetCount, - isRendered: !isLoading, - datacy: 'dataset-count' - }, [`(${datasetCount})`]) - ]); + return ( +
+ Datasets Requested + {!isLoading && + ({datasetCount}) + } +
+ ); }; const DatasetList = () => { const datasetRows = map(dataset => { - return div({style: {display: 'flex'}, key: dataset.dataSetId, className: 'dataset-list-item'}, [ - div({style: {width: '12.5%'}}, [datasetId(dataset)]), - div({style: {width: '75%'}}, [datasetName(dataset)]) - ]); + return ( +
+
{datasetId(dataset)}
+
{datasetName(dataset)}
+
+ ); })(visibleDatasets); - return isLoading - ? div({className: 'text-placeholder', style: styles.skeletonLoader}) - : div({style: styles.datasetList, datacy: 'dataset-list'}, [datasetRows]); + return isLoading ? ( +
+ ) : ( +
+ {datasetRows} +
+ ); }; const datasetId = (dataset) => { @@ -108,12 +114,17 @@ export default function DatasetsRequestedPanel(props) { `- View ${hiddenDatasetCount} less` : `+ View ${hiddenDatasetCount} more`; - return a({ - datacy: 'collapse-expand-link', - style: styles.link, - onClick: expanded ? collapseDatasetList : expandDatasetList, - isRendered: hiddenDatasetCount > 0 - }, [linkMessage]); + return ( + <> + {hiddenDatasetCount > 0 && + {linkMessage} + } + + ); }; const expandDatasetList = () => { @@ -126,9 +137,11 @@ export default function DatasetsRequestedPanel(props) { setVisibleDatasets(filteredDatasets.slice(0, collapsedDatasetCapacity)); }; - return div({style: styles.baseStyle}, [ - h(SectionHeading), - h(DatasetList), - h(CollapseExpandLink) - ]); + return ( +
+ + + +
+ ); } From cc638023d4d48f6fb0c258479776ddae34138a68 Mon Sep 17 00:00:00 2001 From: Florian Boulnois Date: Fri, 1 Mar 2024 16:49:18 -0500 Subject: [PATCH 15/15] refactor: switch SigningOfficialTable to JSX --- .../SigningOfficialTable.js | 272 +++++++++--------- 1 file changed, 139 insertions(+), 133 deletions(-) diff --git a/src/pages/signing_official_console/SigningOfficialTable.js b/src/pages/signing_official_console/SigningOfficialTable.js index 535d5a61c..56e5eaf8b 100644 --- a/src/pages/signing_official_console/SigningOfficialTable.js +++ b/src/pages/signing_official_console/SigningOfficialTable.js @@ -1,6 +1,6 @@ -import { useState, useEffect, useCallback, useRef, Fragment } from 'react'; +import React from 'react'; +import { useState, useEffect, useCallback, useRef } from 'react'; import { Styles, Theme } from '../../libs/theme'; -import { a, h, div } from 'react-hyperscript-helpers'; import { cloneDeep, find, findIndex, join, map, sortedUniq, sortBy, isEmpty, isNil, flow, filter } from 'lodash/fp'; import SimpleTable from '../../components/SimpleTable'; import SimpleButton from '../../components/SimpleButton'; @@ -63,22 +63,24 @@ const DeactivateLibraryCardButton = (props) => { const {card = {}, showConfirmationModal} = props; const message = 'Are you sure you want to deactivate this library card?'; const title = 'Deactivate Library Card'; - return h(SimpleButton, { - keyProp: `deactivate-card-${card.id}`, - label: 'Deactivate', - baseColor: Theme.palette.error, - hoverStyle: { - backgroundColor: 'rgb(194, 38,11)', - color: 'white' - }, - additionalStyle: { - padding: '2.25% 5%', - fontSize: '1.45rem', - fontWeight: 600, - fontFamily: 'Montserrat' - }, - onClick: () => showConfirmationModal({card, message, title, confirmType: confirmModalType.delete}) - }); + return ( + showConfirmationModal({card, message, title, confirmType: confirmModalType.delete})} + /> + ); }; const IssueLibraryCardButton = (props) => { @@ -86,24 +88,29 @@ const IssueLibraryCardButton = (props) => { //username can be confirmed on back-end -> if userId exists pull data from db, otherwise only save email //institution id should be determined from the logged in SO account on the back-end const {card, showConfirmationModal} = props; - const message = div({}, [ - // LCA Terms Download - LibraryCardAgreementTermsDownload, - 'Are you sure you want to issue this library card?']); + const message = ( +
+ {/* LCA Terms Download */} + + {'Are you sure you want to issue this library card?'} +
+ ); const title = 'Issue Library Card'; - return h(SimpleButton, { - keyProp: `issue-card-${card.userEmail}`, - label: 'Issue', - baseColor: Theme.palette.secondary, - additionalStyle: { - width: '30%', - padding: '2.25% 5%', - fontSize: '1.45rem', - fontWeight: 600, - fontFamily: 'Montserrat' - }, - onClick: () => showConfirmationModal({ card, message, title, confirmType: confirmModalType.issue }), - }); + return ( + showConfirmationModal({ card, message, title, confirmType: confirmModalType.issue })} + /> + ); }; const researcherFilterFunction = getSearchFilterFunctions().signingOfficialResearchers; @@ -135,15 +142,16 @@ const LibraryCardCell = ({ isComponent: true, id, label: 'lc-button', - data: div( - { - style: { + data: ( +
+ {button} +
), }; }; @@ -269,13 +277,15 @@ export default function SigningOfficialTable(props) { } }, []); - const paginationBar = h(PaginationBar, { - pageCount, - currentPage, - tableSize, - goToPage, - changeTableSize - }); + const paginationBar = ( + + ); const processResearcherRowData = (researchers = []) => { return researchers.map(researcher => { @@ -370,91 +380,87 @@ export default function SigningOfficialTable(props) { const lcaContent = ScrollableMarkdownContainer({markdown: LcaMarkdown}); - return h(Fragment, {}, [ - div({ style: { display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', width: '112%', marginLeft: '-6%' } }, [ - div({ style: Styles.LEFT_HEADER_SECTION }, [ - div({ style: { ...Styles.HEADER_CONTAINER , marginRight: '-7%' }}, [ - div({ style: { ...Styles.SUB_HEADER, - marginTop: '0', - fontFamily: 'Montserrat', - fontWeight: 600, - fontSize: '2.8rem'} - }, [ - 'My Institution\'s Researchers',]), - div({ - style: Object.assign({}, Styles.MEDIUM_DESCRIPTION, { + return ( + <> +
+
+
+
+ My Institution's Researchers +
+
+ Issue or Remove Library Card privileges to allow researchers to submit DARs. + + i + +
+
showModalOnClick(), - baseColor: Theme.palette.secondary, - label: 'Add Library Card', - additionalStyle: { - width: '22rem', - height: '4rem', - padding: '4% 10%', - fontWeight: '600' - } - }), - ]) - ]), - h(SimpleTable, { - isLoading, - rowData: processResearcherRowData(visibleResearchers), - columnHeaders: columnHeaderData, - styles, - tableSize, - paginationBar, - }), - h(LibraryCardFormModal, { - showModal, - createOnClick: (card) => issueLibraryCard(card, researchers), - closeModal: () => setShowModal(false), - card: selectedCard, - users: filter(onlyResearchersWithoutCardFilter(signingOfficial.institutionId))(researchers), - institutions: [], //pass in empty array to force modal to hide institution dropdown - modalType: 'add', - lcaContent: lcaContent - }), - h(ConfirmationModal, { - showConfirmation, - closeConfirmation: () => setShowConfirmation(false), - title: confirmationTitle, - // The issue modal requires a larger view than normal - styleOverride: confirmType === confirmModalType.issue ? { minWidth: '725px', minHeight: '475px' } : {}, - message: - confirmType === confirmModalType.delete - ? div({}, [confirmationModalMsg]) + })}> + Issuing Library Card privileges is done in accordance with the Broad and NHGRI Library Card Agreements. +
+
+
+ +
+ showModalOnClick()} + baseColor={Theme.palette.secondary} + label="Add Library Card" + additionalStyle={{ + width: '22rem', + height: '4rem', + padding: '4% 10%', + fontWeight: '600' }} + /> +
+
+ + issueLibraryCard(card, researchers)} + closeModal={() => setShowModal(false)} + card={selectedCard} + users={filter(onlyResearchersWithoutCardFilter(signingOfficial.institutionId))(researchers)} + institutions={[]} //pass in empty array to force modal to hide institution dropdown + modalType="add" + lcaContent={lcaContent} /> + setShowConfirmation(false)} + title={confirmationTitle} + // The issue modal requires a larger view than normal + styleOverride={confirmType === confirmModalType.issue ? { minWidth: '725px', minHeight: '475px' } : {}} + message={confirmType === confirmModalType.delete + ?
{confirmationModalMsg}
// Library Card Agreement Text - : div({}, [lcaContent, confirmationModalMsg]), - header: `${selectedCard.userName || selectedCard.userEmail} - ${ - !isNil(selectedCard.institution) ? selectedCard.institution.name : '' - }`, - onConfirm: () => - confirmType === confirmModalType.delete - ? deactivateLibraryCard(selectedCard, researchers) - : issueLibraryCard(selectedCard, researchers) - }), - ]); + :
{lcaContent}{confirmationModalMsg}
} + header={`${selectedCard.userName || selectedCard.userEmail} - ${ + !isNil(selectedCard.institution) ? selectedCard.institution.name : '' + }`} + onConfirm={() => + confirmType === confirmModalType.delete + ? deactivateLibraryCard(selectedCard, researchers) + : issueLibraryCard(selectedCard, researchers)} + /> + + ); } \ No newline at end of file