Add flags to disable retraction warnings
Separate flags for hiding the retraction altogether and for hiding citation warnings for it New functions: Zotero.Retractions.hideRetraction(item) Zotero.Retractions.shouldShowCitationWarning(item) Zotero.Retractions.disableCitationWarningsForItem(item) Addresses #1710
This commit is contained in:
parent
f49d5805cd
commit
0beddb9680
5 changed files with 126 additions and 15 deletions
|
@ -1039,7 +1039,7 @@ Zotero.Search.prototype._buildQuery = Zotero.Promise.coroutine(function* () {
|
|||
}
|
||||
|
||||
if (retracted) {
|
||||
sql += " AND (itemID IN (SELECT itemID FROM retractedItems))";
|
||||
sql += " AND (itemID IN (SELECT itemID FROM retractedItems WHERE flag=0))";
|
||||
}
|
||||
|
||||
if (publications) {
|
||||
|
|
|
@ -28,6 +28,10 @@ Zotero.Retractions = {
|
|||
TYPE_PMID: 'p',
|
||||
TYPE_NAMES: ['DOI', 'PMID'],
|
||||
|
||||
FLAG_NORMAL: 0,
|
||||
FLAG_HIDDEN: 1,
|
||||
FLAG_NO_CITATION_WARNING: 2,
|
||||
|
||||
_prefObserverRegistered: false,
|
||||
_initialized: false,
|
||||
_version: 1,
|
||||
|
@ -60,13 +64,13 @@ Zotero.Retractions = {
|
|||
|
||||
// Load existing retracted items
|
||||
var rows = await Zotero.DB.queryAsync(
|
||||
"SELECT libraryID, itemID, DI.itemID IS NOT NULL AS deleted FROM items "
|
||||
+ "JOIN retractedItems USING (itemID) "
|
||||
"SELECT libraryID, itemID, DI.itemID IS NOT NULL AS deleted, RI.flag FROM items "
|
||||
+ "JOIN retractedItems RI USING (itemID) "
|
||||
+ "LEFT JOIN deletedItems DI USING (itemID)"
|
||||
);
|
||||
for (let row of rows) {
|
||||
this._retractedItems.add(row.itemID);
|
||||
if (!row.deleted) {
|
||||
this._retractedItems.set(row.itemID, row.flag);
|
||||
if (!row.deleted && row.flag != this.FLAG_HIDDEN) {
|
||||
if (!this._retractedItemsByLibrary[row.libraryID]) {
|
||||
this._retractedItemsByLibrary[row.libraryID] = new Set();
|
||||
}
|
||||
|
@ -88,7 +92,7 @@ Zotero.Retractions = {
|
|||
this._itemKeys = {};
|
||||
this._queuedItems = new Set();
|
||||
this._queuedPrefixStrings = new Set();
|
||||
this._retractedItems = new Set();
|
||||
this._retractedItems = new Map();
|
||||
this._retractedItemsByLibrary = {};
|
||||
this._librariesWithRetractions = new Set();
|
||||
this._cacheVersion = null;
|
||||
|
@ -99,11 +103,53 @@ Zotero.Retractions = {
|
|||
},
|
||||
|
||||
/**
|
||||
* @param {Zotero.Item}
|
||||
* If item was retracted and the retraction hasn't been hidden
|
||||
*
|
||||
* @param {Zotero.Item} item
|
||||
* @return {Boolean}
|
||||
*/
|
||||
isRetracted: function (item) {
|
||||
return this._retractedItems.has(item.id);
|
||||
var flag = this._retractedItems.get(item.id);
|
||||
return flag !== undefined && flag !== this.FLAG_HIDDEN;
|
||||
},
|
||||
|
||||
/**
|
||||
* If item was retracted and hasn't been marked to not show citation warnings
|
||||
*
|
||||
* @param {Zotero.Item}
|
||||
* @return {Boolean}
|
||||
*/
|
||||
shouldShowCitationWarning: function (item) {
|
||||
return this._retractedItems.get(item.id) === this.FLAG_NORMAL;
|
||||
},
|
||||
|
||||
/**
|
||||
* Don't show any future retraction warnings for this item
|
||||
*
|
||||
* @param {Zotero.Item} item
|
||||
* @return {Promise}
|
||||
*/
|
||||
hideRetraction: async function (item) {
|
||||
return this._updateItemFlag(item, this.FLAG_HIDDEN);
|
||||
},
|
||||
|
||||
/**
|
||||
* Don't show future citation warnings for this item
|
||||
*
|
||||
* @param {Zotero.Item} item
|
||||
* @return {Promise}
|
||||
*/
|
||||
disableCitationWarningsForItem: async function (item) {
|
||||
return this._updateItemFlag(item, this.FLAG_NO_CITATION_WARNING);
|
||||
},
|
||||
|
||||
_updateItemFlag: async function (item, flag) {
|
||||
this._retractedItems.set(item.id, flag);
|
||||
await Zotero.DB.queryAsync(
|
||||
"UPDATE retractedItems SET flag=? WHERE itemID=?",
|
||||
[flag, item.id]
|
||||
);
|
||||
await Zotero.Notifier.trigger('modify', 'item', [item.id]);
|
||||
},
|
||||
|
||||
getRetractionsFromJSON: Zotero.serial(async function (jsonItems) {
|
||||
|
@ -369,8 +415,9 @@ Zotero.Retractions = {
|
|||
// handled for newly detected items in _addEntry(), which gets called by
|
||||
// _updateItem() above after a delay (such that the item won't yet be retracted
|
||||
// here).
|
||||
if (this._retractedItems.has(item.id)) {
|
||||
if (item.deleted) {
|
||||
let flag = this._retractedItems.get(item.id);
|
||||
if (flag !== undefined) {
|
||||
if (item.deleted || flag == this.FLAG_HIDDEN) {
|
||||
await this._removeLibraryRetractedItem(item.libraryID, item.id);
|
||||
}
|
||||
else {
|
||||
|
@ -577,7 +624,7 @@ Zotero.Retractions = {
|
|||
// Remove existing retracted items that no longer match
|
||||
var removed = 0;
|
||||
if (removeExisting) {
|
||||
for (let itemID of this._retractedItems) {
|
||||
for (let itemID of this._retractedItems.keys()) {
|
||||
if (!allItemIDs.has(itemID)) {
|
||||
let item = await Zotero.Items.getAsync(itemID);
|
||||
await this._removeEntry(itemID, item.libraryID);
|
||||
|
@ -800,13 +847,17 @@ Zotero.Retractions = {
|
|||
delete o.retractionDOI;
|
||||
delete o.retractionPMID;
|
||||
|
||||
var sql = "REPLACE INTO retractedItems VALUES (?, ?)";
|
||||
var sql = "REPLACE INTO retractedItems (itemID, data) VALUES (?, ?)";
|
||||
await Zotero.DB.queryAsync(sql, [itemID, JSON.stringify(o)]);
|
||||
|
||||
var item = await Zotero.Items.getAsync(itemID);
|
||||
var libraryID = item.libraryID;
|
||||
this._retractedItems.add(itemID);
|
||||
if (!item.deleted) {
|
||||
// Check whether the retraction is already hidden by the user
|
||||
var flag = this._retractedItems.get(itemID);
|
||||
if (flag === undefined) {
|
||||
this._retractedItems.set(itemID, this.FLAG_NORMAL);
|
||||
}
|
||||
if (!item.deleted && flag !== this.FLAG_HIDDEN) {
|
||||
if (!this._retractedItemsByLibrary[libraryID]) {
|
||||
this._retractedItemsByLibrary[libraryID] = new Set();
|
||||
}
|
||||
|
|
|
@ -2518,6 +2518,10 @@ Zotero.Schema = new function(){
|
|||
yield Zotero.DB.queryAsync("CREATE TABLE IF NOT EXISTS retractedItems (\n itemID INTEGER PRIMARY KEY,\n data TEXT,\n FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE\n);");
|
||||
}
|
||||
|
||||
else if (i == 105) {
|
||||
yield Zotero.DB.queryAsync("ALTER TABLE retractedItems ADD COLUMN flag INT DEFAULT 0");
|
||||
}
|
||||
|
||||
// If breaking compatibility or doing anything dangerous, clear minorUpdateFrom
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-- 104
|
||||
-- 105
|
||||
|
||||
-- Copyright (c) 2009 Center for History and New Media
|
||||
-- George Mason University, Fairfax, Virginia, USA
|
||||
|
@ -289,6 +289,7 @@ CREATE TABLE publicationsItems (
|
|||
CREATE TABLE retractedItems (
|
||||
itemID INTEGER PRIMARY KEY,
|
||||
data TEXT,
|
||||
flag INT DEFAULT 0,
|
||||
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
|
|
|
@ -174,6 +174,23 @@ describe("Retractions", function() {
|
|||
});
|
||||
|
||||
|
||||
describe("#shouldShowCitationWarning()", function () {
|
||||
it("should return false if citation warning is hidden", async function () {
|
||||
var item = await createRetractedItem();
|
||||
assert.isTrue(Zotero.Retractions.shouldShowCitationWarning(item));
|
||||
await Zotero.Retractions.disableCitationWarningsForItem(item);
|
||||
assert.isFalse(Zotero.Retractions.shouldShowCitationWarning(item));
|
||||
});
|
||||
|
||||
it("should return false if retraction is hidden", async function () {
|
||||
var item = await createRetractedItem();
|
||||
assert.isTrue(Zotero.Retractions.shouldShowCitationWarning(item));
|
||||
await Zotero.Retractions.hideRetraction(item);
|
||||
assert.isFalse(Zotero.Retractions.shouldShowCitationWarning(item));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("#getRetractionsFromJSON()", function () {
|
||||
it("should identify object with retracted DOI", async function () {
|
||||
var spy = sinon.spy(Zotero.HTTP, 'request');
|
||||
|
@ -275,6 +292,44 @@ describe("Retractions", function() {
|
|||
assert.equal(zp.collectionsView.selectedTreeRow.id, "L" + userLibraryID);
|
||||
});
|
||||
|
||||
it("should hide Retracted Items collection when last retracted item is marked as hidden", async function () {
|
||||
var rowID = "R" + userLibraryID;
|
||||
|
||||
// Create item
|
||||
var item = await createRetractedItem();
|
||||
assert.ok(zp.collectionsView.getRowIndexByID(rowID));
|
||||
|
||||
// Select Retracted Items collection
|
||||
await zp.collectionsView.selectByID(rowID);
|
||||
await waitForItemsLoad(win);
|
||||
|
||||
await Zotero.Retractions.hideRetraction(item);
|
||||
|
||||
await Zotero.Promise.delay(50);
|
||||
// Retracted Items should be gone
|
||||
assert.isFalse(zp.collectionsView.getRowIndexByID(rowID));
|
||||
// And My Library should be selected
|
||||
assert.equal(zp.collectionsView.selectedTreeRow.id, "L" + userLibraryID);
|
||||
});
|
||||
|
||||
it("shouldn't hide Retracted Items collection when last retracted item is marked to not show a citation warning", async function () {
|
||||
var rowID = "R" + userLibraryID;
|
||||
|
||||
// Create item
|
||||
var item = await createRetractedItem();
|
||||
assert.ok(zp.collectionsView.getRowIndexByID(rowID));
|
||||
|
||||
// Select Retracted Items collection
|
||||
await zp.collectionsView.selectByID(rowID);
|
||||
await waitForItemsLoad(win);
|
||||
|
||||
await Zotero.Retractions.disableCitationWarningsForItem(item);
|
||||
|
||||
await Zotero.Promise.delay(50);
|
||||
// Should still be showing
|
||||
assert.ok(zp.collectionsView.getRowIndexByID("R" + userLibraryID));
|
||||
});
|
||||
|
||||
it("should show Retracted Items collection when retracted item is restored from trash", async function () {
|
||||
// Create trashed item
|
||||
var item = await createRetractedItem({ deleted: true });
|
||||
|
|
Loading…
Reference in a new issue