Mark trashed items as unsynced and update parents (including note list)
Regression from 3a0e0cb088
This commit is contained in:
parent
41538ebca6
commit
3830aa1125
5 changed files with 86 additions and 5 deletions
|
@ -1775,6 +1775,7 @@ Zotero.Item.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
|
|||
// Update child item counts and contents
|
||||
if (reloadParentChildItems) {
|
||||
for (let parentItemID in reloadParentChildItems) {
|
||||
// Keep in sync with Zotero.Items.trash()
|
||||
let parentItem = yield this.ObjectsClass.getAsync(parentItemID);
|
||||
yield parentItem.reload(['primaryData', 'childItems'], true);
|
||||
parentItem.clearBestAttachmentState();
|
||||
|
|
|
@ -852,12 +852,17 @@ Zotero.Items = function() {
|
|||
libraryIDs.add(item.libraryID);
|
||||
}
|
||||
|
||||
var parentItemIDs = new Set();
|
||||
items.forEach(item => {
|
||||
item.setDeleted(true);
|
||||
item.synced = false;
|
||||
if (item.parentItemID) {
|
||||
parentItemIDs.add(item.parentItemID);
|
||||
}
|
||||
});
|
||||
yield Zotero.Utilities.Internal.forEachChunkAsync(ids, 250, Zotero.Promise.coroutine(function* (chunk) {
|
||||
yield Zotero.DB.queryAsync(
|
||||
"UPDATE items SET synced=1, clientDateModified=CURRENT_TIMESTAMP "
|
||||
"UPDATE items SET synced=0, clientDateModified=CURRENT_TIMESTAMP "
|
||||
+ `WHERE itemID IN (${chunk.map(id => parseInt(id)).join(", ")})`
|
||||
);
|
||||
yield Zotero.DB.queryAsync(
|
||||
|
@ -866,6 +871,11 @@ Zotero.Items = function() {
|
|||
);
|
||||
}.bind(this)));
|
||||
|
||||
// Keep in sync with Zotero.Item::saveData()
|
||||
for (let parentItemID of parentItemIDs) {
|
||||
let parentItem = yield Zotero.Items.getAsync(parentItemID);
|
||||
yield parentItem.reload(['primaryData', 'childItems'], true);
|
||||
}
|
||||
Zotero.Notifier.queue('trash', 'item', ids);
|
||||
Array.from(libraryIDs).forEach(libraryID => {
|
||||
Zotero.Notifier.queue('refresh', 'trash', libraryID);
|
||||
|
|
|
@ -151,6 +151,55 @@ describe("Item pane", function () {
|
|||
|
||||
assert.equal(noteBox.noteField.value, '<p>Test</p>');
|
||||
})
|
||||
|
||||
it("should refresh on note trash", function* () {
|
||||
var item = yield createDataObject('item');
|
||||
|
||||
var note = new Zotero.Item('note');
|
||||
note.parentItemID = item.id;
|
||||
yield note.saveTx();
|
||||
yield itemsView.selectItem(note.id);
|
||||
|
||||
// Wait for the note editor, just to be polite
|
||||
var noteBox = doc.getElementById('zotero-note-editor');
|
||||
var val = false;
|
||||
do {
|
||||
try {
|
||||
val = noteBox.noteField.value;
|
||||
}
|
||||
catch (e) {}
|
||||
yield Zotero.Promise.delay(1);
|
||||
}
|
||||
while (val === false)
|
||||
|
||||
// Select parent and make sure there's 1 note
|
||||
yield itemsView.selectItem(item.id);
|
||||
var tabs = doc.getElementById('zotero-editpane-tabs');
|
||||
var infoTab = doc.getElementById('zotero-editpane-info-tab');
|
||||
var notesTab = doc.getElementById('zotero-editpane-notes-tab');
|
||||
var notesList = doc.getElementById('zotero-editpane-dynamic-notes');
|
||||
tabs.selectedItem = notesTab;
|
||||
// Wait for note list to update
|
||||
do {
|
||||
yield Zotero.Promise.delay(1);
|
||||
}
|
||||
while (notesList.childNodes.length !== 1);
|
||||
tabs.selectedItem = infoTab;
|
||||
|
||||
// Select child and trash it
|
||||
yield itemsView.selectItem(note.id);
|
||||
yield Zotero.Items.trashTx([note.id]);
|
||||
|
||||
// Select parent and select notes pane
|
||||
yield itemsView.selectItem(item.id);
|
||||
tabs.selectedItem = notesTab;
|
||||
// Wait for note list to update
|
||||
var len = false;
|
||||
do {
|
||||
yield Zotero.Promise.delay(1);
|
||||
}
|
||||
while (notesList.childNodes.length !== 0);
|
||||
})
|
||||
})
|
||||
|
||||
describe("Feed buttons", function() {
|
||||
|
|
|
@ -301,6 +301,8 @@ describe("Zotero.Item", function () {
|
|||
it("should be set to true after save", function* () {
|
||||
var item = yield createDataObject('item');
|
||||
item.deleted = true;
|
||||
// Sanity check for itemsTest#trash()
|
||||
assert.isTrue(item._changed.deleted);
|
||||
yield item.saveTx();
|
||||
assert.ok(item.deleted);
|
||||
})
|
||||
|
|
|
@ -92,19 +92,38 @@ describe("Zotero.Items", function () {
|
|||
it("should send items to the trash", function* () {
|
||||
var items = [];
|
||||
items.push(
|
||||
(yield createDataObject('item')),
|
||||
(yield createDataObject('item')),
|
||||
(yield createDataObject('item'))
|
||||
(yield createDataObject('item', { synced: true })),
|
||||
(yield createDataObject('item', { synced: true })),
|
||||
(yield createDataObject('item', { synced: true }))
|
||||
);
|
||||
items.forEach(item => {
|
||||
// Sanity-checked as true in itemTest#deleted
|
||||
assert.isUndefined(item._changed.deleted);
|
||||
});
|
||||
var ids = items.map(item => item.id);
|
||||
yield Zotero.Items.trashTx(ids);
|
||||
items.forEach(item => {
|
||||
assert.isTrue(item.deleted);
|
||||
assert.isFalse(item.hasChanged());
|
||||
// Item should be saved (can't use hasChanged() because that includes .synced)
|
||||
assert.isUndefined(item._changed.deleted);
|
||||
assert.isFalse(item.synced);
|
||||
});
|
||||
assert.equal((yield Zotero.DB.valueQueryAsync(
|
||||
`SELECT COUNT(*) FROM deletedItems WHERE itemID IN (${ids})`
|
||||
)), 3);
|
||||
for (let item of items) {
|
||||
assert.equal((yield Zotero.DB.valueQueryAsync(
|
||||
`SELECT synced FROM items WHERE itemID=${item.id}`
|
||||
)), 0);
|
||||
}
|
||||
});
|
||||
|
||||
it("should update parent item when trashing child item", function* () {
|
||||
var item = yield createDataObject('item');
|
||||
var note = yield createDataObject('item', { itemType: 'note', parentID: item.id });
|
||||
assert.lengthOf(item.getNotes(), 1);
|
||||
yield Zotero.Items.trashTx([note.id]);
|
||||
assert.lengthOf(item.getNotes(), 0);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue