Mark trashed items as unsynced and update parents (including note list)

Regression from 3a0e0cb088
This commit is contained in:
Dan Stillman 2017-02-15 13:15:30 -05:00
parent 41538ebca6
commit 3830aa1125
5 changed files with 86 additions and 5 deletions

View file

@ -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();

View file

@ -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);

View file

@ -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() {

View file

@ -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);
})

View file

@ -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);
});
});