fx-compat: Update conflict resolution merge window (#3090)
Tests passing, but not yet styled properly
This commit is contained in:
parent
dbefdaac2c
commit
4a77bc4be0
13 changed files with 626 additions and 656 deletions
|
@ -1,452 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
|
|
||||||
Copyright © 2009 Center for History and New Media
|
|
||||||
George Mason University, Fairfax, Virginia, USA
|
|
||||||
http://zotero.org
|
|
||||||
|
|
||||||
This file is part of Zotero.
|
|
||||||
|
|
||||||
Zotero is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Zotero is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!DOCTYPE bindings SYSTEM "chrome://zotero/locale/zotero.dtd">
|
|
||||||
|
|
||||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
|
||||||
xmlns:xbl="http://www.mozilla.org/xbl"
|
|
||||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
||||||
xmlns:html="http://www.w3.org/1999/xhtml">
|
|
||||||
|
|
||||||
<binding id="merge-group">
|
|
||||||
<resources>
|
|
||||||
<stylesheet src="chrome://zotero/skin/merge.css"/>
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
<implementation>
|
|
||||||
<constructor>
|
|
||||||
<![CDATA[
|
|
||||||
this._leftpane = this._id('leftpane');
|
|
||||||
this._rightpane = this._id('rightpane');
|
|
||||||
this._mergepane = this._id('mergepane');
|
|
||||||
]]>
|
|
||||||
</constructor>
|
|
||||||
|
|
||||||
<field name="libraryID"/>
|
|
||||||
|
|
||||||
<field name="_data"/>
|
|
||||||
<property name="data" onget="return this._data;">
|
|
||||||
<setter>
|
|
||||||
<![CDATA[
|
|
||||||
this._data = val;
|
|
||||||
this.refresh();
|
|
||||||
]]>
|
|
||||||
</setter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<property name="merged" onget="return this._mergepane.data"/>
|
|
||||||
|
|
||||||
<field name="_type"/>
|
|
||||||
<property name="type" onget="return this._type;">
|
|
||||||
<setter>
|
|
||||||
<![CDATA[
|
|
||||||
switch (val) {
|
|
||||||
case 'item':
|
|
||||||
case 'attachment':
|
|
||||||
case 'note':
|
|
||||||
case 'annotation':
|
|
||||||
case 'file':
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error(`Unsupported merge object type '${type}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._type = val;
|
|
||||||
var hbox = document.getAnonymousNodes(this)[0];
|
|
||||||
hbox.setAttribute('mergetype', val);
|
|
||||||
]]>
|
|
||||||
</setter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<property name="leftCaption" onset="this._leftpane.caption.label = val"/>
|
|
||||||
<property name="rightCaption" onset="this._rightpane.caption.label = val"/>
|
|
||||||
<property name="mergeCaption" onset="this._mergepane.caption.label = val"/>
|
|
||||||
|
|
||||||
<field name="_leftpane"/>
|
|
||||||
<property name="leftpane" onget="return this._leftpane"/>
|
|
||||||
<field name="_rightpane"/>
|
|
||||||
<property name="rightpane" onget="return this._rightpane"/>
|
|
||||||
<field name="_mergepane"/>
|
|
||||||
<property name="mergepane" onget="return this._mergepane"/>
|
|
||||||
|
|
||||||
<property name="onSelectionChange"/>
|
|
||||||
|
|
||||||
<method name="refresh">
|
|
||||||
<body>
|
|
||||||
<![CDATA[
|
|
||||||
if (this._data.left.deleted && this._data.right.deleted) {
|
|
||||||
throw new Error("'left' and 'right' cannot both be deleted");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for note or attachment
|
|
||||||
this.type = this._getTypeFromObject(
|
|
||||||
this._data.left.deleted ? this._data.right : this._data.left
|
|
||||||
);
|
|
||||||
|
|
||||||
var showButton = this.type != 'item';
|
|
||||||
|
|
||||||
this._leftpane.showButton = showButton;
|
|
||||||
this._rightpane.showButton = showButton;
|
|
||||||
this._leftpane.libraryID = this.libraryID;
|
|
||||||
this._rightpane.libraryID = this.libraryID;
|
|
||||||
this._mergepane.libraryID = this.libraryID;
|
|
||||||
this._leftpane.data = this._data.left;
|
|
||||||
this._rightpane.data = this._data.right;
|
|
||||||
this._mergepane.data = this._data.merge;
|
|
||||||
|
|
||||||
if (this._data.selected == 'left') {
|
|
||||||
this.choosePane(this._leftpane);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.choosePane(this._rightpane);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
Code to display only the different values -- not used
|
|
||||||
|
|
||||||
var diff = this._leftpane.ref.diff(this._rightpane.ref, true);
|
|
||||||
|
|
||||||
var fields = [];
|
|
||||||
var diffFields = [];
|
|
||||||
for (var field in diff[0].primary) {
|
|
||||||
fields.push(field);
|
|
||||||
if (diff[0].primary[field] != diff[1].primary[field]) {
|
|
||||||
diffFields.push(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (var field in diff[0].fields) {
|
|
||||||
fields.push(field);
|
|
||||||
if (diff[0].fields[field] != diff[1].fields[field]) {
|
|
||||||
diffFields.push(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._leftpane.objectbox.fieldOrder = fields;
|
|
||||||
this._rightpane.objectbox.fieldOrder = fields;
|
|
||||||
|
|
||||||
// Display merge pane if item types match
|
|
||||||
if (this._leftpane.ref.itemTypeID == this._rightpane.ref.itemTypeID) {
|
|
||||||
this._leftpane.objectbox.visibleFields = fields;
|
|
||||||
this._rightpane.objectbox.visibleFields = fields;
|
|
||||||
|
|
||||||
this._leftpane.objectbox.clickable = false;
|
|
||||||
this._rightpane.objectbox.clickable = false;
|
|
||||||
this._leftpane.objectbox.clickableFields = diffFields;
|
|
||||||
this._rightpane.objectbox.clickableFields = diffFields;
|
|
||||||
|
|
||||||
var mergeItem = new Zotero.Item(this._leftpane.ref.itemTypeID);
|
|
||||||
this._mergepane.ref = mergeItem;
|
|
||||||
this._mergepane.objectbox.visibleFields = fields;
|
|
||||||
}
|
|
||||||
// Otherwise only allow clicking on item types
|
|
||||||
else {
|
|
||||||
this._leftpane.objectbox.clickableFields = ['itemType'];
|
|
||||||
this._rightpane.objectbox.clickableFields = ['itemType'];
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
this._mergepane.objectbox.editable = true;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
No need to refresh if not comparing fields
|
|
||||||
|
|
||||||
this._leftpane.objectbox.refresh();
|
|
||||||
this._rightpane.objectbox.refresh();
|
|
||||||
*/
|
|
||||||
]]>
|
|
||||||
</body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
|
|
||||||
<method name="choosePane">
|
|
||||||
<parameter name="pane"/>
|
|
||||||
<body>
|
|
||||||
<![CDATA[
|
|
||||||
if (pane.getAttribute('anonid') == 'leftpane') {
|
|
||||||
var position = 'left';
|
|
||||||
var otherPane = this._rightpane;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var position = 'right';
|
|
||||||
var otherPane = this._leftpane;
|
|
||||||
}
|
|
||||||
|
|
||||||
pane.removeAttribute("selected");
|
|
||||||
otherPane.removeAttribute("selected");
|
|
||||||
pane.setAttribute("selected", "true");
|
|
||||||
|
|
||||||
if (pane.deleted) {
|
|
||||||
this._mergepane.deleted = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._mergepane.data = pane.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.onSelectionChange) {
|
|
||||||
this.onSelectionChange();
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
|
|
||||||
<method name="_getTypeFromObject">
|
|
||||||
<parameter name="obj"/>
|
|
||||||
<body>
|
|
||||||
<![CDATA[
|
|
||||||
if (!obj.itemType) {
|
|
||||||
Zotero.debug(obj, 1);
|
|
||||||
throw new Error("obj is not item JSON");
|
|
||||||
}
|
|
||||||
switch (obj.itemType) {
|
|
||||||
case 'attachment':
|
|
||||||
case 'note':
|
|
||||||
case 'annotation':
|
|
||||||
return obj.itemType;
|
|
||||||
}
|
|
||||||
return 'item';
|
|
||||||
]]>
|
|
||||||
</body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="_id">
|
|
||||||
<parameter name="id"/>
|
|
||||||
<body>
|
|
||||||
<![CDATA[
|
|
||||||
return document.getAnonymousNodes(this)[0].getElementsByAttribute('anonid',id)[0];
|
|
||||||
]]>
|
|
||||||
</body>
|
|
||||||
</method>
|
|
||||||
</implementation>
|
|
||||||
|
|
||||||
<content>
|
|
||||||
<xul:hbox id="merge-group" flex="1">
|
|
||||||
<xul:zoteromergepane anonid="leftpane" flex="1"/>
|
|
||||||
<xul:zoteromergepane anonid="rightpane" flex="1"/>
|
|
||||||
<xul:zoteromergepane anonid="mergepane" flex="1"/>
|
|
||||||
</xul:hbox>
|
|
||||||
</content>
|
|
||||||
</binding>
|
|
||||||
|
|
||||||
|
|
||||||
<binding id="merge-pane">
|
|
||||||
<resources>
|
|
||||||
<stylesheet src="chrome://zotero/skin/bindings/merge.css"/>
|
|
||||||
</resources>
|
|
||||||
|
|
||||||
<implementation>
|
|
||||||
<constructor>
|
|
||||||
<![CDATA[
|
|
||||||
this.parent = document.getBindingParent(this.parentNode);
|
|
||||||
this.isMergePane = this.getAttribute('anonid') == 'mergepane';
|
|
||||||
|
|
||||||
if (!this.isMergePane) {
|
|
||||||
this.pane.onclick = function () {
|
|
||||||
this.parent.choosePane(this);
|
|
||||||
}.bind(this);
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</constructor>
|
|
||||||
|
|
||||||
<property name="type" onget="return this.parent.type" readonly="true"/>
|
|
||||||
<property name="caption" onget="return this._id('caption')" readonly="true"/>
|
|
||||||
<field name="showButton"/>
|
|
||||||
<property name="pane" onget="return document.getAnonymousNodes(this)[0]"/>
|
|
||||||
<property name="objectbox" onget="return this._id('objectbox')" readonly="true"/>
|
|
||||||
|
|
||||||
<field name="_deleted"/>
|
|
||||||
<property name="deleted">
|
|
||||||
<setter>
|
|
||||||
<![CDATA[
|
|
||||||
this._deleted = !!val;
|
|
||||||
|
|
||||||
var placeholder = this._id('object-placeholder');
|
|
||||||
if (placeholder) {
|
|
||||||
placeholder.hidden = !!val;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this._id('objectbox').hidden = true;
|
|
||||||
}
|
|
||||||
var deleteBox = this._id('delete-box');
|
|
||||||
deleteBox.hidden = !val;
|
|
||||||
]]>
|
|
||||||
</setter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<field name="libraryID"/>
|
|
||||||
|
|
||||||
<field name="_data"/>
|
|
||||||
<property name="data" onget="return this._data">
|
|
||||||
<setter>
|
|
||||||
<![CDATA[
|
|
||||||
this._data = val;
|
|
||||||
|
|
||||||
var button = this._id('choose-button');
|
|
||||||
button.label = Zotero.getString('sync.conflict.chooseThisVersion');
|
|
||||||
if (this.showButton) {
|
|
||||||
button.onclick = () => this.parent.choosePane(this);
|
|
||||||
button.style.visibility = 'visible';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
button.style.visibility = 'hidden';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val.deleted) {
|
|
||||||
this.deleted = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.deleted = false;
|
|
||||||
|
|
||||||
// Replace XUL placeholder with XUL object box of given type
|
|
||||||
var elementName;
|
|
||||||
switch (this.type) {
|
|
||||||
case 'item':
|
|
||||||
elementName = 'zoteroitembox';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'attachment':
|
|
||||||
case 'file':
|
|
||||||
elementName = 'zoteroattachmentbox';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'note':
|
|
||||||
var type = Zotero.Libraries.get(this.libraryID).libraryType;
|
|
||||||
elementName = 'note-editor';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'annotation':
|
|
||||||
elementName = 'div';
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new Error("Object type '" + this.type + "' not supported");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elementName == 'div') {
|
|
||||||
let HTML_NS = 'http://www.w3.org/1999/xhtml';
|
|
||||||
var objbox = document.createElementNS(HTML_NS, elementName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var objbox = document.createElement(elementName);
|
|
||||||
}
|
|
||||||
|
|
||||||
var parentRow = this._id('parent-row');
|
|
||||||
if (val.parentItem) {
|
|
||||||
parentRow.textContent = '';
|
|
||||||
|
|
||||||
let label = document.createElement('span');
|
|
||||||
label.textContent = Zotero.getString('pane.item.parentItem');
|
|
||||||
parentRow.appendChild(label);
|
|
||||||
|
|
||||||
let parentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, val.parentItem);
|
|
||||||
let text = document.createTextNode(" " + parentItem.getDisplayTitle(true));
|
|
||||||
parentRow.appendChild(text);
|
|
||||||
|
|
||||||
parentRow.hidden = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
parentRow.hidden = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._id('object-placeholder')) {
|
|
||||||
var placeholder = this._id('object-placeholder');
|
|
||||||
placeholder.parentNode.replaceChild(objbox, placeholder);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var oldObjBox = this._id('objectbox');
|
|
||||||
oldObjBox.parentNode.replaceChild(objbox, oldObjBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
objbox.setAttribute("anonid", "objectbox");
|
|
||||||
objbox.setAttribute("flex", "1");
|
|
||||||
objbox.mode = this.type == 'file' ? 'filemerge' : 'merge';
|
|
||||||
|
|
||||||
// Store JSON
|
|
||||||
this._data = val;
|
|
||||||
|
|
||||||
// Create a copy of the JSON that we can clean for display, since the remote object
|
|
||||||
// might reference things that don't exist locally
|
|
||||||
var displayJSON = Object.assign({}, val);
|
|
||||||
displayJSON.collections = [];
|
|
||||||
|
|
||||||
// Create item from JSON for metadata box
|
|
||||||
var item = new Zotero.Item(val.itemType);
|
|
||||||
item.libraryID = this.libraryID;
|
|
||||||
item.fromJSON(displayJSON);
|
|
||||||
|
|
||||||
if (item.isAnnotation()) {
|
|
||||||
Zotero.Annotations.toJSON(item)
|
|
||||||
.then((data) => {
|
|
||||||
Zotero.AnnotationBox.render(objbox, { data });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
objbox.item = item;
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</setter>
|
|
||||||
</property>
|
|
||||||
|
|
||||||
<field name="parent"/>
|
|
||||||
|
|
||||||
<method name="click">
|
|
||||||
<body><![CDATA[
|
|
||||||
this.pane.click();
|
|
||||||
]]></body>
|
|
||||||
</method>
|
|
||||||
|
|
||||||
<method name="_id">
|
|
||||||
<parameter name="id"/>
|
|
||||||
<body>
|
|
||||||
<![CDATA[
|
|
||||||
var elems = document.getAnonymousNodes(this)[0].getElementsByAttribute('anonid', id);
|
|
||||||
return elems.length ? elems[0] : false;
|
|
||||||
]]>
|
|
||||||
</body>
|
|
||||||
</method>
|
|
||||||
</implementation>
|
|
||||||
|
|
||||||
<content>
|
|
||||||
<xul:vbox flex="1">
|
|
||||||
<xul:groupbox anonid="merge-pane" flex="1">
|
|
||||||
<xul:caption anonid="caption"/>
|
|
||||||
<html:div anonid="parent-row" hidden="true"/>
|
|
||||||
<xul:box anonid="object-placeholder"/>
|
|
||||||
<xul:hbox anonid="delete-box" hidden="true" flex="1">
|
|
||||||
<xul:label value="&zotero.merge.deleted;"/>
|
|
||||||
</xul:hbox>
|
|
||||||
</xul:groupbox>
|
|
||||||
<xul:button anonid="choose-button"/>
|
|
||||||
</xul:vbox>
|
|
||||||
</content>
|
|
||||||
</binding>
|
|
||||||
</bindings>
|
|
|
@ -1901,7 +1901,7 @@ var CollectionTree = class CollectionTree extends LibraryTree {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
window.openDialog('chrome://zotero/content/merge.xul', '', 'chrome,modal,centerscreen', io);
|
window.openDialog('chrome://zotero/content/merge.xhtml', '', 'chrome,modal,centerscreen', io);
|
||||||
|
|
||||||
await Zotero.DB.executeTransaction(async function () {
|
await Zotero.DB.executeTransaction(async function () {
|
||||||
// DEBUG: This probably needs to be updated if this starts being used
|
// DEBUG: This probably needs to be updated if this starts being used
|
||||||
|
|
|
@ -32,6 +32,7 @@ Services.scriptloader.loadSubScript("chrome://zotero/content/elements/base.js",
|
||||||
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/attachmentBox.js', this);
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/attachmentBox.js', this);
|
||||||
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/guidancePanel.js', this);
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/guidancePanel.js', this);
|
||||||
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/itemBox.js', this);
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/itemBox.js', this);
|
||||||
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/mergeGroup.js', this);
|
||||||
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/menulistItemTypes.js', this);
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/menulistItemTypes.js', this);
|
||||||
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/noteEditor.js', this);
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/noteEditor.js', this);
|
||||||
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/notesBox.js', this);
|
Services.scriptloader.loadSubScript('chrome://zotero/content/elements/notesBox.js', this);
|
||||||
|
|
439
chrome/content/zotero/elements/mergeGroup.js
Normal file
439
chrome/content/zotero/elements/mergeGroup.js
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2023 Corporation for Digital Scholarship
|
||||||
|
Vienna, Virginia, USA
|
||||||
|
https://www.zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
class MergeGroup extends XULElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.libraryID = null;
|
||||||
|
this._data = null;
|
||||||
|
this._type = null;
|
||||||
|
|
||||||
|
this.content = MozXULElement.parseXULToFragment(`
|
||||||
|
<div id="merge-group" xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<merge-pane id="left-pane" flex="1" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
|
||||||
|
<merge-pane id="right-pane" flex="1" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
|
||||||
|
<merge-pane id="merge-pane" flex="1" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"/>
|
||||||
|
</div>
|
||||||
|
`, ['chrome://zotero/locale/zotero.dtd']);
|
||||||
|
}
|
||||||
|
|
||||||
|
get stylesheets() {
|
||||||
|
return [
|
||||||
|
'chrome://zotero/skin/merge.css'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.append(document.importNode(this.content, true));
|
||||||
|
|
||||||
|
this._leftPane = this._id('left-pane');
|
||||||
|
this._rightPane = this._id('right-pane');
|
||||||
|
this._mergePane = this._id('merge-pane');
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
set data(val) {
|
||||||
|
this._data = val;
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
get merged() {
|
||||||
|
return this._mergePane.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return this._type;
|
||||||
|
}
|
||||||
|
set type(val) {
|
||||||
|
switch (val) {
|
||||||
|
case 'item':
|
||||||
|
case 'attachment':
|
||||||
|
case 'note':
|
||||||
|
case 'annotation':
|
||||||
|
case 'file':
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(`Unsupported merge object type '${type}'`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._type = val;
|
||||||
|
this._id('merge-group').setAttribute('mergetype', val);
|
||||||
|
}
|
||||||
|
|
||||||
|
set leftCaption(val) {
|
||||||
|
this._leftPane.caption.label = val;
|
||||||
|
}
|
||||||
|
set rightCaption(val) {
|
||||||
|
this._rightPane.caption.label = val;
|
||||||
|
}
|
||||||
|
set mergeCaption(val) {
|
||||||
|
this._mergePane.caption.label = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
get leftPane() {
|
||||||
|
return this._leftPane;
|
||||||
|
}
|
||||||
|
get rightPane() {
|
||||||
|
return this._rightPane;
|
||||||
|
}
|
||||||
|
get mergePane() {
|
||||||
|
return this._mergePane;
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
if (this._data.left.deleted && this._data.right.deleted) {
|
||||||
|
throw new Error("'left' and 'right' cannot both be deleted");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for note or attachment
|
||||||
|
this.type = this._getTypeFromObject(
|
||||||
|
this._data.left.deleted ? this._data.right : this._data.left
|
||||||
|
);
|
||||||
|
|
||||||
|
var showButton = this.type != 'item';
|
||||||
|
|
||||||
|
this._leftPane.showButton = showButton;
|
||||||
|
this._rightPane.showButton = showButton;
|
||||||
|
this._leftPane.libraryID = this.libraryID;
|
||||||
|
this._rightPane.libraryID = this.libraryID;
|
||||||
|
this._mergePane.libraryID = this.libraryID;
|
||||||
|
this._leftPane.data = this._data.left;
|
||||||
|
this._rightPane.data = this._data.right;
|
||||||
|
this._mergePane.data = this._data.merge;
|
||||||
|
|
||||||
|
if (this._data.selected == 'left') {
|
||||||
|
this.choosePane(this._leftPane);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.choosePane(this._rightPane);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Code to display only the different values -- not used
|
||||||
|
|
||||||
|
var diff = this._leftPane.ref.diff(this._rightPane.ref, true);
|
||||||
|
|
||||||
|
var fields = [];
|
||||||
|
var diffFields = [];
|
||||||
|
for (var field in diff[0].primary) {
|
||||||
|
fields.push(field);
|
||||||
|
if (diff[0].primary[field] != diff[1].primary[field]) {
|
||||||
|
diffFields.push(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var field in diff[0].fields) {
|
||||||
|
fields.push(field);
|
||||||
|
if (diff[0].fields[field] != diff[1].fields[field]) {
|
||||||
|
diffFields.push(field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._leftPane.objectBox.fieldOrder = fields;
|
||||||
|
this._rightPane.objectBox.fieldOrder = fields;
|
||||||
|
|
||||||
|
// Display merge pane if item types match
|
||||||
|
if (this._leftPane.ref.itemTypeID == this._rightPane.ref.itemTypeID) {
|
||||||
|
this._leftPane.objectBox.visibleFields = fields;
|
||||||
|
this._rightPane.objectBox.visibleFields = fields;
|
||||||
|
|
||||||
|
this._leftPane.objectBox.clickable = false;
|
||||||
|
this._rightPane.objectBox.clickable = false;
|
||||||
|
this._leftPane.objectBox.clickableFields = diffFields;
|
||||||
|
this._rightPane.objectBox.clickableFields = diffFields;
|
||||||
|
|
||||||
|
var mergeItem = new Zotero.Item(this._leftPane.ref.itemTypeID);
|
||||||
|
this._mergePane.ref = mergeItem;
|
||||||
|
this._mergePane.objectBox.visibleFields = fields;
|
||||||
|
}
|
||||||
|
// Otherwise only allow clicking on item types
|
||||||
|
else {
|
||||||
|
this._leftPane.objectBox.clickableFields = ['itemType'];
|
||||||
|
this._rightPane.objectBox.clickableFields = ['itemType'];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
this._mergePane.objectBox.editable = true;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
No need to refresh if not comparing fields
|
||||||
|
|
||||||
|
this._leftPane.objectBox.refresh();
|
||||||
|
this._rightPane.objectBox.refresh();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
choosePane(pane) {
|
||||||
|
Zotero.debug(new Error().stack);
|
||||||
|
if (pane.id == 'left-pane') {
|
||||||
|
var position = 'left';
|
||||||
|
var otherPane = this._rightPane;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var position = 'right';
|
||||||
|
var otherPane = this._leftPane;
|
||||||
|
}
|
||||||
|
|
||||||
|
pane.removeAttribute("selected");
|
||||||
|
otherPane.removeAttribute("selected");
|
||||||
|
pane.setAttribute("selected", "true");
|
||||||
|
|
||||||
|
this._mergePane.data = pane.data;
|
||||||
|
|
||||||
|
if (this.onSelectionChange) {
|
||||||
|
this.onSelectionChange();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_getTypeFromObject(obj) {
|
||||||
|
if (!obj.itemType) {
|
||||||
|
Zotero.debug(obj, 1);
|
||||||
|
throw new Error("obj is not item JSON");
|
||||||
|
}
|
||||||
|
switch (obj.itemType) {
|
||||||
|
case 'attachment':
|
||||||
|
case 'note':
|
||||||
|
case 'annotation':
|
||||||
|
return obj.itemType;
|
||||||
|
}
|
||||||
|
return 'item';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_id(id) {
|
||||||
|
return this.querySelector(`#${id}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define("merge-group", MergeGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
class MergePane extends XULElement {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._data = null;
|
||||||
|
this._deleted = false;
|
||||||
|
|
||||||
|
this.content = MozXULElement.parseXULToFragment(`
|
||||||
|
<vbox flex="1">
|
||||||
|
<groupbox class="merge-pane" flex="1">
|
||||||
|
<caption class="caption"/>
|
||||||
|
<html:div class="parent-row" hidden="true"/>
|
||||||
|
<box class="object-placeholder"/>
|
||||||
|
<hbox class="delete-box" hidden="true" flex="1">
|
||||||
|
<label value="&zotero.merge.deleted;"/>
|
||||||
|
</hbox>
|
||||||
|
</groupbox>
|
||||||
|
<button class="choose-button"/>
|
||||||
|
</vbox>
|
||||||
|
`, ['chrome://zotero/locale/zotero.dtd']);
|
||||||
|
}
|
||||||
|
|
||||||
|
get stylesheets() {
|
||||||
|
return ['chrome://zotero/skin/bindings/merge.css'];
|
||||||
|
}
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
this.append(document.importNode(this.content, true));
|
||||||
|
|
||||||
|
this.parent = document.querySelector('merge-group');
|
||||||
|
this.isMergePane = this.id == 'merge-pane';
|
||||||
|
|
||||||
|
if (!this.isMergePane) {
|
||||||
|
this.pane.onclick = function () {
|
||||||
|
this.parent.choosePane(this);
|
||||||
|
}.bind(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return this.parent.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
get pane() {
|
||||||
|
return this._class('merge-pane');
|
||||||
|
}
|
||||||
|
|
||||||
|
get caption() {
|
||||||
|
return this._class('caption');
|
||||||
|
}
|
||||||
|
|
||||||
|
get parentRow() {
|
||||||
|
return this._class('parent-row');
|
||||||
|
}
|
||||||
|
|
||||||
|
get objectBox() {
|
||||||
|
return this._class('object-box');
|
||||||
|
}
|
||||||
|
|
||||||
|
get deleted() {
|
||||||
|
return this._deleted;
|
||||||
|
}
|
||||||
|
set deleted(val) {
|
||||||
|
this._deleted = val;
|
||||||
|
|
||||||
|
var placeholder = this._class('object-placeholder');
|
||||||
|
if (placeholder) {
|
||||||
|
placeholder.hidden = !!val;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._class('object-box').hidden = true;
|
||||||
|
}
|
||||||
|
var deleteBox = this._class('delete-box');
|
||||||
|
deleteBox.hidden = !val;
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
set data(val) {
|
||||||
|
this._data = val;
|
||||||
|
|
||||||
|
var button = this._class('choose-button');
|
||||||
|
button.label = Zotero.getString('sync.conflict.chooseThisVersion');
|
||||||
|
if (this.showButton) {
|
||||||
|
button.onclick = () => this.parent.choosePane(this);
|
||||||
|
button.style.visibility = 'visible';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
button.style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (val.deleted) {
|
||||||
|
this.deleted = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.deleted = false;
|
||||||
|
|
||||||
|
// Replace XUL placeholder with XUL object box of given type
|
||||||
|
var elementName;
|
||||||
|
switch (this.type) {
|
||||||
|
case 'item':
|
||||||
|
elementName = 'item-box';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'attachment':
|
||||||
|
case 'file':
|
||||||
|
elementName = 'attachment-box';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'note':
|
||||||
|
var type = Zotero.Libraries.get(this.libraryID).libraryType;
|
||||||
|
elementName = 'note-editor';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'annotation':
|
||||||
|
elementName = 'div';
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error("Object type '" + this.type + "' not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elementName == 'div') {
|
||||||
|
var objbox = document.createElement(elementName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var objbox = document.createXULElement(elementName);
|
||||||
|
}
|
||||||
|
|
||||||
|
var parentRow = this._class('parent-row');
|
||||||
|
if (val.parentItem) {
|
||||||
|
parentRow.textContent = '';
|
||||||
|
|
||||||
|
let label = document.createElement('span');
|
||||||
|
label.textContent = Zotero.getString('pane.item.parentItem');
|
||||||
|
parentRow.appendChild(label);
|
||||||
|
|
||||||
|
let parentItem = Zotero.Items.getByLibraryAndKey(this.libraryID, val.parentItem);
|
||||||
|
let text = document.createTextNode(" " + parentItem.getDisplayTitle(true));
|
||||||
|
parentRow.appendChild(text);
|
||||||
|
|
||||||
|
parentRow.hidden = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parentRow.hidden = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._class('object-placeholder')) {
|
||||||
|
var placeholder = this._class('object-placeholder');
|
||||||
|
placeholder.parentNode.replaceChild(objbox, placeholder);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let oldObjBox = this.objectBox;
|
||||||
|
oldObjBox.parentNode.replaceChild(objbox, oldObjBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
objbox.className = "object-box";
|
||||||
|
objbox.setAttribute("flex", "1");
|
||||||
|
objbox.mode = this.type == 'file' ? 'filemerge' : 'merge';
|
||||||
|
|
||||||
|
// Store JSON
|
||||||
|
this._data = val;
|
||||||
|
|
||||||
|
// Create a copy of the JSON that we can clean for display, since the remote object
|
||||||
|
// might reference things that don't exist locally
|
||||||
|
var displayJSON = Object.assign({}, val);
|
||||||
|
displayJSON.collections = [];
|
||||||
|
|
||||||
|
// Create item from JSON for metadata box
|
||||||
|
var item = new Zotero.Item(val.itemType);
|
||||||
|
item.libraryID = this.libraryID;
|
||||||
|
item.fromJSON(displayJSON);
|
||||||
|
|
||||||
|
if (item.isAnnotation()) {
|
||||||
|
Zotero.Annotations.toJSON(item)
|
||||||
|
.then((data) => {
|
||||||
|
Zotero.AnnotationBox.render(objbox, { data });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
objbox.item = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
click() {
|
||||||
|
this.pane.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
_class(className) {
|
||||||
|
return this.querySelector(`.${className}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customElements.define("merge-pane", MergePane);
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
/*
|
/*
|
||||||
***** BEGIN LICENSE BLOCK *****
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
Copyright © 2009 Center for History and New Media
|
Copyright © 2023 Corporation for Digital Scholarship
|
||||||
George Mason University, Fairfax, Virginia, USA
|
Vienna, Virginia, USA
|
||||||
http://zotero.org
|
https://www.zotero.org
|
||||||
|
|
||||||
This file is part of Zotero.
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
@ -35,13 +35,18 @@ var Zotero_Merge_Window = new function () {
|
||||||
var _pos = -1;
|
var _pos = -1;
|
||||||
|
|
||||||
this.init = function () {
|
this.init = function () {
|
||||||
_wizard = document.getElementsByTagName('wizard')[0];
|
_wizard = document.getElementById('merge-window');
|
||||||
_wizardPage = document.getElementsByTagName('wizardpage')[0];
|
_wizardPage = document.querySelector('wizardpage');
|
||||||
_mergeGroup = document.getElementsByTagName('zoteromergegroup')[0];
|
_mergeGroup = document.querySelector('merge-group');
|
||||||
|
|
||||||
_wizard.setAttribute('width', Math.min(980, screen.width - 20));
|
_wizard.setAttribute('width', Math.min(980, screen.width - 20));
|
||||||
_wizard.setAttribute('height', Math.min(718, screen.height - 30));
|
_wizard.setAttribute('height', Math.min(718, screen.height - 30));
|
||||||
|
|
||||||
|
_wizard.addEventListener('wizardback', this.onBack.bind(this));
|
||||||
|
_wizard.addEventListener('wizardnext', this.onNext.bind(this));
|
||||||
|
_wizard.addEventListener('wizardcancel', this.onCancel.bind(this));
|
||||||
|
_wizard.addEventListener('wizardfinish', this.onFinish.bind(this));
|
||||||
|
|
||||||
// Set font size from pref
|
// Set font size from pref
|
||||||
Zotero.setFontSize(_wizardPage);
|
Zotero.setFontSize(_wizardPage);
|
||||||
|
|
||||||
|
@ -91,28 +96,11 @@ var Zotero_Merge_Window = new function () {
|
||||||
|
|
||||||
_updateGroup();
|
_updateGroup();
|
||||||
|
|
||||||
var nextButton = _wizard.getButton("next");
|
this.updateNextFinish();
|
||||||
|
|
||||||
if (Zotero.isMac) {
|
|
||||||
nextButton.setAttribute("hidden", "false");
|
|
||||||
_wizard.getButton("finish").setAttribute("hidden", "true");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
|
||||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
|
||||||
deck.selectedIndex = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
_setInstructionsString(nextButton.label);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.onNext = function () {
|
this.onNext = function () {
|
||||||
// At end or resolving all
|
|
||||||
if (_pos + 1 == _conflicts.length || _resolveAllCheckbox.checked) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First page
|
// First page
|
||||||
if (_pos == -1) {
|
if (_pos == -1) {
|
||||||
_wizard.canRewind = false;
|
_wizard.canRewind = false;
|
||||||
|
@ -134,13 +122,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateResolveAllCheckbox();
|
_updateResolveAllCheckbox();
|
||||||
|
this.updateNextFinish();
|
||||||
if (_isLastConflict()) {
|
|
||||||
_showFinishButton();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
_showNextButton();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -149,7 +131,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
this.onFinish = function () {
|
this.onFinish = function () {
|
||||||
// If using one side for all remaining, update merge object
|
// If using one side for all remaining, update merge object
|
||||||
if (!_isLastConflict() && _resolveAllCheckbox.checked) {
|
if (!_isLastConflict() && _resolveAllCheckbox.checked) {
|
||||||
let side = _mergeGroup.rightpane.getAttribute("selected") == "true" ? 'right' : 'left'
|
let side = _mergeGroup.rightPane.getAttribute("selected") == "true" ? 'right' : 'left'
|
||||||
for (let i = _pos; i < _conflicts.length; i++) {
|
for (let i = _pos; i < _conflicts.length; i++) {
|
||||||
_merged[i] = {
|
_merged[i] = {
|
||||||
data: _getMergeDataWithSide(i, side),
|
data: _getMergeDataWithSide(i, side),
|
||||||
|
@ -180,11 +162,14 @@ var Zotero_Merge_Window = new function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
this.onResolveAllChange = function (resolveAll) {
|
this.updateNextFinish = function () {
|
||||||
if (resolveAll || _isLastConflict()) {
|
if (_isLastConflict() || _resolveAllCheckbox.checked) {
|
||||||
_showFinishButton();
|
// The Mozilla wizard CE checks 'next' to determine if it's on the last page
|
||||||
|
_wizardPage.next = '';
|
||||||
|
_showFinishButton()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
_wizardPage.next = 'page-id';
|
||||||
_showNextButton();
|
_showNextButton();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +197,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
function _getCurrentMergeInfo() {
|
function _getCurrentMergeInfo() {
|
||||||
return {
|
return {
|
||||||
data: _mergeGroup.merged,
|
data: _mergeGroup.merged,
|
||||||
selected: _mergeGroup.leftpane.getAttribute("selected") == "true" ? "left" : "right"
|
selected: _mergeGroup.leftPane.getAttribute("selected") == "true" ? "left" : "right"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,6 +263,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
throw new Error("Side not provided");
|
throw new Error("Side not provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If either side is deleted, nothing to merge
|
||||||
if (_conflicts[pos].left.deleted || _conflicts[pos].right.deleted) {
|
if (_conflicts[pos].left.deleted || _conflicts[pos].right.deleted) {
|
||||||
return _conflicts[pos][side];
|
return _conflicts[pos][side];
|
||||||
}
|
}
|
||||||
|
@ -293,7 +279,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
|
|
||||||
|
|
||||||
function _updateResolveAllCheckbox() {
|
function _updateResolveAllCheckbox() {
|
||||||
if (_mergeGroup.rightpane.getAttribute("selected") == 'true') {
|
if (_mergeGroup.rightPane.getAttribute("selected") == 'true') {
|
||||||
var label = 'resolveAllRemote';
|
var label = 'resolveAllRemote';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -316,8 +302,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
_wizard.getButton("finish").setAttribute("hidden", "true");
|
_wizard.getButton("finish").setAttribute("hidden", "true");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
let deck = document.querySelector(".wizard-next-deck");
|
||||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
|
||||||
deck.selectedIndex = 1;
|
deck.selectedIndex = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,8 +320,7 @@ var Zotero_Merge_Window = new function () {
|
||||||
// Windows uses a deck to switch between the Next and Finish buttons
|
// Windows uses a deck to switch between the Next and Finish buttons
|
||||||
// TODO: check Linux
|
// TODO: check Linux
|
||||||
else {
|
else {
|
||||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
let deck = document.querySelector(".wizard-next-deck");
|
||||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
|
||||||
deck.selectedIndex = 0;
|
deck.selectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
66
chrome/content/zotero/merge.xhtml
Normal file
66
chrome/content/zotero/merge.xhtml
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2023 Corporation for Digital Scholarship
|
||||||
|
Vienna, Virginia, USA
|
||||||
|
https://www.zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
-->
|
||||||
|
|
||||||
|
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://zotero/skin/merge.css" type="text/css"?>
|
||||||
|
<?xml-stylesheet href="chrome://zotero-platform/content/zotero.css"?>
|
||||||
|
|
||||||
|
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
||||||
|
|
||||||
|
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||||
|
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||||
|
onload="Zotero_Merge_Window.init()"
|
||||||
|
>
|
||||||
|
<wizard id="merge-window" title="">
|
||||||
|
<script>
|
||||||
|
var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/include.js", this);
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/customElements.js", this);
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/components/annotation.js", this);
|
||||||
|
Services.scriptloader.loadSubScript("chrome://zotero/content/merge.js", this);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<wizardpage label="&zotero.merge.title;" pageid="page-id">
|
||||||
|
<description id="zotero-merge-instructions"/>
|
||||||
|
<merge-group flex="1"/>
|
||||||
|
<separator class="thin"/>
|
||||||
|
<hbox align="center">
|
||||||
|
<separator orient="vertical" flex="1"/>
|
||||||
|
<hbox>
|
||||||
|
<checkbox id="resolve-all"
|
||||||
|
oncommand="Zotero_Merge_Window.updateNextFinish()"/>
|
||||||
|
</hbox>
|
||||||
|
<separator orient="vertical"/>
|
||||||
|
<hbox id="zotero-step-count">
|
||||||
|
<label id="zotero-merge-num-objects"/>
|
||||||
|
<label value="&zotero.merge.of;"/>
|
||||||
|
<label id="zotero-merge-total-objects"/>
|
||||||
|
</hbox>
|
||||||
|
</hbox>
|
||||||
|
</wizardpage>
|
||||||
|
</wizard>
|
||||||
|
</window>
|
|
@ -1,67 +0,0 @@
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!--
|
|
||||||
***** BEGIN LICENSE BLOCK *****
|
|
||||||
|
|
||||||
Copyright © 2009 Center for History and New Media
|
|
||||||
George Mason University, Fairfax, Virginia, USA
|
|
||||||
http://zotero.org
|
|
||||||
|
|
||||||
This file is part of Zotero.
|
|
||||||
|
|
||||||
Zotero is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
Zotero is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
***** END LICENSE BLOCK *****
|
|
||||||
-->
|
|
||||||
|
|
||||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
|
||||||
<?xml-stylesheet href="chrome://zotero/skin/zotero.css" type="text/css"?>
|
|
||||||
<?xml-stylesheet href="chrome://zotero/skin/merge.css" type="text/css"?>
|
|
||||||
<?xml-stylesheet href="chrome://zotero-platform/content/zotero.css"?>
|
|
||||||
|
|
||||||
<!DOCTYPE window SYSTEM "chrome://zotero/locale/zotero.dtd">
|
|
||||||
|
|
||||||
<wizard
|
|
||||||
id="zotero-merge-window"
|
|
||||||
orient="vertical"
|
|
||||||
title=""
|
|
||||||
onwizardfinish="return Zotero_Merge_Window.onFinish()"
|
|
||||||
onwizardcancel="return Zotero_Merge_Window.onCancel()"
|
|
||||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
||||||
|
|
||||||
<script src="include.js"/>
|
|
||||||
<script src="merge.js"/>
|
|
||||||
<script src="components/annotation.js"/>
|
|
||||||
|
|
||||||
<wizardpage onpageshow="Zotero_Merge_Window.init()"
|
|
||||||
onpagerewound="Zotero_Merge_Window.onBack(); return false"
|
|
||||||
onpageadvanced="return Zotero_Merge_Window.onNext()"
|
|
||||||
label="&zotero.merge.title;">
|
|
||||||
<description id="zotero-merge-instructions"/>
|
|
||||||
<zoteromergegroup flex="1"/>
|
|
||||||
<separator class="thin"/>
|
|
||||||
<hbox align="center">
|
|
||||||
<separator orient="vertical" flex="1"/>
|
|
||||||
<hbox>
|
|
||||||
<checkbox id="resolve-all"
|
|
||||||
oncommand="Zotero_Merge_Window.onResolveAllChange(this.checked)"/>
|
|
||||||
</hbox>
|
|
||||||
<separator orient="vertical"/>
|
|
||||||
<hbox id="zotero-step-count">
|
|
||||||
<label id="zotero-merge-num-objects"/>
|
|
||||||
<label value="&zotero.merge.of;"/>
|
|
||||||
<label id="zotero-merge-total-objects"/>
|
|
||||||
</hbox>
|
|
||||||
</hbox>
|
|
||||||
</wizardpage>
|
|
||||||
</wizard>
|
|
|
@ -1043,10 +1043,9 @@ Zotero.Sync.Storage.Local = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
var wm = Services.wm;
|
||||||
.getService(Components.interfaces.nsIWindowMediator);
|
|
||||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||||
lastWin.openDialog('chrome://zotero/content/merge.xul', '', 'chrome,modal,centerscreen', io);
|
lastWin.openDialog('chrome://zotero/content/merge.xhtml', '', 'chrome,modal,centerscreen', io);
|
||||||
|
|
||||||
if (!io.dataOut) {
|
if (!io.dataOut) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1439,7 +1439,7 @@ Zotero.Sync.Data.Local = {
|
||||||
conflicts
|
conflicts
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var url = 'chrome://zotero/content/merge.xul';
|
var url = 'chrome://zotero/content/merge.xhtml';
|
||||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||||
.getService(Components.interfaces.nsIWindowMediator);
|
.getService(Components.interfaces.nsIWindowMediator);
|
||||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* merge.xul */
|
/* merge.xhtml */
|
||||||
wizard {
|
wizard {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
|
|
|
@ -625,14 +625,14 @@ describe("Zotero.Sync.Storage.Local", function () {
|
||||||
item3.attachmentSyncState = "in_conflict";
|
item3.attachmentSyncState = "in_conflict";
|
||||||
yield item3.saveTx({ skipAll: true });
|
yield item3.saveTx({ skipAll: true });
|
||||||
|
|
||||||
var promise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var promise = waitForWindow('chrome://zotero/content/merge.xhtml', async function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Later remote version should be selected
|
// Later remote version should be selected
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
// Check checkbox text
|
// Check checkbox text
|
||||||
assert.equal(
|
assert.equal(
|
||||||
|
@ -641,17 +641,17 @@ describe("Zotero.Sync.Storage.Local", function () {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Select local object
|
// Select local object
|
||||||
mergeGroup.leftpane.click();
|
mergeGroup.leftPane.click();
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (local)
|
// 2 (local)
|
||||||
// Later local version should be selected
|
// Later local version should be selected
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
// Select remote object
|
// Select remote object
|
||||||
mergeGroup.rightpane.click();
|
mergeGroup.rightPane.click();
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
if (Zotero.isMac) {
|
if (Zotero.isMac) {
|
||||||
assert.isTrue(wizard.getButton('next').hidden);
|
assert.isTrue(wizard.getButton('next').hidden);
|
||||||
|
@ -686,18 +686,18 @@ describe("Zotero.Sync.Storage.Local", function () {
|
||||||
item1.attachmentSyncState = "in_conflict";
|
item1.attachmentSyncState = "in_conflict";
|
||||||
yield item1.saveTx({ skipAll: true });
|
yield item1.saveTx({ skipAll: true });
|
||||||
|
|
||||||
var promise = waitForWindow('chrome://zotero/content/merge.xul', async function (dialog) {
|
var promise = waitForWindow('chrome://zotero/content/merge.xhtml', async function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Identical, so remote version should be selected
|
// Identical, so remote version should be selected
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
// Select local object
|
// Select local object
|
||||||
mergeGroup.leftpane.click();
|
mergeGroup.leftPane.click();
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
if (Zotero.isMac) {
|
if (Zotero.isMac) {
|
||||||
assert.isTrue(wizard.getButton('next').hidden);
|
assert.isTrue(wizard.getButton('next').hidden);
|
||||||
|
|
|
@ -2384,18 +2384,18 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// 1 (accept remote deletion)
|
// 1 (accept remote deletion)
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
mergeGroup.rightpane.click();
|
mergeGroup.rightPane.click();
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (ignore remote deletion)
|
// 2 (ignore remote deletion)
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
wizard.getButton('finish').click();
|
wizard.getButton('finish').click();
|
||||||
})
|
})
|
||||||
yield engine._startDownload();
|
yield engine._startDownload();
|
||||||
|
@ -2655,9 +2655,9 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
wizard.getButton('cancel').click();
|
wizard.getButton('cancel').click();
|
||||||
})
|
})
|
||||||
var e = yield getPromiseError(engine._startDownload());
|
var e = yield getPromiseError(engine._startDownload());
|
||||||
|
@ -2750,9 +2750,9 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
wizard.getButton('cancel').click();
|
wizard.getButton('cancel').click();
|
||||||
})
|
})
|
||||||
var e = yield getPromiseError(engine._startDownload());
|
var e = yield getPromiseError(engine._startDownload());
|
||||||
|
@ -3609,21 +3609,21 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (local)
|
// 2 (local)
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
// Select local object
|
// Select local object
|
||||||
mergeGroup.leftpane.click();
|
mergeGroup.leftPane.click();
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
if (Zotero.isMac) {
|
if (Zotero.isMac) {
|
||||||
assert.isTrue(wizard.getButton('next').hidden);
|
assert.isTrue(wizard.getButton('next').hidden);
|
||||||
assert.isFalse(wizard.getButton('finish').hidden);
|
assert.isFalse(wizard.getButton('finish').hidden);
|
||||||
|
@ -3716,21 +3716,21 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (local)
|
// 2 (local)
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
// Select local object
|
// Select local object
|
||||||
mergeGroup.leftpane.click();
|
mergeGroup.leftPane.click();
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
if (Zotero.isMac) {
|
if (Zotero.isMac) {
|
||||||
assert.isTrue(wizard.getButton('next').hidden);
|
assert.isTrue(wizard.getButton('next').hidden);
|
||||||
assert.isFalse(wizard.getButton('finish').hidden);
|
assert.isFalse(wizard.getButton('finish').hidden);
|
||||||
|
@ -3841,28 +3841,28 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// TODO: Make this function async and verify that annotation widgets show up here
|
// TODO: Make this function async and verify that annotation widgets show up here
|
||||||
// after rendering. This may not be possible as long as this is within XBL.
|
// after rendering. This may not be possible as long as this is within XBL.
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (local)
|
// 2 (local)
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
// Select local object
|
// Select local object
|
||||||
mergeGroup.leftpane.click();
|
mergeGroup.leftPane.click();
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (remote)
|
// 2 (remote)
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
if (Zotero.isMac) {
|
if (Zotero.isMac) {
|
||||||
assert.isTrue(wizard.getButton('next').hidden);
|
assert.isTrue(wizard.getButton('next').hidden);
|
||||||
|
@ -3984,15 +3984,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
var resolveAll = doc.getElementById('resolve-all');
|
var resolveAll = doc.getElementById('resolve-all');
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
resolveAll.label,
|
resolveAll.label,
|
||||||
Zotero.getString('sync.conflict.resolveAllRemote')
|
Zotero.getString('sync.conflict.resolveAllRemote')
|
||||||
|
@ -4000,8 +4000,8 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (local and Resolve All checkbox)
|
// 2 (local and Resolve All checkbox)
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
mergeGroup.leftpane.click();
|
mergeGroup.leftPane.click();
|
||||||
assert.equal(
|
assert.equal(
|
||||||
resolveAll.label,
|
resolveAll.label,
|
||||||
Zotero.getString('sync.conflict.resolveAllLocal')
|
Zotero.getString('sync.conflict.resolveAllLocal')
|
||||||
|
@ -4106,15 +4106,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
var resolveAll = doc.getElementById('resolve-all');
|
var resolveAll = doc.getElementById('resolve-all');
|
||||||
|
|
||||||
// 1 (remote)
|
// 1 (remote)
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
resolveAll.label,
|
resolveAll.label,
|
||||||
Zotero.getString('sync.conflict.resolveAllRemote')
|
Zotero.getString('sync.conflict.resolveAllRemote')
|
||||||
|
@ -4122,7 +4122,7 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 click Resolve All checkbox
|
// 2 click Resolve All checkbox
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
assert.equal(
|
assert.equal(
|
||||||
resolveAll.label,
|
resolveAll.label,
|
||||||
Zotero.getString('sync.conflict.resolveAllRemote')
|
Zotero.getString('sync.conflict.resolveAllRemote')
|
||||||
|
@ -4191,16 +4191,16 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
assert.ok(mergeGroup.leftpane.pane.onclick);
|
assert.ok(mergeGroup.leftPane.pane.onclick);
|
||||||
// Select local deleted version
|
// Select local deleted version
|
||||||
mergeGroup.leftpane.pane.click();
|
mergeGroup.leftPane.pane.click();
|
||||||
wizard.getButton('finish').click();
|
wizard.getButton('finish').click();
|
||||||
})
|
})
|
||||||
yield engine._downloadObjects('item', [obj.key]);
|
yield engine._downloadObjects('item', [obj.key]);
|
||||||
|
@ -4251,16 +4251,16 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
assert.ok(mergeGroup.leftpane.pane.onclick);
|
assert.ok(mergeGroup.leftPane.pane.onclick);
|
||||||
// Select local deleted version
|
// Select local deleted version
|
||||||
mergeGroup.leftpane.pane.click();
|
mergeGroup.leftPane.pane.click();
|
||||||
wizard.getButton('finish').click();
|
wizard.getButton('finish').click();
|
||||||
});
|
});
|
||||||
yield engine._downloadObjects('item', [obj.key]);
|
yield engine._downloadObjects('item', [obj.key]);
|
||||||
|
@ -4306,15 +4306,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
json: responseJSON
|
json: responseJSON
|
||||||
});
|
});
|
||||||
|
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
assert.isTrue(doc.getElementById('resolve-all').hidden);
|
assert.isTrue(doc.getElementById('resolve-all').hidden);
|
||||||
|
|
||||||
// Remote version should be selected by default
|
// Remote version should be selected by default
|
||||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||||
wizard.getButton('finish').click();
|
wizard.getButton('finish').click();
|
||||||
})
|
})
|
||||||
yield engine._downloadObjects('item', [key]);
|
yield engine._downloadObjects('item', [key]);
|
||||||
|
@ -4797,15 +4797,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Apply remote deletions
|
// Apply remote deletions
|
||||||
var crPromise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var crPromise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// Should be one conflict for each object type; select local
|
// Should be one conflict for each object type; select local
|
||||||
var numConflicts = Object.keys(objects).length;
|
var numConflicts = Object.keys(objects).length;
|
||||||
for (let i = 0; i < numConflicts; i++) {
|
for (let i = 0; i < numConflicts; i++) {
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
|
|
||||||
if (i < numConflicts - 1) {
|
if (i < numConflicts - 1) {
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
|
@ -1233,16 +1233,16 @@ describe("Zotero.Sync.Data.Local", function() {
|
||||||
note.setNote("Test");
|
note.setNote("Test");
|
||||||
yield note.saveTx();
|
yield note.saveTx();
|
||||||
|
|
||||||
var promise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var promise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// Show title for middle and right panes
|
// Show title for middle and right panes
|
||||||
var parentText = Zotero.getString('pane.item.parentItem') + " Parent";
|
var parentText = Zotero.getString('pane.item.parentItem') + " Parent";
|
||||||
assert.equal(mergeGroup.leftpane._id('parent-row').textContent, "");
|
assert.equal(mergeGroup.leftPane.parentRow.textContent, "");
|
||||||
assert.equal(mergeGroup.rightpane._id('parent-row').textContent, parentText);
|
assert.equal(mergeGroup.rightPane.parentRow.textContent, parentText);
|
||||||
assert.equal(mergeGroup.mergepane._id('parent-row').textContent, parentText);
|
assert.equal(mergeGroup.mergePane.parentRow.textContent, parentText);
|
||||||
|
|
||||||
wizard.getButton('finish').click();
|
wizard.getButton('finish').click();
|
||||||
});
|
});
|
||||||
|
@ -1268,18 +1268,18 @@ describe("Zotero.Sync.Data.Local", function() {
|
||||||
var note = await createDataObject('item', { itemType: 'note' });
|
var note = await createDataObject('item', { itemType: 'note' });
|
||||||
var item = await createDataObject('item');
|
var item = await createDataObject('item');
|
||||||
|
|
||||||
var promise = waitForWindow('chrome://zotero/content/merge.xul', function (dialog) {
|
var promise = waitForWindow('chrome://zotero/content/merge.xhtml', function (dialog) {
|
||||||
var doc = dialog.document;
|
var doc = dialog.document;
|
||||||
var wizard = doc.documentElement;
|
var wizard = doc.querySelector('wizard');
|
||||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||||
|
|
||||||
// 1 (accept remote deletion)
|
// 1 (accept remote deletion)
|
||||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||||
mergeGroup.rightpane.click();
|
mergeGroup.rightPane.click();
|
||||||
wizard.getButton('next').click();
|
wizard.getButton('next').click();
|
||||||
|
|
||||||
// 2 (accept remote deletion)
|
// 2 (accept remote deletion)
|
||||||
mergeGroup.rightpane.click();
|
mergeGroup.rightPane.click();
|
||||||
if (Zotero.isMac) {
|
if (Zotero.isMac) {
|
||||||
assert.isTrue(wizard.getButton('next').hidden);
|
assert.isTrue(wizard.getButton('next').hidden);
|
||||||
assert.isFalse(wizard.getButton('finish').hidden);
|
assert.isFalse(wizard.getButton('finish').hidden);
|
||||||
|
|
Loading…
Add table
Reference in a new issue