Fix #940, UI not updating when dragging child item between parents
This commit is contained in:
parent
d78089d4b9
commit
79748b9132
4 changed files with 152 additions and 2 deletions
|
@ -491,6 +491,7 @@ Zotero.Items = function() {
|
||||||
var onRow = function (row, setFunc) {
|
var onRow = function (row, setFunc) {
|
||||||
var itemID = row.getResultByIndex(0);
|
var itemID = row.getResultByIndex(0);
|
||||||
|
|
||||||
|
// If we've finished a set of rows for an item, process them
|
||||||
if (lastItemID && itemID !== lastItemID) {
|
if (lastItemID && itemID !== lastItemID) {
|
||||||
setFunc(lastItemID, rows);
|
setFunc(lastItemID, rows);
|
||||||
rows = [];
|
rows = [];
|
||||||
|
@ -543,9 +544,14 @@ Zotero.Items = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
// Process unprocessed rows
|
||||||
if (lastItemID) {
|
if (lastItemID) {
|
||||||
setAttachmentItem(lastItemID, rows);
|
setAttachmentItem(lastItemID, rows);
|
||||||
}
|
}
|
||||||
|
// Otherwise clear existing entries for passed items
|
||||||
|
else if (ids.length) {
|
||||||
|
ids.forEach(id => setAttachmentItem(id, []));
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Notes
|
// Notes
|
||||||
|
@ -591,9 +597,14 @@ Zotero.Items = function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
// Process unprocessed rows
|
||||||
if (lastItemID) {
|
if (lastItemID) {
|
||||||
setNoteItem(lastItemID, rows);
|
setNoteItem(lastItemID, rows);
|
||||||
}
|
}
|
||||||
|
// Otherwise clear existing entries for passed items
|
||||||
|
else if (ids.length) {
|
||||||
|
ids.forEach(id => setNoteItem(id, []));
|
||||||
|
}
|
||||||
|
|
||||||
// Mark all top-level items as having child items loaded
|
// Mark all top-level items as having child items loaded
|
||||||
sql = "SELECT itemID FROM items I WHERE libraryID=?" + idSQL + " AND itemID NOT IN "
|
sql = "SELECT itemID FROM items I WHERE libraryID=?" + idSQL + " AND itemID NOT IN "
|
||||||
|
|
|
@ -712,9 +712,13 @@ Zotero.ItemTreeView.prototype.notify = Zotero.Promise.coroutine(function* (actio
|
||||||
|
|
||||||
sort = id;
|
sort = id;
|
||||||
}
|
}
|
||||||
|
// If item was moved from one parent to another, remove from old parent
|
||||||
|
else if (parentItemID && parentIndex != -1 && this._rowMap[parentItemID] != parentIndex) {
|
||||||
|
this._removeRow(row);
|
||||||
|
}
|
||||||
// If not moved from under one item to another, just resort the row,
|
// If not moved from under one item to another, just resort the row,
|
||||||
// which also invalidates it and refreshes it
|
// which also invalidates it and refreshes it
|
||||||
else if (!(parentItemID && parentIndex != -1 && this._rowMap[parentItemID] != parentIndex)) {
|
else {
|
||||||
sort = id;
|
sort = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -870,6 +874,7 @@ Zotero.ItemTreeView.prototype.notify = Zotero.Promise.coroutine(function* (actio
|
||||||
else {
|
else {
|
||||||
this._refreshItemRowMap();
|
this._refreshItemRowMap();
|
||||||
}
|
}
|
||||||
|
this._refreshItemRowMap();
|
||||||
|
|
||||||
if (singleSelect) {
|
if (singleSelect) {
|
||||||
if (!extraData[singleSelect] || !extraData[singleSelect].skipSelect) {
|
if (!extraData[singleSelect] || !extraData[singleSelect].skipSelect) {
|
||||||
|
|
|
@ -372,6 +372,26 @@ describe("Zotero.Item", function () {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("#getCreators()", function () {
|
||||||
|
it("should update after creators are removed", function* () {
|
||||||
|
var item = createUnsavedDataObject('item');
|
||||||
|
item.setCreators([
|
||||||
|
{
|
||||||
|
creatorType: "author",
|
||||||
|
name: "A"
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
yield item.saveTx();
|
||||||
|
|
||||||
|
assert.lengthOf(item.getCreators(), 1);
|
||||||
|
|
||||||
|
item.setCreators([]);
|
||||||
|
yield item.saveTx();
|
||||||
|
|
||||||
|
assert.lengthOf(item.getCreators(), 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("#setCreators", function () {
|
describe("#setCreators", function () {
|
||||||
it("should accept an array of creators in API JSON format", function* () {
|
it("should accept an array of creators in API JSON format", function* () {
|
||||||
var creators = [
|
var creators = [
|
||||||
|
@ -459,6 +479,25 @@ describe("Zotero.Item", function () {
|
||||||
var item = yield createDataObject('item');
|
var item = yield createDataObject('item');
|
||||||
assert.lengthOf(item.getAttachments(), 0);
|
assert.lengthOf(item.getAttachments(), 0);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("should update after an attachment is moved to another item", function* () {
|
||||||
|
var item1 = yield createDataObject('item');
|
||||||
|
var item2 = yield createDataObject('item');
|
||||||
|
var item3 = new Zotero.Item('attachment');
|
||||||
|
item3.parentID = item1.id;
|
||||||
|
item3.attachmentLinkMode = 'linked_url';
|
||||||
|
item3.setField('url', 'http://example.com');
|
||||||
|
yield item3.saveTx();
|
||||||
|
|
||||||
|
assert.lengthOf(item1.getAttachments(), 1);
|
||||||
|
assert.lengthOf(item2.getAttachments(), 0);
|
||||||
|
|
||||||
|
item3.parentID = item2.id;
|
||||||
|
yield item3.saveTx();
|
||||||
|
|
||||||
|
assert.lengthOf(item1.getAttachments(), 0);
|
||||||
|
assert.lengthOf(item2.getAttachments(), 1);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("#getNotes()", function () {
|
describe("#getNotes()", function () {
|
||||||
|
@ -499,7 +538,22 @@ describe("Zotero.Item", function () {
|
||||||
it("#should return an empty array for an item with no notes", function* () {
|
it("#should return an empty array for an item with no notes", function* () {
|
||||||
var item = yield createDataObject('item');
|
var item = yield createDataObject('item');
|
||||||
assert.lengthOf(item.getNotes(), 0);
|
assert.lengthOf(item.getNotes(), 0);
|
||||||
})
|
});
|
||||||
|
|
||||||
|
it("should update after a note is moved to another item", function* () {
|
||||||
|
var item1 = yield createDataObject('item');
|
||||||
|
var item2 = yield createDataObject('item');
|
||||||
|
var item3 = yield createDataObject('item', { itemType: 'note', parentID: item1.id });
|
||||||
|
|
||||||
|
assert.lengthOf(item1.getNotes(), 1);
|
||||||
|
assert.lengthOf(item2.getNotes(), 0);
|
||||||
|
|
||||||
|
item3.parentID = item2.id;
|
||||||
|
yield item3.saveTx();
|
||||||
|
|
||||||
|
assert.lengthOf(item1.getNotes(), 0);
|
||||||
|
assert.lengthOf(item2.getNotes(), 1);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("#attachmentCharset", function () {
|
describe("#attachmentCharset", function () {
|
||||||
|
|
|
@ -308,6 +308,86 @@ describe("Zotero.ItemTreeView", function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("#drop()", function () {
|
describe("#drop()", function () {
|
||||||
|
it("should move a child item from one item to another", function* () {
|
||||||
|
var collection = yield createDataObject('collection');
|
||||||
|
yield waitForItemsLoad(win);
|
||||||
|
var item1 = yield createDataObject('item', { title: "A", collections: [collection.id] });
|
||||||
|
var item2 = yield createDataObject('item', { title: "B", collections: [collection.id] });
|
||||||
|
var item3 = yield createDataObject('item', { itemType: 'note', parentID: item1.id });
|
||||||
|
|
||||||
|
let view = zp.itemsView;
|
||||||
|
yield view.selectItem(item3.id, true);
|
||||||
|
|
||||||
|
var deferred = Zotero.Promise.defer();
|
||||||
|
view.addEventListener('select', () => deferred.resolve());
|
||||||
|
|
||||||
|
view.drop(view.getRowIndexByID(item2.id), 0, {
|
||||||
|
dropEffect: 'copy',
|
||||||
|
effectAllowed: 'copy',
|
||||||
|
types: {
|
||||||
|
contains: function (type) {
|
||||||
|
return type == 'zotero/item';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getData: function (type) {
|
||||||
|
if (type == 'zotero/item') {
|
||||||
|
return item3.id + "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mozItemCount: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
yield deferred.promise;
|
||||||
|
|
||||||
|
// Old parent should be empty
|
||||||
|
assert.isFalse(view.isContainerOpen(view.getRowIndexByID(item1.id)));
|
||||||
|
assert.isTrue(view.isContainerEmpty(view.getRowIndexByID(item1.id)));
|
||||||
|
|
||||||
|
// New parent should be open
|
||||||
|
assert.isTrue(view.isContainerOpen(view.getRowIndexByID(item2.id)));
|
||||||
|
assert.isFalse(view.isContainerEmpty(view.getRowIndexByID(item2.id)));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should move a child item from last item in list to another", function* () {
|
||||||
|
var collection = yield createDataObject('collection');
|
||||||
|
yield waitForItemsLoad(win);
|
||||||
|
var item1 = yield createDataObject('item', { title: "A", collections: [collection.id] });
|
||||||
|
var item2 = yield createDataObject('item', { title: "B", collections: [collection.id] });
|
||||||
|
var item3 = yield createDataObject('item', { itemType: 'note', parentID: item2.id });
|
||||||
|
|
||||||
|
let view = zp.itemsView;
|
||||||
|
yield view.selectItem(item3.id, true);
|
||||||
|
|
||||||
|
var deferred = Zotero.Promise.defer();
|
||||||
|
view.addEventListener('select', () => deferred.resolve());
|
||||||
|
|
||||||
|
view.drop(view.getRowIndexByID(item1.id), 0, {
|
||||||
|
dropEffect: 'copy',
|
||||||
|
effectAllowed: 'copy',
|
||||||
|
types: {
|
||||||
|
contains: function (type) {
|
||||||
|
return type == 'zotero/item';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getData: function (type) {
|
||||||
|
if (type == 'zotero/item') {
|
||||||
|
return item3.id + "";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mozItemCount: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
yield deferred.promise;
|
||||||
|
|
||||||
|
// Old parent should be empty
|
||||||
|
assert.isFalse(view.isContainerOpen(view.getRowIndexByID(item2.id)));
|
||||||
|
assert.isTrue(view.isContainerEmpty(view.getRowIndexByID(item2.id)));
|
||||||
|
|
||||||
|
// New parent should be open
|
||||||
|
assert.isTrue(view.isContainerOpen(view.getRowIndexByID(item1.id)));
|
||||||
|
assert.isFalse(view.isContainerEmpty(view.getRowIndexByID(item1.id)));
|
||||||
|
});
|
||||||
|
|
||||||
it("should create a top-level attachment when a file is dragged", function* () {
|
it("should create a top-level attachment when a file is dragged", function* () {
|
||||||
var file = getTestDataDirectory();
|
var file = getTestDataDirectory();
|
||||||
file.append('test.png');
|
file.append('test.png');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue