diff --git a/source/actions/getPublicationFromDoi.js b/source/actions/getPublicationFromDoi.js
index bfc551e..1024e33 100644
--- a/source/actions/getPublicationFromDoi.js
+++ b/source/actions/getPublicationFromDoi.js
@@ -21,12 +21,13 @@ export function fetchPublicationFromDoi(doi) {
};
}
-export function resolvePublicationFromDoi(doi, crossrefMessage, bibtexRequestId) {
+export function resolvePublicationFromDoi(doi, crossrefMessage, bibtexRequestId, timestamp) {
return {
type: RESOLVE_PUBLICATION_FROM_DOI,
doi,
crossrefMessage,
bibtexRequestId,
+ timestamp,
};
}
diff --git a/source/actions/manageMenu.js b/source/actions/manageMenu.js
index 24b705f..1e4a3dd 100644
--- a/source/actions/manageMenu.js
+++ b/source/actions/manageMenu.js
@@ -222,12 +222,10 @@ export function bibtexToPublications(bibtex) {
++position;
switch (status) {
case 'root':
- if (character === '%') {
- status = 'comment';
- } else if (character === '@') {
+ if (character === '@') {
status = 'type';
} else if (/\S/.test(character)) {
- throwError(character);
+ status = 'comment';
}
break;
case 'comment':
diff --git a/source/actions/manageScholarPage.js b/source/actions/manageScholarPage.js
index dc4a43d..2302b75 100644
--- a/source/actions/manageScholarPage.js
+++ b/source/actions/manageScholarPage.js
@@ -201,7 +201,7 @@ export function resolveHtml(url, text) {
let metadata = '';
for (let child of metadataCandidates[0].children) {
if (child.type === 'text') {
- metadata += child.data;
+ metadata += child.data.replace(/ /g, ' ');
} else if (
child.type === 'tag'
&& child.name === 'a'
diff --git a/source/actors/manageCrossref.js b/source/actors/manageCrossref.js
index cb533b3..b12bd18 100644
--- a/source/actors/manageCrossref.js
+++ b/source/actors/manageCrossref.js
@@ -117,7 +117,8 @@ export default function manageCrossref(store) {
store.dispatch(resolvePublicationFromDoi(
doi,
json.message,
- Array.from(bytes).map(byte => byte.toString(16)).join('')
+ Array.from(bytes).map(byte => byte.toString(16)).join(''),
+ new Date().getTime()
));
})
.catch(error => {
diff --git a/source/components/ProgressBar.js b/source/components/ProgressBar.js
index dfe1143..0af4db1 100644
--- a/source/components/ProgressBar.js
+++ b/source/components/ProgressBar.js
@@ -1,5 +1,4 @@
import React from 'react'
-import Radium from 'radium'
import PropTypes from 'prop-types'
class ProgressBar extends React.Component {
@@ -45,4 +44,4 @@ class ProgressBar extends React.Component {
}
}
-export default Radium(ProgressBar);
+export default ProgressBar;
diff --git a/source/containers/AddDoi.js b/source/containers/AddDoi.js
index dceb3cb..f1ba343 100644
--- a/source/containers/AddDoi.js
+++ b/source/containers/AddDoi.js
@@ -76,7 +76,7 @@ class AddDoi extends React.Component {
},
}}
onClick={() => {
- this.props.dispatch(publicationFromDoi(this.state.value.match(doiPattern)[1]));
+ this.props.dispatch(publicationFromDoi(this.state.value.match(doiPattern)[1], new Date().getTime()));
this.setState({valid: false, value: ''});
}}
>
diff --git a/source/containers/Graph.js b/source/containers/Graph.js
index be540be..3dbca1a 100644
--- a/source/containers/Graph.js
+++ b/source/containers/Graph.js
@@ -1,5 +1,4 @@
import React from 'react'
-import Radium from 'radium'
import {connect} from 'react-redux'
import PropTypes from 'prop-types'
import {
@@ -41,6 +40,10 @@ class Graph extends React.Component {
this.svg = null;
this.nodes = [];
this.edges = [];
+ this.d3Node = null;
+ this.d3Edge = null;
+ this.zoom = null;
+ this.reheatSimulation = false;
this.simulation = d3.forceSimulation(this.nodes)
.stop()
.force('link', d3.forceLink(this.edges).distance(80).strength(1).id(node => node.doi))
@@ -68,10 +71,6 @@ class Graph extends React.Component {
}
})
;
- this.d3Node = null;
- this.d3Edge = null;
- this.zoom = null;
- this.reheatSimulation = false;
}
componentWillReceiveProps(nextProps) {
@@ -388,6 +387,7 @@ class Graph extends React.Component {
})
;
this.svg.call(this.zoom);
+ this.zoom.scaleTo(this.svg, 2 ** (this.props.zoom / 20));
this.d3Node = this.svg.selectAll('.node');
this.d3Edge = this.svg.selectAll('.edge');
this.simulation.alpha(0);
@@ -466,4 +466,4 @@ export default connect(
colors: state.colors,
};
}
-)(Radium(Graph));
+)(Graph);
diff --git a/source/containers/GraphWithToolbar.js b/source/containers/GraphWithToolbar.js
index 893c836..5462d54 100644
--- a/source/containers/GraphWithToolbar.js
+++ b/source/containers/GraphWithToolbar.js
@@ -86,7 +86,6 @@ class GraphWithToolbar extends React.Component {
xOffset={0}
yOffset={0}
/>
-
state,
- })
+ }),
+ (state = {}, action) => {
+ if (process.env.ORIGAMI_ENV === 'development') {
+ console.log(action.type, action, state);
+ }
+ return state;
+ }
)(state, action);
}
diff --git a/source/reducers/publications.js b/source/reducers/publications.js
index 127c633..bcf1592 100644
--- a/source/reducers/publications.js
+++ b/source/reducers/publications.js
@@ -24,6 +24,7 @@ import {
PUBLICATION_STATUS_IN_COLLECTION,
PAGE_TYPE_INITIALIZE,
} from '../constants/enums'
+import {isOlderThan} from '../actions/managePublication'
export default function publications(state = new Map(), action, appState) {
switch (action.type) {
@@ -98,9 +99,24 @@ export default function publications(state = new Map(), action, appState) {
newState.set(action.doi, {
...state.get(action.doi),
title: action.crossrefMessage.title[0] == null ? '' : action.crossrefMessage.title[0],
- authors: action.crossrefMessage.author.map(author => `${author.given} ${author.family}`),
+ authors: action.crossrefMessage.author.filter(
+ author => author.given != null || author.family != null
+ ).map(
+ author => {
+ if (author.given == null) {
+ return author.family;
+ }
+ if (author.family == null) {
+ return author.given;
+ }
+ return `${author.given} ${author.family}`;
+ }
+ ),
journal: action.crossrefMessage.publisher,
- date: action.crossrefMessage.created['date-parts'][0],
+ date: (isOlderThan(action.crossrefMessage.created['date-parts'][0], action.crossrefMessage.issued['date-parts'][0]) ?
+ action.crossrefMessage.created['date-parts'][0]
+ : action.crossrefMessage.issued['date-parts'][0]
+ ),
status: PUBLICATION_STATUS_IN_COLLECTION,
updated: action.timestamp,
validating: false,
@@ -144,17 +160,18 @@ export default function publications(state = new Map(), action, appState) {
if (!state.has(action.doi) || state.get(action.doi).status !== PUBLICATION_STATUS_IN_COLLECTION) {
return state;
}
+ const doisToRemove = new Set([
+ ...state.get(action.doi).citers.filter(citer => state.get(citer).status === PUBLICATION_STATUS_DEFAULT),
+ action.doi,
+ ]);
const newState = new Map(state);
newState.set(action.doi, {
...state.get(action.doi),
status: PUBLICATION_STATUS_DEFAULT,
bibtex: null,
locked: false,
+ citers: [],
});
- const doisToRemove = new Set([
- ...state.get(action.doi).citers.filter(citer => state.get(citer).status === PUBLICATION_STATUS_DEFAULT),
- action.doi,
- ]);
for (const publication of newState.values()) {
if (publication.status === PUBLICATION_STATUS_IN_COLLECTION) {
for (const citer of publication.citers) {
@@ -246,17 +263,47 @@ export default function publications(state = new Map(), action, appState) {
newState.set(doi, {
...newState.get(doi),
title: action.crossrefMessage.title[0],
- authors: action.crossrefMessage.author.map(author => `${author.given ? `${author.given} ` : ''}${author.family}`),
+ authors: action.crossrefMessage.author.filter(
+ author => author.given != null || author.family != null
+ ).map(
+ author => {
+ if (author.given == null) {
+ return author.family;
+ }
+ if (author.family == null) {
+ return author.given;
+ }
+ return `${author.given} ${author.family}`;
+ }
+ ),
journal: action.crossrefMessage.publisher,
- date: action.crossrefMessage.created['date-parts'][0],
+ date: (isOlderThan(action.crossrefMessage.created['date-parts'][0], action.crossrefMessage.issued['date-parts'][0]) ?
+ action.crossrefMessage.created['date-parts'][0]
+ : action.crossrefMessage.issued['date-parts'][0]
+ ),
});
} else {
newState.set(doi, {
status: PUBLICATION_STATUS_DEFAULT,
title: action.crossrefMessage.title[0],
- authors: action.crossrefMessage.author.map(author => `${author.given ? `${author.given} ` : ''}${author.family}`),
+ authors: action.crossrefMessage.author.filter(
+ author => author.given != null || author.family != null
+ ).map(
+ author => {
+ if (author.given == null) {
+ return author.family;
+ }
+ if (author.family == null) {
+ return author.given;
+ }
+ return `${author.given} ${author.family}`;
+ }
+ ),
journal: action.crossrefMessage.publisher,
- date: action.crossrefMessage.created['date-parts'][0],
+ date: (isOlderThan(action.crossrefMessage.created['date-parts'][0], action.crossrefMessage.issued['date-parts'][0]) ?
+ action.crossrefMessage.created['date-parts'][0]
+ : action.crossrefMessage.issued['date-parts'][0]
+ ),
citers: [],
updated: null,
selected: false,
@@ -289,18 +336,48 @@ export default function publications(state = new Map(), action, appState) {
...newState.get(doi),
status: PUBLICATION_STATUS_IN_COLLECTION,
title: action.crossrefMessage.title[0],
- authors: action.crossrefMessage.author.map(author => `${author.given ? `${author.given} ` : ''}${author.family}`),
+ authors: action.crossrefMessage.author.filter(
+ author => author.given != null || author.family != null
+ ).map(
+ author => {
+ if (author.given == null) {
+ return author.family;
+ }
+ if (author.family == null) {
+ return author.given;
+ }
+ return `${author.given} ${author.family}`;
+ }
+ ),
journal: action.crossrefMessage.publisher,
- date: action.crossrefMessage.created['date-parts'][0],
+ date: (isOlderThan(action.crossrefMessage.created['date-parts'][0], action.crossrefMessage.issued['date-parts'][0]) ?
+ action.crossrefMessage.created['date-parts'][0]
+ : action.crossrefMessage.issued['date-parts'][0]
+ ),
updated: action.timestamp,
});
} else {
newState.set(doi, {
status: PUBLICATION_STATUS_IN_COLLECTION,
title: action.crossrefMessage.title[0],
- authors: action.crossrefMessage.author.map(author => `${author.given ? `${author.given} ` : ''}${author.family}`),
+ authors: action.crossrefMessage.author.filter(
+ author => author.given != null || author.family != null
+ ).map(
+ author => {
+ if (author.given == null) {
+ return author.family;
+ }
+ if (author.family == null) {
+ return author.given;
+ }
+ return `${author.given} ${author.family}`;
+ }
+ ),
journal: action.crossrefMessage.publisher,
- date: action.crossrefMessage.created['date-parts'][0],
+ date: (isOlderThan(action.crossrefMessage.created['date-parts'][0], action.crossrefMessage.issued['date-parts'][0]) ?
+ action.crossrefMessage.created['date-parts'][0]
+ : action.crossrefMessage.issued['date-parts'][0]
+ ),
citers: [],
updated: action.timestamp,
selected: false,
diff --git a/source/reducers/scholar.js b/source/reducers/scholar.js
index 7682200..5140058 100644
--- a/source/reducers/scholar.js
+++ b/source/reducers/scholar.js
@@ -3,6 +3,7 @@ import {
REMOVE_PUBLICATION,
UPDATE_PUBLICATION,
UPDATE_ALL_PUBLICATIONS,
+ PUBLICATION_FROM_DOI,
RESOLVE_PUBLICATION_FROM_DOI,
FETCH_SCHOLAR_PAGE,
RESOLVE_SCHOLAR_INITIAL_PAGE,
@@ -58,7 +59,7 @@ export default function scholar(
url: `https://scholar.google.com/scholar?hl=en&q=${encodeURIComponent(action.doi)}`,
}],
};
- case RESOLVE_PUBLICATION_FROM_IMPORTED_METADATA:
+ case RESOLVE_PUBLICATION_FROM_IMPORTED_METADATA: {
const doi = action.crossrefMessage.DOI.toLowerCase();
if (appState.publications.has(doi) && appState.publications.get(doi).status !== PUBLICATION_STATUS_DEFAULT) {
return state;
@@ -71,6 +72,7 @@ export default function scholar(
url: `https://scholar.google.com/scholar?hl=en&q=${encodeURIComponent(doi)}`,
}],
};
+ }
case REMOVE_PUBLICATION:
return {
...state,
@@ -120,6 +122,20 @@ export default function scholar(
}),
],
}
+ case PUBLICATION_FROM_DOI: {
+ const doi = action.doi.toLowerCase();
+ if (!appState.publications.has(doi) || appState.publications.get(doi).status !== PUBLICATION_STATUS_DEFAULT) {
+ return state;
+ }
+ return {
+ ...state,
+ pages: [...state.pages, {
+ type: PAGE_TYPE_INITIALIZE,
+ doi,
+ url: `https://scholar.google.com/scholar?hl=en&q=${encodeURIComponent(doi)}`,
+ }],
+ };
+ }
case RESOLVE_PUBLICATION_FROM_DOI:
if (!appState.publications.has(action.doi) || appState.publications.get(action.doi).status !== PUBLICATION_STATUS_UNVALIDATED) {
return state;
diff --git a/source/reducers/warnings.js b/source/reducers/warnings.js
index 82cf983..60ed91c 100644
--- a/source/reducers/warnings.js
+++ b/source/reducers/warnings.js
@@ -1,5 +1,5 @@
import {
- RESOLVE_PUBLICATION_FROM_DOI,
+ PUBLICATION_FROM_DOI,
REJECT_PUBLICATION_FROM_DOI,
REJECT_SCHOLAR_CITERS_PAGE,
REJECT_SCHOLAR_CITER_PARSING,
@@ -11,11 +11,17 @@ import {
REMOVE_WARNING,
REMOVE_ALL_WARNINGS,
} from '../constants/actionTypes'
+import {
+ PUBLICATION_STATUS_UNVALIDATED,
+ PUBLICATION_STATUS_DEFAULT,
+ PUBLICATION_STATUS_IN_COLLECTION,
+} from '../constants/enums'
export default function warnings(state = {list: [], hash: 0}, action, appState) {
switch (action.type) {
- case RESOLVE_PUBLICATION_FROM_DOI:
- if (!appState.publications.has(action.doi) || !appState.publications.get(action.doi).isInCollection) {
+ case PUBLICATION_FROM_DOI: {
+ const doi = action.doi.toLowerCase();
+ if (!appState.publications.has(doi) || appState.publications.get(doi).status === PUBLICATION_STATUS_DEFAULT) {
return state;
}
return {
@@ -23,13 +29,14 @@ export default function warnings(state = {list: [], hash: 0}, action, appState)
list: [
{
title: 'The publication was not added to the collection',
- subtitle: `${action.doi} is already in the collection`,
+ subtitle: `${doi} is already in the collection`,
level: 'warning',
},
...state.list,
],
hash: state.hash + 1,
};
+ }
case REJECT_PUBLICATION_FROM_DOI:
return {
...state,
diff --git a/webpack.common.js b/webpack.common.js
index db04e43..a856c1b 100644
--- a/webpack.common.js
+++ b/webpack.common.js
@@ -7,13 +7,13 @@ const recursive = require(`${__dirname}/recursive`);
module.exports = {
/// package uses electron-packager to convert the output of webpack to actual apps.
- package: (all, callback) => {
+ package: (production, callback) => {
try {
fs.mkdirSync(`${__dirname}/build/origami`);
} catch (error) {}
- for (const sourceFileToCopy of ['main.js', 'package.json']) {
- fs.copyFileSync(`${__dirname}/source/${sourceFileToCopy}`, `${__dirname}/build/origami/${sourceFileToCopy}`);
- }
+ fs.copyFileSync(`${__dirname}/source/package.json`, `${__dirname}/build/origami/package.json`);
+ fs.writeFileSync(`${__dirname}/build/origami/main.js`, `process.env.ORIGAMI_ENV = '${production ? 'production' : 'development'}';\n`);
+ fs.appendFileSync(`${__dirname}/build/origami/main.js`, fs.readFileSync(`${__dirname}/source/main.js`));
fs.copyFileSync(`${__dirname}/themes/default.json`, `${__dirname}/build/origami/colors.json`);
try {
fs.mkdirSync(`${__dirname}/build/origami/fonts`);
@@ -24,7 +24,7 @@ module.exports = {
child_process.execSync('npm install', {cwd: `${__dirname}/build/origami`}, {stdio: 'inherit'});
packager({
dir: `${__dirname}/build/origami`,
- all: all,
+ all: production,
out: `${__dirname}/build`,
overwrite: true,
icon: `${__dirname}/icons/origami`,
@@ -59,7 +59,7 @@ module.exports = {
exclude: /node_modules/,
query: {
presets: [
- ['env', {'targets': {'electron': '1.7.6', 'browsers': 'last 2 versions'}}],
+ ['env', {'targets': {'electron': '1.7.6'}}],
'react',
],
plugins: [
diff --git a/webpack.prod.js b/webpack.prod.js
index d7fc819..88cc469 100644
--- a/webpack.prod.js
+++ b/webpack.prod.js
@@ -15,9 +15,7 @@ module.exports = merge(common.configuration, {
});
},
new webpack.DefinePlugin({
- 'process.env': {
- 'NODE_ENV': JSON.stringify('production'),
- },
+ 'process.env.NODE_ENV': JSON.stringify('production'),
}),
new HtmlWebpackPlugin({
template: './source/index.ejs',