Various feeds changes
- Change sort order for feed items to natural order - Remove display of dates in itembox - Trim html tags from creators in FeedReader parser
This commit is contained in:
parent
5e706c31ad
commit
e206b0af5e
14 changed files with 118 additions and 192 deletions
|
@ -341,7 +341,9 @@
|
|||
fieldNames.push(Zotero.ItemFields.getName(fields[i]));
|
||||
}
|
||||
|
||||
fieldNames.push("dateAdded", "dateModified");
|
||||
if (! (this.item instanceof Zotero.FeedItem)) {
|
||||
fieldNames.push("dateAdded", "dateModified");
|
||||
}
|
||||
}
|
||||
|
||||
for (var i=0; i<fieldNames.length; i++) {
|
||||
|
|
|
@ -85,7 +85,7 @@ Zotero.defineProperty(Zotero.Feed, '_unreadCountSQL', {
|
|||
|
||||
Zotero.defineProperty(Zotero.Feed, '_dbColumns', {
|
||||
value: Object.freeze(['name', 'url', 'lastUpdate', 'lastCheck',
|
||||
'lastCheckError', 'cleanupAfter', 'refreshInterval'])
|
||||
'lastCheckError', 'lastGUID', 'cleanupAfter', 'refreshInterval'])
|
||||
});
|
||||
|
||||
Zotero.defineProperty(Zotero.Feed, '_primaryDataSQLParts');
|
||||
|
@ -130,7 +130,7 @@ for (let i=0; i<accessors.length; i++) {
|
|||
set: function(v) this._set(prop, v)
|
||||
})
|
||||
}
|
||||
let getters = ['lastCheck', 'lastUpdate', 'lastCheckError'];
|
||||
let getters = ['lastCheck', 'lastUpdate', 'lastCheckError', 'lastGUID'];
|
||||
for (let i=0; i<getters.length; i++) {
|
||||
let name = getters[i];
|
||||
let prop = Zotero.Feed._colToProp(name);
|
||||
|
@ -212,6 +212,7 @@ Zotero.Feed.prototype._loadDataFromRow = function(row) {
|
|||
this._feedLastCheckError = row._feedLastCheckError || null;
|
||||
this._feedLastCheck = row._feedLastCheck || null;
|
||||
this._feedLastUpdate = row._feedLastUpdate || null;
|
||||
this._feedLastGUID = row._feedLastGUID || null;
|
||||
this._feedCleanupAfter = parseInt(row._feedCleanupAfter) || null;
|
||||
this._feedRefreshInterval = parseInt(row._feedRefreshInterval) || null;
|
||||
this._feedUnreadCount = parseInt(row._feedUnreadCount);
|
||||
|
@ -328,6 +329,7 @@ Zotero.Feed.prototype.clearExpiredItems = Zotero.Promise.coroutine(function* ()
|
|||
|
||||
Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
||||
var toAdd = [];
|
||||
var createNew = true;
|
||||
if (this._updating) {
|
||||
return this._updating;
|
||||
}
|
||||
|
@ -343,20 +345,16 @@ Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
|||
let itemIterator = new fr.ItemIterator();
|
||||
let item, processedGUIDs = [];
|
||||
while (item = yield itemIterator.next().value) {
|
||||
// NOTE: Might cause issues with feeds that set pubDate for publication date of the item
|
||||
// rather than the date the item was added to the feed.
|
||||
if (item.dateModified && this.lastUpdate
|
||||
&& item.dateModified < this.lastUpdate
|
||||
) {
|
||||
Zotero.debug("Item modification date before last update date (" + this.lastCheck + ")");
|
||||
// Append id at the end to prevent same item collisions from different feeds
|
||||
// when to terminate item retrieval.
|
||||
item.guid += ":" + this.id;
|
||||
if (item.guid == this.lastGUID) {
|
||||
Zotero.debug("Feed#update: last seen item reached (" + this.lastGUID + ")");
|
||||
Zotero.debug(item);
|
||||
// We can stop now
|
||||
fr.terminate();
|
||||
break;
|
||||
// Don't create new items (expired and deleted), but update existing ones
|
||||
createNew = false;
|
||||
}
|
||||
|
||||
// Append id at the end to prevent same item collisions from different feeds
|
||||
item.guid += ":" + this.id;
|
||||
if (processedGUIDs.indexOf(item.guid) != -1) {
|
||||
Zotero.debug("Feed item " + item.guid + " already processed from feed.");
|
||||
continue;
|
||||
|
@ -367,30 +365,29 @@ Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
|||
Zotero.debug(item, 5);
|
||||
|
||||
let feedItem = yield Zotero.FeedItems.getAsyncByGUID(item.guid);
|
||||
if (!feedItem) {
|
||||
if (!feedItem && createNew) {
|
||||
feedItem = new Zotero.FeedItem();
|
||||
feedItem.guid = item.guid;
|
||||
feedItem.libraryID = this.id;
|
||||
} else {
|
||||
} else if(! feedItem.isTranslated) {
|
||||
Zotero.debug("Feed item " + item.guid + " already in library.");
|
||||
|
||||
if (!item.dateModified ||
|
||||
(feedItem.dateModified && feedItem.dateModified == item.dateModified)
|
||||
) {
|
||||
Zotero.debug("Modification date has not changed. Skipping update.");
|
||||
continue;
|
||||
}
|
||||
Zotero.debug("Updating metadata");
|
||||
yield feedItem.loadItemData();
|
||||
yield feedItem.loadCreators();
|
||||
feedItem.isRead = false;
|
||||
} else {
|
||||
// Either has been translated or beyond lastGUID
|
||||
continue;
|
||||
}
|
||||
|
||||
// Delete invalid data
|
||||
delete item.guid;
|
||||
delete item.dateAdded;
|
||||
|
||||
feedItem.fromJSON(item);
|
||||
|
||||
if (!feedItem.hasChanged()) {
|
||||
Zotero.debug("Feed item " + feedItem.guid + " has not changed");
|
||||
continue
|
||||
}
|
||||
feedItem.isRead = false;
|
||||
toAdd.push(feedItem);
|
||||
}
|
||||
}
|
||||
|
@ -411,6 +408,7 @@ Zotero.Feed.prototype._updateFeed = Zotero.Promise.coroutine(function* () {
|
|||
}
|
||||
});
|
||||
this._set('_feedLastUpdate', Zotero.Date.dateToSQL(new Date(), true));
|
||||
this._set('_feedLastGUID', toAdd[0].guid);
|
||||
}
|
||||
this._set('_feedLastCheck', Zotero.Date.dateToSQL(new Date(), true));
|
||||
yield this.saveTx();
|
||||
|
|
|
@ -31,6 +31,7 @@ Zotero.FeedItem = function(itemTypeOrID, params = {}) {
|
|||
Zotero.FeedItem._super.call(this, itemTypeOrID);
|
||||
|
||||
this._feedItemReadTime = null;
|
||||
this._feedItemTranslatedTime = null;
|
||||
|
||||
Zotero.Utilities.assignProps(this, params, ['guid']);
|
||||
};
|
||||
|
@ -70,21 +71,21 @@ Zotero.defineProperty(Zotero.FeedItem.prototype, 'isRead', {
|
|||
}
|
||||
});
|
||||
//
|
||||
//Zotero.defineProperty(Zotero.FeedItem.prototype, 'isTranslated', {
|
||||
// get: function() {
|
||||
// return !!this._feedItemTranslationTime;
|
||||
// },
|
||||
// set: function(state) {
|
||||
// if (state != !!this._feedItemTranslationTime) {
|
||||
// if (state) {
|
||||
// this._feedItemTranslationTime = Zotero.Date.dateToSQL(new Date(), true);
|
||||
// } else {
|
||||
// this._feedItemTranslationTime = null;
|
||||
// }
|
||||
// this._changed.feedItemData = true;
|
||||
// }
|
||||
// }
|
||||
//});
|
||||
Zotero.defineProperty(Zotero.FeedItem.prototype, 'isTranslated', {
|
||||
get: function() {
|
||||
return !!this._feedItemTranslatedTime;
|
||||
},
|
||||
set: function(state) {
|
||||
if (state != !!this._feedItemTranslatedTime) {
|
||||
if (state) {
|
||||
this._feedItemTranslatedTime = Zotero.Date.dateToSQL(new Date(), true);
|
||||
} else {
|
||||
this._feedItemTranslatedTime = null;
|
||||
}
|
||||
this._changed.feedItemData = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Zotero.FeedItem.prototype.loadPrimaryData = Zotero.Promise.coroutine(function* (reload, failOnMissing) {
|
||||
if (this.guid && !this.id) {
|
||||
|
@ -166,17 +167,12 @@ Zotero.FeedItem.prototype.forceSaveTx = function(options) {
|
|||
return this.saveTx(newOptions);
|
||||
}
|
||||
|
||||
Zotero.FeedItem.prototype.save = function(options = {}) {
|
||||
options.skipDateModifiedUpdate = true;
|
||||
return Zotero.FeedItem._super.prototype.save.apply(this, arguments)
|
||||
}
|
||||
|
||||
Zotero.FeedItem.prototype._saveData = Zotero.Promise.coroutine(function* (env) {
|
||||
yield Zotero.FeedItem._super.prototype._saveData.apply(this, arguments);
|
||||
|
||||
if (this._changed.feedItemData || env.isNew) {
|
||||
var sql = "REPLACE INTO feedItems VALUES (?,?,?)";
|
||||
yield Zotero.DB.queryAsync(sql, [env.id, this.guid, this._feedItemReadTime]);
|
||||
var sql = "REPLACE INTO feedItems VALUES (?,?,?,?)";
|
||||
yield Zotero.DB.queryAsync(sql, [env.id, this.guid, this._feedItemReadTime, this._feedItemTranslatedTime]);
|
||||
|
||||
this._clearChanged('feedItemData');
|
||||
}
|
||||
|
@ -262,6 +258,7 @@ Zotero.FeedItem.prototype.translate = Zotero.Promise.coroutine(function* (librar
|
|||
// TODO: handle no items like the ones in french history studies feed
|
||||
// set new translated data for item
|
||||
this.fromJSON(itemData);
|
||||
this.isTranslated = true;
|
||||
this.forceSaveTx();
|
||||
|
||||
return this;
|
||||
|
|
|
@ -40,6 +40,7 @@ Zotero.FeedItems = new Proxy(function() {
|
|||
let obj = zi_primaryDataSQLParts.call(this);
|
||||
obj.feedItemGUID = "FeI.guid AS feedItemGUID";
|
||||
obj.feedItemReadTime = "FeI.readTime AS feedItemReadTime";
|
||||
obj.feedItemTranslatedTime = "FeI.translatedTime AS feedItemTranslatedTime";
|
||||
return obj;
|
||||
}
|
||||
}, {lazy: true});
|
||||
|
|
|
@ -289,7 +289,7 @@ Zotero.FeedReader._processCreators = function(feedEntry, field, role) {
|
|||
let person = personArr.queryElementAt(i, Components.interfaces.nsIFeedPerson);
|
||||
if (!person || !person.name) continue;
|
||||
|
||||
let name = Zotero.Utilities.trimInternal(person.name);
|
||||
let name = Zotero.Utilities.cleanTags(Zotero.Utilities.trimInternal(person.name));
|
||||
if (!name) continue;
|
||||
|
||||
let commas = name.split(',').length - 1,
|
||||
|
@ -336,6 +336,10 @@ Zotero.FeedReader._processCreators = function(feedEntry, field, role) {
|
|||
if (!creator.firstName) {
|
||||
creator.fieldMode = 1;
|
||||
}
|
||||
// Sometimes these end up empty when parsing really nasty HTML based fields, so just skip.
|
||||
if (!creator.firstName && !creator.lastName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
creators.push(creator);
|
||||
}
|
||||
|
@ -376,43 +380,6 @@ Zotero.FeedReader._getFeedItem = function(feedEntry, feedInfo) {
|
|||
|
||||
if (feedEntry.link) item.url = feedEntry.link.spec;
|
||||
|
||||
if (feedEntry.updated) item.dateModified = new Date(feedEntry.updated);
|
||||
|
||||
if (feedEntry.published) {
|
||||
var date = new Date(feedEntry.published);
|
||||
|
||||
if (!date.getUTCSeconds() && !(date.getUTCHours() && date.getUTCMinutes())) {
|
||||
// There was probably no time, but there may have been a a date range,
|
||||
// so something could have ended up in the hour _or_ minute field
|
||||
date = getFeedField(feedEntry, 'pubDate')
|
||||
/* In case it was magically pulled from some other field */
|
||||
|| ( date.getUTCFullYear() + '-'
|
||||
+ (date.getUTCMonth() + 1) + '-'
|
||||
+ date.getUTCDate() );
|
||||
}
|
||||
else {
|
||||
date = Zotero.Date.dateToSQL(date, true);
|
||||
}
|
||||
item.dateAdded = date;
|
||||
|
||||
if (!item.dateModified) {
|
||||
items.dateModified = date;
|
||||
}
|
||||
}
|
||||
|
||||
if (!item.dateModified) {
|
||||
// When there's no reliable modification date, we can assume that item doesn't get updated
|
||||
Zotero.debug("FeedReader: Feed item missing a modification date (" + item.guid + ")");
|
||||
} else {
|
||||
// Convert date modified to string, since those are directly comparable
|
||||
item.dateModified = Zotero.Date.dateToSQL(item.dateModified, true);
|
||||
}
|
||||
|
||||
if (!item.dateAdded && item.dateModified) {
|
||||
// Use lastModified date
|
||||
item.dateAdded = item.dateModified;
|
||||
}
|
||||
|
||||
if (feedEntry.rights) item.rights = Zotero.FeedReader._getRichText(feedEntry.rights, 'rights');
|
||||
|
||||
item.creators = Zotero.FeedReader._processCreators(feedEntry, 'authors', 'author');
|
||||
|
@ -429,8 +396,11 @@ Zotero.FeedReader._getFeedItem = function(feedEntry, feedInfo) {
|
|||
|
||||
/** Done with basic metadata, now look for better data **/
|
||||
|
||||
date = Zotero.FeedReader._getFeedField(feedEntry, 'publicationDate', 'prism')
|
||||
|| Zotero.FeedReader._getFeedField(feedEntry, 'date', 'dc');
|
||||
let date = Zotero.FeedReader._getFeedField(feedEntry, 'publicationDate', 'prism')
|
||||
|| Zotero.FeedReader._getFeedField(feedEntry, 'date', 'dc')
|
||||
|| Zotero.FeedReader._getFeedField(feedEntry, 'pubDate') // RSS
|
||||
|| Zotero.FeedReader._getFeedField(feedEntry, 'published') // Atom
|
||||
|| Zotero.FeedReader._getFeedField(feedEntry, 'updated'); // Atom
|
||||
if (date) item.date = date;
|
||||
|
||||
let publicationTitle = Zotero.FeedReader._getFeedField(feedEntry, 'publicationName', 'prism')
|
||||
|
|
|
@ -98,7 +98,6 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
|
|||
}
|
||||
|
||||
this._treebox = treebox;
|
||||
this.setSortColumn();
|
||||
|
||||
if (this._ownerDocument.defaultView.ZoteroPane_Local) {
|
||||
this._ownerDocument.defaultView.ZoteroPane_Local.setItemsPaneMessage(Zotero.getString('pane.items.loading'));
|
||||
|
@ -260,48 +259,6 @@ Zotero.ItemTreeView.prototype.setTree = Zotero.Promise.coroutine(function* (tree
|
|||
});
|
||||
|
||||
|
||||
Zotero.ItemTreeView.prototype.setSortColumn = function() {
|
||||
var dir, col, currentCol, currentDir;
|
||||
|
||||
for (let i=0, len=this._treebox.columns.count; i<len; i++) {
|
||||
let column = this._treebox.columns.getColumnAt(i);
|
||||
if (column.element.getAttribute('sortActive')) {
|
||||
currentCol = column;
|
||||
currentDir = column.element.getAttribute('sortDirection');
|
||||
column.element.removeAttribute('sortActive');
|
||||
column.element.removeAttribute('sortDirection');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let colId = Zotero.Prefs.get('itemTree.sortColumnId');
|
||||
// Restore previous sort setting (feed -> non-feed)
|
||||
if (! this.collectionTreeRow.isFeed() && colId) {
|
||||
col = this._treebox.columns.getNamedColumn(colId);
|
||||
dir = Zotero.Prefs.get('itemTree.sortDirection');
|
||||
Zotero.Prefs.clear('itemTree.sortColumnId');
|
||||
Zotero.Prefs.clear('itemTree.sortDirection');
|
||||
// Sort Feeds by dateAdded (anything -> feed)
|
||||
} else if (this.collectionTreeRow.isFeed()) {
|
||||
col = this._treebox.columns.getNamedColumn("zotero-items-column-dateAdded");
|
||||
dir = 'descending';
|
||||
// No previous sort setting stored, so store it (non-feed -> feed)
|
||||
if (!colId && currentCol) {
|
||||
Zotero.Prefs.set('itemTree.sortColumnId', currentCol.id);
|
||||
Zotero.Prefs.set('itemTree.sortDirection', currentDir);
|
||||
}
|
||||
// Retain current sort setting (non-feed -> non-feed)
|
||||
} else {
|
||||
col = currentCol;
|
||||
dir = currentDir;
|
||||
}
|
||||
if (col) {
|
||||
col.element.setAttribute('sortActive', true);
|
||||
col.element.setAttribute('sortDirection', dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reload the rows from the data access methods
|
||||
* (doesn't call the tree.invalidate methods, etc.)
|
||||
|
@ -2130,9 +2087,12 @@ Zotero.ItemTreeView.prototype.getSortedItems = function(asIDs) {
|
|||
|
||||
|
||||
Zotero.ItemTreeView.prototype.getSortField = function() {
|
||||
var column = this._treebox.columns.getSortedColumn()
|
||||
if (this.collectionTreeRow.isFeed()) {
|
||||
return 'id';
|
||||
}
|
||||
var column = this._treebox.columns.getSortedColumn();
|
||||
if (!column) {
|
||||
column = this._treebox.columns.getFirstColumn()
|
||||
column = this._treebox.columns.getFirstColumn();
|
||||
}
|
||||
// zotero-items-column-_________
|
||||
return column.id.substring(20);
|
||||
|
@ -2176,6 +2136,9 @@ Zotero.ItemTreeView.prototype.getSortFields = function () {
|
|||
* Returns 'ascending' or 'descending'
|
||||
*/
|
||||
Zotero.ItemTreeView.prototype.getSortDirection = function() {
|
||||
if (this.collectionTreeRow.isFeed) {
|
||||
return Zotero.Prefs.get('feedSortAsc') ? 'asc' : 'desc';
|
||||
}
|
||||
var column = this._treebox.columns.getSortedColumn();
|
||||
if (!column) {
|
||||
return 'ascending';
|
||||
|
|
|
@ -2188,9 +2188,6 @@ Zotero.Schema = new function(){
|
|||
yield Zotero.DB.queryAsync("DROP TABLE tagsOld");
|
||||
yield Zotero.DB.queryAsync("DROP TABLE librariesOld");
|
||||
|
||||
// Feeds
|
||||
yield Zotero.DB.queryAsync("CREATE TABLE feeds (\n libraryID INTEGER PRIMARY KEY,\n name TEXT NOT NULL,\n url TEXT NOT NULL UNIQUE,\n lastUpdate TIMESTAMP,\n lastCheck TIMESTAMP,\n lastCheckError TEXT,\n cleanupAfter INT,\n refreshInterval INT,\n FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE\n)");
|
||||
yield Zotero.DB.queryAsync("CREATE TABLE feedItems (\n itemID INTEGER PRIMARY KEY,\n guid TEXT NOT NULL UNIQUE,\n readTime TIMESTAMP,\n FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE\n)");
|
||||
}
|
||||
|
||||
if (i == 81) {
|
||||
|
@ -2214,6 +2211,14 @@ Zotero.Schema = new function(){
|
|||
yield Zotero.DB.queryAsync("INSERT INTO itemTypeFields VALUES (17, 98, NULL, 8)");
|
||||
yield Zotero.DB.queryAsync("INSERT INTO itemTypeFields VALUES (17, 42, NULL, 9)");
|
||||
}
|
||||
|
||||
if (i == 83) {
|
||||
// Feeds
|
||||
yield Zotero.DB.queryAsync("DROP TABLE IF EXISTS feeds");
|
||||
yield Zotero.DB.queryAsync("DROP TABLE IF EXISTS feedItems");
|
||||
yield Zotero.DB.queryAsync("CREATE TABLE feeds (\n libraryID INTEGER PRIMARY KEY,\n name TEXT NOT NULL,\n url TEXT NOT NULL UNIQUE,\n lastUpdate TIMESTAMP,\n lastCheck TIMESTAMP,\n lastCheckError TEXT,\n lastGUID TEXT,\n cleanupAfter INT,\n refreshInterval INT,\n FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE\n)");
|
||||
yield Zotero.DB.queryAsync("CREATE TABLE feedItems (\n itemID INTEGER PRIMARY KEY,\n guid TEXT NOT NULL UNIQUE,\n readTime TIMESTAMP,\n translatedTime TIMESTAMP,\n FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE\n)");
|
||||
}
|
||||
}
|
||||
|
||||
yield _updateDBVersion('userdata', toVersion);
|
||||
|
|
|
@ -1376,7 +1376,9 @@ var ZoteroPane = new function()
|
|||
}
|
||||
|
||||
if (item.isFeedItem) {
|
||||
item.translate();
|
||||
if (! item.isTranslated) {
|
||||
item.translate();
|
||||
}
|
||||
this.startItemReadTimeout(item.id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ pref("extensions.zotero.lastLongTagMode", 0);
|
|||
pref("extensions.zotero.lastLongTagDelimiter", ";");
|
||||
|
||||
pref("extensions.zotero.fallbackSort", 'firstCreator,date,title,dateAdded');
|
||||
pref("extensions.zotero.feedSortAsc", false);
|
||||
pref("extensions.zotero.sortCreatorAsString", false);
|
||||
|
||||
//Tag Cloud
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
-- 82
|
||||
-- 83
|
||||
|
||||
-- Copyright (c) 2009 Center for History and New Media
|
||||
-- George Mason University, Fairfax, Virginia, USA
|
||||
|
@ -203,6 +203,7 @@ CREATE TABLE feeds (
|
|||
lastUpdate TIMESTAMP,
|
||||
lastCheck TIMESTAMP,
|
||||
lastCheckError TEXT,
|
||||
lastGUID TEXT,
|
||||
cleanupAfter INT,
|
||||
refreshInterval INT,
|
||||
FOREIGN KEY (libraryID) REFERENCES libraries(libraryID) ON DELETE CASCADE
|
||||
|
@ -212,6 +213,7 @@ CREATE TABLE feedItems (
|
|||
itemID INTEGER PRIMARY KEY,
|
||||
guid TEXT NOT NULL UNIQUE,
|
||||
readTime TIMESTAMP,
|
||||
translatedTime TIMESTAMP,
|
||||
FOREIGN KEY (itemID) REFERENCES items(itemID) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
|
|
|
@ -19,11 +19,6 @@
|
|||
<pubDate>Tue, 03 Jun 2003 09:39:21 GMT</pubDate>
|
||||
<guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>
|
||||
</item>
|
||||
<item>
|
||||
<description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm">partial eclipse of the Sun</a> on Saturday, May 31st.</description>
|
||||
<pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
|
||||
<guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>
|
||||
</item>
|
||||
<item>
|
||||
<title>The Engine That Does More</title>
|
||||
<link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
|
||||
|
|
|
@ -13,17 +13,17 @@
|
|||
<managingEditor>editor@example.com</managingEditor>
|
||||
<webMaster>webmaster@example.com</webMaster>
|
||||
<item>
|
||||
<title>Star City</title>
|
||||
<description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm">partial eclipse of the Sun</a> on Saturday, May 31st.</description>
|
||||
<pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
|
||||
<guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>
|
||||
</item>
|
||||
<item>
|
||||
<title>Star City (Updated)</title>
|
||||
<link>http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp</link>
|
||||
<description>How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's <a href="http://howe.iki.rssi.ru/GCTC/gctc_e.htm">Star City</a>.</description>
|
||||
<pubDate>Tue, 03 Jun 2037 09:39:21 GMT</pubDate>
|
||||
<guid>http://liftoff.msfc.nasa.gov/2003/06/03.html#item573</guid>
|
||||
</item>
|
||||
<item>
|
||||
<description>Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a <a href="http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm">partial eclipse of the Sun</a> on Saturday, May 31st.</description>
|
||||
<pubDate>Fri, 30 May 2003 11:06:42 GMT</pubDate>
|
||||
<guid>http://liftoff.msfc.nasa.gov/2003/05/30.html#item572</guid>
|
||||
</item>
|
||||
<item>
|
||||
<title>The Engine That Does More</title>
|
||||
<link>http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp</link>
|
||||
|
|
|
@ -111,14 +111,13 @@ describe("Zotero.FeedReader", function () {
|
|||
title: 'Star City',
|
||||
abstractNote: 'How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia\'s Star City.',
|
||||
url: 'http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp',
|
||||
dateModified: '2003-06-03 09:39:21',
|
||||
dateAdded: '2003-06-03 09:39:21',
|
||||
creators: [{
|
||||
firstName: '',
|
||||
lastName: 'editor@example.com',
|
||||
creatorType: 'author',
|
||||
fieldMode: 1
|
||||
}],
|
||||
date: 'Tue, 03 Jun 2003 09:39:21 GMT',
|
||||
language: 'en-us',
|
||||
itemType: 'journalArticle'
|
||||
};
|
||||
|
@ -136,8 +135,6 @@ describe("Zotero.FeedReader", function () {
|
|||
title: 'Title 1',
|
||||
abstractNote: 'Description 1',
|
||||
url: 'http://www.example.com/item1',
|
||||
dateModified: '2016-01-07 00:00:00',
|
||||
dateAdded: '2016-01-07 00:00:00',
|
||||
creators: [
|
||||
{ firstName: 'Author1 A. T.', lastName: 'Rohtua', creatorType: 'author' },
|
||||
{ firstName: 'Author2 A.', lastName: 'Auth', creatorType: 'author' },
|
||||
|
|
|
@ -206,9 +206,16 @@ describe("Zotero.Feed", function() {
|
|||
});
|
||||
|
||||
describe('#updateFeed()', function() {
|
||||
var feed;
|
||||
var feedUrl = getTestDataItemUrl("feed.rss");
|
||||
var modifiedFeedUrl = getTestDataItemUrl("feedModified.rss");
|
||||
|
||||
beforeEach(function* (){
|
||||
feed = yield createFeed();
|
||||
feed._feedUrl = feedUrl;
|
||||
yield feed.updateFeed();
|
||||
});
|
||||
|
||||
afterEach(function* () {
|
||||
yield clearFeeds();
|
||||
});
|
||||
|
@ -225,15 +232,11 @@ describe("Zotero.Feed", function() {
|
|||
});
|
||||
|
||||
it('should add new feed items', function* () {
|
||||
let feed = yield createFeed();
|
||||
feed._feedUrl = feedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
|
||||
assert.equal(feedItems.length, 4);
|
||||
assert.equal(feedItems.length, 3);
|
||||
});
|
||||
|
||||
it('should set lastCheck and lastUpdated values', function* () {
|
||||
it('should set lastCheck, lastUpdated and lastGUID values', function* () {
|
||||
let feed = yield createFeed();
|
||||
feed._feedUrl = feedUrl;
|
||||
|
||||
|
@ -244,61 +247,36 @@ describe("Zotero.Feed", function() {
|
|||
|
||||
assert.ok(feed.lastCheck >= Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60), true));
|
||||
assert.ok(feed.lastUpdate >= Zotero.Date.dateToSQL(new Date(Date.now() - 1000*60), true));
|
||||
assert.equal(feed.lastGUID, 'http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:'+feed.id);
|
||||
});
|
||||
it('should update modified items and set unread', function* () {
|
||||
let feed = yield createFeed();
|
||||
feed._feedUrl = feedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
let feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
|
||||
feedItem.isRead = true;
|
||||
yield feedItem.forceSaveTx();
|
||||
feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
|
||||
assert.isTrue(feedItem.isRead);
|
||||
|
||||
let oldDateModified = feedItem.dateModified;
|
||||
let oldDateModified = feedItem.getField('date');
|
||||
|
||||
feed._feedUrl = modifiedFeedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
feedItem = yield Zotero.FeedItems.getAsyncByGUID("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
|
||||
|
||||
assert.notEqual(oldDateModified, feedItem.dateModified);
|
||||
assert.notEqual(oldDateModified, feedItem.getField('date'));
|
||||
assert.isFalse(feedItem.isRead)
|
||||
});
|
||||
it('should skip items that are not modified', function* () {
|
||||
let feed = yield createFeed();
|
||||
feed._feedUrl = feedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
|
||||
let datesAdded = [], datesModified = [];
|
||||
for(let feedItem of feedItems) {
|
||||
datesAdded.push(feedItem.dateAdded);
|
||||
datesModified.push(feedItem.dateModified);
|
||||
}
|
||||
let save = sinon.spy(Zotero.FeedItem.prototype, 'save');
|
||||
|
||||
feed._feedUrl = modifiedFeedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
feedItems = yield Zotero.FeedItems.getAll(feed.id);
|
||||
|
||||
let changedCount = 0;
|
||||
for (let i = 0; i < feedItems.length; i++) {
|
||||
assert.equal(feedItems[i].dateAdded, datesAdded[i]);
|
||||
if (feedItems[i].dateModified != datesModified[i]) {
|
||||
changedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
assert.equal(changedCount, 1);
|
||||
assert.equal(save.thisValues[0].guid, "http://liftoff.msfc.nasa.gov/2003/06/03.html#item573:"+feed.id);
|
||||
save.restore();
|
||||
});
|
||||
it('should update unread count', function* () {
|
||||
let feed = yield createFeed();
|
||||
feed._feedUrl = feedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
assert.equal(feed.unreadCount, 4);
|
||||
assert.equal(feed.unreadCount, 3);
|
||||
|
||||
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
|
||||
for (let feedItem of feedItems) {
|
||||
|
@ -309,7 +287,22 @@ describe("Zotero.Feed", function() {
|
|||
feed._feedUrl = modifiedFeedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
assert.equal(feed.unreadCount, 1);
|
||||
assert.equal(feed.unreadCount, 2);
|
||||
});
|
||||
it('should not re-add deleted items, but add new ones', function* () {
|
||||
let feedItems = yield Zotero.FeedItems.getAll(feed.id);
|
||||
yield feedItems[1].forceEraseTx();
|
||||
|
||||
feedItems = yield Zotero.FeedItems.getAll(feed.id);
|
||||
for (let feedItem of feedItems) {
|
||||
feedItem.isRead = true;
|
||||
yield feedItem.forceSaveTx();
|
||||
}
|
||||
|
||||
feed._feedUrl = modifiedFeedUrl;
|
||||
yield feed.updateFeed();
|
||||
|
||||
assert.equal(feed.unreadCount, 2);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue