@chameleoncloud/jupyterlab_zenodo
Version:
JupyterLab extension for uploading to Zenodo
165 lines (164 loc) • 8.48 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const React = require("react");
const apputils_1 = require("@jupyterlab/apputils");
class ZenodoFormInput extends React.Component {
constructor(props) {
super(props);
this.id = `zenInput-${this.props.id}`;
}
render() {
const classNames = ['label'];
if (this.props.required) {
classNames.push('required');
}
return (React.createElement("div", { className: "zenodo-InputRow" },
React.createElement("label", { htmlFor: this.id, className: classNames.join(' ') }, this.props.label),
this.props.multiline ? (React.createElement("textarea", { id: this.id, name: this.props.id, required: this.props.required, placeholder: this.props.placeholder, rows: 5, defaultValue: this.props.default })) : (React.createElement("input", { type: "text", id: this.id, name: this.props.id, required: this.props.required, placeholder: this.props.placeholder, defaultValue: this.props.default }))));
}
}
exports.ZenodoFormInput = ZenodoFormInput;
ZenodoFormInput.defaultProps = {
label: '',
id: '',
required: false,
multiline: false
};
class ZenodoUploadForm extends React.Component {
constructor(props) {
super(props);
this.state = {
error: null
};
}
render() {
return (React.createElement("form", { id: 'submit-form', onSubmit: this.props.onSubmit },
React.createElement("h2", null, "Final Submission Details"),
React.createElement("p", null,
React.createElement("em", null, "Note:"),
" this will make your code publicly accessible on",
' ',
React.createElement("a", { href: this.props.baseUrl, target: "_blank" }, this.props.baseUrl),
"."),
React.createElement("div", { id: 'form-error-div' }, this.state.error),
React.createElement(ZenodoFormInput, { id: 'title', label: 'Title', required: true, default: this.props.defaults.title }),
React.createElement(ZenodoFormInput, { id: 'author', label: 'Author(s)', required: true, default: this.props.defaults.author, placeholder: 'Name <email@example.com>' }),
React.createElement(ZenodoFormInput, { id: 'affiliation', label: 'Affiliation', required: true, default: this.props.defaults.affiliation }),
React.createElement(ZenodoFormInput, { id: 'description', label: 'Description', default: this.props.defaults.description, required: true, multiline: true, placeholder: 'A short description of your artifact/files.' }),
React.createElement(ZenodoFormInput, { id: 'directory', label: 'Directory to publish', default: this.props.defaults.directory, placeholder: './my-dir' }),
React.createElement(ZenodoFormInput, { id: 'zenodo_token', label: 'Zenodo access token', default: this.props.defaults.zenodoToken, placeholder: '7I8PwXn60...' }),
React.createElement("button", { type: 'submit', className: 'zenodo-PublishButton jp-mod-styled jp-mod-accept' }, "Publish")));
}
}
exports.ZenodoUploadForm = ZenodoUploadForm;
class ZenodoSuccessMessage extends React.Component {
constructor(props) {
super(props);
this.onViewButtonClick = this.onViewButtonClick.bind(this);
}
get recordUrl() {
const record = this.props.doi.split('.').pop();
return `${this.props.baseUrl}/record/${record}`;
}
onViewButtonClick(event) {
event.preventDefault();
window.open(this.recordUrl, '_blank');
}
render() {
if (!this.props.doi) {
return React.createElement(React.Fragment, null);
}
return (React.createElement("div", null,
React.createElement("h2", null, "Your code is now published for citation"),
React.createElement("div", null,
React.createElement("button", { onClick: this.onViewButtonClick, className: 'jp-mod-styled jp-mod-accept' }, "View on Zenodo")),
React.createElement("div", { className: 'zenodo-SuccessMessageFAQ' },
React.createElement("h3", null, "How is my code shared?"),
React.createElement("p", null,
"Your code is now publicly accessible as an archive on",
' ',
React.createElement("a", { href: this.recordUrl, target: "_blank" }, "Zenodo"),
". It has been assigned a DOI (digital object identifier):",
React.createElement("em", null, this.props.doi)),
React.createElement("h3", null, "What if my code changes?"),
React.createElement("p", null, "If you make changes to your files, you can create a new version on Zenodo (which will be linked to the first) by clicking 'Update Zenodo Deposition' in the share menu."))));
}
}
exports.ZenodoSuccessMessage = ZenodoSuccessMessage;
class ZenodoManager extends React.Component {
constructor(props) {
super(props);
// TODO: is there a way to have TS actually check that this
// encompasses all the states?
this._allStates = ['waiting', 'success', 'error', 'form'];
this.state = {
currentState: 'form',
doi: null,
errorMessage: null
};
this.onSubmit = this.onSubmit.bind(this);
this.onSuccess = this.onSuccess.bind(this);
this.onError = this.onError.bind(this);
}
onSubmit(event) {
const form = event.target;
event.preventDefault();
// Convert form data to JSON
const formData = new FormData(form);
const zenodoPost = {
title: formData.get('title'),
author: formData.get('author'),
affiliation: formData.get('affiliation'),
description: formData.get('description'),
directory: formData.get('directory'),
zenodoToken: formData.get('zenodo_token')
};
// Send a POST request with data
this.setState({ currentState: 'waiting' });
this.props.zenodoRegistry
.createDeposition(zenodoPost.directory || '/', zenodoPost)
.then(this.onSuccess)
.catch(this.onError);
}
render() {
const hidden = { display: 'none' };
const block = { display: 'block' };
const visibilities = this._allStates.reduce((memo, state) => {
memo[state] = this.state.currentState === state ? block : hidden;
return memo;
}, {});
return (React.createElement("div", { className: 'zenodo-Upload' },
React.createElement("div", { className: 'zenodo-WaitMessage', style: visibilities.waiting },
React.createElement("div", { className: 'jp-Spinner' },
React.createElement("div", { className: 'jp-SpinnerContent' }),
React.createElement("div", { className: 'zenodo-LoadingMessage' }, "Please wait while your files are uploaded."))),
React.createElement("div", { className: 'zenodo-SuccessMessage', style: visibilities.success },
React.createElement(ZenodoSuccessMessage, { baseUrl: this.props.zenodoConfig.baseUrl, doi: this.state.doi })),
React.createElement("div", { className: 'zenodo-ErrorMessage', style: visibilities.error }, this.state.errorMessage),
React.createElement("div", { style: visibilities.form },
React.createElement(ZenodoUploadForm, { onSubmit: this.onSubmit, baseUrl: this.props.zenodoConfig.baseUrl, defaults: this.props.formDefaults }))));
}
onSuccess(record) {
this.setState({ currentState: 'success', doi: record.doi });
}
onError(error) {
this.setState({
currentState: 'error',
errorMessage: error.message
});
}
}
exports.ZenodoManager = ZenodoManager;
class ZenodoWidget extends apputils_1.ReactWidget {
constructor(zenodoRegistry, zenodoConfig, formDefaults) {
super();
this.id = 'zenodo-Widget';
this._zenodoRegistry = zenodoRegistry;
this._zenodoConfig = zenodoConfig;
this._formDefaults = formDefaults;
}
render() {
return (React.createElement(ZenodoManager, { zenodoRegistry: this._zenodoRegistry, zenodoConfig: this._zenodoConfig, formDefaults: this._formDefaults }));
}
}
exports.ZenodoWidget = ZenodoWidget;