mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Desktop, Cli: Fixes #2331: Only de-duplicate imported notebook titles when needed
This commit is contained in:
parent
d601575549
commit
eb8841379c
@ -79,6 +79,45 @@ describe('services_InteropService', function() {
|
|||||||
fieldsEqual(folder3, folder1, fieldNames);
|
fieldsEqual(folder3, folder1, fieldNames);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it('should import folders and de-duplicate titles when needed', asyncTest(async () => {
|
||||||
|
const service = new InteropService();
|
||||||
|
const folder1 = await Folder.save({ title: 'folder' });
|
||||||
|
const folder2 = await Folder.save({ title: 'folder' });
|
||||||
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
|
await service.export({ path: filePath });
|
||||||
|
|
||||||
|
await Folder.delete(folder1.id);
|
||||||
|
await Folder.delete(folder2.id);
|
||||||
|
|
||||||
|
await service.import({ path: filePath });
|
||||||
|
|
||||||
|
const allFolders = await Folder.all();
|
||||||
|
expect(allFolders.map(f => f.title).sort().join(' - ')).toBe('folder - folder (1)');
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should import folders, and only de-duplicate titles when needed', asyncTest(async () => {
|
||||||
|
const service = new InteropService();
|
||||||
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
|
const folder2 = await Folder.save({ title: 'folder2' });
|
||||||
|
const sub1 = await Folder.save({ title: 'Sub', parent_id: folder1.id });
|
||||||
|
const sub2 = await Folder.save({ title: 'Sub', parent_id: folder2.id });
|
||||||
|
const filePath = `${exportDir()}/test.jex`;
|
||||||
|
await service.export({ path: filePath });
|
||||||
|
|
||||||
|
await Folder.delete(folder1.id);
|
||||||
|
await Folder.delete(folder2.id);
|
||||||
|
|
||||||
|
await service.import({ path: filePath });
|
||||||
|
|
||||||
|
const importedFolder1 = await Folder.loadByTitle('folder1');
|
||||||
|
const importedFolder2 = await Folder.loadByTitle('folder2');
|
||||||
|
const importedSub1 = await Folder.load((await Folder.childrenIds(importedFolder1.id))[0]);
|
||||||
|
const importedSub2 = await Folder.load((await Folder.childrenIds(importedFolder2.id))[0]);
|
||||||
|
|
||||||
|
expect(importedSub1.title).toBe('Sub');
|
||||||
|
expect(importedSub2.title).toBe('Sub');
|
||||||
|
}));
|
||||||
|
|
||||||
it('should export and import folders and notes', asyncTest(async () => {
|
it('should export and import folders and notes', asyncTest(async () => {
|
||||||
const service = new InteropService();
|
const service = new InteropService();
|
||||||
const folder1 = await Folder.save({ title: 'folder1' });
|
const folder1 = await Folder.save({ title: 'folder1' });
|
||||||
|
@ -284,6 +284,21 @@ class BaseModel {
|
|||||||
return this.modelSelectOne(sql, [fieldValue]);
|
return this.modelSelectOne(sql, [fieldValue]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static loadByFields(fields, options = null) {
|
||||||
|
if (!options) options = {};
|
||||||
|
if (!('caseInsensitive' in options)) options.caseInsensitive = false;
|
||||||
|
if (!options.fields) options.fields = '*';
|
||||||
|
const whereSql = [];
|
||||||
|
const params = [];
|
||||||
|
for (const fieldName in fields) {
|
||||||
|
whereSql.push(`\`${fieldName}\` = ?`);
|
||||||
|
params.push(fields[fieldName]);
|
||||||
|
}
|
||||||
|
let sql = `SELECT ${this.db().escapeFields(options.fields)} FROM \`${this.tableName()}\` WHERE ${whereSql.join(' AND ')}`;
|
||||||
|
if (options.caseInsensitive) sql += ' COLLATE NOCASE';
|
||||||
|
return this.modelSelectOne(sql, params);
|
||||||
|
}
|
||||||
|
|
||||||
static loadByTitle(fieldValue) {
|
static loadByTitle(fieldValue) {
|
||||||
return this.modelSelectOne(`SELECT * FROM \`${this.tableName()}\` WHERE \`title\` = ?`, [fieldValue]);
|
return this.modelSelectOne(`SELECT * FROM \`${this.tableName()}\` WHERE \`title\` = ?`, [fieldValue]);
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,21 @@ class BaseItem extends BaseModel {
|
|||||||
throw new Error(`Invalid class name: ${className}`);
|
throw new Error(`Invalid class name: ${className}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async findUniqueItemTitle(title) {
|
static async findUniqueItemTitle(title, parentId = null) {
|
||||||
let counter = 1;
|
let counter = 1;
|
||||||
let titleToTry = title;
|
let titleToTry = title;
|
||||||
while (true) {
|
while (true) {
|
||||||
const item = await this.loadByField('title', titleToTry);
|
let item = null;
|
||||||
|
|
||||||
|
if (parentId !== null) {
|
||||||
|
item = await this.loadByFields({
|
||||||
|
title: titleToTry,
|
||||||
|
parent_id: parentId,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
item = await this.loadByField('title', titleToTry);
|
||||||
|
}
|
||||||
|
|
||||||
if (!item) return titleToTry;
|
if (!item) return titleToTry;
|
||||||
titleToTry = `${title} (${counter})`;
|
titleToTry = `${title} (${counter})`;
|
||||||
counter++;
|
counter++;
|
||||||
|
@ -46,7 +46,7 @@ class InteropService_Importer_Raw extends InteropService_Importer_Base {
|
|||||||
let defaultFolder_ = null;
|
let defaultFolder_ = null;
|
||||||
const defaultFolder = async () => {
|
const defaultFolder = async () => {
|
||||||
if (defaultFolder_) return defaultFolder_;
|
if (defaultFolder_) return defaultFolder_;
|
||||||
const folderTitle = await Folder.findUniqueItemTitle(this.options_.defaultFolderTitle ? this.options_.defaultFolderTitle : 'Imported');
|
const folderTitle = await Folder.findUniqueItemTitle(this.options_.defaultFolderTitle ? this.options_.defaultFolderTitle : 'Imported', '');
|
||||||
// eslint-disable-next-line require-atomic-updates
|
// eslint-disable-next-line require-atomic-updates
|
||||||
defaultFolder_ = await Folder.save({ title: folderTitle });
|
defaultFolder_ = await Folder.save({ title: folderTitle });
|
||||||
return defaultFolder_;
|
return defaultFolder_;
|
||||||
@ -96,7 +96,7 @@ class InteropService_Importer_Raw extends InteropService_Importer_Base {
|
|||||||
|
|
||||||
if (!itemIdMap[item.id]) itemIdMap[item.id] = uuid.create();
|
if (!itemIdMap[item.id]) itemIdMap[item.id] = uuid.create();
|
||||||
item.id = itemIdMap[item.id];
|
item.id = itemIdMap[item.id];
|
||||||
item.title = await Folder.findUniqueItemTitle(item.title);
|
item.title = await Folder.findUniqueItemTitle(item.title, item.parent_id);
|
||||||
|
|
||||||
if (item.parent_id) {
|
if (item.parent_id) {
|
||||||
await setFolderToImportTo(item.parent_id);
|
await setFolderToImportTo(item.parent_id);
|
||||||
|
Loading…
Reference in New Issue
Block a user