From c26680fd7399e8e1fb5e3c10a3f72f592d59e370 Mon Sep 17 00:00:00 2001 From: Birudo un Date: Mon, 18 Mar 2024 20:29:53 +0800 Subject: feat: support skipping already import dictionaries (#769) --- ext/js/dictionary/dictionary-importer.js | 5 ++++- ext/js/pages/settings/dictionary-import-controller.js | 13 ++++++++++--- test/database.test.js | 14 +++++++++----- types/ext/dictionary-importer.d.ts | 2 +- types/ext/dictionary-worker.d.ts | 4 ++-- 5 files changed, 26 insertions(+), 12 deletions(-) diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index 16998a8f..310b2ec1 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -106,7 +106,10 @@ export class DictionaryImporter { // Verify database is not already imported if (await dictionaryDatabase.dictionaryExists(dictionaryTitle)) { - throw new Error('Dictionary is already imported'); + return { + errors: [new Error(`Dictionary ${dictionaryTitle} is already imported, skipped it.`)], + result: null + }; } // Load schemas diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js index 64d94a52..f63eb49e 100644 --- a/ext/js/pages/settings/dictionary-import-controller.js +++ b/ext/js/pages/settings/dictionary-import-controller.js @@ -149,6 +149,8 @@ export class DictionaryImportController { const prevention = this._preventPageExit(); + /** @type {Error[]} */ + let errors = []; try { this._setModifying(true); this._hideErrors(); @@ -196,12 +198,12 @@ export class DictionaryImportController { count: 0 }); if (statusFooter !== null) { statusFooter.setTaskActive(progressSelector, true); } - - await this._importDictionary(files[i], importDetails, onProgress); + errors = [...errors, ...(await this._importDictionary(files[i], importDetails, onProgress) ?? [])]; } } catch (error) { - this._showErrors([toError(error)]); + errors.push(toError(error)); } finally { + this._showErrors(errors); prevention.end(); for (const progress of progressContainers) { progress.hidden = true; } if (statusFooter !== null) { statusFooter.setTaskActive(progressSelector, false); } @@ -231,10 +233,15 @@ export class DictionaryImportController { * @param {File} file * @param {import('dictionary-importer').ImportDetails} importDetails * @param {import('dictionary-worker').ImportProgressCallback} onProgress + * @returns {Promise} */ async _importDictionary(file, importDetails, onProgress) { const archiveContent = await this._readFile(file); const {result, errors} = await new DictionaryWorker().importDictionary(archiveContent, importDetails, onProgress); + if (!result) { + return errors; + } + void this._settingsController.application.api.triggerDatabaseUpdated('dictionary', 'import'); const errors2 = await this._addDictionarySettings(result.sequenced, result.title); diff --git a/test/database.test.js b/test/database.test.js index a930d68d..9d57ecab 100644 --- a/test/database.test.js +++ b/test/database.test.js @@ -121,7 +121,7 @@ describe('Database', () => { // Setup database const dictionaryDatabase = new DictionaryDatabase(); /** @type {import('dictionary-importer').ImportDetails} */ - const detaultImportDetails = {prefixWildcardsSupported: false}; + const defaultImportDetails = {prefixWildcardsSupported: false}; // Database not open await expect.soft(dictionaryDatabase.deleteDictionary(title, 1000, () => {})).rejects.toThrow('Database not open'); @@ -135,17 +135,17 @@ describe('Database', () => { await expect.soft(dictionaryDatabase.findTagForTitle('tag', title)).rejects.toThrow('Database not open'); await expect.soft(dictionaryDatabase.getDictionaryInfo()).rejects.toThrow('Database not open'); await expect.soft(dictionaryDatabase.getDictionaryCounts([...titles.keys()], true)).rejects.toThrow('Database not open'); - await expect.soft(createDictionaryImporter(expect).importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails)).rejects.toThrow('Database is not ready'); + await expect.soft(createDictionaryImporter(expect).importDictionary(dictionaryDatabase, testDictionarySource, defaultImportDetails)).rejects.toThrow('Database is not ready'); await dictionaryDatabase.prepare(); // Already prepared await expect.soft(dictionaryDatabase.prepare()).rejects.toThrow('Database already open'); - await createDictionaryImporter(expect).importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails); + await createDictionaryImporter(expect).importDictionary(dictionaryDatabase, testDictionarySource, defaultImportDetails); // Dictionary already imported - await expect.soft(createDictionaryImporter(expect).importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails)).rejects.toThrow('Dictionary is already imported'); + expect.soft(await createDictionaryImporter(expect).importDictionary(dictionaryDatabase, testDictionarySource, defaultImportDetails)).toEqual({result: null, errors: [new Error('Dictionary Test Dictionary is already imported, skipped it.')]}); await dictionaryDatabase.close(); }); @@ -200,7 +200,11 @@ describe('Database', () => { testDictionarySource, {prefixWildcardsSupported: true} ); - importDictionaryResult.importDate = fakeImportDate; + + if (importDictionaryResult) { + importDictionaryResult.importDate = fakeImportDate; + } + expect.soft(importDictionaryErrors).toStrictEqual([]); expect.soft(importDictionaryResult).toStrictEqual(testData.expectedSummary); expect.soft(progressEvent1).toBe(true); diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts index 17bd1bb4..3a320f96 100644 --- a/types/ext/dictionary-importer.d.ts +++ b/types/ext/dictionary-importer.d.ts @@ -45,7 +45,7 @@ export type ProgressData = { }; export type ImportResult = { - result: Summary; + result: Summary | null; errors: Error[]; }; diff --git a/types/ext/dictionary-worker.d.ts b/types/ext/dictionary-worker.d.ts index f10ed4a5..215ff94c 100644 --- a/types/ext/dictionary-worker.d.ts +++ b/types/ext/dictionary-worker.d.ts @@ -59,12 +59,12 @@ export type MessageGetImageDetailsParams = { export type MessageData = MessageCompleteData | MessageProgressData | MessageGetImageDetailsData; export type MessageCompleteResultSerialized = { - result: DictionaryImporter.Summary; + result: DictionaryImporter.Summary | null; errors: Core.SerializedError[]; }; export type MessageCompleteResult = { - result: DictionaryImporter.Summary; + result: DictionaryImporter.Summary | null; errors: Error[]; }; -- cgit v1.2.3