mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
91 lines
2.7 KiB
TypeScript
91 lines
2.7 KiB
TypeScript
import { getRestoreFolder } from '.';
|
|
import { ModelType } from '../../BaseModel';
|
|
import Folder from '../../models/Folder';
|
|
import Note from '../../models/Note';
|
|
import { FolderEntity, NoteEntity } from '../database/types';
|
|
import { checkObjectHasProperties } from '@joplin/utils/object';
|
|
|
|
export interface RestoreItemsOptions {
|
|
targetFolderId?: string;
|
|
|
|
// Restore item to a special "Restore" folder if the item doesn't have a non-deleted parent to
|
|
// be restored to.
|
|
useRestoreFolder?: boolean;
|
|
}
|
|
|
|
const restoreItems = async (itemType: ModelType, itemsOrIds: NoteEntity[] | FolderEntity[] | string[], options: RestoreItemsOptions = null) => {
|
|
if (!itemsOrIds.length) return;
|
|
|
|
options = {
|
|
targetFolderId: null,
|
|
useRestoreFolder: false,
|
|
...options,
|
|
};
|
|
|
|
const ModelClass = itemType === ModelType.Note ? Note : Folder;
|
|
|
|
let items: NoteEntity[] | FolderEntity[] = [];
|
|
|
|
if (typeof itemsOrIds[0] === 'string') {
|
|
items = await ModelClass.byIds(itemsOrIds as string[], { fields: ['id', 'parent_id', 'deleted_time'] });
|
|
} else {
|
|
items = itemsOrIds as (NoteEntity[] | FolderEntity[]);
|
|
}
|
|
|
|
let restoreFolder: FolderEntity = null;
|
|
|
|
for (const item of items) {
|
|
checkObjectHasProperties(item, ['id', 'parent_id']);
|
|
|
|
let itemParentId = item.parent_id;
|
|
|
|
const parentItem = await Folder.load(item.parent_id, { fields: ['id', 'deleted_time'] });
|
|
if (!parentItem || parentItem.deleted_time) {
|
|
if (options.useRestoreFolder) {
|
|
if (!restoreFolder) restoreFolder = await getRestoreFolder();
|
|
itemParentId = restoreFolder.id;
|
|
} else {
|
|
itemParentId = '';
|
|
}
|
|
}
|
|
|
|
if (options.targetFolderId !== null) itemParentId = options.targetFolderId;
|
|
|
|
let toSave: FolderEntity | NoteEntity = null;
|
|
|
|
if (itemType === ModelType.Note) {
|
|
// We need to preview conflicts -- they can be trashed.
|
|
toSave = await Note.preview(item.id, { excludeConflicts: false });
|
|
} else {
|
|
toSave = await Folder.load(item.id);
|
|
}
|
|
|
|
toSave = {
|
|
...toSave,
|
|
deleted_time: 0,
|
|
updated_time: Date.now(),
|
|
parent_id: itemParentId,
|
|
};
|
|
|
|
await ModelClass.save(toSave, {
|
|
autoTimestamp: false,
|
|
});
|
|
|
|
if (itemType === ModelType.Folder) {
|
|
const childrenFolderIds = await Folder.childrenIds(item.id, { includeDeleted: true });
|
|
const childrenFolders: FolderEntity[] = await Folder.byIds(childrenFolderIds, { fields: ['id', 'parent_id', 'deleted_time'] });
|
|
const deletedChildrenFolders = childrenFolders.filter(f => !!f.deleted_time);
|
|
await restoreItems(ModelType.Folder, deletedChildrenFolders);
|
|
|
|
const notes = await Folder.notes(item.id, {
|
|
fields: ['id', 'parent_id'],
|
|
includeDeleted: true,
|
|
});
|
|
|
|
await restoreItems(ModelType.Note, notes);
|
|
}
|
|
}
|
|
};
|
|
|
|
export default restoreItems;
|