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 () {
|
||||
// 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/guidancePanel.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/noteEditor.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 *****
|
||||
|
||||
Copyright © 2009 Center for History and New Media
|
||||
George Mason University, Fairfax, Virginia, USA
|
||||
http://zotero.org
|
||||
Copyright © 2023 Corporation for Digital Scholarship
|
||||
Vienna, Virginia, USA
|
||||
https://www.zotero.org
|
||||
|
||||
This file is part of Zotero.
|
||||
|
||||
|
@ -35,13 +35,18 @@ var Zotero_Merge_Window = new function () {
|
|||
var _pos = -1;
|
||||
|
||||
this.init = function () {
|
||||
_wizard = document.getElementsByTagName('wizard')[0];
|
||||
_wizardPage = document.getElementsByTagName('wizardpage')[0];
|
||||
_mergeGroup = document.getElementsByTagName('zoteromergegroup')[0];
|
||||
_wizard = document.getElementById('merge-window');
|
||||
_wizardPage = document.querySelector('wizardpage');
|
||||
_mergeGroup = document.querySelector('merge-group');
|
||||
|
||||
_wizard.setAttribute('width', Math.min(980, screen.width - 20));
|
||||
_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
|
||||
Zotero.setFontSize(_wizardPage);
|
||||
|
||||
|
@ -91,28 +96,11 @@ var Zotero_Merge_Window = new function () {
|
|||
|
||||
_updateGroup();
|
||||
|
||||
var nextButton = _wizard.getButton("next");
|
||||
|
||||
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.updateNextFinish();
|
||||
}
|
||||
|
||||
|
||||
this.onNext = function () {
|
||||
// At end or resolving all
|
||||
if (_pos + 1 == _conflicts.length || _resolveAllCheckbox.checked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// First page
|
||||
if (_pos == -1) {
|
||||
_wizard.canRewind = false;
|
||||
|
@ -134,13 +122,7 @@ var Zotero_Merge_Window = new function () {
|
|||
}
|
||||
|
||||
_updateResolveAllCheckbox();
|
||||
|
||||
if (_isLastConflict()) {
|
||||
_showFinishButton();
|
||||
}
|
||||
else {
|
||||
_showNextButton();
|
||||
}
|
||||
this.updateNextFinish();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -149,7 +131,7 @@ var Zotero_Merge_Window = new function () {
|
|||
this.onFinish = function () {
|
||||
// If using one side for all remaining, update merge object
|
||||
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++) {
|
||||
_merged[i] = {
|
||||
data: _getMergeDataWithSide(i, side),
|
||||
|
@ -180,11 +162,14 @@ var Zotero_Merge_Window = new function () {
|
|||
}
|
||||
|
||||
|
||||
this.onResolveAllChange = function (resolveAll) {
|
||||
if (resolveAll || _isLastConflict()) {
|
||||
_showFinishButton();
|
||||
this.updateNextFinish = function () {
|
||||
if (_isLastConflict() || _resolveAllCheckbox.checked) {
|
||||
// The Mozilla wizard CE checks 'next' to determine if it's on the last page
|
||||
_wizardPage.next = '';
|
||||
_showFinishButton()
|
||||
}
|
||||
else {
|
||||
_wizardPage.next = 'page-id';
|
||||
_showNextButton();
|
||||
}
|
||||
}
|
||||
|
@ -212,7 +197,7 @@ var Zotero_Merge_Window = new function () {
|
|||
function _getCurrentMergeInfo() {
|
||||
return {
|
||||
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");
|
||||
}
|
||||
|
||||
// If either side is deleted, nothing to merge
|
||||
if (_conflicts[pos].left.deleted || _conflicts[pos].right.deleted) {
|
||||
return _conflicts[pos][side];
|
||||
}
|
||||
|
@ -293,7 +279,7 @@ var Zotero_Merge_Window = new function () {
|
|||
|
||||
|
||||
function _updateResolveAllCheckbox() {
|
||||
if (_mergeGroup.rightpane.getAttribute("selected") == 'true') {
|
||||
if (_mergeGroup.rightPane.getAttribute("selected") == 'true') {
|
||||
var label = 'resolveAllRemote';
|
||||
}
|
||||
else {
|
||||
|
@ -316,8 +302,7 @@ var Zotero_Merge_Window = new function () {
|
|||
_wizard.getButton("finish").setAttribute("hidden", "true");
|
||||
}
|
||||
else {
|
||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
||||
let deck = document.querySelector(".wizard-next-deck");
|
||||
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
|
||||
// TODO: check Linux
|
||||
else {
|
||||
var buttons = document.getAnonymousElementByAttribute(_wizard, "anonid", "Buttons");
|
||||
var deck = document.getAnonymousElementByAttribute(buttons, "anonid", "WizardButtonDeck");
|
||||
let deck = document.querySelector(".wizard-next-deck");
|
||||
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"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var wm = Services.wm;
|
||||
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) {
|
||||
return false;
|
||||
|
|
|
@ -1439,7 +1439,7 @@ Zotero.Sync.Data.Local = {
|
|||
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"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var lastWin = wm.getMostRecentWindow("navigator:browser");
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* merge.xul */
|
||||
/* merge.xhtml */
|
||||
wizard {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
|
|
@ -625,14 +625,14 @@ describe("Zotero.Sync.Storage.Local", function () {
|
|||
item3.attachmentSyncState = "in_conflict";
|
||||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 1 (remote)
|
||||
// Later remote version should be selected
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
|
||||
// Check checkbox text
|
||||
assert.equal(
|
||||
|
@ -641,17 +641,17 @@ describe("Zotero.Sync.Storage.Local", function () {
|
|||
);
|
||||
|
||||
// Select local object
|
||||
mergeGroup.leftpane.click();
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftPane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
|
||||
wizard.getButton('next').click();
|
||||
|
||||
// 2 (local)
|
||||
// Later local version should be selected
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
// Select remote object
|
||||
mergeGroup.rightpane.click();
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.rightPane.click();
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
|
||||
if (Zotero.isMac) {
|
||||
assert.isTrue(wizard.getButton('next').hidden);
|
||||
|
@ -686,18 +686,18 @@ describe("Zotero.Sync.Storage.Local", function () {
|
|||
item1.attachmentSyncState = "in_conflict";
|
||||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 1 (remote)
|
||||
// Identical, so remote version should be selected
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
|
||||
// Select local object
|
||||
mergeGroup.leftpane.click();
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftPane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
|
||||
if (Zotero.isMac) {
|
||||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 1 (accept remote deletion)
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.rightpane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
mergeGroup.rightPane.click();
|
||||
wizard.getButton('next').click();
|
||||
|
||||
// 2 (ignore remote deletion)
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
wizard.getButton('finish').click();
|
||||
})
|
||||
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 wizard = doc.documentElement;
|
||||
var wizard = doc.querySelector('wizard');
|
||||
wizard.getButton('cancel').click();
|
||||
})
|
||||
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 wizard = doc.documentElement;
|
||||
var wizard = doc.querySelector('wizard');
|
||||
wizard.getButton('cancel').click();
|
||||
})
|
||||
var e = yield getPromiseError(engine._startDownload());
|
||||
|
@ -3609,21 +3609,21 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 1 (remote)
|
||||
// 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();
|
||||
|
||||
// 2 (local)
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
// Select local object
|
||||
mergeGroup.leftpane.click();
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftPane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
if (Zotero.isMac) {
|
||||
assert.isTrue(wizard.getButton('next').hidden);
|
||||
assert.isFalse(wizard.getButton('finish').hidden);
|
||||
|
@ -3716,21 +3716,21 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 1 (remote)
|
||||
// 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();
|
||||
|
||||
// 2 (local)
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
// Select local object
|
||||
mergeGroup.leftpane.click();
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftPane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
if (Zotero.isMac) {
|
||||
assert.isTrue(wizard.getButton('next').hidden);
|
||||
assert.isFalse(wizard.getButton('finish').hidden);
|
||||
|
@ -3841,28 +3841,28 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 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.
|
||||
|
||||
// 1 (remote)
|
||||
// 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();
|
||||
|
||||
// 2 (local)
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
// Select local object
|
||||
mergeGroup.leftpane.click();
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftPane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
wizard.getButton('next').click();
|
||||
|
||||
// 2 (remote)
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
|
||||
if (Zotero.isMac) {
|
||||
assert.isTrue(wizard.getButton('next').hidden);
|
||||
|
@ -3984,15 +3984,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
var resolveAll = doc.getElementById('resolve-all');
|
||||
|
||||
// 1 (remote)
|
||||
// Remote version should be selected by default
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
assert.equal(
|
||||
resolveAll.label,
|
||||
Zotero.getString('sync.conflict.resolveAllRemote')
|
||||
|
@ -4000,8 +4000,8 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
wizard.getButton('next').click();
|
||||
|
||||
// 2 (local and Resolve All checkbox)
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftpane.click();
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
mergeGroup.leftPane.click();
|
||||
assert.equal(
|
||||
resolveAll.label,
|
||||
Zotero.getString('sync.conflict.resolveAllLocal')
|
||||
|
@ -4106,15 +4106,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
var resolveAll = doc.getElementById('resolve-all');
|
||||
|
||||
// 1 (remote)
|
||||
// Remote version should be selected by default
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
assert.equal(
|
||||
resolveAll.label,
|
||||
Zotero.getString('sync.conflict.resolveAllRemote')
|
||||
|
@ -4122,7 +4122,7 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
wizard.getButton('next').click();
|
||||
|
||||
// 2 click Resolve All checkbox
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
assert.equal(
|
||||
resolveAll.label,
|
||||
Zotero.getString('sync.conflict.resolveAllRemote')
|
||||
|
@ -4191,16 +4191,16 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// Remote version should be selected by default
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.ok(mergeGroup.leftpane.pane.onclick);
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
assert.ok(mergeGroup.leftPane.pane.onclick);
|
||||
// Select local deleted version
|
||||
mergeGroup.leftpane.pane.click();
|
||||
mergeGroup.leftPane.pane.click();
|
||||
wizard.getButton('finish').click();
|
||||
})
|
||||
yield engine._downloadObjects('item', [obj.key]);
|
||||
|
@ -4251,16 +4251,16 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// Remote version should be selected by default
|
||||
assert.equal(mergeGroup.rightpane.getAttribute('selected'), 'true');
|
||||
assert.ok(mergeGroup.leftpane.pane.onclick);
|
||||
assert.equal(mergeGroup.rightPane.getAttribute('selected'), 'true');
|
||||
assert.ok(mergeGroup.leftPane.pane.onclick);
|
||||
// Select local deleted version
|
||||
mergeGroup.leftpane.pane.click();
|
||||
mergeGroup.leftPane.pane.click();
|
||||
wizard.getButton('finish').click();
|
||||
});
|
||||
yield engine._downloadObjects('item', [obj.key]);
|
||||
|
@ -4306,15 +4306,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
assert.isTrue(doc.getElementById('resolve-all').hidden);
|
||||
|
||||
// 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();
|
||||
})
|
||||
yield engine._downloadObjects('item', [key]);
|
||||
|
@ -4797,15 +4797,15 @@ describe("Zotero.Sync.Data.Engine", function () {
|
|||
});
|
||||
|
||||
// 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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// Should be one conflict for each object type; select local
|
||||
var numConflicts = Object.keys(objects).length;
|
||||
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) {
|
||||
wizard.getButton('next').click();
|
||||
|
|
|
@ -1233,16 +1233,16 @@ describe("Zotero.Sync.Data.Local", function() {
|
|||
note.setNote("Test");
|
||||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// Show title for middle and right panes
|
||||
var parentText = Zotero.getString('pane.item.parentItem') + " Parent";
|
||||
assert.equal(mergeGroup.leftpane._id('parent-row').textContent, "");
|
||||
assert.equal(mergeGroup.rightpane._id('parent-row').textContent, parentText);
|
||||
assert.equal(mergeGroup.mergepane._id('parent-row').textContent, parentText);
|
||||
assert.equal(mergeGroup.leftPane.parentRow.textContent, "");
|
||||
assert.equal(mergeGroup.rightPane.parentRow.textContent, parentText);
|
||||
assert.equal(mergeGroup.mergePane.parentRow.textContent, parentText);
|
||||
|
||||
wizard.getButton('finish').click();
|
||||
});
|
||||
|
@ -1268,18 +1268,18 @@ describe("Zotero.Sync.Data.Local", function() {
|
|||
var note = await createDataObject('item', { itemType: 'note' });
|
||||
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 wizard = doc.documentElement;
|
||||
var mergeGroup = wizard.getElementsByTagName('zoteromergegroup')[0];
|
||||
var wizard = doc.querySelector('wizard');
|
||||
var mergeGroup = wizard.getElementsByTagName('merge-group')[0];
|
||||
|
||||
// 1 (accept remote deletion)
|
||||
assert.equal(mergeGroup.leftpane.getAttribute('selected'), 'true');
|
||||
mergeGroup.rightpane.click();
|
||||
assert.equal(mergeGroup.leftPane.getAttribute('selected'), 'true');
|
||||
mergeGroup.rightPane.click();
|
||||
wizard.getButton('next').click();
|
||||
|
||||
// 2 (accept remote deletion)
|
||||
mergeGroup.rightpane.click();
|
||||
mergeGroup.rightPane.click();
|
||||
if (Zotero.isMac) {
|
||||
assert.isTrue(wizard.getButton('next').hidden);
|
||||
assert.isFalse(wizard.getButton('finish').hidden);
|
||||
|
|
Loading…
Add table
Reference in a new issue