diff --git a/src/components/ExportFinished.tsx b/src/components/ExportFinished.tsx index 2a22d718f..f2f0faf97 100644 --- a/src/components/ExportFinished.tsx +++ b/src/components/ExportFinished.tsx @@ -32,12 +32,13 @@ export default function ExportFinished(props: Props) { {props.exportStats.success} / {totalFiles} + {props.exportStats.failed>0 && {props.exportStats.failed} / {totalFiles} - + }
diff --git a/src/components/ExportModal.tsx b/src/components/ExportModal.tsx index 483d3e210..c2a080477 100644 --- a/src/components/ExportModal.tsx +++ b/src/components/ExportModal.tsx @@ -26,7 +26,18 @@ const FolderIconWrapper = styled.div` &:hover{ background-color:#444; } - `; +`; + +const ExportFolderPathContainer =styled.span` + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 200px; + + /* Beginning of string */ + direction: rtl; + text-align: left; +`; interface Props { show: boolean @@ -88,7 +99,6 @@ export default function ExportModal(props: Props) { updateExportProgress({ current: exportedFileCnt + failedFilesCnt, total: syncedFilesCnt }); const exportFileUIDs = new Set([...exportRecord.exportedFiles, ...exportRecord.failedFiles]); const unExportedFiles = localFiles.filter((file) => !exportFileUIDs.has(getFileUID(file))); - console.log(exportedFileCnt + failedFilesCnt + unExportedFiles.length, syncedFilesCnt); exportService.addFilesQueuedRecord(exportFolder, unExportedFiles); updateExportStage(ExportStage.PAUSED); } @@ -266,11 +276,13 @@ export default function ExportModal(props: Props) { {!exportFolder ? - () : + () : (<> - + {/* */} + {exportFolder} - + + {/* */} {(exportStage === ExportStage.FINISHED || exportStage === ExportStage.INIT) && ( diff --git a/src/services/billingService.ts b/src/services/billingService.ts index 89b352b9c..189e550e0 100644 --- a/src/services/billingService.ts +++ b/src/services/billingService.ts @@ -2,7 +2,7 @@ import { getEndpoint } from 'utils/common/apiUtil'; import { getStripePublishableKey, getToken } from 'utils/common/key'; import { checkConnectivity, runningInBrowser } from 'utils/common/'; import { setData, LS_KEYS } from 'utils/storage/localStorage'; -import { convertBytesToGBs } from 'utils/billingUtil'; +import { convertToHumanReadable } from 'utils/billingUtil'; import { loadStripe, Stripe } from '@stripe/stripe-js'; import { SUBSCRIPTION_VERIFICATION_ERROR } from 'utils/common/errorUtil'; import HTTPService from './HTTPService'; @@ -242,7 +242,7 @@ class billingService { 'X-Auth-Token': getToken(), }, ); - return convertBytesToGBs(response.data.usage); + return convertToHumanReadable(response.data.usage); } catch (e) { logError(e, 'error getting usage'); } diff --git a/src/services/exportService.ts b/src/services/exportService.ts index 18c67d76b..5e2c4a61b 100644 --- a/src/services/exportService.ts +++ b/src/services/exportService.ts @@ -49,6 +49,10 @@ export enum ExportType { PENDING, RETRY_FAILED } + +const ExportRecordFileName='export_status.json'; +const MetadataFolderName='metadata'; + class ExportService { ElectronAPIs: any; @@ -124,6 +128,9 @@ class ExportService { await this.ElectronAPIs.checkExistsAndCreateCollectionDir( collectionFolderPath, ); + await this.ElectronAPIs.checkExistsAndCreateCollectionDir( + `${collectionFolderPath}/${MetadataFolderName}`, + ); collectionIDMap.set(collection.id, collectionFolderPath); } for (const [index, file] of files.entries()) { @@ -137,12 +144,9 @@ class ExportService { } break; } - const uid = `${file.id}_${this.sanitizeName( - file.metadata.title, - )}`; - const filePath = `${collectionIDMap.get(file.collectionID)}/${uid}`; + const collectionPath = collectionIDMap.get(file.collectionID); try { - await this.downloadAndSave(file, filePath); + await this.downloadAndSave(file, collectionPath); await this.addFileExportRecord(dir, file, RecordType.SUCCESS); } catch (e) { await this.addFileExportRecord(dir, file, RecordType.FAILED); @@ -222,7 +226,7 @@ class ExportService { } const exportRecord = await this.getExportRecord(folder); const newRecord = { ...exportRecord, ...newData }; - await this.ElectronAPIs.setExportRecord(folder, JSON.stringify(newRecord, null, 2)); + await this.ElectronAPIs.setExportRecord(`${folder}/${ExportRecordFileName}`, JSON.stringify(newRecord, null, 2)); } catch (e) { logError(e, 'error updating Export Record'); } @@ -235,7 +239,7 @@ class ExportService { if (!folder) { folder = getData(LS_KEYS.EXPORT)?.folder; } - const recordFile = await this.ElectronAPIs.getExportRecord(folder); + const recordFile = await this.ElectronAPIs.getExportRecord(`${folder}/${ExportRecordFileName}`); if (recordFile) { return JSON.parse(recordFile); } else { @@ -246,11 +250,14 @@ class ExportService { } } - async downloadAndSave(file: File, path) { + async downloadAndSave(file: File, collectionPath:string) { + const uid = `${file.id}_${this.sanitizeName( + file.metadata.title, + )}`; const fileStream = await retryPromise(downloadManager.downloadFile(file)); - this.ElectronAPIs.saveStreamToDisk(path, fileStream); + this.ElectronAPIs.saveStreamToDisk(`${collectionPath}/${uid}`, fileStream); this.ElectronAPIs.saveFileToDisk( - `${path}.json`, + `${collectionPath}/${MetadataFolderName}/${uid}.json`, JSON.stringify(file.metadata, null, 2), ); } diff --git a/src/utils/billingUtil.ts b/src/utils/billingUtil.ts index 0c20cc7c0..b773deaa9 100644 --- a/src/utils/billingUtil.ts +++ b/src/utils/billingUtil.ts @@ -16,6 +16,14 @@ const STRIPE = 'stripe'; export function convertBytesToGBs(bytes, precision?): string { return (bytes / (1024 * 1024 * 1024)).toFixed(precision ?? 2); } + +export function convertToHumanReadable(bytes:number, precision=2): string { + const i = Math.floor(Math.log(bytes) / Math.log(1024)); + const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; + + return (bytes / Math.pow(1024, i)).toFixed(precision)+ ' ' + sizes[i]; +} + export function hasPaidSubscription(subscription?: Subscription) { subscription = subscription ?? getUserSubscription(); return ( diff --git a/src/utils/export/index.ts b/src/utils/export/index.ts index 49ee4a07c..4aa551cca 100644 --- a/src/utils/export/index.ts +++ b/src/utils/export/index.ts @@ -2,7 +2,7 @@ import { ExportRecord } from 'services/exportService'; import { File } from 'services/fileService'; -export const getFileUID = (file: File) => `${file.id}_${file.collectionID}`; +export const getFileUID = (file: File) => `${file.id}_${file.collectionID}_${file.updationTime}`; export const getExportPendingFiles = async (allFiles: File[], exportRecord: ExportRecord) => { diff --git a/src/utils/strings/englishConstants.tsx b/src/utils/strings/englishConstants.tsx index 876537af3..3c94c6fd3 100644 --- a/src/utils/strings/englishConstants.tsx +++ b/src/utils/strings/englishConstants.tsx @@ -260,7 +260,7 @@ const englishConstants = {

you have used {usage} {' '} - GB out of your {quota} + out of your {quota} {' '} GB quota

@@ -439,10 +439,10 @@ const englishConstants = { RESUME: 'resume', MINIMIZE: 'minimize', LAST_EXPORT_TIME: 'last export time', - SUCCESSFULLY_EXPORTED_FILES: 'successfully exported files', - FAILED_EXPORTED_FILES: 'failed file export', - EXPORT_AGAIN: 'export new data ', - RETRY_EXPORT_: 'retry failed files ', + SUCCESSFULLY_EXPORTED_FILES: 'successful exports', + FAILED_EXPORTED_FILES: 'failed exports', + EXPORT_AGAIN: 'resync', + RETRY_EXPORT_: 'retry failed exports', LOCAL_STORAGE_NOT_ACCESSIBLE: 'local storage not accessible', LOCAL_STORAGE_NOT_ACCESSIBLE_MESSAGE: 'your browser or an addon is blocking ente from saving data into local storage. please try loading this page after switching your browsing mode.', RETRY: 'retry',