zotero-web-library
Version:
Web library from zotero.org
473 lines (456 loc) • 14.8 kB
JavaScript
'use strict';
var log = require('libzotero/lib/Log').Logger('zotero-web-library:ZoteroLibrary');
var React = require('react');
var ReactDOM = require('react-dom');
var ControlPanel = require('./ControlPanel.js');
var FilterGuide = require('./FilterGuide.js');
var Collections = require('./Collections.js');
var Tags = require('./Tags.js');
var FeedLink = require('./FeedLink.js');
var LibrarySearchBox = require('./LibrarySearchBox.js');
var Items = require('./Items.js');
var ItemDetails = require('./ItemDetails.js');
var SendToLibraryDialog = require('./SendToLibraryDialog.js');
var CreateCollectionDialog = require('./CreateCollectionDialog.js');
var UpdateCollectionDialog = require('./UpdateCollectionDialog.js');
var DeleteCollectionDialog = require('./DeleteCollectionDialog.js');
var AddToCollectionDialog = require('./AddToCollectionDialog.js');
var CreateItemDialog = require('./CreateItemDialog.js');
var CiteItemDialog = require('./CiteItemDialog.js');
var UploadAttachmentDialog = require('./UploadAttachmentDialog.js');
var ExportItemsDialog = require('./ExportItemsDialog.js');
var LibrarySettingsDialog = require('./LibrarySettingsDialog.js');
var ChooseSortingDialog = require('./ChooseSortingDialog.js');
Zotero.ui.widgets.library = {};
Zotero.ui.widgets.library.init = function (el) {
log.debug('Zotero.ui.widgets.library.init', 3);
var library = Zotero.ui.getAssociatedLibrary(el);
var reactInstance = ReactDOM.render(React.createElement(ZoteroLibrary, { library: library }), document.getElementById('library-widget'));
};
var ZoteroLibrary = React.createClass({
displayName: 'ZoteroLibrary',
componentWillMount: function componentWillMount() {
//preload library
log.debug('ZoteroLibrary componentWillMount', 3);
var reactInstance = this;
Zotero.reactLibraryInstance = reactInstance;
var library = this.props.library;
library.loadSettings();
library.listen('deleteIdb', function () {
library.idbLibrary.deleteDB();
});
library.listen('indexedDBError', function () {
Zotero.ui.jsNotificationMessage('There was an error initializing your library. Some data may not load properly.', 'notice');
});
library.listen('cachedDataLoaded', function () {});
window.addEventListener('resize', function () {
if (!window.matchMedia('(min-width: 768px)').matches) {
if (reactInstance.state.narrow != true) {
reactInstance.setState({ narrow: true });
}
} else {
if (reactInstance.state.narrow != false) {
reactInstance.setState({ narrow: false });
}
}
});
},
componentDidMount: function componentDidMount() {
var reactInstance = this;
var library = this.props.library;
library.listen('displayedItemsChanged', function () {
reactInstance.refs.itemsWidget.loadItems();
}, {});
library.listen('tagsChanged libraryTagsUpdated selectedTagsChanged', function () {
reactInstance.refs.tagsWidget.setState({ tags: library.tags });
});
//trigger loading of more items on scroll reaching bottom
reactInstance.refs.itemsPanel.addEventListener('scroll', function () {
var el = reactInstance.refs.itemsPanel;
if (el.scrollTop + el.clientHeight >= el.scrollHeight) {
reactInstance.refs.itemsWidget.loadMoreItems();
}
});
},
getInitialState: function getInitialState() {
var narrow;
if (!window.matchMedia('(min-width: 768px)').matches) {
log.debug('Library set to narrow', 3);
narrow = true;
} else {
narrow = false;
}
return {
narrow: narrow,
activePanel: 'items',
deviceSize: 'xs'
};
},
showFiltersPanel: function showFiltersPanel(evt) {
evt.preventDefault();
this.setState({ activePanel: 'filters' });
},
showItemsPanel: function showItemsPanel(evt) {
evt.preventDefault();
this.setState({ activePanel: 'items' });
},
reflowPanelContainer: function reflowPanelContainer() {},
render: function render() {
log.debug('ZoteroLibrary render', 3);
var reactInstance = this;
var library = this.props.library;
var user = Zotero.config.loggedInUser;
var userDisplayName = user ? user.displayName : null;
var base = Zotero.config.baseWebsiteUrl;
var settingsUrl = base + '/settings';
var inboxUrl = base + '/messages/inbox'; //TODO
var downloadUrl = base + '/download';
var documentationUrl = base + '/support';
var forumsUrl = Zotero.config.baseForumsUrl; //TODO
var logoutUrl = base + '/user/logout';
var loginUrl = base + '/user/login';
var homeUrl = base;
var staticUrl = function staticUrl(path) {
return base + '/static' + path;
};
var inboxText = '';
var siteActionsMenu;
if (user) {
inboxText = user.unreadMessages > 0 ? React.createElement(
'strong',
null,
'Inbox (',
user.unreadMessages,
')'
) : 'Inbox';
siteActionsMenu = [React.createElement(
'button',
{ key: 'button', type: 'button', href: '#', className: 'btn btn-default navbar-btn dropdown-toggle', 'data-toggle': 'dropdown', role: 'button', 'aria-expanded': 'false' },
userDisplayName,
React.createElement('span', { className: 'caret' }),
React.createElement(
'span',
{ className: 'sr-only' },
'Toggle Dropdown'
)
), React.createElement(
'ul',
{ key: 'listEntries', className: 'dropdown-menu', role: 'menu' },
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: settingsUrl },
'Settings'
)
),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: inboxUrl },
inboxText
)
),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: downloadUrl },
'Download'
)
),
React.createElement('li', { className: 'divider' }),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: documentationUrl, className: 'documentation' },
'Documentation'
)
),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: forumsUrl, className: 'forums' },
'Forums'
)
),
React.createElement('li', { className: 'divider' }),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: logoutUrl },
'Log Out'
)
)
)];
} else {
siteActionsMenu = React.createElement(
'div',
{ className: 'btn-group' },
React.createElement(
'a',
{ href: loginUrl, className: 'btn btn-default navbar-btn', role: 'button' },
'Log In'
),
React.createElement(
'button',
{ type: 'button', href: '#', className: 'btn btn-default navbar-btn dropdown-toggle', 'data-toggle': 'dropdown', role: 'button', 'aria-haspopup': 'true', 'aria-expanded': 'false' },
React.createElement('span', { className: 'caret' }),
React.createElement(
'span',
{ className: 'sr-only' },
'Toggle Dropdown'
)
),
React.createElement(
'ul',
{ className: 'dropdown-menu', role: 'menu' },
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: downloadUrl },
'Download'
)
),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: documentationUrl, className: 'documentation' },
'Documentation'
)
),
React.createElement(
'li',
null,
React.createElement(
'a',
{ href: forumsUrl, className: 'forums' },
'Forums'
)
)
)
);
}
//figure out panel visibility based on state.activePanel
var narrow = reactInstance.state.narrow;
var leftPanelVisible = !narrow;
var rightPanelVisible = !narrow;
var itemsPanelVisible = !narrow;
var itemPanelVisible = !narrow;
var tagsPanelVisible = !narrow;
var collectionsPanelVisible = !narrow;
if (narrow) {
switch (reactInstance.state.activePanel) {
case 'items':
rightPanelVisible = true;
itemsPanelVisible = true;
break;
case 'item':
rightPanelVisible = true;
itemPanelVisible = true;
break;
case 'tags':
leftPanelVisible = true;
tagsPanelVisible = true;
break;
case 'collections':
leftPanelVisible = true;
collectionsPanelVisible = true;
break;
case 'filters':
leftPanelVisible = true;
break;
}
}
return React.createElement(
'div',
null,
React.createElement(
'nav',
{ id: 'primarynav', className: 'navbar navbar-default', role: 'navigation' },
React.createElement(
'div',
{ className: 'container-fluid' },
React.createElement(
'div',
{ className: 'navbar-header' },
React.createElement(
'button',
{ type: 'button', className: 'navbar-toggle collapsed', 'data-toggle': 'collapse', 'data-target': '#primary-nav-linklist' },
userDisplayName,
React.createElement(
'span',
{ className: 'sr-only' },
'Toggle navigation'
),
React.createElement('span', { className: 'glyphicons fonticon glyphicons-menu-hamburger' })
),
React.createElement(
'a',
{ className: 'navbar-brand hidden-sm hidden-xs', href: homeUrl },
React.createElement('img', { src: staticUrl('/images/theme/zotero.png'), alt: 'Zotero', height: '20px' })
),
React.createElement(
'a',
{ className: 'navbar-brand visible-sm-block visible-xs-block', href: homeUrl },
React.createElement('img', { src: staticUrl('/images/theme/zotero_theme/zotero_48.png'), alt: 'Zotero', height: '24px' })
)
),
React.createElement(
'div',
{ className: 'collapse navbar-collapse', id: 'primary-nav-linklist' },
React.createElement(ControlPanel, { library: library, editable: Zotero.config.librarySettings.allowEdit, ref: 'controlPanel' }),
React.createElement(
'ul',
{ className: 'nav navbar-nav navbar-right' },
siteActionsMenu
),
React.createElement(
'div',
{ className: 'btn-toolbar hidden-xs navbar-right' },
React.createElement(LibrarySearchBox, { library: library })
)
)
)
),
React.createElement(
'div',
{ id: 'js-message' },
React.createElement('ul', { id: 'js-message-list' })
),
React.createElement(
'div',
{ id: 'library', className: 'row' },
React.createElement(
'div',
{ id: 'panel-container' },
React.createElement(
'div',
{ id: 'left-panel', hidden: !leftPanelVisible, className: 'panelcontainer-panelcontainer col-xs-12 col-sm-4 col-md-3' },
React.createElement(FilterGuide, { ref: 'filterGuide', library: library }),
React.createElement(
'div',
{ role: 'tabpanel' },
React.createElement(
'ul',
{ className: 'nav nav-tabs', role: 'tablist' },
React.createElement(
'li',
{ role: 'presentation', className: 'active' },
React.createElement(
'a',
{ href: '#collections-panel', 'aria-controls': 'collections-panel', role: 'tab', 'data-toggle': 'tab' },
'Collections'
)
),
React.createElement(
'li',
{ role: 'presentation' },
React.createElement(
'a',
{ href: '#tags-panel', 'aria-controls': 'tags-panel', role: 'tab', 'data-toggle': 'tab' },
'Tags'
)
)
),
React.createElement(
'div',
{ className: 'tab-content' },
React.createElement(
'div',
{ id: 'collections-panel', role: 'tabpanel', className: 'tab-pane active' },
React.createElement(Collections, { ref: 'collectionsWidget', library: library })
),
React.createElement(
'div',
{ id: 'tags-panel', role: 'tabpanel', className: 'tab-pane' },
React.createElement(Tags, { ref: 'tagsWidget', library: library }),
React.createElement(FeedLink, { ref: 'feedLinkWidget', library: library })
)
)
)
),
React.createElement(
'div',
{ id: 'right-panel', hidden: !rightPanelVisible, className: 'panelcontainer-panelcontainer col-xs-12 col-sm-8 col-md-9' },
React.createElement(
'div',
{ hidden: !itemsPanelVisible, ref: 'itemsPanel', id: 'items-panel', className: 'panelcontainer-panel col-sm-12 col-md-7' },
React.createElement(
'div',
{ className: 'visible-xs library-search-box-container' },
React.createElement(LibrarySearchBox, { library: library })
),
React.createElement(Items, { ref: 'itemsWidget', library: library, narrow: narrow })
),
React.createElement(
'div',
{ hidden: !itemPanelVisible, id: 'item-panel', className: 'panelcontainer-panel col-sm-12 col-md-5' },
React.createElement(
'div',
{ id: 'item-widget-div', className: 'item-details-div' },
React.createElement(ItemDetails, { ref: 'itemWidget', library: library })
)
)
),
React.createElement(
'nav',
{ id: 'panelcontainer-nav', className: 'navbar navbar-default navbar-fixed-bottom visible-xs-block', role: 'navigation' },
React.createElement(
'div',
{ className: 'container-fluid' },
React.createElement(
'ul',
{ className: 'nav navbar-nav' },
React.createElement(
'li',
{ onClick: reactInstance.showFiltersPanel, className: 'filters-nav' },
React.createElement(
'a',
{ href: '#' },
'Filters'
)
),
React.createElement(
'li',
{ onClick: reactInstance.showItemsPanel, className: 'items-nav' },
React.createElement(
'a',
{ href: '#' },
'Items'
)
)
)
)
),
React.createElement(SendToLibraryDialog, { ref: 'sendToLibraryDialogWidget', library: library }),
React.createElement(CreateCollectionDialog, { ref: 'createCollectionDialogWidget', library: library }),
React.createElement(UpdateCollectionDialog, { library: library }),
React.createElement(DeleteCollectionDialog, { library: library }),
React.createElement(AddToCollectionDialog, { library: library }),
React.createElement(CreateItemDialog, { library: library }),
React.createElement(CiteItemDialog, { library: library }),
React.createElement(UploadAttachmentDialog, { library: library }),
React.createElement(ExportItemsDialog, { library: library }),
React.createElement(LibrarySettingsDialog, { library: library }),
React.createElement(ChooseSortingDialog, { library: library })
)
)
);
}
});
module.exports = ZoteroLibrary;