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) {
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;
// 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
// 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
@ -2324,169 +2428,174 @@ var ZoteroPane = new function()
}.bind(this));
}
var options = [
"newCollection",
"newSavedSearch",
"newSubcollection",
"refreshFeed",
"sep1",
"showDuplicates",
"showUnfiled",
"editSelectedCollection",
"markReadFeed",
"editSelectedFeed",
"deleteCollection",
"deleteCollectionAndItems",
"sep2",
"exportCollection",
"createBibCollection",
"exportFile",
"loadReport",
"emptyTrash",
"createCommonsBucket",
"refreshCommonsBucket"
];
// Set attributes on the menu from the configuration object
var menu = document.getElementById('zotero-collectionmenu');
var m = {};
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;
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;
}
}
var menu = document.getElementById('zotero-collectionmenu');
// By default things are hidden and visible, so we only need to record
// when things are visible and when they're visible but disabled
var show = [], disable = [];
if (collectionTreeRow.isCollection()) {
show = [
m.newSubcollection,
m.sep1,
m.editSelectedCollection,
m.deleteCollection,
m.deleteCollectionAndItems,
m.sep2,
m.exportCollection,
m.createBibCollection,
m.loadReport
'newSubcollection',
'sep2',
'editSelectedCollection',
'deleteCollection',
'deleteCollectionAndItems',
'sep3',
'exportCollection',
'createBibCollection',
'loadReport'
];
var s = [m.exportCollection, m.createBibCollection, m.loadReport];
if (!this.itemsView.rowCount) {
disable = s;
disable = ['exportCollection', 'createBibCollection', 'loadReport'];
}
// Adjust labels
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection'));
menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('pane.collections.menu.delete.collection'));
menu.childNodes[m.deleteCollectionAndItems].setAttribute('label', Zotero.getString('pane.collections.menu.delete.collectionAndItems'));
menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.collection'));
menu.childNodes[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.editSelectedCollection.setAttribute('label', Zotero.getString('pane.collections.menu.rename.collection'));
m.deleteCollection.setAttribute('label', Zotero.getString('pane.collections.menu.delete.collection'));
m.deleteCollectionAndItems.setAttribute('label', Zotero.getString('pane.collections.menu.delete.collectionAndItems'));
m.exportCollection.setAttribute('label', Zotero.getString('pane.collections.menu.export.collection'));
m.createBibCollection.setAttribute('label', Zotero.getString('pane.collections.menu.createBib.collection'));
m.loadReport.setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.collection'));
}
else if (collectionTreeRow.isFeed()) {
show = [
m.refreshFeed,
m.sep1,
m.markReadFeed,
m.editSelectedFeed,
m.deleteCollectionAndItems
'refreshFeed',
'sep2',
'markReadFeed',
'editSelectedFeed',
'deleteCollectionAndItems'
];
if (collectionTreeRow.ref.unreadCount == 0) {
disable.push(m.markReadFeed);
disable = ['markReadFeed'];
}
// 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()) {
show = [
m.editSelectedCollection,
m.deleteCollection,
m.sep2,
m.exportCollection,
m.createBibCollection,
m.loadReport
'editSelectedCollection',
'deleteCollection',
'sep3',
'exportCollection',
'createBibCollection',
'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) {
disable = s;
disable.push('exportCollection', 'createBibCollection', 'loadReport');
}
// Adjust labels
menu.childNodes[m.editSelectedCollection].setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
menu.childNodes[m.exportCollection].setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch'));
menu.childNodes[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.editSelectedCollection.setAttribute('label', Zotero.getString('pane.collections.menu.edit.savedSearch'));
m.exportCollection.setAttribute('label', Zotero.getString('pane.collections.menu.export.savedSearch'));
m.createBibCollection.setAttribute('label', Zotero.getString('pane.collections.menu.createBib.savedSearch'));
m.loadReport.setAttribute('label', Zotero.getString('pane.collections.menu.generateReport.savedSearch'));
}
else if (collectionTreeRow.isTrash()) {
show = [m.emptyTrash];
show = ['emptyTrash'];
}
else if (collectionTreeRow.isDuplicates() || collectionTreeRow.isUnfiled()) {
show = [
m.deleteCollection
];
show = ['deleteCollection'];
menu.childNodes[m.deleteCollection].setAttribute('label', Zotero.getString('general.hide'));
m.deleteCollection.setAttribute('label', Zotero.getString('general.hide'));
}
else if (collectionTreeRow.isHeader()) {
if (collectionTreeRow.ref.id == 'commons-header') {
show = [m.createCommonsBucket];
}
}
else if (collectionTreeRow.isBucket()) {
show = [m.refreshCommonsBucket];
}
else if (collectionTreeRow.isPublications()) {
show = [m.exportFile];
show = [
'sync',
'sep1',
'exportFile'
];
}
// Library
else {
show = [
m.newCollection,
m.newSavedSearch,
m.sep1,
m.showDuplicates,
m.showUnfiled,
m.sep2,
m.exportFile
'sync',
'sep1',
'newCollection',
'newSavedSearch',
];
// 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
//
// 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()) {
disable = disable.concat(s);
disable.push(
'newSubcollection',
'editSelectedCollection',
'deleteCollection',
'deleteCollectionAndItems'
);
}
// If within non-editable group or trash it empty, disable Empty Trash
if (collectionTreeRow.isTrash()) {
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)
for (let i in m) {
let pos = m[i];
menu.childNodes[pos].setAttribute('hidden', true);
menu.childNodes[pos].setAttribute('disabled', false);
m[i].setAttribute('hidden', true);
m[i].setAttribute('disabled', false);
}
for (var i in show)
{
menu.childNodes[show[i]].setAttribute('hidden', false);
for (let id of show) {
m[id].setAttribute('hidden', false);
}
for (var i in disable)
{
menu.childNodes[disable[i]].setAttribute('disabled', true);
for (let id of disable) {
m[id].setAttribute('disabled', true);
}
}

View file

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

View file

@ -397,6 +397,10 @@
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
{
list-style-image: url('chrome://zotero/skin/toolbar-collection-add.png');