Skip to content

Commit

Permalink
Merge from upstream Zotero
Browse files Browse the repository at this point in the history
  • Loading branch information
fbennett committed May 21, 2017
2 parents 29d14f3 + ddc9989 commit b00e675
Show file tree
Hide file tree
Showing 14 changed files with 306 additions and 41 deletions.
14 changes: 13 additions & 1 deletion chrome/content/zotero/bindings/noteeditor.xml
Expand Up @@ -201,10 +201,13 @@
//var scrollPos = textbox.inputField.scrollTop;
if (this.item) {
// For sanity check in save()
textbox.setAttribute('itemID', this.item.id);
textbox.value = this.item.getNote();
}
else {
textbox.value = '';
textbox.removeAttribute('itemID');
}
//textbox.inputField.scrollTop = scrollPos;
Expand Down Expand Up @@ -251,6 +254,15 @@
// Update note
var noteField = this._id('noteField');
if (this.item) {
// If note field doesn't match item, abort save and run error handler
if (noteField.getAttribute('itemID') != this.item.id) {
if (this.hasAttribute('onerror')) {
let fn = new Function("", this.getAttribute('onerror'));
fn.call(this)
}
throw new Error("Note field doesn't match current item");
}
let changed = this.item.setNote(noteField.value);
if (changed && this.saveOnEdit) {
this.noteField.changed = false;
Expand Down Expand Up @@ -548,7 +560,7 @@
</xul:rows>
</xul:grid>
<xul:popupset>
<xul:menupopup id="relatedPopup" width="300" onpopupshowing="this.firstChild.reload();">
<xul:menupopup id="relatedPopup" width="300" onpopupshowing="this.firstChild.refresh();">
<xul:relatedbox id="related" flex="1"/>
</xul:menupopup>
<!-- The onpopup* stuff is an ugly hack to keep track of when the
Expand Down
12 changes: 11 additions & 1 deletion chrome/content/zotero/bindings/relatedbox.xml
Expand Up @@ -81,6 +81,11 @@
if (keys.length) {
for (let key of keys) {
let item = Zotero.Items.getByLibraryAndKey(this.item.libraryID, key);
if (!item) {
Zotero.debug(`Related item ${this.item.libraryID}/${key} not found `
+ `for item ${this.item.libraryKey}`, 2);
continue;
}
r = r + item.getDisplayTitle() + ", ";
}
r = r.substr(0,r.length-2);
Expand Down Expand Up @@ -139,6 +144,11 @@
let relatedItem = Zotero.Items.getByLibraryAndKey(
this.item.libraryID, key
);
if (!relatedItem) {
Zotero.debug(`Related item ${this.item.libraryID}/${key} not found `
+ `for item ${this.item.libraryKey}`, 2);
continue;
}
let id = relatedItem.id;
let icon = document.createElement("image");
icon.className = "zotero-box-icon";
Expand Down Expand Up @@ -194,7 +204,7 @@
}
rows.appendChild(row);
}
this.updateCount(relatedKeys.length);
this.updateCount(rows.childNodes.length);
}
]]></body>
</method>
Expand Down
34 changes: 28 additions & 6 deletions chrome/content/zotero/fileInterface.js
Expand Up @@ -107,7 +107,11 @@ Zotero_File_Exporter.prototype._exportDone = function(obj, worked) {
Zotero_File_Interface.Progress.close();

if(!worked) {
window.alert(Zotero.getString("fileInterface.exportError"));
Zotero.alert(
null,
Zotero.getString('general.error'),
Zotero.getString("fileInterface.exportError")
);
}
}

Expand Down Expand Up @@ -191,7 +195,9 @@ var Zotero_File_Interface = new function() {
*/
function _copyToClipboard(obj, worked) {
if(!worked) {
window.alert(Zotero.getString("fileInterface.exportError"));
Zotero.alert(
null, Zotero.getString('general.error'), Zotero.getString("fileInterface.exportError")
);
} else {
Components.classes["@mozilla.org/widget/clipboardhelper;1"]
.getService(Components.interfaces.nsIClipboardHelper)
Expand Down Expand Up @@ -250,7 +256,11 @@ var Zotero_File_Interface = new function() {
if(!str) {
var ps = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
ps.alert(null, "", Zotero.getString('fileInterface.importClipboardNoDataError'));
ps.alert(
null,
Zotero.getString('general.error'),
Zotero.getString('fileInterface.importClipboardNoDataError')
);
}

var translation = new Zotero.Translate.Import();
Expand Down Expand Up @@ -355,7 +365,11 @@ var Zotero_File_Interface = new function() {
});
} catch(e) {
Zotero.logError(e);
window.alert(Zotero.getString("fileInterface.importError"));
Zotero.alert(
null,
Zotero.getString('general.error'),
Zotero.getString("fileInterface.importError")
);
return;
}

Expand Down Expand Up @@ -500,7 +514,11 @@ var Zotero_File_Interface = new function() {
}
}
if (!haveRegularItem) {
window.alert(Zotero.getString("fileInterface.noReferencesError"));
Zotero.alert(
null,
Zotero.getString('general.error'),
Zotero.getString("fileInterface.noReferencesError")
);
return;
}

Expand Down Expand Up @@ -538,7 +556,11 @@ var Zotero_File_Interface = new function() {
items, format, io.mode === "citations");
}
} catch(e) {
window.alert(Zotero.getString("fileInterface.bibliographyGenerationError"));
Zotero.alert(
null,
Zotero.getString('general.error'),
Zotero.getString("fileInterface.bibliographyGenerationError")
);
throw(e);
}

Expand Down
8 changes: 7 additions & 1 deletion chrome/content/zotero/itemPane.xul
Expand Up @@ -107,7 +107,13 @@

<!-- Note item -->
<groupbox id="zotero-view-note" flex="1">
<zoteronoteeditor id="zotero-note-editor" flex="1" notitle="1" previousfocus="zotero-items-tree"/>
<!--
'onerror' handler crashes the app on a save error to prevent typing in notes
while they're not being saved
-->
<zoteronoteeditor id="zotero-note-editor" flex="1" notitle="1"
previousfocus="zotero-items-tree"
onerror="ZoteroPane.displayErrorMessage()"/>
<button id="zotero-view-note-button" label="&zotero.notes.separate;" oncommand="ZoteroPane_Local.openNoteWindow(this.getAttribute('noteID')); if(this.hasAttribute('sourceID')) ZoteroPane_Local.selectItem(this.getAttribute('sourceID'));"/>
</groupbox>

Expand Down
23 changes: 18 additions & 5 deletions chrome/content/zotero/xpcom/citeproc.js
Expand Up @@ -23,7 +23,7 @@
* <http://www.gnu.org/licenses/> respectively.
*/
var CSL = {
PROCESSOR_VERSION: "1.1.165",
PROCESSOR_VERSION: "1.1.167",
CONDITION_LEVEL_TOP: 1,
CONDITION_LEVEL_BOTTOM: 2,
PLAIN_HYPHEN_REGEX: /(?:[^\\]-|\u2013)/,
Expand Down Expand Up @@ -3796,6 +3796,10 @@ CSL.Output.Queue.prototype.append = function (str, tokname, notSerious, ignorePr
this.state.parallel.AppendBlobPointer(curr);
}
if ("string" === typeof str) {
if ("string" === typeof blob.blobs && [':', '!', '?', '.', ',', ';'].indexOf(blob.blobs.slice(0, 1)) > -1) {
blob.strings.prefix = blob.strings.prefix + blob.blobs.slice(0, 1);
blob.blobs = blob.blobs.slice(1);
}
if (blob.strings["text-case"]) {
blob.blobs = CSL.Output.Formatters[blob.strings["text-case"]](this.state, str);
}
Expand Down Expand Up @@ -14689,7 +14693,7 @@ CSL.Util.FlipFlopper = function(state) {
}
return false;
}
function _undoppelToQueue(blob, doppel) {
function _undoppelToQueue(blob, doppel, leadingSpace) {
var TOP = blob;
var firstString = true;
var tagReg = new _TagReg(blob);
Expand Down Expand Up @@ -14767,7 +14771,11 @@ CSL.Util.FlipFlopper = function(state) {
};
var stack = new Stack(blob);
if (doppel.strings.length) {
stack.addStyling(doppel.strings[0]);
var str = doppel.strings[0];
if (leadingSpace) {
str = " " + str;
}
stack.addStyling(str);
}
for (var i=0,ilen=doppel.tags.length;i<ilen;i++) {
var tag = doppel.tags[i];
Expand All @@ -14783,7 +14791,12 @@ CSL.Util.FlipFlopper = function(state) {
}
}
function processTags(blob) {
var str = " " + blob.blobs;
var str = blob.blobs;
var leadingSpace = false;
if (str.slice(0, 1) === " " && !str.match(/^\s+[\'\"]/)) {
leadingSpace = true;
}
var str = " " + str;
var doppel = _doppelString(str);
if (doppel.tags.length === 0) return;
var quoteFormSeen = false;
Expand Down Expand Up @@ -14862,7 +14875,7 @@ CSL.Util.FlipFlopper = function(state) {
doppel.strings[i] += tag.slice(0, 1);
}
}
_undoppelToQueue(blob, doppel);
_undoppelToQueue(blob, doppel, leadingSpace);
}
}
CSL.Output.Formatters = new function () {
Expand Down
12 changes: 10 additions & 2 deletions chrome/content/zotero/xpcom/data/item.js
Expand Up @@ -1523,6 +1523,8 @@ for (let name of ['deleted', 'inPublications']) {


/**
* Relate this item to another. A separate save is required.
*
* @param {Zotero.Item}
* @return {Boolean}
*/
Expand Down Expand Up @@ -4583,8 +4585,14 @@ Zotero.Item.prototype._eraseData = Zotero.Promise.coroutine(function* (env) {
}
}

// Flag related items for notification
// TEMP: Do something with relations
// Remove related-item relations pointing to this item
var relatedItems = Zotero.Relations.getByPredicateAndObject(
'item', Zotero.Relations.relatedItemPredicate, Zotero.URI.getItemURI(this)
);
for (let relatedItem of relatedItems) {
relatedItem.removeRelatedItem(this);
relatedItem.save();
}

// Clear fulltext cache
if (this.isAttachment()) {
Expand Down
2 changes: 1 addition & 1 deletion chrome/content/zotero/xpcom/integration.js
Expand Up @@ -1014,7 +1014,7 @@ Zotero.Integration.Document.prototype._getSession = Zotero.Promise.coroutine(fun
data.prefs.fieldType = "ReferenceMark";
}

var warning = this._doc.displayAlert(Zotero.getString("integration.upgradeWarning", Zotero.clientName, '5.0'),
var warning = this._doc.displayAlert(Zotero.getString("integration.upgradeWarning", [Zotero.clientName, '5.0']),
DIALOG_ICON_WARNING, DIALOG_BUTTONS_OK_CANCEL);
if(!warning) {
return Zotero.Promise.reject(new Zotero.Exception.UserCancelled("document upgrade"));
Expand Down
53 changes: 34 additions & 19 deletions chrome/content/zotero/xpcom/schema.js
Expand Up @@ -1278,61 +1278,72 @@ Zotero.Schema = new function(){
}


// For non-foreign key checks, there should be an equivalent entry for every statement
// run by the DB Repair Tool. Repair entry (second position) can be either a string or
// an array with multiple statements.
var queries = [
// Non-foreign key checks
//
// The first position is for testing and the second is for repairing. Can be either SQL
// statements or promise-returning functions. For statements, the repair entry can be either a
// string or an array with multiple statements. Functions should avoid assuming any global state
// (e.g., loaded data).
var checks = [
// Can't be a FK with itemTypesCombined
[
"SELECT COUNT(*) FROM items WHERE itemTypeID IS NULL",
"SELECT COUNT(*) > 1 FROM items WHERE itemTypeID IS NULL",
"DELETE FROM items WHERE itemTypeID IS NULL",
],
// Attachments row with itemTypeID != 14
[
"SELECT COUNT(*) FROM itemAttachments JOIN items USING (itemID) WHERE itemTypeID != 14",
"SELECT COUNT(*) > 1 FROM itemAttachments JOIN items USING (itemID) WHERE itemTypeID != 14",
"UPDATE items SET itemTypeID=14, clientDateModified=CURRENT_TIMESTAMP WHERE itemTypeID != 14 AND itemID IN (SELECT itemID FROM itemAttachments)",
],
// Fields not in type
[
"SELECT COUNT(*) FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM itemTypeFieldsCombined WHERE itemTypeID=(SELECT itemTypeID FROM items WHERE itemID=itemData.itemID))",
"SELECT COUNT(*) > 1 FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM itemTypeFieldsCombined WHERE itemTypeID=(SELECT itemTypeID FROM items WHERE itemID=itemData.itemID))",
"DELETE FROM itemData WHERE fieldID NOT IN (SELECT fieldID FROM itemTypeFieldsCombined WHERE itemTypeID=(SELECT itemTypeID FROM items WHERE itemID=itemData.itemID))",
],
// Missing itemAttachments row
[
"SELECT COUNT(*) FROM items WHERE itemTypeID=14 AND itemID NOT IN (SELECT itemID FROM itemAttachments)",
"SELECT COUNT(*) > 1 FROM items WHERE itemTypeID=14 AND itemID NOT IN (SELECT itemID FROM itemAttachments)",
"INSERT INTO itemAttachments (itemID, linkMode) SELECT itemID, 0 FROM items WHERE itemTypeID=14 AND itemID NOT IN (SELECT itemID FROM itemAttachments)",
],
// Note/child parents
[
"SELECT COUNT(*) FROM itemAttachments WHERE parentItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
"SELECT COUNT(*) > 1 FROM itemAttachments WHERE parentItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
"UPDATE itemAttachments SET parentItemID=NULL WHERE parentItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
],
[
"SELECT COUNT(*) FROM itemNotes WHERE parentItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
"SELECT COUNT(*) > 1 FROM itemNotes WHERE parentItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
"UPDATE itemNotes SET parentItemID=NULL WHERE parentItemID IN (SELECT itemID FROM items WHERE itemTypeID IN (1,14))",
],

// Delete empty creators
// This may cause itemCreator gaps, but that's better than empty creators
[
"SELECT COUNT(*) FROM creators WHERE firstName='' AND lastName=''",
"SELECT COUNT(*) > 1 FROM creators WHERE firstName='' AND lastName=''",
"DELETE FROM creators WHERE firstName='' AND lastName=''"
],

// Non-attachment items in the full-text index
[
"SELECT COUNT(*) FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
"SELECT COUNT(*) > 1 FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
"DELETE FROM fulltextItemWords WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)"
],
// Full-text items must be attachments
[
"SELECT COUNT(*) FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
"SELECT COUNT(*) > 1 FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)",
"DELETE FROM fulltextItems WHERE itemID NOT IN (SELECT itemID FROM items WHERE itemTypeID=14)"
]
];

for (let sql of queries) {
let errorsFound = yield Zotero.DB.valueQueryAsync(sql[0]);
for (let check of checks) {
let errorsFound = false;
// SQL statement
if (typeof check[0] == 'string') {
errorsFound = yield Zotero.DB.valueQueryAsync(check[0]);
}
// Function
else {
errorsFound = yield check[0]();
}
if (!errorsFound) {
continue;
}
Expand All @@ -1342,15 +1353,19 @@ Zotero.Schema = new function(){
if (fix) {
try {
// Single query
if (typeof sql[1] == 'string') {
yield Zotero.DB.queryAsync(sql[1]);
if (typeof check[1] == 'string') {
yield Zotero.DB.queryAsync(check[1]);
}
// Multiple queries
else {
for (let s of sql[1]) {
else if (Array.isArray(check[1])) {
for (let s of check[1]) {
yield Zotero.DB.queryAsync(s);
}
}
// Function
else {
yield check[1]();
}
continue;
}
catch (e) {
Expand Down
11 changes: 9 additions & 2 deletions chrome/content/zotero/xpcom/translation/translate_item.js
Expand Up @@ -792,9 +792,16 @@ Zotero.Translate.ItemGetter.prototype = {
var exportDir = this._exportFileDirectory;

// Add path and filename if not an internet link
var attachFile = Zotero.File.pathToFile(attachmentArray.localPath);
let attachFile;
if (attachmentArray.localPath) {
attachFile = Zotero.File.pathToFile(attachmentArray.localPath);
}
else {
Zotero.logError(`Path doesn't exist for attachment ${attachment.libraryKey} `
+ '-- not exporting file');
}
// TODO: Make async, but that will require translator changes
if (attachFile.exists()) {
if (attachFile && attachFile.exists()) {
attachmentArray.defaultPath = "files/" + attachment.id + "/" + attachFile.leafName;
attachmentArray.filename = attachFile.leafName;

Expand Down

0 comments on commit b00e675

Please sign in to comment.