Skip to content

Commit

Permalink
citeproc-rs conversion: remote ids, read-only bib
Browse files Browse the repository at this point in the history
  • Loading branch information
tnajdek committed Jun 8, 2021
1 parent eda139d commit 45a873b
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 31 deletions.
65 changes: 44 additions & 21 deletions src/js/components/bibliography.jsx
Expand Up @@ -10,7 +10,8 @@ import { default as DropdownMenu } from 'reactstrap/lib/DropdownMenu';
import { default as DropdownItem } from 'reactstrap/lib/DropdownItem';
import Button from './ui/button';
import Icon from './ui/icon';
import { noop } from '../utils';
import { noop, parseTagAndAttrsFromNode } from '../utils';
import formatBib from '../cite';
// import { getHtmlNodeFromBibliography, makeBibliographyContentIterator } from '../utils' ;


Expand Down Expand Up @@ -196,26 +197,48 @@ class Bibliography extends React.PureComponent {
render() {
const { items, bibliographyItems, bibliographyMeta } = this.props;

return (
<ul className="bibliography" key="bibliography">
{ bibliographyItems.map((renderedItem, index) => (
<BibliographyItem
key={ items[index].key }
rawItem={ items[index] }
renderedItem={ renderedItem }
clipboardConfirmations= { [] /*TODO*/ }
dropdownsOpen = { [] /*TODO*/ }
isNoteStyle = { false /*TODO*/ }
isNumericStyle = { false /*TODO*/ }
onCopyCitationDialogOpen = { noop }
onDeleteCitation = { noop }
onEditCitation = { noop }
onFocus = { noop }
onToggleDropdown = { noop }
/>
)) }
</ul>
);
const bibliographyRendered = formatBib([
{
bibstart: bibliographyMeta.formatMeta.markupPre,
bibend: bibliographyMeta.formatMeta.markupPost,
hangingindent: bibliographyMeta.hangingIndent,
maxoffset: bibliographyMeta.maxOffset,
entryspacing: bibliographyMeta.entrySpacing,
linespacing: bibliographyMeta.lineSpacing,
'second-field-align': bibliographyMeta.secondFieldAlign
},
bibliographyItems.map((renderedItem, index) => (
`<div className="csl-entry">${renderedItem.value}</div>`
)).join('')
]);

if(this.props.isReadOnly) {
// TODO: { this.keyHandlers }
return (
<div className="bibliography read-only" dangerouslySetInnerHTML={ { __html: bibliographyRendered } } />
);
} else {
return (
<ul className="bibliography" key="bibliography">
{ bibliographyItems.map((renderedItem, index) => (
<BibliographyItem
key={ items[index].key }
rawItem={ items[index] }
renderedItem={ renderedItem }
clipboardConfirmations= { [] /*TODO*/ }
dropdownsOpen = { [] /*TODO*/ }
isNoteStyle = { false /*TODO*/ }
isNumericStyle = { false /*TODO*/ }
onCopyCitationDialogOpen = { noop }
onDeleteCitation = { noop }
onEditCitation = { noop }
onFocus = { noop }
onToggleDropdown = { noop }
/>
)) }
</ul>
);
}



Expand Down
70 changes: 61 additions & 9 deletions src/js/components/container.jsx
@@ -1,36 +1,51 @@
import React, { memo, useCallback, useEffect, useRef, useState } from 'react';
import ZoteroBib from 'zotero-translation-client';
import { useParams, useHistory } from "react-router-dom";

import { getCiteproc, noop } from '../utils';

import { fetchFromPermalink, getExpandedCitationStyles, getCiteproc, noop, retrieveStylesData } from '../utils';
import { coreCitationStyles } from '../../../data/citation-styles-data.json';
import defaults from '../constants/defaults';
import ZBib from './zbib';
import { usePrevious } from '../hooks';

const BibWebContainer = props => {
const { id: remoteId } = useParams();
const history = useHistory();
const citeproc = useRef(null);
const bib = useRef(null);
const [isCiteprocReady, setIsCiteprocReady] = useState(false);
const [isDataReady, setIsDataReady] = useState(!remoteId);
const [messages, setMessages] = useState([]);
const [bibliographyItems, setBibliographyItems] = useState([]);
const [bibliographyMeta, setBibliographyMeta] = useState({});
const [citationStyle, setCitationStyle] = useState(
localStorage.getItem('zotero-bib-citation-style') || coreCitationStyles.find(cs => cs.isDefault).name
);
const prevCitationStyle = usePrevious(citationStyle);
const config = { ...defaults, ...props.config };

const citationStyles = [
const isReady = isCiteprocReady && isDataReady;
const isReadOnly = !!remoteId;

const [citationStyles, setCitationStyles] = useState([
...coreCitationStyles.map(cs => ({
...cs, isDependent: 0, parent: null, isCore: true })
),
...(JSON.parse(localStorage.getItem('zotero-bib-extra-citation-styles')) || [])
];
]);
citationStyles.sort((a, b) => a.title.toUpperCase().localeCompare(b.title.toUpperCase()));

const handleCitationStyleChanged = useCallback(ev => {
console.log({ ev });
setCitationStyle(ev.value);
}, []);

const handleError = useCallback((message, e) => {
// TODO: display message
throw e;
}, []);

const refreshBibliography = useCallback(async (citationStyle) => {
if(citeproc.current) {
citeproc.current.free();
Expand All @@ -48,22 +63,59 @@ const BibWebContainer = props => {
setIsCiteprocReady(true);
}, []);

const fetchRemoteBibliography = useCallback(async () => {
try {
const remoteData = await fetchFromPermalink(`${config.storeURL}/${remoteId}`);
if(remoteData && 'items' in remoteData) {
const citationStyle = remoteData.citationStyle || citationStyle;
const title = 'title' in remoteData && remoteData.title || null;

var citationStyleMeta = citationStyles.find(cs => cs.name === citationStyle);
if(!citationStyleMeta) {
const stylesData = await retrieveStylesData(config.stylesURL);
const newStyleMeta = stylesData.find(sd => sd.name === citationStyle);
setCitationStyle(getExpandedCitationStyles(citationStyles, newStyleMeta));
}

bib.current = new ZoteroBib({
...config,
initialItems: remoteData.items,
persist: false
});

setIsDataReady(true);
refreshBibliography(citationStyle);
}
} catch(e) {
history.push('/');
handleError('Failed to load citations by id', e);
}
}, [citationStyles, config, handleError, history, refreshBibliography, remoteId]);

useEffect(() => {
refreshBibliography(citationStyle);
}, [citationStyle, refreshBibliography]);
if(typeof(prevCitationStyle) !== 'undefined' && citationStyle !== prevCitationStyle) {
refreshBibliography(citationStyle);
}
}, [citationStyle, prevCitationStyle, refreshBibliography]);

useEffect(() => {
bib.current = new ZoteroBib(config);
bib.current.reloadItems();
refreshBibliography(citationStyle);
if(remoteId) {
fetchRemoteBibliography();
} else {
bib.current = new ZoteroBib(config);
bib.current.reloadItems();
refreshBibliography(citationStyle);
}
}, []);


return (<ZBib
bibliographyItems={ bibliographyItems }
bibliographyMeta={ bibliographyMeta }
citationStyle={ citationStyle }
citationStyles={ citationStyles }
isReadOnly={ !isCiteprocReady }
isReadOnly={ isReadOnly }
isReady={ isReady }
messages={ messages }
items={ bib?.current?.items || [] }
onCitationCopy = { noop }
Expand Down
3 changes: 2 additions & 1 deletion src/js/components/zbib.jsx
Expand Up @@ -50,7 +50,7 @@ class ZBib extends React.PureComponent {

render() {
return (
typeof this.props.isReadOnly === 'undefined'
!this.props.isReady
? <div className={ cx(this.className) }>
<Spinner />
</div>
Expand Down Expand Up @@ -183,6 +183,7 @@ class ZBib extends React.PureComponent {
isKeyboardUser: PropTypes.bool,
isMouseUser: PropTypes.bool,
isReadOnly: PropTypes.bool,
isReady: PropTypes.bool,
isSaveToZoteroVisible: PropTypes.bool,
isTouchUser: PropTypes.bool,
itemUnderReviewBibliography: PropTypes.object,
Expand Down
1 change: 1 addition & 0 deletions src/js/hooks/index.js
@@ -0,0 +1 @@
export * from './use-previous';
11 changes: 11 additions & 0 deletions src/js/hooks/use-previous.js
@@ -0,0 +1,11 @@
import { useEffect, useRef } from 'react';

const usePrevious = value => {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}

export { usePrevious };
20 changes: 20 additions & 0 deletions src/js/utils.jsx
Expand Up @@ -674,6 +674,25 @@ const splice = (array, at, count = 0, ...items) => {
];
};

const getExpandedCitationStyles = (citationStyles, styleMeta) => {
if(citationStyles.find(cs => cs.name === styleMeta.name)) {
return citationStyles;
}

const newCitationStyles = [
...citationStyles,
{
name: styleMeta.name,
title: styleMeta.title,
isDependent: styleMeta.dependent,
isCore: false
}
];

newCitationStyles.sort((a, b) => a.title.toUpperCase().localeCompare(b.title.toUpperCase()));
return newCitationStyles;
};

export {
dedupMultipleChoiceItems,
fetchFromPermalink,
Expand All @@ -685,6 +704,7 @@ export {
getHtmlNodeFromBibliography,
getItemTypeMeta,
getItemTypes,
getExpandedCitationStyles,
isLikeUrl,
isNoteStyle,
isNumericStyle,
Expand Down

0 comments on commit 45a873b

Please sign in to comment.