zotero-web-library
Version:
Web library from zotero.org
1,026 lines (962 loc) • 28.7 kB
JavaScript
'use strict';
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
var log = require('libzotero/lib/Log').Logger('zotero-web-library:ItemDetails');
var React = require('react');
var LoadingSpinner = require('./LoadingSpinner.js');
//TODO: trigger showChildren with an extra itemID filter so quick clicks back and forth
//between items don't overwrite with the wrong children?
var editMatches = function editMatches(props, edit) {
if (props === null || edit === null) {
return false;
}
if (edit.field != props.field) {
return false;
}
//field is the same, make sure index matches if set
if (edit.creatorIndex != props.creatorIndex) {
//log.debug("creatorIndex mismatch");
return false;
}
if (props.tagIndex != edit.tagIndex) {
//log.debug("tagIndex mismatch");
return false;
}
return true;
};
var genericDisplayedFields = function genericDisplayedFields(item) {
var genericDisplayedFields = Object.keys(item.apiObj.data).filter(function (field) {
if (item.hideFields.indexOf(field) != -1) {
return false;
}
if (!item.fieldMap.hasOwnProperty(field)) {
return false;
}
if (field == 'title' || field == 'creators' || field == 'itemType') {
return false;
}
return true;
});
return genericDisplayedFields;
};
var CreatorRow = React.createClass({
displayName: 'CreatorRow',
getDefaultProps: function getDefaultProps() {
return {
item: null,
library: null,
creatorIndex: 0,
edit: null
};
},
render: function render() {
//log.debug("CreatorRow render");
if (this.props.item == null) {
return null;
}
var item = this.props.item;
var creator = item.get('creators')[this.props.creatorIndex];
var nameSpans = null;
if (creator.name && creator.name != '') {
nameSpans = React.createElement(ItemField, _extends({}, this.props, { key: 'name', field: 'name' }));
} else {
nameSpans = [React.createElement(ItemField, _extends({}, this.props, { key: 'lastName', field: 'lastName' })), ', ', React.createElement(ItemField, _extends({}, this.props, { key: 'firstName', field: 'firstName' }))];
}
return React.createElement(
'tr',
{ className: 'creator-row' },
React.createElement(
'th',
null,
React.createElement(ItemField, _extends({}, this.props, { field: 'creatorType' }))
),
React.createElement(
'td',
null,
nameSpans,
React.createElement(
'div',
{ className: 'btn-toolbar', role: 'toolbar' },
React.createElement(ToggleCreatorFieldButton, this.props),
React.createElement(AddRemoveCreatorFieldButtons, this.props)
)
)
);
}
});
var ToggleCreatorFieldButton = React.createClass({
displayName: 'ToggleCreatorFieldButton',
render: function render() {
//log.debug("ToggleCreatorFieldButton render");
return React.createElement(
'div',
{ className: 'btn-group' },
React.createElement(
'button',
{ type: 'button',
className: 'switch-two-field-creator-link btn btn-default',
title: 'Toggle single field creator',
'data-itemkey': this.props.item.get('key'),
'data-creatorindex': this.props.creatorIndex,
onClick: this.switchCreatorFields },
React.createElement('span', { className: 'fonticon glyphicons glyphicons-unchecked' })
)
);
},
switchCreatorFields: function switchCreatorFields(evt) {
//log.debug("CreatorRow switchCreatorFields");
var creatorIndex = this.props.creatorIndex;
var item = this.props.item;
var creators = item.get('creators');
var creator = creators[creatorIndex];
//split a single name creator into first/last, or combine first/last
//into a single name
if (creator.name !== undefined) {
var split = creator.name.split(' ');
if (split.length > 1) {
creator.lastName = split.splice(-1, 1)[0];
creator.firstName = split.join(' ');
} else {
creator.lastName = creator.name;
creator.firstName = '';
}
delete creator.name;
} else {
if (creator.firstName === '' && creator.lastName === '') {
creator.name = '';
} else {
creator.name = creator.firstName + ' ' + creator.lastName;
}
delete creator.firstName;
delete creator.lastName;
}
creators[creatorIndex] = creator;
Zotero.ui.saveItem(item);
this.props.parentItemDetailsInstance.setState({ item: item });
}
});
var AddRemoveCreatorFieldButtons = React.createClass({
displayName: 'AddRemoveCreatorFieldButtons',
render: function render() {
//log.debug("AddRemoveCreatorFieldButtons render");
return React.createElement(
'div',
{ className: 'btn-group' },
React.createElement(
'button',
{ type: 'button',
className: 'btn btn-default',
'data-creatorindex': this.props.creatorIndex,
onClick: this.removeCreator },
React.createElement('span', { className: 'fonticon glyphicons glyphicons-minus' })
),
React.createElement(
'button',
{ type: 'button',
className: 'btn btn-default',
'data-creatorindex': this.props.creatorIndex,
onClick: this.addCreator },
React.createElement('span', { className: 'fonticon glyphicons glyphicons-plus' })
)
);
},
addCreator: function addCreator(evt) {
log.debug('addCreator', 3);
var item = this.props.item;
var creatorIndex = this.props.creatorIndex;
var creators = item.get('creators');
var newCreator = { creatorType: 'author', firstName: '', lastName: '' };
creators.splice(creatorIndex + 1, 0, newCreator);
this.props.parentItemDetailsInstance.setState({
item: item,
edit: {
field: 'lastName',
creatorIndex: creatorIndex + 1
}
});
},
removeCreator: function removeCreator(evt) {
log.debug('removeCreator', 3);
var creatorIndex = this.props.creatorIndex;
var item = this.props.item;
var creators = item.get('creators');
creators.splice(creatorIndex, 1);
Zotero.ui.saveItem(item);
this.props.parentItemDetailsInstance.setState({ item: item });
}
});
var ItemNavTabs = React.createClass({
displayName: 'ItemNavTabs',
getDefaultProps: function getDefaultProps() {
return {
item: null
};
},
render: function render() {
log.debug('ItemNavTabs render', 4);
if (this.props.item == null) {
return null;
}
if (!this.props.item.isSupplementaryItem()) {
return React.createElement(
'ul',
{ className: 'nav nav-tabs', role: 'tablist' },
React.createElement(
'li',
{ role: 'presentation', className: 'active' },
React.createElement(
'a',
{ href: '#item-info-panel', 'aria-controls': 'item-info-panel', role: 'tab', 'data-toggle': 'tab' },
'Info'
)
),
React.createElement(
'li',
{ role: 'presentation' },
React.createElement(
'a',
{ href: '#item-children-panel', 'aria-controls': 'item-children-panel', role: 'tab', 'data-toggle': 'tab' },
'Children'
)
),
React.createElement(
'li',
{ role: 'presentation' },
React.createElement(
'a',
{ href: '#item-tags-panel', 'aria-controls': 'item-tags-panel', role: 'tab', 'data-toggle': 'tab' },
'Tags'
)
)
);
}
return null;
}
});
var ItemFieldRow = React.createClass({
displayName: 'ItemFieldRow',
getDefaultProps: function getDefaultProps() {
return {
item: null,
edit: null
};
},
render: function render() {
//log.debug("ItemFieldRow render");
var item = this.props.item;
var field = this.props.field;
var placeholderOrValue = React.createElement(ItemField, { item: item, field: field, edit: this.props.edit, parentItemDetailsInstance: this.props.parentItemDetailsInstance });
if (field == 'url') {
var url = item.get('url');
return React.createElement(
'tr',
null,
React.createElement(
'th',
null,
React.createElement(
'a',
{ rel: 'nofollow', href: url },
item.fieldMap[field]
)
),
React.createElement(
'td',
{ className: field },
placeholderOrValue
)
);
} else if (field == 'DOI') {
var doi = item.get('DOI');
return React.createElement(
'tr',
null,
React.createElement(
'th',
null,
React.createElement(
'a',
{ rel: 'nofollow', href: 'http://dx.doi.org/' + doi },
item.fieldMap[field]
)
),
React.createElement(
'td',
{ className: field },
placeholderOrValue
)
);
} else if (Zotero.config.richTextFields[field]) {
return React.createElement(
'tr',
null,
React.createElement(
'th',
null,
item.fieldMap[field],
'}'
),
React.createElement(
'td',
{ className: field },
placeholderOrValue
)
);
} else {
return React.createElement(
'tr',
null,
React.createElement(
'th',
null,
item.fieldMap[field] || field
),
React.createElement(
'td',
{ className: field },
placeholderOrValue
)
);
}
}
});
//set onChange
var ItemField = React.createClass({
displayName: 'ItemField',
getDefaultProps: function getDefaultProps() {
return {
item: null,
field: null,
edit: null,
creatorIndex: null,
tagIndex: null
};
},
handleChange: function handleChange(evt) {
//set field to new value
var item = this.props.item;
switch (this.props.field) {
case 'creatorType':
case 'name':
case 'firstName':
case 'lastName':
var creators = item.get('creators');
var creator = creators[this.props.creatorIndex];
creator[this.props.field] = evt.target.value;
break;
case 'tag':
var tags = item.get('tags');
var tag = tags[this.props.tagIndex];
tag.tag = evt.target.value;
break;
default:
item.set(this.props.field, evt.target.value);
}
this.props.parentItemDetailsInstance.setState({ item: item });
},
handleBlur: function handleBlur(evt) {
//save item, move edit to next field
this.handleChange(evt);
this.props.parentItemDetailsInstance.setState({ edit: null });
Zotero.ui.saveItem(this.props.item);
},
handleFocus: function handleFocus(evt) {
var field = evt.currentTarget.getAttribute('data-field');
var creatorIndex = evt.target.getAttribute('data-creatorindex');
var tagIndex = evt.target.getAttribute('data-tagindex');
var edit = {
field: field,
creatorIndex: creatorIndex,
tagIndex: tagIndex
};
this.props.parentItemDetailsInstance.setState({
edit: edit
});
},
checkKey: function checkKey(evt) {
evt.stopPropagation();
if (evt.keyCode === Zotero.ui.keyCode.ENTER) {
//var nextEdit = Zotero.ui.widgets.reactitem.nextEditField(this.props.item, this.props.edit);
evt.target.blur();
}
},
render: function render() {
var item = this.props.item;
var field = this.props.field;
var creatorField = false;
var tagField = false;
var value;
switch (field) {
case 'creatorType':
case 'name':
case 'firstName':
case 'lastName':
creatorField = true;
var creatorIndex = this.props.creatorIndex;
var creator = item.get('creators')[creatorIndex];
value = creator[field];
var creatorPlaceHolders = {
'name': '(name)',
'lastName': '(Last Name)',
'firstName': '(First Name)'
};
break;
case 'tag':
tagField = true;
var tagIndex = this.props.tagIndex;
var tag = item.get('tags')[tagIndex];
value = tag.tag;
break;
default:
value = item.get(field);
}
var editThisField = editMatches(this.props, this.props.edit);
if (!editThisField) {
var spanProps = {
className: 'editable-item-field',
tabIndex: 0,
'data-field': field,
onFocus: this.handleFocus
};
var p = null;
if (creatorField) {
spanProps.className += ' creator-field';
spanProps['data-creatorindex'] = this.props.creatorIndex;
p = value == '' ? creatorPlaceHolders[field] : value;
} else if (tagField) {
spanProps.className += ' tag-field';
spanProps['data-tagindex'] = this.props.tagIndex;
p = value;
} else {
p = value == '' ? React.createElement('div', { className: 'empty-field-placeholder' }) : Zotero.format.itemField(field, item);
}
return React.createElement(
'span',
spanProps,
p
);
}
var focusEl = function focusEl(el) {
if (el != null) {
el.focus();
}
};
var inputProps = {
className: 'form-control item-field-control ' + this.props.field,
name: field,
defaultValue: value,
//onChange: this.handleChange,
onKeyDown: this.checkKey,
onBlur: this.handleBlur,
creatorindex: this.props.creatorIndex,
tagindex: this.props.tagIndex,
ref: focusEl
};
if (creatorField) {
inputProps.placeholder = creatorPlaceHolders[field];
}
switch (this.props.field) {
case null:
return null;
break;
case 'itemType':
var itemTypeOptions = item.itemTypes.map(function (itemType) {
return React.createElement(
'option',
{ key: itemType.itemType,
label: itemType.localized,
value: itemType.itemType },
itemType.localized
);
});
return React.createElement(
'select',
inputProps,
itemTypeOptions
);
break;
case 'creatorType':
var creatorTypeOptions = item.creatorTypes[item.get('itemType')].map(function (creatorType) {
return React.createElement(
'option',
{ key: creatorType.creatorType,
label: creatorType.localized,
value: creatorType.creatorType
},
creatorType.localized
);
});
return React.createElement(
'select',
_extends({ id: 'creatorType' }, inputProps, { 'data-creatorindex': this.props.creatorIndex }),
creatorTypeOptions
);
break;
default:
if (Zotero.config.largeFields[this.props.field]) {
return React.createElement('textarea', inputProps);
} else if (Zotero.config.richTextFields[this.props.field]) {
return React.createElement('textarea', _extends({}, inputProps, { className: 'rte default' }));
} else {
//default single line input field
return React.createElement('input', _extends({ type: 'text' }, inputProps));
}
}
}
});
var ItemInfoPanel = React.createClass({
displayName: 'ItemInfoPanel',
componentWillMount: function componentWillMount() {
var _this = this;
var library = this.props.library;
library.listen('totalResultsLoaded', function () {
_this.setState({ libraryItemsLoaded: true });
});
},
getDefaultProps: function getDefaultProps() {
return {
item: null,
loading: false,
edit: null
};
},
getInitialState: function getInitialState() {
return { libraryItemsLoaded: false };
},
render: function render() {
log.debug('ItemInfoPanel render', 3);
var reactInstance = this;
var library = this.props.library;
var item = this.props.item;
var itemCountP = React.createElement(
'p',
{ className: 'item-count', hidden: !this.state.libraryItemsLoaded },
library.items.totalResults + ' items in this view'
);
var edit = this.props.edit;
if (item == null) {
return React.createElement(
'div',
{ id: 'item-info-panel', role: 'tabpanel', className: 'item-details-div tab-pane active' },
React.createElement(LoadingSpinner, { loading: this.props.loading }),
itemCountP
);
}
var itemKey = item.get('key');
var libraryType = item.owningLibrary.libraryType;
var parentUrl = false;
if (item.get('parentItem')) {
parentUrl = library.websiteUrl({ itemKey: item.get('parentItem') });
}
var parentLink = parentUrl ? React.createElement(
'a',
{ href: parentUrl, className: 'item-select-link', 'data-itemkey': item.get('parentItem') },
'Parent Item'
) : null;
var libraryIDSpan;
if (libraryType == 'user') {
libraryIDSpan = React.createElement('span', { id: 'libraryUserID', title: item.apiObj.library.id });
} else {
libraryIDSpan = React.createElement('span', { id: 'libraryGroupID', title: item.apiObj.library.id });
}
//the Zotero user that created the item, if it's a group library item
var zoteroItemCreatorRow = null;
if (libraryType == 'group') {
zoteroItemCreatorRow = React.createElement(
'tr',
null,
React.createElement(
'th',
null,
'Added by'
),
React.createElement(
'td',
{ className: 'user-creator' },
React.createElement(
'a',
{ href: item.apiObj.meta.createdByUser.links.alternate.href, className: 'user-link' },
item.apiObj.meta.createdByUser.name
)
)
);
}
var creatorRows = [];
var creators = item.get('creators');
if (creators.length == 0) {
creators.push({
lastName: '',
firstName: ''
});
}
if (item.isSupplementaryItem()) {
creatorRows = null;
} else {
creatorRows = item.get('creators').map(function (creator, ind) {
return React.createElement(CreatorRow, { key: ind, library: library, creatorIndex: ind, item: item, edit: edit, parentItemDetailsInstance: reactInstance.props.parentItemDetailsInstance });
});
}
var genericFieldRows = [];
//filter out fields we don't want to display or don't want to include as generic
var genDisplayedFields = genericDisplayedFields(item);
genDisplayedFields.forEach(function (key) {
genericFieldRows.push(React.createElement(ItemFieldRow, _extends({ key: key }, reactInstance.props, { field: key })));
});
var typeAndTitle = ['itemType', 'title'].map(function (key) {
return React.createElement(ItemFieldRow, _extends({ key: key }, reactInstance.props, { field: key }));
});
return React.createElement(
'div',
{ id: 'item-info-panel', role: 'tabpanel', className: 'item-details-div tab-pane active' },
React.createElement(LoadingSpinner, { loading: this.props.loading }),
parentLink,
libraryIDSpan,
React.createElement(
'table',
{ className: 'item-info-table table', 'data-itemkey': itemKey },
React.createElement(
'tbody',
null,
zoteroItemCreatorRow,
typeAndTitle,
creatorRows,
genericFieldRows
)
)
);
}
});
var TagListRow = React.createClass({
displayName: 'TagListRow',
getDefaultProps: function getDefaultProps() {
return {
tagIndex: 0,
tag: { tag: '' },
item: null,
library: null,
edit: null
};
},
removeTag: function removeTag(evt) {
var tag = this.props.tag.tag;
var item = this.props.item;
var tagIndex = this.props.tagIndex;
var tags = item.get('tags');
tags.splice(tagIndex, 1);
Zotero.ui.saveItem(item);
this.props.parentItemDetailsInstance.setState({ item: item });
},
render: function render() {
return React.createElement(
'div',
{ className: 'row item-tag-row' },
React.createElement(
'div',
{ className: 'col-xs-1' },
React.createElement('span', { className: 'glyphicons fonticon glyphicons-tag' })
),
React.createElement(
'div',
{ className: 'col-xs-9' },
React.createElement(ItemField, _extends({}, this.props, { field: 'tag' }))
),
React.createElement(
'div',
{ className: 'col-xs-2' },
React.createElement(
'button',
{ type: 'button', className: 'remove-tag-link btn btn-default', onClick: this.removeTag },
React.createElement('span', { className: 'glyphicons fonticon glyphicons-minus' })
)
)
);
}
});
var ItemTagsPanel = React.createClass({
displayName: 'ItemTagsPanel',
getInitialState: function getInitialState() {
return {
newTagString: ''
};
},
newTagChange: function newTagChange(evt) {
this.setState({ newTagString: evt.target.value });
},
//add the new tag to the item and save if keydown is ENTER
checkKey: function checkKey(evt) {
evt.stopPropagation();
if (evt.keyCode === Zotero.ui.keyCode.ENTER) {
var item = this.props.item;
var tags = item.get('tags');
tags.push({
tag: evt.target.value
});
Zotero.ui.saveItem(item);
this.setState({ newTagString: '' });
this.props.parentItemDetailsInstance.setState({ item: item });
}
},
render: function render() {
log.debug('ItemTagsPanel render', 3);
var reactInstance = this;
var item = this.props.item;
var library = this.props.library;
if (item == null) {
return React.createElement('div', { id: 'item-tags-panel', role: 'tabpanel', className: 'item-tags-div tab-pane' });
}
var tagRows = item.apiObj.data.tags.map(function (tag, ind) {
return React.createElement(TagListRow, _extends({ key: tag.tag }, reactInstance.props, { tag: tag, tagIndex: ind }));
});
return React.createElement(
'div',
{ id: 'item-tags-panel', role: 'tabpanel', className: 'item-tags-div tab-pane' },
React.createElement(
'p',
null,
React.createElement(
'span',
{ className: 'tag-count' },
item.get('tags').length
),
' tags'
),
React.createElement(
'button',
{ className: 'add-tag-button btn btn-default' },
'Add Tag'
),
React.createElement(
'div',
{ className: 'item-tags-list' },
tagRows
),
React.createElement(
'div',
{ className: 'add-tag-form form-horizontal' },
React.createElement(
'div',
{ className: 'form-group' },
React.createElement(
'div',
{ className: 'col-xs-1' },
React.createElement(
'label',
{ htmlFor: 'add-tag-input' },
React.createElement('span', { className: 'glyphicons fonticon glyphicons-tag' })
)
),
React.createElement(
'div',
{ className: 'col-xs-11' },
React.createElement('input', { type: 'text', onKeyDown: this.checkKey, onChange: this.newTagChange, value: this.state.newTagString, id: 'add-tag-input', className: 'add-tag-input form-control' })
)
)
)
);
}
});
var ItemChildrenPanel = React.createClass({
displayName: 'ItemChildrenPanel',
getDefaultProps: function getDefaultProps() {
return {
childItems: []
};
},
triggerUpload: function triggerUpload() {
this.props.library.trigger('uploadAttachment');
},
render: function render() {
log.debug('ItemChildrenPanel render', 3);
var childListEntries = this.props.childItems.map(function (item) {
var title = item.get('title');
var href = Zotero.url.itemHref(item);
var iconClass = item.itemTypeIconClass();
var key = item.get('key');
if (item.itemType == 'note') {
return React.createElement(
'li',
{ key: key },
React.createElement('span', { className: 'fonticon barefonticon ' + iconClass }),
React.createElement(
'a',
{ className: 'item-select-link', 'data-itemkey': item.get('key'), href: href, title: title },
title
)
);
} else if (item.attachmentDownloadUrl == false) {
return React.createElement(
'li',
{ key: key },
React.createElement('span', { className: 'fonticon barefonticon ' + iconClass }),
title,
'(',
React.createElement(
'a',
{ className: 'item-select-link', 'data-itemkey': item.get('key'), href: href, title: title },
'Attachment Details'
),
')'
);
} else {
var attachmentDownloadUrl = Zotero.url.attachmentDownloadUrl(item);
return React.createElement(
'li',
{ key: key },
React.createElement('span', { className: 'fonticon barefonticon ' + iconClass }),
React.createElement(
'a',
{ className: 'itemdownloadlink', href: attachmentDownloadUrl },
title,
' ',
Zotero.url.attachmentFileDetails(item)
),
'(',
React.createElement(
'a',
{ className: 'item-select-link', 'data-itemkey': item.get('key'), href: href, title: title },
'Attachment Details'
),
')'
);
}
});
return React.createElement(
'div',
{ id: 'item-children-panel', role: 'tabpanel', className: 'item-children-div tab-pane' },
React.createElement(
'ul',
{ id: 'notes-and-attachments' },
childListEntries
),
React.createElement(
'button',
{ type: 'button', onClick: this.triggerUpload, id: 'upload-attachment-link', className: 'btn btn-primary upload-attachment-button', hidden: !Zotero.config.librarySettings.allowUpload },
'Upload File'
)
);
}
});
var ItemDetails = React.createClass({
displayName: 'ItemDetails',
getInitialState: function getInitialState() {
return {
item: null,
childItems: [],
itemLoading: false,
childrenLoading: false,
libraryItemsLoaded: false,
edit: null
};
},
componentWillMount: function componentWillMount() {
var reactInstance = this;
var library = this.props.library;
library.listen('displayedItemChanged', reactInstance.loadItem, {});
library.listen('uploadSuccessful', reactInstance.refreshChildren, {});
library.listen('tagsChanged', reactInstance.updateTypeahead, {});
library.listen('showChildren', reactInstance.refreshChildren, {});
library.trigger('displayedItemChanged');
},
componentDidMount: function componentDidMount() {},
loadItem: function loadItem() {
log.debug('Zotero eventful loadItem', 3);
var reactInstance = this;
var library = this.props.library;
//clean up RTEs before we end up removing their dom elements out from under them
//Zotero.ui.cleanUpRte(widgetEl);
//get the key of the item we need to display, or display library stats
var itemKey = Zotero.state.getUrlVar('itemKey');
if (!itemKey) {
log.debug('No itemKey - ' + itemKey, 3);
reactInstance.setState({ item: null });
return Promise.reject(new Error('No itemkey - ' + itemKey));
}
//if we are showing an item, load it from local library of API
//then display it
var loadedItem = library.items.getItem(itemKey);
var loadingPromise;
if (loadedItem) {
log.debug('have item locally, loading details into ui', 3);
loadingPromise = Promise.resolve(loadedItem);
} else {
log.debug('must fetch item from server', 3);
reactInstance.setState({ itemLoading: true });
loadingPromise = library.loadItem(itemKey);
}
loadingPromise.then(function (item) {
loadedItem = item;
}).then(function () {
return loadedItem.getCreatorTypes(loadedItem.get('itemType'));
}).then(function (creatorTypes) {
reactInstance.setState({ item: loadedItem, itemLoading: false });
library.trigger('showChildren');
//Zotero.eventful.initTriggers(widgetEl);
try {
//trigger event for Zotero translator detection
var ev = document.createEvent('HTMLEvents');
ev.initEvent('ZoteroItemUpdated', true, true);
document.dispatchEvent(ev);
} catch (e) {
log.error('Error triggering ZoteroItemUpdated event');
}
});
loadingPromise.catch(function (err) {
log.error('loadItem promise failed');
log.error(err);
}).then(function () {
reactInstance.setState({ itemLoading: false });
}).catch(Zotero.catchPromiseError);
return loadingPromise;
},
refreshChildren: function refreshChildren() {
log.debug('reactitem.refreshChildren', 3);
var reactInstance = this;
var library = this.props.library;
var itemKey = Zotero.state.getUrlVar('itemKey');
if (!itemKey) {
log.debug('No itemKey - ' + itemKey, 3);
return Promise.reject(new Error('No itemkey - ' + itemKey));
}
var item = library.items.getItem(itemKey);
reactInstance.setState({ loadingChildren: true });
var p = item.getChildren(library).then(function (childItems) {
reactInstance.setState({ childItems: childItems, loadingChildren: false });
}).catch(Zotero.catchPromiseError);
return p;
},
updateTypeahead: function updateTypeahead() {
log.debug('updateTypeahead', 3);
return;
},
addTagTypeahead: function addTagTypeahead() {
//TODO: reactify
},
addTagTypeaheadToInput: function addTagTypeaheadToInput() {
//TODO: reactify
},
render: function render() {
log.debug('ItemDetails render', 3);
var reactInstance = this;
var library = this.props.library;
var item = this.state.item;
var childItems = this.state.childItems;
return React.createElement(
'div',
{ role: 'tabpanel' },
React.createElement(ItemNavTabs, { library: library, item: item }),
React.createElement(
'div',
{ className: 'tab-content' },
React.createElement(ItemInfoPanel, { library: library,
item: item,
loading: this.state.itemLoading,
libraryItemsLoaded: this.state.libraryItemsLoaded,
edit: this.state.edit,
parentItemDetailsInstance: reactInstance
}),
React.createElement(ItemChildrenPanel, { parentItemDetailsInstance: reactInstance, library: library, childItems: childItems, loading: this.state.childrenLoading }),
React.createElement(ItemTagsPanel, { parentItemDetailsInstance: reactInstance, library: library, item: item, edit: this.state.edit })
)
);
}
});
module.exports = ItemDetails;