1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Electron: Resolves #612: Allow duplicating a note

This commit is contained in:
Laurent Cozic 2018-06-27 21:45:31 +01:00
parent 7d7e1e1637
commit 310afb0ad6
8 changed files with 33 additions and 18 deletions

View File

@ -59,7 +59,7 @@ class ImportScreenComponent extends React.Component {
async doImport() { async doImport() {
const filePath = this.props.filePath; const filePath = this.props.filePath;
const folderTitle = await Folder.findUniqueFolderTitle(filename(filePath)); const folderTitle = await Folder.findUniqueItemTitle(filename(filePath));
const messages = this.state.messages.slice(); const messages = this.state.messages.slice();
this.addMessage('start', _('New notebook "%s" will be created and file "%s" will be imported into it', folderTitle, basename(filePath))); this.addMessage('start', _('New notebook "%s" will be created and file "%s" will be imported into it', folderTitle, basename(filePath)));

View File

@ -88,6 +88,15 @@ class NoteListComponent extends React.Component {
}); });
}})); }}));
menu.append(new MenuItem({label: _('Duplicate'), click: async () => {
for (let i = 0; i < noteIds.length; i++) {
const note = await Note.load(noteIds[i]);
await Note.duplicate(noteIds[i], {
uniqueTitle: _('%s - Copy', note.title),
});
}
}}));
menu.append(new MenuItem({label: _('Switch between note and to-do type'), click: async () => { menu.append(new MenuItem({label: _('Switch between note and to-do type'), click: async () => {
for (let i = 0; i < noteIds.length; i++) { for (let i = 0; i < noteIds.length; i++) {
const note = await Note.load(noteIds[i]); const note = await Note.load(noteIds[i]);

View File

@ -29,6 +29,19 @@ class BaseItem extends BaseModel {
throw new Error('Invalid class name: ' + className); throw new Error('Invalid class name: ' + className);
} }
static async findUniqueItemTitle(title) {
let counter = 1;
let titleToTry = title;
while (true) {
const item = await this.loadByField('title', titleToTry);
if (!item) return titleToTry;
titleToTry = title + ' (' + counter + ')';
counter++;
if (counter >= 100) titleToTry = title + ' (' + ((new Date()).getTime()) + ')';
if (counter >= 1000) throw new Error('Cannot find unique title');
}
}
// Need to dynamically load the classes like this to avoid circular dependencies // Need to dynamically load the classes like this to avoid circular dependencies
static getClass(name) { static getClass(name) {
for (let i = 0; i < BaseItem.syncItemDefinitions_.length; i++) { for (let i = 0; i < BaseItem.syncItemDefinitions_.length; i++) {

View File

@ -33,19 +33,6 @@ class Folder extends BaseItem {
} }
} }
static async findUniqueFolderTitle(title) {
let counter = 1;
let titleToTry = title;
while (true) {
const folder = await this.loadByField('title', titleToTry);
if (!folder) return titleToTry;
titleToTry = title + ' (' + counter + ')';
counter++;
if (counter >= 100) titleToTry = title + ' (' + ((new Date()).getTime()) + ')';
if (counter >= 1000) throw new Error('Cannot find unique title');
}
}
static noteIds(parentId) { static noteIds(parentId) {
return this.db().selectAll('SELECT id FROM notes WHERE is_conflict = 0 AND parent_id = ?', [parentId]).then((rows) => { return this.db().selectAll('SELECT id FROM notes WHERE is_conflict = 0 AND parent_id = ?', [parentId]).then((rows) => {
let output = []; let output = [];

View File

@ -420,6 +420,7 @@ class Note extends BaseItem {
static async duplicate(noteId, options = null) { static async duplicate(noteId, options = null) {
const changes = options && options.changes; const changes = options && options.changes;
const uniqueTitle = options && options.uniqueTitle;
const originalNote = await Note.load(noteId); const originalNote = await Note.load(noteId);
if (!originalNote) throw new Error('Unknown note: ' + noteId); if (!originalNote) throw new Error('Unknown note: ' + noteId);
@ -432,6 +433,11 @@ class Note extends BaseItem {
newNote[n] = changes[n]; newNote[n] = changes[n];
} }
if (uniqueTitle) {
const title = await Note.findUniqueItemTitle(uniqueTitle);
newNote.title = title;
}
return this.save(newNote); return this.save(newNote);
} }

View File

@ -23,7 +23,7 @@ class InteropService_Importer_Enex extends InteropService_Importer_Base {
let folder = this.options_.destinationFolder; let folder = this.options_.destinationFolder;
if (!folder) { if (!folder) {
const folderTitle = await Folder.findUniqueFolderTitle(filename(this.sourcePath_)); const folderTitle = await Folder.findUniqueItemTitle(filename(this.sourcePath_));
folder = await Folder.save({ title: folderTitle }); folder = await Folder.save({ title: folderTitle });
} }

View File

@ -34,7 +34,7 @@ class InteropService_Importer_Md extends InteropService_Importer_Base {
} }
if (!this.options_.destinationFolder) { if (!this.options_.destinationFolder) {
const folderTitle = await Folder.findUniqueFolderTitle(basename(rtrimSlashes(this.sourcePath_))); const folderTitle = await Folder.findUniqueItemTitle(basename(rtrimSlashes(this.sourcePath_)));
const folder = await Folder.save({ title: folderTitle }); const folder = await Folder.save({ title: folderTitle });
parentFolderId = folder.id; parentFolderId = folder.id;
} else { } else {

View File

@ -51,7 +51,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.findUniqueFolderTitle(this.options_.defaultFolderTitle ? this.options_.defaultFolderTitle : 'Imported'); const folderTitle = await Folder.findUniqueItemTitle(this.options_.defaultFolderTitle ? this.options_.defaultFolderTitle : 'Imported');
defaultFolder_ = await Folder.save({ title: folderTitle }); defaultFolder_ = await Folder.save({ title: folderTitle });
return defaultFolder_; return defaultFolder_;
} }
@ -100,7 +100,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.findUniqueFolderTitle(item.title); item.title = await Folder.findUniqueItemTitle(item.title);
if (item.parent_id) { if (item.parent_id) {
await setFolderToImportTo(item.parent_id); await setFolderToImportTo(item.parent_id);