From 8ee9048b00703e72dc95d4a2233409a2f49ae4ce Mon Sep 17 00:00:00 2001 From: vilarodr Date: Tue, 19 Mar 2024 15:55:37 +0100 Subject: [PATCH] More alerts and MAXFILES validation --- .../components/data-files-input.ts | 18 ++-- src/index-renderer/components/user-dataset.ts | 1 + src/main/controllers/upload-controller.ts | 25 +++-- src/main/controllers/user-controller.ts | 2 +- src/main/interfaces/repository-interface.ts | 13 +++ src/main/main.ts | 98 +++++++++++++------ 6 files changed, 109 insertions(+), 48 deletions(-) diff --git a/src/index-renderer/components/data-files-input.ts b/src/index-renderer/components/data-files-input.ts index 4b54959..9cda533 100755 --- a/src/index-renderer/components/data-files-input.ts +++ b/src/index-renderer/components/data-files-input.ts @@ -49,7 +49,6 @@ export class DataFilesInput extends Cmp { } configure():void { - this.MAXFILES = 2000; const regexp = /[:;#<>"\*\?\/\|]/ ; const regexp2 = /[^A-Za-z0-9_ .\/\-]+/ ; @@ -66,13 +65,12 @@ export class DataFilesInput extends Cmp { this.backdropElement.style.visibility = "hidden"; ipcRenderer.on('DO_FILE_SELECT', (event: Event, folder: string, filesCount: number) => { - if (this.isDSSelected) { + if (this.isDSSelected()) { this.filesButtonElement.disabled = false; } else { this.filesButtonElement.disabled = true; } - //dataFiles.clear(); - this.remainingFiles = this.MAXFILES - filesCount; + dataFiles.clear(); }) ipcRenderer.on('FILE_SELECT_DONE', (event: Event, enteredFiles: FileInfo[]) => { @@ -87,7 +85,7 @@ export class DataFilesInput extends Cmp { } }); if (dataFiles.length()) { - if (this.isDSSelected) { + if (this.isDSSelected()) { this.submitButtonElement.disabled = false; } this.resetButtonElement.disabled = false; @@ -96,17 +94,17 @@ export class DataFilesInput extends Cmp { }) ipcRenderer.on('DO_FOLDER_SELECT', (event: Event, folder: string, filesCount: number) => { - if (this.isDSSelected) { + if (this.isDSSelected()) { this.folderButtonElement.disabled = false; } else { this.folderButtonElement.disabled = true; } - this.remainingFiles = this.MAXFILES - filesCount; + dataFiles.clear(); }) ipcRenderer.on('FOLDER_SELECT_DONE', (event: Event, enteredFiles: FileInfo[]) => { this.clearView(); - if (enteredFiles.length) { + if (enteredFiles.length) {; let lastPath = ''; const files = Array.from(enteredFiles); enteredFiles.forEach((file) => { @@ -124,7 +122,7 @@ export class DataFilesInput extends Cmp { } }); if (dataFiles.length()) { - if (this.isDSSelected) { + if (this.isDSSelected()) { this.submitButtonElement.disabled = false; } this.resetButtonElement.disabled = false; @@ -260,4 +258,4 @@ export class DataFilesInput extends Cmp { this.modalElement.classList.remove("show"); } -} +} \ No newline at end of file diff --git a/src/index-renderer/components/user-dataset.ts b/src/index-renderer/components/user-dataset.ts index 9faf500..7782300 100755 --- a/src/index-renderer/components/user-dataset.ts +++ b/src/index-renderer/components/user-dataset.ts @@ -83,6 +83,7 @@ export class UserDataset extends Cmp { private refreshHandler(event: Event) { event.preventDefault(); + (document.getElementById("upload") as HTMLButtonElement).disabled = true; ipcRenderer.send('DO_DS_LIST_REFRESH'); } diff --git a/src/main/controllers/upload-controller.ts b/src/main/controllers/upload-controller.ts index 9394385..55ddda3 100755 --- a/src/main/controllers/upload-controller.ts +++ b/src/main/controllers/upload-controller.ts @@ -1,7 +1,7 @@ import { calcChecksum, getUploadUrls, uploadSinglepartToStore, uploadMultipartToStore, completeMultipartUpload, abortMultipartUpload, addMultipleFilesToDataset } from '../services/upload-service'; import { FileInfo } from '../../model/file-info'; -import { IpcMainEvent, Notification } from "electron"; +import { IpcMainEvent, Notification, dialog } from "electron"; import { Observable } from 'rxjs'; let abort = false; @@ -49,7 +49,7 @@ export const filesTransfer = (event: IpcMainEvent, persistentId: string, items: } } catch (err) { const title = `Error uploading file ${itemInfo.name} to store.` - new Notification({ title: title, body: err }).show(); + alert(title, err); event.sender.send('actionFor' + itemInfo.id.toString(), 'fail', 0); itemsFailed++; continue; @@ -84,7 +84,7 @@ export const filesTransfer = (event: IpcMainEvent, persistentId: string, items: } } catch (err) { const title = `Error uploading file ${itemInfo.name} to store.` - new Notification({ title: title, body: err }).show(); + alert(title, err); event.sender.send('actionFor' + itemInfo.id.toString(), 'fail', 0); itemsFailed++; continue; @@ -104,7 +104,7 @@ export const filesTransfer = (event: IpcMainEvent, persistentId: string, items: } } catch (err) { const title = `Error uploading part of file ${itemInfo.name} to store.` - new Notification({ title: title, body: err }).show(); + alert(title, err); throw new Error(title + '\n' + err); } const responseHeaders = JSON.parse(JSON.stringify(uploadToStoreResponse.headers)); @@ -125,7 +125,7 @@ export const filesTransfer = (event: IpcMainEvent, persistentId: string, items: }; } catch (err) { const title = 'Error aborting multipart upload.'; - new Notification({ title: title, body: err }).show(); + alert(title, err); throw new Error(title + '\n' + err); } } else { @@ -136,7 +136,7 @@ export const filesTransfer = (event: IpcMainEvent, persistentId: string, items: } } catch (err) { const title = 'Error completing multipart upload to store.'; - new Notification({ title: title, body: err }).show(); + alert(title, err); throw new Error(title + '\n' + err); } itemInfo.etag = await calcChecksum(itemInfo); @@ -177,3 +177,16 @@ export const filesTransfer = (event: IpcMainEvent, persistentId: string, items: } ) } + +function alert(message: string, detail: string) { + console.log(message); + new Notification({ title: 'Upverse upload alert', body: message }).show(); + const options = { + buttons: ['OK'], + defaultId: 0, + title: 'Upverse upload alert', + message: message, + detail: detail, + }; + dialog.showMessageBox(null, options); + } diff --git a/src/main/controllers/user-controller.ts b/src/main/controllers/user-controller.ts index a7b54d2..c4f2a37 100755 --- a/src/main/controllers/user-controller.ts +++ b/src/main/controllers/user-controller.ts @@ -37,7 +37,7 @@ export const getUserDatasets = () => { selectedPage++; await getMyDatasetsPage(selectedPage).then((responseBody: Datasets) => { responseBody.data.items.forEach((item: Item) => { - const datasetInfo = new DatasetInfo(item.name, item.global_id, responseBody.data.dvobject_counts.files_count); + const datasetInfo = new DatasetInfo(item.name, item.global_id, item.fileCount); datasetList.push(Object.assign({}, datasetInfo)); }) nextPage = responseBody.data.pagination.nextPageNumber; diff --git a/src/main/interfaces/repository-interface.ts b/src/main/interfaces/repository-interface.ts index a9c41c9..9c3ee7f 100644 --- a/src/main/interfaces/repository-interface.ts +++ b/src/main/interfaces/repository-interface.ts @@ -28,10 +28,22 @@ export interface Item { description: string; published_at: Date; citationHtml: string; + identifier_of_dataverse: string; + name_of_dataverse: string; citation: string; matches: any[]; score: number; entity_id: number; + storageIdentifier: string; + subjects: any[]; + fileCount: number; + versionId: number; + versionState: string; + majorVersion: number; + minorVersion: number; + createdAt: Date; + updatedAt: Date; + contacts: {}[]; api_url: string; authors: string[]; publication_statuses: string[]; @@ -40,6 +52,7 @@ export interface Item { is_unpublished_state: boolean; is_published: boolean; is_deaccesioned: boolean; + is_valid: boolean; date_to_display_on_card: string; parentId: string; parentName: string; diff --git a/src/main/main.ts b/src/main/main.ts index 0fbb731..1c72ff1 100755 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -14,6 +14,8 @@ import { UserInfo } from "../model/user-info"; let mainWindow: BrowserWindow; let settingsWindow: BrowserWindow; +const MAXFILES = 2000; + function createMainWindow() { mainWindow = new BrowserWindow({ title: "Research Data Uploader", @@ -34,7 +36,7 @@ function createMainWindow() { mainWindow.loadURL(indexPath); // for Debugging - //mainWindow.webContents.openDevTools(); + mainWindow.webContents.openDevTools(); mainWindow.on('close', function () { app.quit(); @@ -62,7 +64,7 @@ function createSettingsWindow() { settingsWindow.show(); // for Debugging - //settingsWindow.webContents.openDevTools(); + // settingsWindow.webContents.openDevTools(); } function createMenu() { @@ -97,6 +99,18 @@ function createMenu() { Menu.setApplicationMenu(menu); } +function alert(message: string) { + console.log(message); + new Notification({ title: 'Upverse alert', body: message }).show(); + const options = { + buttons: ['OK'], + defaultId: 0, + title: 'Upverse alert', + message: message, + }; + dialog.showMessageBox(null, options); +} + app.on("ready", () => { const userData = app.getPath("userData"); netLog.startLogging(path.join(userData, "net-log")); @@ -106,14 +120,12 @@ app.on("ready", () => { try { new Settings(); - if (Settings.loadSettings()) { - new Notification({ title: 'Upverse', body: 'Settings successfully read' }).show(); - } else { - new Notification({ title: 'Upverse', body: 'Please, set your Settings'}).show(); + if (!Settings.loadSettings()) { + alert('Please, set your Settings'); createSettingsWindow(); } } catch (err) { - new Notification({ title: 'Upverse !!!', body: err.message }).show(); + alert(err.message); } app.on("activate", function () { @@ -138,7 +150,7 @@ app.on("ready", () => { }); } } catch (err) { - new Notification({ title: 'Upverse Settings', body: err.message }).show(); + alert(err.message); } }); @@ -173,7 +185,7 @@ ipcMain.on('DO_TEST_CONN', async (event: IpcMainEvent, givenSettings: string[]) }); } else throw new Error('Please, check Settings'); } catch (error) { - new Notification({ title: 'Upverse Settings', body: error.message }).show(); + alert(error.message); } }) @@ -184,15 +196,15 @@ ipcMain.on('DO_SAVE_SETTINGS', (event: IpcMainEvent, givenSettings: string[]) => process.env.dv_base_uri = givenSettings[1]; if (Settings.save()) { event.reply('SAVE_SETTINGS_SUCCESS'); - new Notification({ title: 'Upverse', body: 'Settings successfully saved to disk' }).show(); + alert('Settings successfully saved to disk'); } else { event.reply('SAVE_SETTINGS_FAILED'); - new Notification({ title: 'Upverse', body: 'Error saving settings ' }).show(); + alert('Error saving settings '); } } else throw new Error('Please, enter values'); } catch (error) { - new Notification({ title: 'Upverse Settings', body: error.message }).show(); + alert('Upverse Settings'); } }) @@ -206,10 +218,12 @@ ipcMain.on('DS_SELECT_DONE', (event: IpcMainEvent, dataset: [DatasetInfo]) => { ipcMain.on('DO_DS_LIST_REFRESH', async (event: IpcMainEvent) => { try { await getDatasets().then((datasetList: DatasetInfo[]) => { + process.env.dest_dataset = null; + process.env.files_loaded = null; mainWindow.webContents.send('DO_DS_SELECT', datasetList); }); } catch (error) { - new Notification({ title: 'Upverse datasets', body: error.message }).show(); + alert(error.message); } }) @@ -222,27 +236,34 @@ ipcMain.on('DO_CLEAR_SELECTED', (event: IpcMainEvent) => { }) ipcMain.on('DO_FILE_SELECT', (event: IpcMainEvent) => { - try { dialog.showOpenDialog(mainWindow, { properties: ['openFile', 'multiSelections'], buttonLabel: "Select" }).then(async result => { + if (result.filePaths.length > ( process.env.files_loaded ? (MAXFILES - Number(process.env.files_loaded.valueOf())) : MAXFILES )) { + alert("Files limit reached. Please, select less files"); + event.reply('FILE_SELECT_FAILED', ''); + return + }; let fileInfoList: FileInfo[] = []; for (const file of result.filePaths) { fileInfoList.push(getFileInfo(file, fileInfoList.length)); } - if (fileInfoList.length) event.reply('FILE_SELECT_DONE', fileInfoList); + if (fileInfoList.length) { + event.reply('FILE_SELECT_DONE', fileInfoList); + } else { + event.reply('FILE_SELECT_FAILED', ''); + } + }).catch (error => { + alert(error.message); + event.reply('FILE_SELECT_FAILED', ''); }); - } catch (error) { - new Notification({ title: 'Upverse File Explorer', body: 'Open file explorer failed' }); - event.reply('FILE_SELECT_FAILED', ''); - } }) ipcMain.on('DO_FOLDER_SELECT', (event: IpcMainEvent) => { - try { dialog.showOpenDialog(mainWindow, { properties: ['openDirectory'], buttonLabel: "Select" }).then(async result => { + console.log("result: " + result.filePaths.length); if (result.filePaths.length ) { let fileList: string[] = []; for (const filePath of result.filePaths) { @@ -250,6 +271,17 @@ ipcMain.on('DO_FOLDER_SELECT', (event: IpcMainEvent) => { fileList = fileList.concat(files); } } + if ( fileList.length > ( process.env.files_loaded ? (MAXFILES - Number(process.env.files_loaded.valueOf())) : MAXFILES ) ) { + alert("Files limit reached. Please, select less files"); + event.reply('FOLDER_SELECT_FAILED', ''); + return; + } + if ( fileList.length === 0 ) { + alert("Please, select a non-empty folder"); + event.reply('FOLDER_SELECT_FAILED', ''); + return; + } + let fileInfoList: FileInfo[] = []; const currentBasePath = path.basename(result.filePaths[0]); @@ -258,23 +290,25 @@ ipcMain.on('DO_FOLDER_SELECT', (event: IpcMainEvent) => { uploadPath = path.join(currentBasePath, uploadPath); fileInfoList.push(getFileInfo(file, fileInfoList.length, uploadPath)); } - if (fileInfoList.length) { + if ( fileInfoList.length ) { event.reply('FOLDER_SELECT_DONE', fileInfoList); - } else new Notification({ title: 'Upverse File Explorer', body: "Please, select a non empty folder" }).show(); + } + } else { + event.reply('FOLDER_SELECT_FAILED', ''); } + }).catch (error => { + alert(error.message); + event.reply('FOLDER_SELECT_FAILED', ''); }); - } catch (error) { - new Notification({ title: 'Upverse File Explorer', body: error.message }).show(); - event.reply('FOLDER_SELECT_FAILED', ''); - } - }) ipcMain.on('DO_UPLOAD', async (event: IpcMainEvent, fileInfoList: FileInfo[]) => { if (!fileInfoList.length) { - new Notification({ title: 'Upverse Upload Failed!', body: 'Nothing selected to Upload' }).show(); + alert('Nothing selected to Upload'); } else if (!process.env.dest_dataset) { - new Notification({ title: 'Upverse Upload Failed!', body: 'No destination Dataset selected' }).show(); + alert('No destination Dataset selected'); + } else if (fileInfoList.length > ( MAXFILES - Number(process.env.files_loaded.valueOf()) ) ) { + alert('Files number limit for this Dataset exceeded'); } else { try { await transferFiles(event, process.env.dest_dataset, fileInfoList).then((result: Record) => { @@ -283,7 +317,7 @@ ipcMain.on('DO_UPLOAD', async (event: IpcMainEvent, fileInfoList: FileInfo[]) => throw error; }) } catch (error) { - new Notification({ title: 'Upverse Upload Failed!', body: error.message }).show(); + alert('error.message'); event.reply('UPLOAD_FAILED', error.message); } } @@ -294,7 +328,7 @@ ipcMain.on('DO_ABORT', (event: IpcMainEvent) => { upload_controller.setAbort.subscribe(); event.reply('DO_LIST_CLEAR', ''); } catch (error) { - new Notification({ title: 'Upload', body: 'Upload aborted' }); + alert('Upload aborted'); event.reply('UPLOAD_FAILED', ''); } }); @@ -384,3 +418,5 @@ const getFileInfo = (file: string, id: number, uploadPath?: string): FileInfo => new Date(stats.mtime) ); }; + +