Close #1053, Manual sync option in library context menu

This also reworks how the collection context menu is built to do more in
JS instead of XUL, though it can't do it all in JS because some
localized strings are in zotero.dtd and are used in standalone.xul too.
This commit is contained in:
Dan Stillman 2016-07-02 01:46:23 -04:00
parent 893b9ae1fc
commit fc857dc496
3 changed files with 226 additions and 113 deletions

View File

@ -2313,7 +2313,111 @@ var ZoteroPane = new function()
this.buildCollectionContextMenu = function (noRepeat) { this.buildCollectionContextMenu = function (noRepeat) {
var libraryID = this.getSelectedLibraryID();
// menuitem configuration
//
// This has to be kept in sync with zotero-collectionmenu in zoteroPane.xul. We could do this
// entirely in JS, but various localized strings are only in zotero.dtd, and they're used in
// standalone.xul as well, so for now they have to remain as XML entities.
var options = [
{
id: "sync",
label: Zotero.getString('sync.sync'),
onclick: () => {
Zotero.Sync.Runner.sync({
libraries: [libraryID],
});
}
},
{
id: "sep1",
},
{
id: "newCollection",
command: "cmd_zotero_newCollection"
},
{
id: "newSavedSearch",
command: "cmd_zotero_newSavedSearch"
},
{
id: "newSubcollection",
onclick: () => {
this.newCollection(this.getSelectedCollection().key);
}
},
{
id: "refreshFeed",
onclick: () => this.refreshFeed()
},
{
id: "sep2",
},
{
id: "showDuplicates",
onclick: () => {
this.setVirtual(libraryID, 'duplicates', true);
}
},
{
id: "showUnfiled",
onclick: () => {
this.setVirtual(libraryID, 'unfiled', true);
}
},
{
id: "editSelectedCollection",
onclick: () => this.editSelectedCollection()
},
{
id: "markReadFeed",
onclick: () => this.markFeedRead()
},
{
id: "editSelectedFeed",
onclick: () => this.editSelectedFeed()
},
{
id: "deleteCollection",
onclick: () => this.deleteSelectedCollection()
},
{
id: "deleteCollectionAndItems",
onclick: () => this.deleteSelectedCollection(true)
},
{
id: "sep3",
},
{
id: "exportCollection",
onclick: () => Zotero_File_Interface.exportCollection()
},
{
id: "createBibCollection",
onclick: () => Zotero_File_Interface.bibliographyFromCollection()
},
{
id: "exportFile",
onclick: () => Zotero_File_Interface.exportFile()
},
{
id: "loadReport",
onclick: event => Zotero_Report_Interface.loadCollectionReport(event)
},
{
id: "emptyTrash",
onclick: () => this.emptyTrash()
}
];
var collectionTreeRow = this.collectionsView.selectedTreeRow; var collectionTreeRow = this.collectionsView.selectedTreeRow;
// This can happen if selection is changing during delayed second call below
if (!collectionTreeRow) {
return;
}
// If the items view isn't initialized, this was a right-click on a different collection and // If the items view isn't initialized, this was a right-click on a different collection and
// the new collection's items are still loading, so update the menu after loading. This causes // the new collection's items are still loading, so update the menu after loading. This causes
// some menu items (e.g., export/createBib/loadReport) to appear gray in the menu at first and // some menu items (e.g., export/createBib/loadReport) to appear gray in the menu at first and
@ -2324,35 +2428,28 @@ var ZoteroPane = new function()
}.bind(this)); }.bind(this));
} }
var options = [ // Set attributes on the menu from the configuration object
"newCollection", var menu = document.getElementById('zotero-collectionmenu');
"newSavedSearch",
"newSubcollection",
"refreshFeed",
"sep1",
"showDuplicates",
"showUnfiled",
"editSelectedCollection",
"markReadFeed",
"editSelectedFeed",
"deleteCollection",
"deleteCollectionAndItems",
"sep2",
"exportCollection",
"createBibCollection",
"exportFile",
"loadReport",
"emptyTrash",
"createCommonsBucket",
"refreshCommonsBucket"
];
var m = {}; var m = {};
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
m[options[i]] = i; let option = options[i];
} let menuitem = menu.childNodes[i];
m[option.id] = menuitem;
var menu = document.getElementById('zotero-collectionmenu'); menuitem.id = option.id;
if (!menuitem.classList.contains('menuitem-iconic')) {
menuitem.classList.add('menuitem-iconic');
}
if (option.label) {
menuitem.setAttribute('label', option.label);
}
if (option.command) {
menuitem.setAttribute('command', option.command);
}
else if (option.onclick) {
menuitem.onclick = option.onclick;
}
}
// By default things are hidden and visible, so we only need to record // By default things are hidden and visible, so we only need to record
// when things are visible and when they're visible but disabled // when things are visible and when they're visible but disabled
@ -2360,133 +2457,145 @@ var ZoteroPane = new function()
if (collectionTreeRow.isCollection()) { if (collectionTreeRow.isCollection()) {
show = [ show = [
m.newSubcollection, 'newSubcollection',
m.sep1, 'sep2',
m.editSelectedCollection, 'editSelectedCollection',
m.deleteCollection, 'deleteCollection',
m.deleteCollectionAndItems, 'deleteCollectionAndItems',
m.sep2, 'sep3',
m.exportCollection, 'exportCollection',
m.createBibCollection, 'createBibCollection',
m.loadReport 'loadReport'
]; ];
var s = [m.exportCollection, m.createBibCollection, m.loadReport];
if (!this.itemsView.rowCount) { if (!this.itemsView.rowCount) {
disable = s; disable = ['exportCollection', 'createBibCollection', 'loadReport'];
} }
// Adjust labels // Adjust labels
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection')); m.editSelectedCollection.setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection'));
menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('pane.collections.menu.delete.collection')); m.deleteCollection.setAttribute('label', Zotero.getString('pane.collections.menu.delete.collection'));
menu.childNodes[m.deleteCollectionAndItems].setAttribute('label', Zotero.getString('pane.collections.menu.delete.collectionAndItems')); m.deleteCollectionAndItems.setAttribute('label', Zotero.getString('pane.collections.menu.delete.collectionAndItems'));
menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.collection')); m.exportCollection.setAttribute('label', Zotero.getString('pane.collections.menu.export.collection'));
menu.childNodes[m.createBibCollection].setAttribute('label', Zotero.getString('pane.collections.menu.createBib.collection')); m.createBibCollection.setAttribute('label', Zotero.getString('pane.collections.menu.createBib.collection'));
menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.collection')); m.loadReport.setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.collection'));
} }
else if (collectionTreeRow.isFeed()) { else if (collectionTreeRow.isFeed()) {
show = [ show = [
m.refreshFeed, 'refreshFeed',
m.sep1, 'sep2',
m.markReadFeed, 'markReadFeed',
m.editSelectedFeed, 'editSelectedFeed',
m.deleteCollectionAndItems 'deleteCollectionAndItems'
]; ];
if (collectionTreeRow.ref.unreadCount == 0) { if (collectionTreeRow.ref.unreadCount == 0) {
disable.push(m.markReadFeed); disable = ['markReadFeed'];
} }
// Adjust labels // Adjust labels
menu.childNodes[m.deleteCollectionAndItems].setAttribute('label', Zotero.getString('pane.collections.menu.delete.feedAndItems')); m.deleteCollectionAndItems.setAttribute('label', Zotero.getString('pane.collections.menu.delete.feedAndItems'));
} }
else if (collectionTreeRow.isSearch()) { else if (collectionTreeRow.isSearch()) {
show = [ show = [
m.editSelectedCollection, 'editSelectedCollection',
m.deleteCollection, 'deleteCollection',
m.sep2, 'sep3',
m.exportCollection, 'exportCollection',
m.createBibCollection, 'createBibCollection',
m.loadReport 'loadReport'
]; ];
menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('pane.collections.menu.delete.savedSearch')); m.deleteCollection.setAttribute('label', Zotero.getString('pane.collections.menu.delete.savedSearch'));
var s = [m.exportCollection, m.createBibCollection, m.loadReport];
if (!this.itemsView.rowCount) { if (!this.itemsView.rowCount) {
disable = s; disable.push('exportCollection', 'createBibCollection', 'loadReport');
} }
// Adjust labels // Adjust labels
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch')); m.editSelectedCollection.setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch')); m.exportCollection.setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch'));
menu.childNodes[m.createBibCollection].setAttribute('label', Zotero.getString('pane.collections.menu.createBib.savedSearch')); m.createBibCollection.setAttribute('label', Zotero.getString('pane.collections.menu.createBib.savedSearch'));
menu.childNodes[m.loadReport].setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.savedSearch')); m.loadReport.setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.savedSearch'));
} }
else if (collectionTreeRow.isTrash()) { else if (collectionTreeRow.isTrash()) {
show = [m.emptyTrash]; show = ['emptyTrash'];
} }
else if (collectionTreeRow.isDuplicates() || collectionTreeRow.isUnfiled()) { else if (collectionTreeRow.isDuplicates() || collectionTreeRow.isUnfiled()) {
show = [ show = ['deleteCollection'];
m.deleteCollection
];
menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('general.hide')); m.deleteCollection.setAttribute('label', Zotero.getString('general.hide'));
} }
else if (collectionTreeRow.isHeader()) { else if (collectionTreeRow.isHeader()) {
if (collectionTreeRow.ref.id == 'commons-header') {
show = [m.createCommonsBucket];
}
}
else if (collectionTreeRow.isBucket()) {
show = [m.refreshCommonsBucket];
} }
else if (collectionTreeRow.isPublications()) { else if (collectionTreeRow.isPublications()) {
show = [m.exportFile]; show = [
'sync',
'sep1',
'exportFile'
];
} }
// Library // Library
else { else {
show = [ show = [
m.newCollection, 'sync',
m.newSavedSearch, 'sep1',
m.sep1, 'newCollection',
m.showDuplicates, 'newSavedSearch',
m.showUnfiled,
m.sep2,
m.exportFile
]; ];
// Only show "Show Duplicates" and "Show Unfiled Items" if rows are hidden
let duplicates = Zotero.Utilities.Internal.getVirtualCollectionStateForLibrary(
libraryID, 'duplicates'
);
let unfiled = Zotero.Utilities.Internal.getVirtualCollectionStateForLibrary(
libraryID, 'unfiled'
);
if (!duplicates || !unfiled) {
show.push('sep2');
if (!duplicates) {
show.push('showDuplicates');
}
if (!unfiled) {
show.push('showUnfiled');
}
}
show.push(
'sep3',
'exportFile'
);
} }
// Disable some actions if user doesn't have write access // Disable some actions if user doesn't have write access
// //
// Some actions are disabled via their commands in onCollectionSelected() // Some actions are disabled via their commands in onCollectionSelected()
var s = [m.newSubcollection, m.editSelectedCollection, m.deleteCollection, m.deleteCollectionAndItems];
if (collectionTreeRow.isWithinGroup() && !collectionTreeRow.editable && !collectionTreeRow.isDuplicates() && !collectionTreeRow.isUnfiled()) { if (collectionTreeRow.isWithinGroup() && !collectionTreeRow.editable && !collectionTreeRow.isDuplicates() && !collectionTreeRow.isUnfiled()) {
disable = disable.concat(s); disable.push(
'newSubcollection',
'editSelectedCollection',
'deleteCollection',
'deleteCollectionAndItems'
);
} }
// If within non-editable group or trash it empty, disable Empty Trash // If within non-editable group or trash it empty, disable Empty Trash
if (collectionTreeRow.isTrash()) { if (collectionTreeRow.isTrash()) {
if ((collectionTreeRow.isWithinGroup() && !collectionTreeRow.isWithinEditableGroup()) || !this.itemsView.rowCount) { if ((collectionTreeRow.isWithinGroup() && !collectionTreeRow.isWithinEditableGroup()) || !this.itemsView.rowCount) {
disable.push(m.emptyTrash); disable.push('emptyTrash');
} }
} }
// Hide and enable all actions by default (so if they're shown they're enabled) // Hide and enable all actions by default (so if they're shown they're enabled)
for (let i in m) { for (let i in m) {
let pos = m[i]; m[i].setAttribute('hidden', true);
menu.childNodes[pos].setAttribute('hidden', true); m[i].setAttribute('disabled', false);
menu.childNodes[pos].setAttribute('disabled', false);
} }
for (var i in show) for (let id of show) {
{ m[id].setAttribute('hidden', false);
menu.childNodes[show[i]].setAttribute('hidden', false);
} }
for (var i in disable) for (let id of disable) {
{ m[id].setAttribute('disabled', true);
menu.childNodes[disable[i]].setAttribute('disabled', true);
} }
} }

View File

@ -256,27 +256,27 @@
<popupset> <popupset>
<menupopup id="zotero-collectionmenu" onpopupshowing="ZoteroPane_Local.buildCollectionContextMenu();"> <menupopup id="zotero-collectionmenu" onpopupshowing="ZoteroPane_Local.buildCollectionContextMenu();">
<!-- Keep order in sync with buildCollectionContextMenu --> <!-- Keep order in sync with buildCollectionContextMenu, which adds additional attributes -->
<menuitem class="menuitem-iconic zotero-menuitem-new-collection" label="&zotero.toolbar.newCollection.label;" command="cmd_zotero_newCollection"/> <menuitem class="zotero-menuitem-sync"/>
<menuitem class="menuitem-iconic zotero-menuitem-new-saved-search" label="&zotero.toolbar.newSavedSearch.label;" command="cmd_zotero_newSavedSearch"/>
<menuitem class="menuitem-iconic zotero-menuitem-new-collection" label="&zotero.toolbar.newSubcollection.label;" oncommand="ZoteroPane_Local.newCollection(ZoteroPane_Local.getSelectedCollection().key)"/>
<menuitem class="menuitem-iconic zotero-menuitem-refresh-feed" label="&zotero.toolbar.feeds.refresh;" oncommand="ZoteroPane_Local.refreshFeed();"/>
<menuseparator/> <menuseparator/>
<menuitem class="menuitem-iconic zotero-menuitem-show-duplicates" label="&zotero.toolbar.duplicate.label;" oncommand="ZoteroPane_Local.setVirtual(ZoteroPane_Local.getSelectedLibraryID(), 'duplicates', true)"/> <menuitem class="zotero-menuitem-new-collection" label="&zotero.toolbar.newCollection.label;"/>
<menuitem class="menuitem-iconic zotero-menuitem-show-unfiled" label="&zotero.collections.showUnfiledItems;" oncommand="ZoteroPane_Local.setVirtual(ZoteroPane_Local.getSelectedLibraryID(), 'unfiled', true)"/> <menuitem class="zotero-menuitem-new-saved-search" label="&zotero.toolbar.newSavedSearch.label;"/>
<menuitem class="menuitem-iconic zotero-menuitem-edit-collection" oncommand="ZoteroPane_Local.editSelectedCollection();"/> <menuitem class="zotero-menuitem-new-collection" label="&zotero.toolbar.newSubcollection.label;"/>
<menuitem class="menuitem-iconic zotero-menuitem-mark-read-feed" label="&zotero.toolbar.markFeedRead.label;" oncommand="ZoteroPane_Local.markFeedRead();"/> <menuitem class="zotero-menuitem-refresh-feed" label="&zotero.toolbar.feeds.refresh;"/>
<menuitem class="menuitem-iconic zotero-menuitem-edit-feed" label="&zotero.toolbar.feeds.edit;" oncommand="ZoteroPane_Local.editSelectedFeed();"/>
<menuitem class="menuitem-iconic zotero-menuitem-delete-collection" oncommand="ZoteroPane_Local.deleteSelectedCollection();"/>
<menuitem class="menuitem-iconic zotero-menuitem-move-to-trash" oncommand="ZoteroPane_Local.deleteSelectedCollection(true);"/>
<menuseparator/> <menuseparator/>
<menuitem class="menuitem-iconic zotero-menuitem-export" oncommand="Zotero_File_Interface.exportCollection();"/> <menuitem class="zotero-menuitem-show-duplicates" label="&zotero.toolbar.duplicate.label;"/>
<menuitem class="menuitem-iconic zotero-menuitem-create-bibliography" oncommand="Zotero_File_Interface.bibliographyFromCollection();"/> <menuitem class="zotero-menuitem-show-unfiled" label="&zotero.collections.showUnfiledItems;"/>
<menuitem class="menuitem-iconic zotero-menuitem-export" label="&zotero.toolbar.export.label;" oncommand="Zotero_File_Interface.exportFile()"/> <menuitem class="zotero-menuitem-edit-collection"/>
<menuitem class="menuitem-iconic zotero-menuitem-create-report" oncommand="Zotero_Report_Interface.loadCollectionReport(event)"/> <menuitem class="zotero-menuitem-mark-read-feed" label="&zotero.toolbar.markFeedRead.label;"/>
<menuitem class="menuitem-iconic zotero-menuitem-delete-from-lib" label="&zotero.toolbar.emptyTrash.label;" oncommand="ZoteroPane_Local.emptyTrash();"/> <menuitem class="zotero-menuitem-edit-feed" label="&zotero.toolbar.feeds.edit;"/>
<menuitem label="&zotero.toolbar.newCollection.label;" oncommand="ZoteroPane_Local.createCommonsBucket();"/><!--TODO localize --> <menuitem class="zotero-menuitem-delete-collection"/>
<menuitem label="Refresh" oncommand="ZoteroPane_Local.refreshCommonsBucket();"/><!--TODO localize --> <menuitem class="zotero-menuitem-move-to-trash"/>
<menuseparator/>
<menuitem class="zotero-menuitem-export"/>
<menuitem class="zotero-menuitem-create-bibliography"/>
<menuitem class="zotero-menuitem-export" label="&zotero.toolbar.export.label;"/>
<menuitem class="zotero-menuitem-create-report"/>
<menuitem class="zotero-menuitem-delete-from-lib" label="&zotero.toolbar.emptyTrash.label;"/>
</menupopup> </menupopup>
<menupopup id="zotero-itemmenu"> <menupopup id="zotero-itemmenu">
<!-- Keep order in sync with buildItemContextMenu --> <!-- Keep order in sync with buildItemContextMenu -->

View File

@ -397,6 +397,10 @@
list-style-image: url('chrome://zotero/skin/treesource-unfiled.png'); list-style-image: url('chrome://zotero/skin/treesource-unfiled.png');
} }
.zotero-menuitem-sync {
list-style-image: url(chrome://zotero/skin/arrow_rotate_static.png);
}
.zotero-menuitem-new-collection .zotero-menuitem-new-collection
{ {
list-style-image: url('chrome://zotero/skin/toolbar-collection-add.png'); list-style-image: url('chrome://zotero/skin/toolbar-collection-add.png');