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

Added File Upload Capability and Loading logic to confirmation screen #55

Open
wants to merge 18 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
53 changes: 45 additions & 8 deletions src/API/API_functions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,53 @@ export async function getServerRootDir() {

export async function fetchSandboxStatus() {
try {
let response = await fetch('zenodo-jupyterlab/env?env_var=ZENODO_SANDBOX');
if (response.ok) {
let data = await response.json();
return data.ZENODO_SANDBOX;
} else {
console.error('Failed to fetch sandbox status');
return null;
}
const data = await requestAPI(`zenodo-jupyterlab/env?env_var=${encodeURIComponent('ZENODO_SANDBOX')}`, {
method: 'GET'
});
return(data.json().ZENODO_SANDBOX);
} catch (error) {
console.error('Error fetching sandbox status:', error);
return null;
}
}

export async function downloadFile(recordID: string, filePath: string) {
try {
/* // Fetch the _xsrf token
const xsrfTokenResponse = await fetch('zenodo-jupyterlab/xsrf_token', {
method: 'GET',
});
const xsrfTokenData = await xsrfTokenResponse.json();
const xsrfToken = xsrfTokenData.xsrfToken; */
const start = filePath.indexOf('files/') + 'files/'.length; // Find the start index
const end = filePath.indexOf('/content'); // Find the end index
const fileName = filePath.substring(start, end);
//console.log(fileName, recordID);
const response = await requestAPI('zenodo-jupyterlab/download-file', {
method: 'POST',
body: JSON.stringify({
file_name: fileName,
record_id: recordID
}),
});

console.log(response['status']);

/* if (!response.ok) {
throw new Error(`Failed to download file: ${response.status}`);
} */

/* // Convert the response into a blob and create a download link
const blob = await response.blob();
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
a.remove(); // Remove the link after download
window.URL.revokeObjectURL(url); // Clean up URL object */
} catch {
console.error('Error downloading file:');
}
}
14 changes: 7 additions & 7 deletions src/API/handler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,18 @@ export async function requestAPI(endPoint: string, init: RequestInit): Promise<a
const settings = ServerConnection.makeSettings();
const requestUrl = URLExt.join(settings.baseUrl, endPoint);

const csrfToken = await getCsrfToken();
/* const csrfToken = await getCsrfToken();
if (!csrfToken) {
throw new Error('CSRF token not available');
}
const headers = {
} */
/* const headers = {
'Content-Type': 'application/json',
'X-XSRFToken': csrfToken // Adjust header name as per your server configuration
};
}; */

let response: Response;
try {
response = await fetch(requestUrl, { ...init, headers});
response = await ServerConnection.makeRequest(requestUrl, init, settings);

if (!response.ok) {
throw new ResponseError(response, `Response error: ${await response.text()}`);
Expand All @@ -57,7 +57,7 @@ export async function requestAPI(endPoint: string, init: RequestInit): Promise<a
}
}

async function getCsrfToken(): Promise<string | undefined> {
/* async function getCsrfToken(): Promise<string | undefined> {
try {
const response = await fetch('/zenodo-jupyterlab/xsrf_token'); // Replace with your actual endpoint
if (!response.ok) {
Expand All @@ -69,4 +69,4 @@ async function getCsrfToken(): Promise<string | undefined> {
console.error('Failed to fetch CSRF token:', error);
return undefined;
}
}
} */
19 changes: 11 additions & 8 deletions src/components/FileBrowser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faFolder, faFile } from '@fortawesome/free-solid-svg-icons';
import { getServerRootDir } from '../API/API_functions';
import { FileEntry, OnSelectFile } from './type';
import { requestAPI } from '../API/handler';

const useStyles = createUseStyles({
container: {
Expand Down Expand Up @@ -133,17 +134,19 @@ const FileBrowser: React.FC<FileBrowserProps> = ({ onSelectFile }) => {
setError('');
try {
if (!currentPath) return;

const response = await fetch(`/zenodo-jupyterlab/files?path=${encodeURIComponent(currentPath)}`);
if (response.ok) {
const data = await response.json();
setEntries(data.entries || []);
console.log(currentPath, rootPath);
const response = await requestAPI(`/zenodo-jupyterlab/files?path=${encodeURIComponent(currentPath)}`, {
method: 'GET'
});
setEntries(response.entries || []);
/* if (response.ok) {
setEntries(response.entries || []);
} else {
setError('Failed to fetch file entries.');
}
} catch (error) {
} */
} catch {
setError('Error fetching file entries.');
console.error('Error fetching file entries:', error);
console.error('Error fetching file entries:');
} finally {
setLoading(false);
}
Expand Down
13 changes: 9 additions & 4 deletions src/components/SearchPanel.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
import { searchRecords, searchCommunities, recordInformation } from '../API/API_functions';
import { searchRecords, searchCommunities, recordInformation, downloadFile } from '../API/API_functions';
import { createUseStyles } from 'react-jss';
import clsx from 'clsx';

Expand Down Expand Up @@ -313,12 +313,12 @@ const SearchWidget: React.FC = () => {
return fileName;
}

function cleanUrl(url: string): string {
/* function cleanUrl(url: string): string {
// Remove "/api" and "/content" from the URL
return url
.replace('/api', '') // Remove "/api"
.replace('/content', ''); // Remove "/content"
}
} */

return (
<div className={classes.searchWidget}>
Expand Down Expand Up @@ -407,7 +407,12 @@ const SearchWidget: React.FC = () => {
<p><strong>Files:</strong></p>
<ul>
{recordInfo.filelist.map((file: string, index: number) => (
<li key={index}><a href={cleanUrl(file)} target='_blank' rel='noopener noreferrer'>{getFileNameFromUrl(file)}</a></li>
<li key={index} style={{ display: 'flex', alignItems: 'center' }}>
<span>{getFileNameFromUrl(file)}</span>
<button onClick={() => downloadFile(result.id, file)} className={classes.button} style={{ marginLeft: '10px' }}>
📥 {/* You can replace this with an icon from a library if desired */}
</button>
</li>
))}
</ul>
</div>
Expand Down
65 changes: 61 additions & 4 deletions src/components/upload.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import { createUseStyles } from 'react-jss';
import FileBrowser from './FileBrowser';
import Confirmation from './confirmation';
import { depositUpload } from '../API/API_functions';
import { depositUpload, getEnvVariable } from '../API/API_functions';
import { UploadPayload } from './type';

const useStyles = createUseStyles({
Expand Down Expand Up @@ -236,6 +236,11 @@ const Upload: React.FC = () => {
const [isSandbox, setIsSandbox] = useState(false);
const [description, setDescription] = useState('');
const [expandedFile, setExpandedFile] = useState<string | null>(null);
const [submissionSuccess, setSubmissionSuccess] = useState(false);
const [submissionFailure, setSubmissionFailure] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [recordLink, setRecordLink] = useState('');
const [recordSandbox, setRecordSandbox] = useState(false);

useEffect(() => {
async function fetchSandboxStatus() {
Expand Down Expand Up @@ -302,6 +307,7 @@ const Upload: React.FC = () => {
};

const handleConfirm = async () => {
setIsLoading(true);
const formData = new FormData();
selectedFilePaths.forEach(filePath => formData.append('filePaths', filePath));
formData.append('title', title);
Expand All @@ -326,18 +332,45 @@ const Upload: React.FC = () => {
console.log(`${key}: ${value}`);
}
console.log(JSON.stringify(payload));
const response = await depositUpload(payload);
console.log(response['status']);
try {
const response = await depositUpload(payload);
console.log(response['status']);

if (response['status'] == "200") {
setSubmissionSuccess(true); // Mark submission as successful
setIsConfirmationVisible(false); // Hide the confirmation section
setSubmissionFailure(false);
const sandbox = await getEnvVariable('ZENODO_SANDBOX');
setRecordSandbox(sandbox['ZENODO_SANDBOX']==='true' ? true : false);
setRecordLink(response['recordID']);
} else {
setSubmissionFailure(true);
setIsConfirmationVisible(false);
setSubmissionSuccess(false);
}
} catch (error) {
console.error('Error during submission:', error);
} finally {
setIsLoading(false);
}
};

const fileName = (filePath: string) => {
const segments = filePath.split('/');
return segments.pop();
}
const removeCreator = (index: number) => {
setCreators(creators.filter((_, i) => i !== index));
};

return (
<div className={classes.container}>
{isConfirmationVisible ? (
{isLoading ? (
<div>
<h2>Submitting...</h2>
<p>Please wait while your submission is being processed.</p>
</div>
) : isConfirmationVisible ? (
<Confirmation
title={title}
resourceType={resourceType}
Expand All @@ -349,6 +382,27 @@ const Upload: React.FC = () => {
onEdit={handleEdit}
onConfirm={handleConfirm}
/>
) : submissionSuccess ? (
<div>
<h2>Submission Successful!</h2>
<p>Your information has been successfully submitted.</p>
{recordSandbox ? (
<div>
<p>Your record has not been published yet. Click here to view it: <a href={'https://sandbox.zenodo.org/uploads/' + recordLink} target='_blank'>Record</a>.</p>
</div>
)
:
(
<div>
<p>Your record has not been published yet. Click here to view it: <a href={'https://zenodo.org/uploads/' + recordLink} target='_blank'>Record</a>.</p>
</div>
)}
</div>
) : submissionFailure ? (
<div>
<h2>Submission Failure!</h2>
<p>Your information has NOT been successfully submitted. Please try again.</p>
</div>
) : (
<>
<h1 className={classes.heading}>Upload</h1>
Expand Down Expand Up @@ -459,6 +513,9 @@ const Upload: React.FC = () => {
placeholder="Affiliation"
className={classes.creatorInput}
/>
{index > 0 && (
<button type="button" onClick={() => removeCreator(index)} className={classes.removeButton}>Remove</button>
)}
</div>
))}
<button type="button" onClick={addCreator} className={classes.addButton}>Add creator</button>
Expand Down
Loading
Loading