Skip to content

Commit

Permalink
Duos UI 2602 affiliation and roles (#2290)
Browse files Browse the repository at this point in the history
* added email text field

* added new user page

* stopped page from reloading

* removed sections that are not needed

* removed all sections except name/email

* removed props

* removed functions that were not needed

* created user profile directory

* changed fields to read-only

* used read-only form fields

* initialized controlled access grants page

* affiliation and roles

* completed affiliation and roles component

* removed unnecessary files

* deleted ControlledAccessGrants

* Update ChairConsole.js

* Update ajax.js

* Update src/Routes.js

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>

* Update Routes.js

* Update Routes.js

* Update src/Routes.js

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>

* Update src/Routes.js

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>

* added new role component

* Revert "Update src/Routes.js"

This reverts commit 86b2511.

* Update src/Routes.js

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>

* Update src/pages/user_profile/NewRole.js

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>

* Update Routes.js

* Delete NewRole.js

* Update UserProfile.js

* Update UserProfile.js

* Update UserProfile.js

* Update package.json

* Update package-lock.json

* fix: ensure lockfile uses lf instead of crlf

---------

Co-authored-by: codacy-production[bot] <61871480+codacy-production[bot]@users.noreply.github.com>
Co-authored-by: Florian Boulnois <fboulnoi@broadinstitute.org>
  • Loading branch information
3 people authored Jul 21, 2023
1 parent cc77769 commit 50cec31
Show file tree
Hide file tree
Showing 4 changed files with 286 additions and 69 deletions.
2 changes: 2 additions & 0 deletions src/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import PrivacyPolicy from './pages/PrivacyPolicy';
import ResearcherConsole from './pages/ResearcherConsole';
import ResearcherProfile from './pages/ResearcherProfile';
import UserProfile from './pages/user_profile/UserProfile';
import AffiliationsAndRoles from './pages/user_profile/AffiliationAndRoles';
import SigningOfficialResearchers from './pages/signing_official_console/SigningOfficialResearchers';
import SigningOfficialDarRequests from './pages/signing_official_console/SigningOfficialDarRequests';
import SigningOfficialDataSubmitters from './pages/signing_official_console/SigningOfficialDataSubmitters';
Expand Down Expand Up @@ -64,6 +65,7 @@ const Routes = (props) => (
<Route path="/nih_dms_policy" component={NIHDMSPolicyInfo} />
<Route path="/anvil_dms_policy" component={AnVILDMSPolicyInfo} />
<AuthenticatedRoute path="/user_profile" component={UserProfile} props={props} rolesAllowed={[USER_ROLES.all]} />
<AuthenticatedRoute path="/affiliation_roles" component={AffiliationsAndRoles} props={props} rolesAllowed={[USER_ROLES.all]} />
<AuthenticatedRoute path="/admin_review_collection/:collectionId" component={DarCollectionReview} props={Object.assign({adminPage: true}, props)} rolesAllowed={[USER_ROLES.admin]} />
<AuthenticatedRoute path="/admin_manage_users" component={AdminManageUsers} props={props} rolesAllowed={[USER_ROLES.admin]} />
<AuthenticatedRoute path="/admin_edit_user/:userId" component={AdminEditUser} props={props} rolesAllowed={[USER_ROLES.admin]} />
Expand Down
2 changes: 1 addition & 1 deletion src/pages/ChairConsole.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,4 @@ export default function ChairConsole(props) {
consoleType: consoleTypes.CHAIR
}),
]);
}
}
208 changes: 208 additions & 0 deletions src/pages/user_profile/AffiliationAndRoles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import { useEffect, useState } from 'react';
import { Institution, User } from '../../libs/ajax';
import { find, isNil, isNumber } from 'lodash';
import { div, p, h1, h, input, button } from 'react-hyperscript-helpers';
import { Notifications } from '../../libs/utils';
import { FormField, FormFieldTypes } from '../../components/forms/forms';


export default function AffiliationAndRole(props) {

const {
user,
userProps,
institutions
} = props;

const [profile, setProfile] = useState({
roles: '',
institutionId: undefined,
suggestedInstitution: undefined,
selectedSigningOfficialId: undefined,
suggestedSigningOfficial: undefined,
id: undefined
});

const [selectedInstitution, setSelectedInstitution] = useState();

useEffect(() => {
const init = async () => {
try {
const rolesList = [];
if (!isNil(user) && !isNil(user.roles)) {
for (let i = 0; i < user.roles.length; i++) {
const newRole = user.roles[i].name;
rolesList.push(newRole);
}
const allRoles = rolesList.join(', ');
setProfile({
roles: allRoles,
institutionId: user.institutionId || userProps.institutionId,
suggestedInstitution: userProps.suggestedInstitution,
selectedSigningOfficialId: parseInt(userProps.selectedSigningOfficialId),
suggestedSigningOfficial: userProps.suggestedSigningOfficial,
id: user.userId
});
}
} catch (error) {
Notifications.showError({ text: 'Error: Unable to retrieve user data from server' });
}
};

init();

}, [user, userProps]);

useEffect(() => {
if (profile.institutionId) {
Institution.getById(profile.institutionId).then((institution) => {
if (!institution) {
return;
}
setSelectedInstitution(institution);
});
} else {
setSelectedInstitution(null);
}
}, [profile.institutionId]);


const hasInstitution = () => {
return (isNumber(profile.institutionId) && profile.institutionId !== 0) || (profile.suggestedInstitution !== undefined && profile.suggestedInstitution !== '');
};

const isSigningOfficial = () => {
return user.isSigningOfficial;
};

const submitForm = async (event) => {
event.preventDefault();
await updateInstitution();
};

const formIsValid = () => {
return !hasInstitution() || !isSigningOfficial();
};

const updateInstitution = async () => {
const payload = {
institutionId: profile.institutionId,
suggestedInstitution: profile.suggestedInstitution
};

let updatedUser = await User.updateSelf(payload);
return updatedUser;
};

const generateInstitutionSelectionDisplay = () => {
if (!isSigningOfficial() || (isNil(profile.institutionId) && isNil(profile.suggestedInstitution))) {
return div({},
[
h(FormField, {
id: 'institutionId',
type: FormFieldTypes.SELECT,
selectOptions: (institutions).map((i) => {
return {
institutionId: i.id,
displayText: i.name,
};
}),
placeholder: 'Search for Institution...',
isCreatable: true,
defaultValue: {
institutionId: selectedInstitution?.institutionId,
suggestedInstitution: profile.suggestedInstitution,
displayText: (
(!isNil(selectedInstitution)
? `${selectedInstitution.name}`
: (!isNil(profile.suggestedInstitution)
? `${profile.suggestedInstitution}`
: ''))
),
},
selectConfig: {
clearValue: () => {
setProfile(Object.assign({},
profile,
{
institutionId: undefined,
suggestedInstitution: undefined
}));
},
},
onChange: ({ value }) => {
if (!isNil(value?.institutionId)) {
setProfile(Object.assign({}, profile, {
institutionId: value?.institutionId,
suggestedInstitution: undefined
}));
} else {
setProfile(Object.assign({}, profile, {
institutionId: undefined,
suggestedInstitution: value?.displayText
}));
}
}
}),
]
);
} else {
let institution = (profile.institutionId ? find(institutions, { id: profile.institutionId }) : null);
const institutionName = (institution ? institution.name : profile.suggestedInstitution);


return div({
className: '',
style: { padding: 0 },
}, [
input({
id: 'profileInstitution',
name: 'institution',
type: 'text',
disabled: true,
className: 'form-control',
value: institutionName,
}),
]);
}
};

return div({}, [
h1({
style: {
color: '#01549F',
fontSize: '20px',
fontWeight: '600',
}
}, ['Affiliation & Role']),
div({ className: '', style: { 'marginTop': '20px' } }, []),
div({
style:
{
color: '#000',
fontFamily: 'Montserrat',
fontSize: '16px',
fontStyle: 'normal',
fontWeight: '600',
lineHeight: 'normal'
}
},
[
p({}, ['Institution']),
div({ style: { marginBottom: '15px' } }, []),
generateInstitutionSelectionDisplay(),
button({
id: 'btn_submit',
onClick: submitForm,
className: 'f-right btn-primary common-background',
style: {
marginTop: '2rem',
},
disabled: !formIsValid(),
}, ['Save']),
div({ className: '', style: { 'marginTop': '83px' } }, []),
p({}, ['Role']),
]),
p({}, [profile.roles]),
]);
}
143 changes: 75 additions & 68 deletions src/pages/user_profile/UserProfile.js
Original file line number Diff line number Diff line change
@@ -1,89 +1,96 @@
import {useState, useEffect} from 'react';
import {div, h, h1, hr} from 'react-hyperscript-helpers';
import {FormField, FormFieldTypes} from '../../components/forms/forms';
import {PageHeading} from '../../components/PageHeading';
import {Notification} from '../../components/Notification';
import {User} from '../../libs/ajax';
import {NotificationService} from '../../libs/notificationService';
import { Notifications} from '../../libs/utils';

import { useState, useEffect } from 'react';
import { div, h, h1, hr } from 'react-hyperscript-helpers';
import { FormField, FormFieldTypes } from '../../components/forms/forms';
import { PageHeading } from '../../components/PageHeading';
import { Notification } from '../../components/Notification';
import AffiliationAndRoles from './AffiliationAndRoles';
import { Institution } from '../../libs/ajax';
import { Storage } from '../../libs/storage';
import { NotificationService } from '../../libs/notificationService';
import { Notifications, getPropertyValuesFromUser } from '../../libs/utils';

export default function UserProfile() {

const [user, setUser] = useState({});
const [userProps, setUserProps] = useState({});
const [institutions, setInstitutions] = useState([]);

const [profile, setProfile] = useState({
profileName: '',
email: undefined,
id: undefined
});

const [notificationData, setNotificationData] = useState();
const [notificationData, setNotificationData] = useState({});

useEffect(() => {
const init = async () => {
try {
await getUserProfile();

const user = Storage.getCurrentUser();
setUser(user);
setUserProps(getPropertyValuesFromUser(user));
setProfile({
profileName: user.displayName,
email: user.email,
id: user.userId
});
const institutions = await Institution.list();
setInstitutions(institutions);
setNotificationData(await NotificationService.getBannerObjectById('eRACommonsOutage'));
} catch (error) {
Notifications.showError({text: 'Error: Unable to retrieve user data from server'});
Notifications.showError({ text: 'Error: Unable to retrieve user data from server' });
}
};

init();
}, []);

const getUserProfile = async () => {
const user = await User.getMe();

setProfile({
profileName: user.displayName,
email: user.email,
id: user.userId
});
};

return (
div({
className: 'container',
return div({
className: '',
style: {
flexDirection: 'column',
padding: '20px 240px 20px'
}
}, [
div({ className: '' }, [
Notification({notificationData}),
PageHeading({
id: 'researcherProfile',
color: 'common',
title: 'Your Profile',
description: 'Please complete the form below to start using DUOS.'
}),
hr({ className: 'section-separator' })
]),
h1({
style: {
color: '#333F52',
},
}, [
div({ className: 'row no-margin'}, [
div({ className: 'col-md-10 col-md-offset-1 col-sm-12 col-xs-12' }, [
Notification({notificationData}),
PageHeading({
id: 'researcherProfile',
color: 'common',
title: 'Your Profile',
description: 'Please complete the form below to start using DUOS.'
}),
hr({ className: 'section-separator' })
]),
div({
className: 'col-md-10 col-md-offset-1 col-xs-12 no-padding',
style: {
fontFamily: 'Montserrat',
} }, [
h1({style: {
color: '#01549F',
fontSize: '20px',
fontWeight: '600',
} }, ['Full Name:']),
div({ className: '', style: { 'marginTop': '10px' } }, []),
h(FormField, {
id: 'profileName',
type: FormFieldTypes.TEXT,
defaultValue: profile.profileName,
readOnly: true,
}),
div({ className: '', style: { 'marginTop': '10px' } }, []),
h(FormField, {
id: 'profileEmail',
type: FormFieldTypes.TEXT,
defaultValue: profile.email,
readOnly: true,
}),
])
])
])
);
}
color: '#01549F',
fontSize: '20px',
fontWeight: '600',
marginBottom: '15px',
marginTop: '40px'
}
}, ['Full Name']),
h(FormField, {
type: FormFieldTypes.TEXT,
id: 'profileName',
defaultValue: profile.profileName,
readOnly: true,
}),
div({ className: '', style: { 'marginTop': '10px' } }, []),
h(FormField, {
type: FormFieldTypes.TEXT,
id: 'profileEmail',
defaultValue: profile.email,
readOnly: true,
}),
div({ className: '', style: { 'marginTop': '60px' } }, []),
AffiliationAndRoles({
user: user,
userProps: userProps,
institutions: institutions
}),
]);

}

0 comments on commit 50cec31

Please sign in to comment.