From 61e3e339bb1ebec5f5c85cc67d176a6ad1a24c67 Mon Sep 17 00:00:00 2001 From: Martynas Bagdonas Date: Mon, 24 May 2021 14:31:16 +0300 Subject: [PATCH 1/2] Restore `tags` and `related` tabs, display note links box --- chrome/content/zotero/bindings/noteeditor.xml | 12 ++- chrome/content/zotero/contextPane.js | 94 +++++++++++++++---- chrome/content/zotero/itemPane.xul | 4 + chrome/content/zotero/zoteroPane.js | 2 + scss/components/_tagsBox.scss | 7 +- 5 files changed, 100 insertions(+), 19 deletions(-) diff --git a/chrome/content/zotero/bindings/noteeditor.xml b/chrome/content/zotero/bindings/noteeditor.xml index 451ca0a144..24dde52693 100644 --- a/chrome/content/zotero/bindings/noteeditor.xml +++ b/chrome/content/zotero/bindings/noteeditor.xml @@ -274,6 +274,7 @@ } this.initEditor(); + this._id('links-box').item = this._item; })(); ]]> @@ -392,6 +393,15 @@ this.id('tags').item = this.item; this.id('related').item = this.item; this.refresh(); + + // Hide popup to prevent it being visible out of the context or + // in some cases even invisible but still blocking the next click + this.id('relatedPopup').addEventListener('click', (event) => { + let target = event.originalTarget; + if (target.classList.contains('zotero-box-label')) { + this.id('relatedPopup').hidePopup(); + } + }); ]]> @@ -568,7 +578,7 @@ - + diff --git a/chrome/content/zotero/contextPane.js b/chrome/content/zotero/contextPane.js index 7958ee9617..1fbfd80431 100644 --- a/chrome/content/zotero/contextPane.js +++ b/chrome/content/zotero/contextPane.js @@ -238,19 +238,7 @@ var ZoteroContextPane = new function () { } if (splitter.getAttribute('state') != 'collapsed') { - if (_panesDeck.selectedIndex == 0) { - let child = _itemPaneDeck.selectedPanel; - if (child) { - var tabPanels = child.querySelector('tabpanels'); - if (tabPanels && tabPanels.selectedIndex == 1) { - var notesDeck = child.querySelector('.notes-deck'); - if (notesDeck.selectedIndex == 1) { - return child.querySelector('zoteronoteeditor'); - } - } - } - } - else { + if (_panesDeck.selectedIndex == 1) { var node = _notesPaneDeck.selectedPanel; if (node.selectedIndex == 1) { return node.querySelector('zoteronoteeditor'); @@ -702,7 +690,6 @@ var ZoteroContextPane = new function () { editor.mode = readOnly ? 'view' : 'edit'; editor.item = item; editor.parentItem = null; - editor.hideLinksContainer = true; node.querySelector('.zotero-context-pane-editor-parent-line').innerHTML = ''; var parentItem = item.parentItem; @@ -772,17 +759,90 @@ var ZoteroContextPane = new function () { return; } var parentItem = Zotero.Items.get(item.parentID); + + // Dynamically create item pane tabs and panels as in itemPane.xul. + // Keep the code below in sync with itemPane.xul - // Info pane - var panelInfo = document.createElement('vbox'); + // tabbox + var tabbox = document.createElement('tabbox'); + tabbox.setAttribute('flex', '1'); + tabbox.className = 'zotero-view-tabbox'; + + container.append(tabbox); + + // tabs + var tabs = document.createElement('tabs'); + tabs.className = 'zotero-editpane-tabs'; + // tabpanels + var tabpanels = document.createElement('tabpanels'); + tabpanels.setAttribute('flex', '1'); + tabpanels.className = 'zotero-view-item'; + tabpanels.addEventListener('select', () => { + _updateAddToNote(); + }); + + tabbox.append(tabs, tabpanels); + + // Info tab + var tabInfo = document.createElement('tab'); + tabInfo.setAttribute('label', Zotero.Intl.strings['zotero.tabs.info.label']); + // Tags tab + var tabTags = document.createElement('tab'); + tabTags.setAttribute('label', Zotero.Intl.strings['zotero.tabs.tags.label']); + // Related tab + var tabRelated = document.createElement('tab'); + tabRelated.setAttribute('label', Zotero.Intl.strings['zotero.tabs.related.label']); + + tabs.append(tabInfo, tabTags, tabRelated); + + // Info panel + var panelInfo = document.createElement('tabpanel'); panelInfo.setAttribute('flex', '1'); panelInfo.className = 'zotero-editpane-item-box'; var itemBox = document.createElement('zoteroitembox'); itemBox.setAttribute('flex', '1'); panelInfo.append(itemBox); - container.append(panelInfo); + // Tags panel + var panelTags = document.createElement('tabpanel'); + panelTags.setAttribute('orient', 'vertical'); + panelTags.setAttribute('context', 'tags-context-menu'); + panelTags.className = 'tags-pane'; + panelTags.style.display = 'flex'; + var div = document.createElementNS(HTML_NS, 'div'); + div.className = 'tags-box-container'; + div.style.display = 'flex'; + div.style.flexGrow = '1'; + panelTags.append(div); + var tagsBoxRef = React.createRef(); + ReactDOM.render( + , + div + ); + // Related panel + var panelRelated = document.createElement('tabpanel'); + var relatedBox = document.createElement('relatedbox'); + relatedBox.setAttribute('flex', '1'); + relatedBox.className = 'zotero-editpane-related'; + panelRelated.addEventListener('click', (event) => { + if (event.originalTarget.closest('.zotero-clicky')) { + Zotero_Tabs.select('zotero-pane'); + } + }); + panelRelated.append(relatedBox); + + tabpanels.append(panelInfo, panelTags, panelRelated); + tabbox.selectedIndex = 0; + itemBox.mode = readOnly ? 'view' : 'edit'; itemBox.item = parentItem; + + relatedBox.mode = readOnly ? 'view' : 'edit'; + relatedBox.item = parentItem; } }; diff --git a/chrome/content/zotero/itemPane.xul b/chrome/content/zotero/itemPane.xul index 35563fafa6..f0201db1c7 100644 --- a/chrome/content/zotero/itemPane.xul +++ b/chrome/content/zotero/itemPane.xul @@ -69,6 +69,10 @@ + diff --git a/chrome/content/zotero/zoteroPane.js b/chrome/content/zotero/zoteroPane.js index d2b7aaa2ad..36ae95098f 100644 --- a/chrome/content/zotero/zoteroPane.js +++ b/chrome/content/zotero/zoteroPane.js @@ -2205,6 +2205,8 @@ var ZoteroPane = new function() if (found) { document.getElementById('zotero-items-tree').focus(); } + + Zotero_Tabs.select('zotero-pane'); }; diff --git a/scss/components/_tagsBox.scss b/scss/components/_tagsBox.scss index be79367f72..b377f46ab3 100644 --- a/scss/components/_tagsBox.scss +++ b/scss/components/_tagsBox.scss @@ -64,7 +64,12 @@ .editable-container { flex-grow: 1; margin: 0 2px; - //width: $item-pane-width - $icon-width - $delete-button-width - ($li-side-margin * 2); + // width: $item-pane-width - $icon-width - $delete-button-width - ($li-side-margin * 2); + + // This container shouldn't force any width for its parent, + // because tagsBox is used in more places than just item pane, + // and it can have smaller width than $item-pane-width + width: 0; } ul.tags-box-list > li:not(.multiline) .editable-container { From 647afbb0893db07d58d6cba185bff81a01d32ea6 Mon Sep 17 00:00:00 2001 From: Dan Stillman Date: Tue, 14 Sep 2021 01:48:36 -0400 Subject: [PATCH 2/2] Update related box if related items are renamed or deleted --- chrome/content/zotero/bindings/relatedbox.xml | 25 +++++-- test/tests/relatedboxTest.js | 66 +++++++++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/chrome/content/zotero/bindings/relatedbox.xml b/chrome/content/zotero/bindings/relatedbox.xml index 46ab5b75a9..a58399d35f 100644 --- a/chrome/content/zotero/bindings/relatedbox.xml +++ b/chrome/content/zotero/bindings/relatedbox.xml @@ -116,14 +116,25 @@ Zotero.Items.getIDFromLibraryAndKey(libraryID, key))); + for (let id of ids) { + if (relatedItemIDs.has(id)) { + this.refresh(); + return; + } + } } ]]> diff --git a/test/tests/relatedboxTest.js b/test/tests/relatedboxTest.js index 8f89d03d0c..81ee450aa0 100644 --- a/test/tests/relatedboxTest.js +++ b/test/tests/relatedboxTest.js @@ -12,6 +12,72 @@ describe("Related Box", function () { win.close(); }) + it("should update if a related item is renamed", async function () { + var title1 = 'aaaaaa'; + var title2 = 'bbbbbb'; + var item1 = await createDataObject('item', { title: title1 }); + var item2 = await createDataObject('item', { title: title2 }); + item1.addRelatedItem(item2); + await item1.saveTx(); + item2.addRelatedItem(item1); + await item2.saveTx(); + + // Select the Related pane + var tabbox = doc.getElementById('zotero-view-tabbox'); + tabbox.selectedIndex = 3; + var relatedbox = doc.getElementById('zotero-editpane-related'); + + // Wait for relations list to populate + do { + await Zotero.Promise.delay(50); + } + while (!relatedbox.id('relatedRows').childNodes.length); + + assert.include(doc.getAnonymousNodes(relatedbox)[0].innerHTML, title1); + + title1 = 'cccccc'; + item1.setField('title', title1); + await item1.saveTx(); + + // New title should appear in list + do { + await Zotero.Promise.delay(50); + } + while (!doc.getAnonymousNodes(relatedbox)[0].innerHTML.includes(title1)); + }); + + it("should update if a related item is deleted", async function () { + var title1 = 'aaaaaa'; + var title2 = 'bbbbbb'; + var item1 = await createDataObject('item', { title: title1 }); + var item2 = await createDataObject('item', { title: title2 }); + item1.addRelatedItem(item2); + await item1.saveTx(); + item2.addRelatedItem(item1); + await item2.saveTx(); + + // Select the Related pane + var tabbox = doc.getElementById('zotero-view-tabbox'); + tabbox.selectedIndex = 3; + var relatedbox = doc.getElementById('zotero-editpane-related'); + + // Wait for relations list to populate + do { + await Zotero.Promise.delay(50); + } + while (!relatedbox.id('relatedRows').childNodes.length); + + assert.include(doc.getAnonymousNodes(relatedbox)[0].innerHTML, title1); + + await item1.eraseTx(); + + // Deleted item should be removed from list + do { + await Zotero.Promise.delay(50); + } + while (doc.getAnonymousNodes(relatedbox)[0].innerHTML.includes(title1)); + }); + describe("Add button", function () { it("should add a related item", function* () { var item1 = yield createDataObject('item');