recursiveCollections: Remove from all subcollections on delete (#2689)

This commit is contained in:
Abe Jellinek 2022-07-09 01:37:14 -04:00 committed by GitHub
parent 7163a196f8
commit 3f282fc25f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 85 additions and 11 deletions

View file

@ -474,14 +474,17 @@ var ItemTree = class ItemTree extends LibraryTree {
return; return;
} }
var visibleSubcollections = Zotero.Prefs.get('recursiveCollections')
? collectionTreeRow.ref.getDescendents(false, 'collection')
: [];
var splitIDs = []; var splitIDs = [];
for (let id of ids) { for (let id of ids) {
var split = id.split('-'); var split = id.split('-');
// Skip if not an item in this collection // Include if an item in this collection or a visible subcollection
if (split[0] != collectionTreeRow.ref.id) { if (split[0] == collectionTreeRow.ref.id
continue; || visibleSubcollections.some(c => split[0] == c.id)) {
splitIDs.push(split[1]);
} }
splitIDs.push(split[1]);
} }
ids = splitIDs; ids = splitIDs;
} }
@ -1740,8 +1743,21 @@ var ItemTree = class ItemTree extends LibraryTree {
await Zotero.Items.trashTx(ids); await Zotero.Items.trashTx(ids);
} }
else if (collectionTreeRow.isCollection()) { else if (collectionTreeRow.isCollection()) {
let collectionIDs = [collectionTreeRow.ref.id];
if (Zotero.Prefs.get('recursiveCollections')) {
collectionIDs.push(...collectionTreeRow.ref.getDescendents(false, 'collection').map(c => c.id));
}
await Zotero.DB.executeTransaction(async () => { await Zotero.DB.executeTransaction(async () => {
await collectionTreeRow.ref.removeItems(ids); for (let itemID of ids) {
let item = Zotero.Items.get(itemID);
for (let collectionID of collectionIDs) {
item.removeFromCollection(collectionID);
}
await item.save({
skipDateModifiedUpdate: true
});
}
}); });
} }
else if (collectionTreeRow.isPublications()) { else if (collectionTreeRow.isPublications()) {

View file

@ -1877,13 +1877,39 @@ var ZoteroPane = new function()
var prompt = (force && !fromMenu) ? false : toTrash; var prompt = (force && !fromMenu) ? false : toTrash;
} }
else if (collectionTreeRow.isCollection()) { else if (collectionTreeRow.isCollection()) {
if (force) {
// Ignore unmodified action if only child items are selected var prompt = toTrash;
if (!force && this.itemsView.getSelectedItems().every(item => !item.isTopLevelItem())) { }
return; else {
// Ignore unmodified action if only child items are selected
if (this.itemsView.getSelectedItems().every(item => !item.isTopLevelItem())) {
return;
}
// If unmodified, recursiveCollections is true, and items are in
// descendant collections (even if also in the selected collection),
// prompt to remove from all
if (Zotero.Prefs.get('recursiveCollections')) {
let descendants = collectionTreeRow.ref.getDescendents(false, 'collection');
let inSubcollection = descendants
.some(({ id }) => this.itemsView.getSelectedItems()
.some(item => item.inCollection(id)));
if (inSubcollection) {
var prompt = {
title: Zotero.getString('pane.items.removeRecursive.title'),
text: Zotero.getString(
'pane.items.removeRecursive' + (this.itemsView.selection.count > 1 ? '.multiple' : '')
)
};
}
else {
var prompt = toRemove;
}
}
else {
var prompt = toRemove;
}
} }
var prompt = force ? toTrash : toRemove;
} }
else if (collectionTreeRow.isTrash() || collectionTreeRow.isBucket()) { else if (collectionTreeRow.isTrash() || collectionTreeRow.isBucket()) {
var prompt = toDelete; var prompt = toDelete;

View file

@ -328,6 +328,9 @@ pane.items.remove.multiple = Are you sure you want to remove the selected items
pane.items.removeFromPublications.title = Remove from My Publications pane.items.removeFromPublications.title = Remove from My Publications
pane.items.removeFromPublications = Are you sure you want to remove the selected item from My Publications? pane.items.removeFromPublications = Are you sure you want to remove the selected item from My Publications?
pane.items.removeFromPublications.multiple = Are you sure you want to remove the selected items from My Publications? pane.items.removeFromPublications.multiple = Are you sure you want to remove the selected items from My Publications?
pane.items.removeRecursive.title = Remove from Collection and Subcollections
pane.items.removeRecursive = Are you sure you want to remove the selected item from this collection and all its subcollections?
pane.items.removeRecursive.multiple = Are you sure you want to remove the selected items from this collection and all its subcollections?
pane.items.menu.addNoteFromAnnotations = Add Note from Annotations pane.items.menu.addNoteFromAnnotations = Add Note from Annotations
pane.items.menu.addNoteFromAnnotations.multiple = Add Notes from Annotations pane.items.menu.addNoteFromAnnotations.multiple = Add Notes from Annotations
pane.items.menu.findAvailablePDF = Find Available PDF pane.items.menu.findAvailablePDF = Find Available PDF

View file

@ -600,6 +600,35 @@ describe("ZoteroPane", function() {
assert.isTrue(item.deleted); assert.isTrue(item.deleted);
}); });
it("should prompt to remove an item from subcollections when recursiveCollections enabled", async function () {
Zotero.Prefs.set('recursiveCollections', true);
let collection1 = await createDataObject('collection');
let collection2 = await createDataObject('collection', { parentID: collection1.id });
let item = await createDataObject('item', { collections: [collection2.id] });
assert.ok(await zp.collectionsView.selectCollection(collection1.id));
await waitForItemsLoad(win);
let iv = zp.itemsView;
assert.ok(await iv.selectItem(item.id));
await Zotero.Promise.delay(1);
let promise = waitForDialog();
let modifyPromise = waitForItemEvent('modify');
await zp.deleteSelectedItems(false);
let dialog = await promise;
await modifyPromise;
assert.include(dialog.document.documentElement.textContent, Zotero.getString('pane.items.removeRecursive'));
assert.isFalse(item.inCollection(collection2.id));
Zotero.Prefs.clear('recursiveCollections');
});
}); });
describe("#deleteSelectedCollection()", function () { describe("#deleteSelectedCollection()", function () {