Skip to content

Commit f749b9c

Browse files
HP-1261 Feat/disco single file download (#1492)
* feat(downloadVariableMetadataButton): initial commit * feat(downloadVariableMetadataButton): Got zip DL to work * feat(downloadVariableMetadataButton): Made DownloadAllModal a reusable DownloadModal, sorted out promise.all logic * feat(downloadVariableMetadataButton): Cleaned up lint issues, added interface for dataDictionaries * feat(downloadVariableMetadataButton): fixed failing unit test for DownloadModal * feat(downloadVariableMetadataButton): Got unit test to work * feat(downloadVariableMetadataButton): Improved unit tesT * feat(downloadVariableMetadataButton): Removed commented code from unit test and update var ref * feat(downloadVariableMetadataButton): Moved constant to constants file * feat(downloadVariableMetadataButton): Ran linter * feat(downloadVariableMetadataButton): Removed commented test code * feat(downloadVariableMetadataButton): updated logic for rendering download variable metadata button, ran linter * feat(downloadVariableMetadataButton): added function createUniqueDownloadErrorMsg * feat(downloadVariableMetadataButton): formatted code for readability in DiscoveryConfig.d.ts and DiscoveryDetails.tsx * feat(downloadVariableMetadataButton): updated unit test for downloadVariableMetadata * feat(downloadVariableMetadataButton): Updated test to pass * feat(downloadVariableMetadataButton): Ran linter * feat(downloadVariableMetadataButton): Updated download failed msg respose * feat(downloadVariableMetadataButton): Change em to strong in messages for readability * feat(downloadVariableMetadataButton): Removed excessive spacing in DownloadVariableMetadata.test.tsx * feat(downloadVariableMetadataButton): Added space for code readability in DownloadVariableMetadata.test.tsx * feat(downloadVariableMetadataButton): Updated to use one modal and disable buttons during downloading * feat(downloadVariableMetadataButton): Added support for loading state for DownloadAllFiles button and DownloadVariableMetadata button * feat(downloadVariableMetadataButton): Made data type for inProgress always a string to improve consistency * feat(downloadVariableMetadataButton): removed unneeded console statement * feat(downloadVariableMetadataButton): Added inline solution for checking noVariableLevelMetadata * feat(downloadVariableMetadataButton): Wrote initial unit test for DownloadDataDictionaryInfo * feat(downloadVariableMetadatabutton): Got second test to pass * feat(downloadVariableMetadataButton): Wrote additional unit tests for DownloadDataDictionaryInfo * feat(downloadVariableMetadataButton): Cleaned up unit test, ran linter * feat(downloadVariableMetadataButton): Updated unit tests based on refacotring of DataDownloadList and DownloadVariableMetadata * feat(downloadVariableMetadataButton): Replaced test data with constant to improve maintainability, ran linter * feat(downloadVariableMetadataButton): Renamed variable showList with resourceFieldValueIsValid to increase clarity, updated unit tests and ran linter * feat(downloadVariableMetadataButton): Updated initial declaration of value for Data Dictionary to an empty object casted to a Data Dictionary type to improve code clarity, removed unneeded console log statement * feat(downloadVariableMetadataButton):removed unneeded console log statement * feat(downloadVariableMetadataButton):removed unintentionally changed file * feat(downloadVariableMetadataButton): Added additional data type checks to CheckHealLoginNeeded to avoid error introduced by function being called with an array containing an empty object * feat individual download button * update redirection, style and popover update * fix tests * fix test * update css * add comment * fix grid gutter * use button title from config * fix test * rename variable * renaming variables and functions * fix * reorg code and add tests * fix redirect to disco detail with slash * disable button base on user access * update test * fix typo * address review comments --------- Co-authored-by: Jarvis Raymond <[email protected]> Co-authored-by: Jarvis <[email protected]>
1 parent db53b47 commit f749b9c

24 files changed

+578
-168
lines changed

src/Discovery/Discovery.css

+4
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,10 @@
370370
max-width: 500px;
371371
}
372372

373+
.discovery-detail-popover {
374+
max-width: 250px;
375+
}
376+
373377
.discovery-popover__text {
374378
color: var(--g3-color__titanium);
375379
font-size: 0.625rem;

src/Discovery/DiscoveryDetails/DataDownloadList/ActionButtons/ActionButtons.tsx

+107-67
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,53 @@
11
import React, { useEffect, useState } from 'react';
2+
import { RouteComponentProps } from 'react-router-dom';
23
import {
34
Col, Row, Button, Popover,
45
} from 'antd';
5-
import { useHistory, useLocation } from 'react-router-dom';
66
import { DiscoveryConfig } from '../../../DiscoveryConfig';
77
import { DiscoveryResource } from '../../../Discovery';
8-
import { INITIAL_DOWNLOAD_STATUS } from './DownloadUtils/Constants';
98
import UseHandleRedirectToLoginClick from './DownloadUtils/UseHandleRedirectToLoginClick';
109
import HandleDownloadManifestClick from './DownloadUtils/HandleDownloadManifestClick';
11-
import DownloadModal from './DownloadModal/DownloadModal';
12-
import DownloadAllFiles from './DownloadUtils/DownloadAllFiles/DownloadAllFiles';
10+
import DownloadDataFiles from './DownloadUtils/DownloadDataFiles/DownloadDataFiles';
1311
import DownloadJsonFile from './DownloadUtils/DownloadJsonFile';
1412
import DownloadVariableMetadata from './DownloadUtils/DownloadVariableMetadata/DownloadVariableMetadata';
1513
import './ActionButtons.css';
1614
import DownloadDataDictionaryInfo from './DownloadUtils/DownloadDataDictionaryInfo';
1715
import DataDictionaries from '../Interfaces/DataDictionaries';
16+
import DownloadStatus from '../Interfaces/DownloadStatus';
1817

1918
interface ActionButtonsProps {
2019
isUserLoggedIn: boolean;
20+
userHasAccessToDownload: boolean;
2121
discoveryConfig: DiscoveryConfig;
2222
resourceInfo: DiscoveryResource;
23-
healLoginNeeded: boolean;
23+
missingRequiredIdentityProviders: string[];
2424
noData: boolean;
25+
downloadStatus: DownloadStatus;
26+
setDownloadStatus: React.Dispatch<React.SetStateAction<DownloadStatus>>;
27+
history: RouteComponentProps['history'],
28+
location: RouteComponentProps['location'],
2529
}
2630

2731
const ActionButtons = ({
2832
isUserLoggedIn,
33+
userHasAccessToDownload,
2934
discoveryConfig,
3035
resourceInfo,
31-
healLoginNeeded,
36+
missingRequiredIdentityProviders,
3237
noData,
38+
downloadStatus,
39+
setDownloadStatus,
40+
history,
41+
location,
3342
}: ActionButtonsProps): JSX.Element => {
34-
const [downloadStatus, setDownloadStatus] = useState(INITIAL_DOWNLOAD_STATUS);
35-
const { HandleRedirectToLoginClick } = UseHandleRedirectToLoginClick();
36-
const history = useHistory();
37-
const location = useLocation();
43+
const { HandleRedirectFromDiscoveryDetailsToLoginClick } = UseHandleRedirectToLoginClick();
3844

3945
const studyMetadataFieldNameReference: string | undefined = discoveryConfig?.features.exportToWorkspace.studyMetadataFieldName;
40-
const manifestFieldName: string | undefined = discoveryConfig?.features.exportToWorkspace.manifestFieldName;
46+
const manifestFieldName: string = discoveryConfig?.features.exportToWorkspace.manifestFieldName || '';
47+
let fileManifest: any[] = [];
48+
if (manifestFieldName) {
49+
fileManifest = resourceInfo?.[manifestFieldName] || [];
50+
}
4151
const showDownloadStudyLevelMetadataButton = Boolean(
4252
discoveryConfig?.features.exportToWorkspace.enableDownloadStudyMetadata
4353
&& studyMetadataFieldNameReference
@@ -52,16 +62,21 @@ const ActionButtons = ({
5262
const verifyExternalLoginsNeeded = Boolean(
5363
discoveryConfig?.features.exportToWorkspace.verifyExternalLogins,
5464
);
55-
5665
const showDownloadVariableMetadataButton = Boolean(
5766
discoveryConfig.features.exportToWorkspace.variableMetadataFieldName
5867
&& discoveryConfig.features.exportToWorkspace.enableDownloadVariableMetadata,
5968
);
69+
6070
const [dataDictionaryInfo, setDataDictionaryInfo] = useState({
6171
noVariableLevelMetadata: true,
6272
dataDictionaries: {} as DataDictionaries,
6373
});
6474

75+
let uid = '';
76+
if (resourceInfo) {
77+
uid = resourceInfo[discoveryConfig.minimalFieldMapping.uid] || '';
78+
}
79+
6580
useEffect(() => {
6681
DownloadDataDictionaryInfo(
6782
discoveryConfig,
@@ -71,23 +86,53 @@ const ActionButtons = ({
7186
);
7287
}, [resourceInfo]);
7388

74-
const ConditionalPopover = ({ children }) => (noData ? (
75-
<Popover title={'This file is not available for the selected study'}>
76-
{children}
77-
</Popover>
78-
) : (
79-
children
80-
));
89+
const ConditionalPopover = ({ children }) => {
90+
if (noData) {
91+
return (
92+
<Popover content={'This file is not available for the selected study'}>
93+
{children}
94+
</Popover>
95+
);
96+
}
97+
if (!userHasAccessToDownload) {
98+
return (
99+
<Popover content={'You don\'t have access to this data'}>
100+
{children}
101+
</Popover>
102+
);
103+
}
104+
if (missingRequiredIdentityProviders.length) {
105+
const onlyInCommonMsg = missingRequiredIdentityProviders.length > 1 ? `Data selection requires [${missingRequiredIdentityProviders.join(', ')}] credentials to access. Please change selection to only need one set of credentials and log in using appropriate credentials`
106+
: `This dataset is only accessible to users who have authenticated via ${missingRequiredIdentityProviders}. Please log in using the ${missingRequiredIdentityProviders} option.`;
107+
return (
108+
<Popover
109+
className='discovery-detail-popover'
110+
arrowPointAtCenter
111+
overlayInnerStyle={{ maxWidth: '300px' }}
112+
content={(
113+
<React.Fragment>
114+
{onlyInCommonMsg}
115+
</React.Fragment>
116+
)}
117+
>
118+
{children}
119+
</Popover>
120+
);
121+
}
122+
return children;
123+
};
81124

125+
const isHEALLoginNeeded = Boolean(missingRequiredIdentityProviders.length);
126+
const downloadManifestButtonText = discoveryConfig.features?.exportToWorkspace?.downloadManifestButtonText || 'Download Manifest';
82127
return (
83128
<div className='discovery-modal_buttons-row' data-testid='actionButtons'>
84-
<DownloadModal
85-
downloadStatus={downloadStatus}
86-
setDownloadStatus={setDownloadStatus}
87-
/>
88-
<Row className='row'>
129+
<Row
130+
className='row'
131+
justify='space-between'
132+
gutter={[8, 8]}
133+
>
89134
{showDownloadVariableMetadataButton && (
90-
<Col flex='1 0 auto'>
135+
<Col>
91136
<Button
92137
className='discovery-action-bar-button'
93138
disabled={Boolean(
@@ -109,7 +154,7 @@ const ActionButtons = ({
109154
</Col>
110155
)}
111156
{showDownloadStudyLevelMetadataButton && (
112-
<Col flex='1 0 auto'>
157+
<Col>
113158
<ConditionalPopover>
114159
<Button
115160
className='discovery-action-bar-button'
@@ -127,80 +172,75 @@ const ActionButtons = ({
127172
</Col>
128173
)}
129174
{showDownloadFileManifestButtons && (
130-
<Col flex='1 0 auto'>
131-
{isUserLoggedIn && !healLoginNeeded && (
175+
<Col>
176+
{isUserLoggedIn && !isHEALLoginNeeded && (
132177
<ConditionalPopover>
133178
<Button
134179
className='discovery-action-bar-button'
135-
disabled={Boolean(noData || downloadStatus.inProgress)}
180+
disabled={Boolean(noData || downloadStatus.inProgress || !userHasAccessToDownload)}
136181
onClick={() => {
137182
HandleDownloadManifestClick(
138183
discoveryConfig,
139184
[resourceInfo],
140-
healLoginNeeded,
185+
missingRequiredIdentityProviders,
141186
);
142187
}}
143188
>
144-
Download File Manifest
189+
{downloadManifestButtonText}
145190
</Button>
146191
</ConditionalPopover>
147192
)}
148-
{(!isUserLoggedIn || healLoginNeeded) && (
149-
<Button
150-
className='discovery-action-bar-button'
151-
disabled={Boolean(noData || downloadStatus.inProgress)}
152-
onClick={() => {
153-
HandleRedirectToLoginClick(
154-
resourceInfo,
155-
discoveryConfig,
156-
'manifest',
157-
);
158-
}}
159-
>
193+
{(!isUserLoggedIn || isHEALLoginNeeded) && (
194+
<ConditionalPopover>
195+
<Button
196+
className='discovery-action-bar-button'
197+
disabled={Boolean(noData || downloadStatus.inProgress)}
198+
onClick={() => {
199+
HandleRedirectFromDiscoveryDetailsToLoginClick(uid);
200+
}}
201+
>
160202
Login to
161-
<br /> Download Manifest
162-
</Button>
203+
<br /> {downloadManifestButtonText}
204+
</Button>
205+
</ConditionalPopover>
163206
)}
164207
</Col>
165208
)}
166209
{showDownloadAllFilesButtons && (
167-
<Col flex='1 0 auto'>
168-
{isUserLoggedIn && !healLoginNeeded && (
210+
<Col>
211+
{isUserLoggedIn && !isHEALLoginNeeded && (
169212
<ConditionalPopover>
170213
<Button
171214
className='discovery-action-bar-button'
172-
disabled={Boolean(noData || downloadStatus.inProgress)}
173-
loading={downloadStatus.inProgress === 'DownloadAllFiles'}
174-
onClick={() => DownloadAllFiles(
175-
resourceInfo,
215+
disabled={Boolean(noData || downloadStatus.inProgress || !userHasAccessToDownload)}
216+
loading={downloadStatus.inProgress === 'DownloadDataFiles'}
217+
onClick={() => DownloadDataFiles(
176218
downloadStatus,
177219
setDownloadStatus,
178220
history,
179221
location,
180-
healLoginNeeded,
222+
missingRequiredIdentityProviders,
181223
verifyExternalLoginsNeeded,
182-
manifestFieldName,
224+
fileManifest,
183225
)}
184226
>
185227
Download All Files
186228
</Button>
187229
</ConditionalPopover>
188230
)}
189-
{(!isUserLoggedIn || healLoginNeeded) && (
190-
<Button
191-
className='discovery-action-bar-button'
192-
disabled={Boolean(noData || downloadStatus.inProgress)}
193-
onClick={() => {
194-
HandleRedirectToLoginClick(
195-
resourceInfo,
196-
discoveryConfig,
197-
'download',
198-
);
199-
}}
200-
>
231+
{(!isUserLoggedIn || isHEALLoginNeeded) && (
232+
<ConditionalPopover>
233+
<Button
234+
className='discovery-action-bar-button'
235+
disabled={Boolean(noData || downloadStatus.inProgress)}
236+
onClick={() => {
237+
HandleRedirectFromDiscoveryDetailsToLoginClick(uid);
238+
}}
239+
>
201240
Login to
202-
<br /> Download All Files
203-
</Button>
241+
<br /> Download All Files
242+
</Button>
243+
</ConditionalPopover>
204244
)}
205245
</Col>
206246
)}

0 commit comments

Comments
 (0)