Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DCJ-286] Add bulk User operations to dropdown on SO Console #2563

Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
996716e
feat: new wip tab & no more email tab
aarohinadkarni Apr 16, 2024
f865458
Merge branch 'develop' into an-DUOS-2916-UI-Update-SO-Console-Manage-…
aarohinadkarni Apr 17, 2024
7506ef7
feat: pull all DAAs & add DAA ajax file
aarohinadkarni Apr 17, 2024
a44b5c3
feat: progress-ish
aarohinadkarni Apr 22, 2024
56cfabf
feat: columns showing & rendering
aarohinadkarni Apr 22, 2024
cf2b37f
feat: add checkbox...
aarohinadkarni Apr 22, 2024
090a617
feat: lots of progress
aarohinadkarni Apr 29, 2024
1bd9d44
feat: more progress on dropdown for users
aarohinadkarni Apr 29, 2024
9d420f1
feat: download agreement working
aarohinadkarni Apr 30, 2024
06e5cc7
feat: zebra stripes
aarohinadkarni Apr 30, 2024
77dfc96
feat: cleanup, try fixing radio, setup redirect
aarohinadkarni Apr 30, 2024
5950df8
feat: make changes only visible on dev
aarohinadkarni May 1, 2024
6a3fd2b
refactor: delete commented out code
aarohinadkarni May 1, 2024
9791e92
feat: fix refresh & begin cleanup?
aarohinadkarni May 1, 2024
c34b8ab
refactor: more cleanup & deleting comments
aarohinadkarni May 1, 2024
8703e19
feat: revert dropdown in simpletable
aarohinadkarni May 1, 2024
d948bba
feat: change routes
aarohinadkarni May 2, 2024
3f8a982
refactor: cleanup from before
aarohinadkarni May 2, 2024
6b7b445
Merge branch 'develop' into an-DUOS-2916-UI-Update-SO-Console-Manage-…
aarohinadkarni May 2, 2024
682051c
Merge branch 'develop' into an-DCJ-286-UI-Update-SO-Console-Add-Bulk-…
aarohinadkarni May 2, 2024
fb02b39
feat: delete commented out, bring up to speed w so console pr & just …
aarohinadkarni May 2, 2024
a00881b
feat: add refreshResearchers & cleanup
aarohinadkarni May 2, 2024
b1c331f
refactor: more cleanup from earlier work
aarohinadkarni May 2, 2024
650f694
refactor: more cleanup from earlier work pt2
aarohinadkarni May 2, 2024
22bd1be
feat: change paths again
aarohinadkarni May 2, 2024
337767e
feat: actually call handleApplyAll onClick & cleanup
aarohinadkarni May 3, 2024
3ecdaec
feat: resolve pr comments
aarohinadkarni May 3, 2024
4b5d9e2
refactor: partially resolve pr comments
aarohinadkarni May 6, 2024
818e1d6
refactor: resolve hook warning
aarohinadkarni May 6, 2024
919afbe
Merge branch 'an-DUOS-2916-UI-Update-SO-Console-Manage-DAAs-to-user-s…
aarohinadkarni May 6, 2024
bc7f1f3
refactor: resolve lint warnings & cleanup
aarohinadkarni May 6, 2024
633566f
refactor: optional striped property
aarohinadkarni May 6, 2024
1b1c1d7
feat: separate out ManageUsersDropdown
aarohinadkarni May 6, 2024
cffd09c
refactor: separate DAACell component
aarohinadkarni May 7, 2024
800c56e
refactor: delete leftover SigningOfficialTable2
aarohinadkarni May 7, 2024
c3ededf
Merge branch 'develop' into an-DCJ-286-UI-Update-SO-Console-Add-Bulk-…
aarohinadkarni May 7, 2024
4e5464f
refactor: cleanup & lint warnings
aarohinadkarni May 7, 2024
5777de7
feat: resolve pr comments
aarohinadkarni May 8, 2024
10d9155
refactor: resolve console warnings
aarohinadkarni May 8, 2024
b41729d
[DCJ-287] Add bulk DAA operations to dropdown on SO Console (#2572)
aarohinadkarni May 9, 2024
bc0abe3
feat: resolve pr comment
aarohinadkarni May 9, 2024
ef6dfe2
refactor: resolve lint warnings
aarohinadkarni May 10, 2024
d024803
fix: pass daas instead of filtereddaas & rename variables
aarohinadkarni May 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/SimpleTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const DataRows = ({rowData, baseStyle, columnHeaders, rowWrapper = ({renderedRow
return rowData.map((row, index) => {
const id = rowData[index][0].id;
const mapKey = id || `noId-index-${index}`;
if (rowData[index][0].label === "display-names") {
if (rowData[index][0].striped) {
baseStyle.backgroundColor = index % 2 === 0 ? 'white' : '#e2e8f4';
}
const renderedRow = (
Expand Down
5 changes: 2 additions & 3 deletions src/libs/ajax/DAA.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as fp from 'lodash/fp';
import fileDownload from 'js-file-download';
import { getApiUrl, fetchOk } from '../ajax';
import { getApiUrl } from '../ajax';
import { Config } from '../config';
import axios from 'axios';

Expand Down Expand Up @@ -52,7 +51,7 @@ export const DAA = {
const url = `${await getApiUrl()}/api/daa/bulk/user/${userId}`;
const res = await axios.delete(url, { ...Config.authOpts(), data: daaList });
return res.data;
},
},

getDaaFileById: async (daaId, daaFileName) => {
const authOpts = Object.assign(Config.authOpts(), { responseType: 'blob' });
Expand Down
45 changes: 45 additions & 0 deletions src/pages/signing_official_console/DAACell.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React from 'react';
import { Checkbox } from '@mui/material';
import { DAA } from '../../libs/ajax/DAA';
import { Notifications } from '../../libs/utils';

export default function DAACell(rowDac, researcher, institutionId, daas, refreshResearchers, setResearchers) {
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
const id = researcher && (researcher.userId || researcher.email);
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
const libraryCards = researcher && researcher.libraryCards;
const card = libraryCards && libraryCards.find(card => card.institutionId === institutionId);
const daaIds = researcher && card && card.daaIds;
const filteredDaas = daaIds && daas.filter(daa => daaIds.includes(daa.daaId));
const hasDacId = filteredDaas && filteredDaas.some(daa => daa.dacs.some(dac => dac.dacId === rowDac.dacId));

const handleClick = async (researcher, specificDac, filteredDaas, checked, refreshResearchers, setResearchers) => {
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
const daaId = filteredDaas.find(daa => daa.dacs.some(dac => dac.dacId === specificDac.dacId))?.daaId;
if (!checked) {
try {
await DAA.createDaaLcLink(daaId, researcher.userId);
Notifications.showSuccess({text: `Approved access to ${specificDac.name} to user: ${researcher.displayName}`});
refreshResearchers(setResearchers);
} catch(error) {
Notifications.showError({text: `Error approving access to ${specificDac.name} to user: ${researcher.displayName}`});
}
} else {
try {
await DAA.deleteDaaLcLink(daaId, researcher.userId);
Notifications.showSuccess({text: `Removed approval of access to ${specificDac.name} to user: ${researcher.displayName}`});
refreshResearchers(setResearchers);
} catch(error) {
Notifications.showError({text: `Error removing approval of access to ${specificDac.name} to user: ${researcher.displayName}`});
}
}
};

return {
isComponent: true,
id,
label: 'lc-button',
data: (
<div>
<Checkbox checked={hasDacId} onClick={() => handleClick(researcher,rowDac, daas, hasDacId, refreshResearchers, setResearchers)}/>
</div>
),
};
}
74 changes: 16 additions & 58 deletions src/pages/signing_official_console/ManageResearcherDAAsTable.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import { Checkbox } from '@mui/material';
import { Styles } from '../../libs/theme';
import { isEmpty } from 'lodash/fp';
import SimpleTable from '../../components/SimpleTable';
Expand All @@ -12,9 +11,10 @@ import {
getSearchFilterFunctions,
searchOnFilteredList
} from '../../libs/utils';
import { DAA } from '../../libs/ajax/DAA';
import {User} from '../../libs/ajax/User';
import { USER_ROLES } from '../../libs/utils';
import ManageUsersDropdown from './ManageUsersDropdown';
import DAACell from './DAACell';

//Styles specific to this table
const styles = {
Expand Down Expand Up @@ -50,28 +50,6 @@ let columnHeaderFormat = {

const researcherFilterFunction = getSearchFilterFunctions().signingOfficialResearchers;

const handleClick = async (researcher, specificDac, filteredDaas, checked, refreshResearchers, setResearchers) => {
if (!checked) {
try {
const daaId = filteredDaas.find(daa => daa.dacs.some(dac => dac.dacId === specificDac.dacId))?.daaId;
await DAA.createDaaLcLink(daaId, researcher.userId);
Notifications.showSuccess({text: `Approved access to ${specificDac.name} to user: ${researcher.displayName}`});
refreshResearchers(setResearchers);
} catch(error) {
Notifications.showError({text: `Error approving access to ${specificDac.name} to user: ${researcher.displayName}`});
}
} else {
try {
const daaId = filteredDaas.find(daa => daa.dacs.some(dac => dac.dacId === specificDac.dacId))?.daaId;
await DAA.deleteDaaLcLink(daaId, researcher.userId);
Notifications.showSuccess({text: `Removed approval of access to ${specificDac.name} to user: ${researcher.displayName}`});
refreshResearchers(setResearchers);
} catch(error) {
Notifications.showError({text: `Error removing approval of access to ${specificDac.name} to user: ${researcher.displayName}`});
}
}
};

const refreshResearchers = async (setResearchers) => {
const researcherList = await User.list(USER_ROLES.signingOfficial);
// the construction of this list is currently a work-around because our endpoint in the backend
Expand All @@ -84,46 +62,26 @@ const refreshResearchers = async (setResearchers) => {
setResearchers(researcherObjectList);
};

const DAACell = (
rowDac,
researcher,
institutionId,
daas,
refreshResearchers,
setResearchers
) => {
const id = researcher && (researcher.userId || researcher.email);
const libraryCards = researcher && researcher.libraryCards;
const card = libraryCards && libraryCards.find(card => card.institutionId === institutionId);
const daaIds = researcher && card && card.daaIds;
const filteredDaas = daaIds && daas.filter(daa => daaIds.includes(daa.daaId));
const hasDacId = filteredDaas && filteredDaas.some(daa => daa.dacs.some(dac => dac.dacId === rowDac.dacId));

return {
isComponent: true,
id,
label: 'lc-button',
data: (
<div>
<Checkbox checked={hasDacId} onClick={() => handleClick(researcher,rowDac, daas, hasDacId, refreshResearchers, setResearchers)}/>
</div>
),
};
};



const displayNameCell = (displayName, email, id) => {
const displayNameCell = (displayName, email, id, daas, setResearchers) => {
return {
data: (
<>
<div>{displayName || 'Invite sent, pending registration'}</div>
<div><a href={`mailto:${email}`}>{email || '- -'}</a></div>
<li className="dropdown" style={{ listStyleType: 'none' }}>
<a role="button" data-toggle="dropdown">
<div id="dacUser" style={{ color: 'black' }}>
{displayName || 'Invite sent, pending registration'}
<span className="caret caret-margin" style={{color: '#337ab7', float: 'right', marginTop: '15px'}}></span>
<small><a href={`mailto:${email}`}>{email || '- -'}</a></small>
</div>
</a>
<ManageUsersDropdown daas={daas} refreshResearchers={refreshResearchers} setResearchers={setResearchers} moreData={{id: id, name: displayName}}/>
</li>
</>
),
id,
style: {},
label: 'display-names'
label: 'display-names',
striped: true
};
};

Expand Down Expand Up @@ -219,7 +177,7 @@ export default function ManageResearcherDAAsTable(props) {
const email = researcher.email || libraryCard.userEmail;
const id = researcher.userId || email;
return [
displayNameCell(displayName, email, id),
displayNameCell(displayName, email, id, daas, setResearchers),
...dacs.map(dac => DAACell(dac, researcher, signingOfficial.institutionId, daas, refreshResearchers, setResearchers))
];
});
Expand Down
78 changes: 78 additions & 0 deletions src/pages/signing_official_console/ManageUsersDropdown.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React, { useState } from 'react';
import { Button } from '@mui/material';
import { DAA } from '../../libs/ajax/DAA';
import { Notifications } from '../../libs/utils';

export default function ManageUsersDropdown(props) {
const [applyAll, setApplyAll] = useState(false);
const [removeAll, setRemoveAll] = useState(false);
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
const {daas, refreshResearchers, setResearchers, moreData} = props;

const handleApplyAllChange = (event) => {
setApplyAll(event.target.checked);
setRemoveAll(!event.target.checked);
};

const handleRemoveAllChange = (event) => {
setRemoveAll(event.target.checked);
setApplyAll(!event.target.checked);
};

const handleApplyAll = async () => {
const daaList = { 'daaList': daas.map(daa => daa.daaId) };
if (applyAll) {
try {
await DAA.bulkAddDaasToUser(moreData.id, daaList);
Notifications.showSuccess({text: `Approved access to request data from all DACs to user: ${moreData.name}`});
refreshResearchers(setResearchers);
} catch(error) {
Notifications.showError({text: `Error approving access to request data from all DACs to user: ${moreData.name}`});
}
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
} else if (removeAll) {
try {
await DAA.bulkRemoveDaasFromUser(moreData.id, daaList);
Notifications.showSuccess({text: `Removed approval of access to request data from all DACs from user: ${moreData.name}`});
refreshResearchers(setResearchers);
} catch(error) {
Notifications.showError({text: `Error removing approval of access to request data from all DACs from user: ${moreData.name}`});
}
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
}
};

return (
<ul className="dropdown-menu" role="menu" style={{ padding: '20px', textTransform:'none'}}>
<th id="link_signOut" style={{display:'flex', padding: '5px', textAlign: 'left'}}>
<strong>Agreement Actions</strong>
</th>
<form>
<li style={{paddingTop: '5px', paddingBottom: '5px'}}>
<label style={{fontWeight: 'normal', whiteSpace: 'nowrap'}}>
<input type="radio" name="users" value="apply" checked={applyAll} onChange={handleApplyAllChange}/>
&nbsp;&nbsp;Apply all agreements to this user
</label>
</li>
<li style={{paddingTop: '5px', paddingBottom: '5px'}}>
<label style={{fontWeight: 'normal', whiteSpace: 'nowrap' }}>
<input type="radio" name="users" value="remove" checked={removeAll} onChange={handleRemoveAllChange}/>
&nbsp;&nbsp;Remove all agreements from this user
</label>
</li>
</form>
<li style={{paddingTop: '5px', paddingBottom: '5px'}}>
<Button style={{
aarohinadkarni marked this conversation as resolved.
Show resolved Hide resolved
fontSize: '15px',
fontWeight: 'normal',
fontFamily: 'Montserrat',
border: '1px solid #0948B7',
borderRadius: '5px',
height: '40px',
marginRight: '1em',
cursor: 'pointer',
color: '#0948B7',
padding: '10px 20px',
textTransform: 'none'
}} onClick={() => handleApplyAll()}>Apply</Button>
</li>
</ul>
);
}
Loading