Skip to content

Commit

Permalink
Merge changes from upstream Zotero
Browse files Browse the repository at this point in the history
  • Loading branch information
fbennett committed Mar 9, 2019
2 parents fb3aef6 + c735423 commit ee54fa9
Show file tree
Hide file tree
Showing 10 changed files with 676 additions and 503 deletions.
747 changes: 376 additions & 371 deletions .eslintrc

Large diffs are not rendered by default.

19 changes: 15 additions & 4 deletions chrome/content/zotero/bindings/itembox.xml
Expand Up @@ -3977,10 +3977,21 @@
newIndex = index + 1;
break;
}
var a = this.item.getCreator(index);
var b = this.item.getCreator(newIndex);
this.item.setCreator(newIndex, a);
this.item.setCreator(index, b);
let creator = this.item.getCreator(index);
// When moving to top, increment index of all other creators
if (dir == 'top') {
let otherCreators = this.item.getCreators();
this.item.setCreator(newIndex, creator);
for (let i = 0; i < index; i++) {
this.item.setCreator(i + 1, otherCreators[i]);
}
}
// When moving up or down, swap places with next creator
else {
let otherCreator = this.item.getCreator(newIndex);
this.item.setCreator(newIndex, creator);
this.item.setCreator(index, otherCreator);
}
if (this.saveOnEdit) {
// See note in transformText()
yield this.blurOpenField();
Expand Down
65 changes: 52 additions & 13 deletions chrome/content/zotero/containers/tagSelector.jsx
Expand Up @@ -68,26 +68,28 @@ Zotero.TagSelector = class TagSelectorContainer extends React.Component {
default:
return;
}
return this.setState({tags: await this.getTags()});
}

// Ignore item events other than 'trash'
if (type == 'item' && (event == 'trash')) {
if (type == 'item' || type == 'item-tag') {
return this.setState({tags: await this.getTags()});
}

// If a selected tag no longer exists, deselect it
if (type == 'item-tag') {
if (event == 'delete' || event == 'trash' || event == 'modify') {
for (let tag of this.selectedTags) {
if (tag == extraData[ids[0]].old.tag) {
this.selectedTags.delete(tag);
}
if (type == 'tag' && (event == 'modify' || event == 'delete')) {
let changed = false;
for (let id of ids) {
let tag = extraData[id].old.tag;
if (this.selectedTags.has(tag)) {
this.selectedTags.delete(tag);
changed = true;
}
}
return this.setState({tags: await this.getTags()});
if (changed && typeof(this.props.onSelection) === 'function') {
this.props.onSelection(this.selectedTags);
}
return;
}

this.setState({tags: await this.getTags()});
}

async getTags(tagsInScope, tagColors) {
Expand Down Expand Up @@ -157,7 +159,7 @@ Zotero.TagSelector = class TagSelectorContainer extends React.Component {
onSelect={this.state.viewOnly ? () => {} : this.handleTagSelected}
onTagContext={this.handleTagContext}
onSearch={this.handleSearch}
onSettings={this.handleSettings}
onSettings={this.handleSettings.bind(this)}
loaded={this.state.loaded}
/>;
}
Expand Down Expand Up @@ -387,6 +389,43 @@ Zotero.TagSelector = class TagSelectorContainer extends React.Component {
this.props.onSelection(this.selectedTags);
}
}

async deleteAutomatic() {
var num = (await Zotero.Tags.getAutomaticInLibrary(this.libraryID)).length;
if (!num) {
return;
}

var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var confirmed = ps.confirm(
window,
Zotero.getString('pane.tagSelector.deleteAutomatic.title'),
Zotero.getString(
'pane.tagSelector.deleteAutomatic.message',
new Intl.NumberFormat().format(num),
num
)
+ "\n\n"
+ Zotero.getString('general.actionCannotBeUndone')
);
if (confirmed) {
Zotero.showZoteroPaneProgressMeter(null, true);
try {
await Zotero.Tags.removeAutomaticFromLibrary(
this.libraryID,
(progress, progressMax) => {
Zotero.updateZoteroPaneProgressMeter(
Math.round(progress / progressMax * 100)
);
}
);
}
finally {
Zotero.hideZoteroPaneOverlays();
}
}
}

get label() {
let count = this.selectedTags.size;
Expand Down
17 changes: 16 additions & 1 deletion chrome/content/zotero/containers/tagSelector.xul
Expand Up @@ -41,7 +41,18 @@
onpopupshowing="
document.getElementById('show-automatic').setAttribute('checked', ZoteroPane.tagSelector.showAutomatic);
document.getElementById('display-all-tags').setAttribute('checked', ZoteroPane.tagSelector.displayAllTags);
document.getElementById('num-selected').label = ZoteroPane.tagSelector.label">
document.getElementById('num-selected').label = ZoteroPane.tagSelector.label;
(async function () {
var libraryID = ZoteroPane.tagSelector.libraryID;
var library = Zotero.Libraries.get(libraryID);
var enabled = false;
if (library.editable) {
if ((await Zotero.Tags.getAutomaticInLibrary(libraryID)).length) {
enabled = true;
}
}
document.getElementById('delete-automatic-tags').disabled = !enabled;
})();">
<menuitem id="num-selected" disabled="true"/>
<menuitem id="deselect-all" label="&zotero.tagSelector.clearAll;"
oncommand="ZoteroPane.tagSelector.deselectAll(); event.stopPropagation();"/>
Expand All @@ -54,5 +65,9 @@
type="checkbox"
oncommand="ZoteroPane.tagSelector.toggleDisplayAllTags(); event.stopPropagation();"
/>
<menuitem id="delete-automatic-tags" label="&zotero.tagSelector.deleteAutomaticInLibrary;" type="checkbox"
oncommand="ZoteroPane.tagSelector.deleteAutomatic();
this.setAttribute('checked', false);
event.stopPropagation();"/>
</menupopup>
</overlay>
3 changes: 2 additions & 1 deletion chrome/content/zotero/overlay.js
Expand Up @@ -83,7 +83,8 @@ var ZoteroOverlay = new function()
if (Zotero.skipLoading) {
throw new Error("Skipping loading");
}


ZoteroPane.Containers.init();
ZoteroPane.init();

// Clear old Zotero icon pref
Expand Down
2 changes: 1 addition & 1 deletion chrome/content/zotero/xpcom/data/item.js
Expand Up @@ -4214,7 +4214,7 @@ Zotero.Item.prototype.getImageSrc = function() {
if (itemType == 'attachment') {
var linkMode = this.attachmentLinkMode;

if (this.attachmentContentType == 'application/pdf') {
if (this.attachmentContentType == 'application/pdf' && this.isFileAttachment()) {
if (linkMode == Zotero.Attachments.LINK_MODE_LINKED_FILE) {
itemType += '-pdf-link';
}
Expand Down
125 changes: 63 additions & 62 deletions chrome/content/zotero/xpcom/data/tags.js
Expand Up @@ -281,105 +281,101 @@ Zotero.Tags = new function() {


/**
* @param {Integer} libraryID
* @param {Integer[]} tagIDs
* @param {Function} [onProgress]
* @param {Integer[]} [types]
* @return {Promise}
*/
this.removeFromLibrary = Zotero.Promise.coroutine(function* (libraryID, tagIDs, onProgress) {
this.removeFromLibrary = Zotero.Promise.coroutine(function* (libraryID, tagIDs, onProgress, types) {
var d = new Date();

tagIDs = Zotero.flattenArguments(tagIDs);
if (!Array.isArray(tagIDs)) {
tagIDs = [tagIDs];
}
if (types && !Array.isArray(types)) {
types = [types];
}

var deletedNames = [];
var colors = this.getColors(libraryID);
var done = 0;

yield Zotero.Utilities.Internal.forEachChunkAsync(
tagIDs,
100,
async function (chunk) {
await Zotero.DB.executeTransaction(function* () {
var oldItemIDs = [];

var notifierPairs = [];
var rowIDs = [];
var itemIDs = [];
var uniqueTags = new Set();
var notifierIDs = [];
var notifierData = {};
var a = new Date();

var sql = 'SELECT tagID, itemID FROM itemTags JOIN items USING (itemID) '
var sql = 'SELECT IT.ROWID AS rowID, tagID, itemID, type FROM itemTags IT '
+ 'JOIN items USING (itemID) '
+ 'WHERE libraryID=? AND tagID IN ('
+ Array(chunk.length).fill('?').join(', ')
+ ') ORDER BY tagID';
var chunkTagItems = yield Zotero.DB.queryAsync(sql, [libraryID, ...chunk]);
var i = 0;

chunk.sort((a, b) => a - b);

for (let tagID of chunk) {
+ ') ';
if (types) {
sql += 'AND type IN (' + types.join(', ') + ') ';
}
sql += 'ORDER BY tagID, type';
var rows = yield Zotero.DB.queryAsync(sql, [libraryID, ...chunk]);
for (let { rowID, tagID, itemID, type } of rows) {
uniqueTags.add(tagID);

let name = this.getName(tagID);
if (name === false) {
continue;
}
deletedNames.push(name);

// Since we're performing the DELETE query directly,
// get the list of items that will need their tags reloaded,
// and generate data for item-tag notifications
let itemIDs = []
while (i < chunkTagItems.length && chunkTagItems[i].tagID == tagID) {
itemIDs.push(chunkTagItems[i].itemID);
i++;
}
for (let itemID of itemIDs) {
let pair = itemID + "-" + tagID;
notifierPairs.push(pair);
notifierData[pair] = {
libraryID: libraryID,
tag: name
};
rowIDs.push(rowID);
itemIDs.push(itemID);

let ids = itemID + '-' + tagID;
notifierIDs.push(ids);
notifierData[ids] = {
libraryID: libraryID,
tag: name,
type
};

// If we're deleting the tag and not just a specific type, also clear any
// tag color
if (colors.has(name) && !types) {
yield this.setColor(libraryID, name, false);
}
oldItemIDs = oldItemIDs.concat(itemIDs);
}
if (oldItemIDs.length) {
Zotero.Notifier.queue('remove', 'item-tag', notifierPairs, notifierData);
if (itemIDs.length) {
Zotero.Notifier.queue('remove', 'item-tag', notifierIDs, notifierData);
}

var sql = "DELETE FROM itemTags WHERE tagID IN ("
+ Array(chunk.length).fill('?').join(', ') + ") AND itemID IN "
+ "(SELECT itemID FROM items WHERE libraryID=?)";
yield Zotero.DB.queryAsync(sql, chunk.concat([libraryID]));
sql = "DELETE FROM itemTags WHERE ROWID IN (" + rowIDs.join(", ") + ")";
yield Zotero.DB.queryAsync(sql);

yield this.purge(chunk);

// Update internal timestamps on all items that had these tags
yield Zotero.Utilities.Internal.forEachChunkAsync(
Zotero.Utilities.arrayUnique(oldItemIDs),
Zotero.Utilities.arrayUnique(itemIDs),
Zotero.DB.MAX_BOUND_PARAMETERS - 1,
Zotero.Promise.coroutine(function* (chunk2) {
var placeholders = Array(chunk2.length).fill('?').join(',');
async function (chunk) {
var sql = 'UPDATE items SET synced=0, clientDateModified=? '
+ 'WHERE itemID IN (' + Array(chunk.length).fill('?').join(',') + ')';
await Zotero.DB.queryAsync(sql, [Zotero.DB.transactionDateTime].concat(chunk));

sql = 'UPDATE items SET synced=0, clientDateModified=? '
+ 'WHERE itemID IN (' + placeholders + ')'
yield Zotero.DB.queryAsync(sql, [Zotero.DB.transactionDateTime].concat(chunk2));

yield Zotero.Items.reload(oldItemIDs, ['primaryData', 'tags'], true);
})
await Zotero.Items.reload(itemIDs, ['primaryData', 'tags'], true);
}
);

done += chunk.length;
if (onProgress) {
done += uniqueTags.size;
onProgress(done, tagIDs.length);
}
}.bind(this));

if (onProgress) {
onProgress(done, tagIDs.length);
}
}.bind(this)
);

// Also delete tag color setting
//
// Note that this isn't done in purge(), so the setting will not
// be removed if the tag is just removed from all items without
// being explicitly deleted.
for (let i=0; i<deletedNames.length; i++) {
yield this.setColor(libraryID, deletedNames[i], false);
}

Zotero.debug(`Removed ${tagIDs.length} ${Zotero.Utilities.pluralize(tagIDs.length, 'tag')} `
+ `in ${new Date() - d} ms`);
});
Expand All @@ -400,11 +396,12 @@ Zotero.Tags = new function() {
* Remove all automatic tags in the given library
*/
this.removeAutomaticFromLibrary = async function (libraryID, onProgress) {
var tagType = 1;
var tagIDs = await this.getAutomaticInLibrary(libraryID);
if (onProgress) {
onProgress(0, tagIDs.length);
}
return this.removeFromLibrary(libraryID, tagIDs, onProgress);
return this.removeFromLibrary(libraryID, tagIDs, onProgress, tagType);
};


Expand All @@ -429,6 +426,10 @@ Zotero.Tags = new function() {
tagIDs = Zotero.flattenArguments(tagIDs);
}

if (tagIDs && !tagIDs.length) {
return;
}

Zotero.DB.requireTransaction();

var sql;
Expand Down
3 changes: 2 additions & 1 deletion resource/schema/renamed-styles.json
Expand Up @@ -280,7 +280,8 @@
"frontiers-in-vascular-physiology": "frontiers",
"frontiers-in-virology": "frontiers",
"frontiers-in-womens-cancer": "frontiers",
"future-science": "future-science-journals",
"future-science": "future-science-group",
"future-science-journals": "future-science-group",
"geistes-und-kulturwissenschaften-teilmann": "geistes-und-kulturwissenschaften-heilmann",
"genetic-vaccines-and-therapy": "biomed-central",
"geological-society-america-bulletin": "geological-society-of-america-bulletin",
Expand Down

0 comments on commit ee54fa9

Please sign in to comment.