UNPKG

zotero-web-library

Version:

Web library from zotero.org

254 lines (231 loc) 8.28 kB
'use strict'; var log = require('libzotero/lib/Log').Logger('zotero-web-library:Collections'); var React = require('react'); var LoadingSpinner = require('./LoadingSpinner.js'); var CollectionRow = React.createClass({ displayName: 'CollectionRow', getDefaultProps: function getDefaultProps() { return { collection: null, selectedCollection: '', depth: 0, expandedCollections: {} }; }, handleCollectionClick: function handleCollectionClick(evt) { evt.preventDefault(); var collectionKey = this.props.collection.get('collectionKey'); //if current collect Zotero.state.clearUrlVars(); Zotero.state.pathVars['collectionKey'] = collectionKey; Zotero.state.pushState(); }, handleTwistyClick: function handleTwistyClick(evt) { log.debug('handleTwistyClick', 3); //toggle expanded state for this collection evt.preventDefault(); var collectionKey = this.props.collection.get('collectionKey'); var exp = this.props.expandedCollections; if (exp[collectionKey]) { delete exp[collectionKey]; } else { exp[collectionKey] = true; } this.props.parentCollectionsInstance.setState({ expandedCollections: exp }); }, render: function render() { if (this.props.collection == null) { return null; } var collection = this.props.collection; var collectionKey = collection.get('key'); var selectedCollection = this.props.selectedCollection; var expandedCollections = this.props.expandedCollections; var expanded = expandedCollections[collectionKey] === true; var isSelectedCollection = this.props.selectedCollection == collectionKey; var childRows = []; collection.children.forEach(function (collection) { childRows.push(React.createElement(CollectionRow, { key: collection.get('key'), collection: collection, selectedCollection: selectedCollection, expandedCollections: expandedCollections })); }); var childrenList = null; if (collection.hasChildren) { childrenList = React.createElement( 'ul', { hidden: !expanded }, childRows ); } var placeholderClasses = 'placeholder small-icon light-icon pull-left'; if (expandedCollections[collectionKey] === true) { placeholderClasses += ' glyphicon glyphicon-chevron-down clickable'; } else if (childRows.length > 0) { placeholderClasses += ' glyphicon glyphicon-chevron-right clickable'; } return React.createElement( 'li', { className: 'collection-row' }, React.createElement( 'div', { className: 'folder-toggle' }, React.createElement('span', { className: placeholderClasses, onClick: this.handleTwistyClick }), React.createElement('span', { className: 'fonticon glyphicons glyphicons-folder-open barefonticon' }) ), React.createElement( 'a', { href: collection.websiteCollectionLink, className: isSelectedCollection ? 'current-collection' : '', onClick: this.handleCollectionClick }, collection.get('name') ), childrenList ); } }); var TrashRow = React.createClass({ displayName: 'TrashRow', getDefaultProps: function getDefaultProps() { return { collectionKey: 'trash', selectedCollection: '' }; }, handleClick: function handleClick() { Zotero.state.clearUrlVars(); Zotero.state.pathVars['collectionKey'] = this.props.collectionKey; Zotero.state.pushState(); }, render: function render() { var className = this.props.selectedCollection == this.props.collectionKey ? 'collection-row current-collection' : 'collection-row'; return React.createElement( 'li', { className: className }, React.createElement( 'div', { className: 'folder-toggle' }, React.createElement('span', { className: 'sprite-placeholder sprite-icon-16 pull-left dui-icon' }), React.createElement('span', { className: 'glyphicons fonticon glyphicons-bin barefonticon' }) ), 'Trash' ); } }); var Collections = React.createClass({ displayName: 'Collections', getDefaultProps: function getDefaultProps() {}, getInitialState: function getInitialState() { var initialCollectionKey = Zotero.state.getUrlVar('collectionKey'); return { collections: null, currentCollectionKey: initialCollectionKey, expandedCollections: {}, loading: false }; }, componentWillMount: function componentWillMount() { var reactInstance = this; var library = this.props.library; library.listen('collectionsDirty', reactInstance.syncCollections, {}); library.listen('libraryCollectionsUpdated', function () { reactInstance.setState({ collections: library.collections }); }, {}); library.listen('selectedCollectionChanged', function () { var collectionKey = Zotero.state.getUrlVar('collectionKey'); reactInstance.setState({ currentCollectionKey: collectionKey }); }, {}); library.listen('cachedDataLoaded', reactInstance.syncCollections, {}); }, returnToLibrary: function returnToLibrary(evt) { evt.preventDefault(); this.setState({ currentCollectionKey: null }); Zotero.state.clearUrlVars(); Zotero.state.pushState(); }, syncCollections: function syncCollections(evt) { log.debug('react collections syncCollections', 3); var reactInstance = this; if (this.state.loading) { return; } var library = this.props.library; //update the widget as soon as we have the cached collections this.setState({ collections: library.collections, loading: true }); //sync collections if loaded from cache but not synced return library.loadUpdatedCollections().then(function () { reactInstance.setState({ collections: library.collections, loading: false }); library.trigger('libraryCollectionsUpdated'); }, function (err) { //sync failed, but we already had some data, so show that log.error('Error syncing collections'); log.error(err); reactInstance.setState({ collections: library.collections, loading: false }); library.trigger('libraryCollectionsUpdated'); Zotero.ui.jsNotificationMessage('Error loading collections. Collections list may not be up to date', 'error'); }); }, render: function render() { log.debug('Collections render', 3); var reactInstance = this; var library = this.props.library; var collections = this.state.collections; if (collections == null) { return null; } var collectionsArray = this.state.collections.collectionsArray; var currentCollectionKey = this.state.currentCollectionKey; var libraryUrlIdentifier = ''; //var libraryUrlIdentifier = (collections == null ? "" : collections.libraryUrlIdentifier); //Set of collections in an expanded state var expandedCollections = this.state.expandedCollections; //path from top level collection to currently selected collection, to ensure that we expand //them all and the current collection is visible var currentCollectionPath = []; if (currentCollectionKey !== null) { var currentCollection = collections.getCollection(currentCollectionKey); var c = currentCollection; while (true) { if (c && !c.topLevel) { var parentCollectionKey = c.get('parentCollection'); c = collections.getCollection(parentCollectionKey); currentCollectionPath.push(parentCollectionKey); expandedCollections[parentCollectionKey] = true; } else { break; } } } var collectionRows = []; collectionsArray.forEach(function (collection) { if (collection.topLevel) { collectionRows.push(React.createElement(CollectionRow, { key: collection.get('key'), collection: collection, selectedCollection: currentCollectionKey, expandedCollections: expandedCollections, parentCollectionsInstance: reactInstance })); } }); var libraryClassName = 'my-library ' + (currentCollectionKey == null ? 'current-collection' : ''); return React.createElement( 'div', { id: 'collection-list-div', className: 'collection-list-container' }, React.createElement( 'ul', { id: 'collection-list' }, React.createElement( 'li', null, React.createElement('span', { className: 'glyphicons fonticon glyphicons-inbox barefonticon' }), React.createElement( 'a', { onClick: this.returnToLibrary, className: libraryClassName, href: library.libraryBaseWebsiteUrl }, 'Library' ) ), collectionRows ) ); } }); module.exports = Collections;