@chameleoncloud/jupyterlab_zenodo
Version:
JupyterLab extension for uploading to Zenodo
249 lines (248 loc) • 9.11 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const application_1 = require("@jupyterlab/application");
const apputils_1 = require("@jupyterlab/apputils");
const settingregistry_1 = require("@jupyterlab/settingregistry");
const mainmenu_1 = require("@jupyterlab/mainmenu");
const widgets_1 = require("@lumino/widgets");
const filebrowser_1 = require("./filebrowser");
const tokens_1 = require("./tokens");
const registry_1 = require("./registry");
const widget_1 = require("./widget");
const filebrowser_2 = require("@jupyterlab/filebrowser");
const zenodoPluginId = '@chameleoncloud/jupyterlab_zenodo:plugin';
/**
* The JupyterFrontEnd plugin for the Zenodo extension.
*/
const zenodoPlugin = {
id: zenodoPluginId,
requires: [
settingregistry_1.ISettingRegistry,
apputils_1.ICommandPalette,
application_1.ILayoutRestorer,
mainmenu_1.IMainMenu,
filebrowser_2.IFileBrowserFactory,
tokens_1.IZenodoRegistry
],
activate: activateZenodoPlugin,
autoStart: true
};
const zenodoRegistryPlugin = {
id: '@chameleoncloud/jupyterlab_zenodo:registry',
provides: tokens_1.IZenodoRegistry,
requires: [],
activate(app) {
return new registry_1.ZenodoRegistry();
}
};
var CommandIDs;
(function (CommandIDs) {
/*
* Open a form that users can submit to publish to Zenodo
*/
CommandIDs.create = 'zenodo:upload';
/*
* Update existing Zenodo deposition (metadata only)
*/
CommandIDs.update = 'zenodo:update';
/*
* Create a new version of a deposition
*/
CommandIDs.newVersion = 'zenodo:newVersion';
/*
* Copy currently selected artifact's DOI to system clipboard
*/
CommandIDs.copyDOI = 'zenodo:copyDOI';
})(CommandIDs || (CommandIDs = {}));
/**
* Activate the Zenodo front-end plugin
*
* NOTE: arguments must be in the same order as in the zenodoPlugin declaration
*/
function activateZenodoPlugin(app, settingRegistry, palette, restorer, mainMenu, fileBrowserFactory, zenodoRegistry) {
// Retrive settings
Promise.all([
settingRegistry.load(zenodoPluginId),
app.restored,
zenodoRegistry.getDepositions()
])
.then(([settings]) => {
const browser = fileBrowserFactory.defaultBrowser;
// Add commands to the extension, including the 'upload' command
addZenodoCommands(app, settings, restorer, browser, zenodoRegistry);
// Create sharing menu with 'upload' and 'update' commands
const menu = new widgets_1.Menu({ commands: app.commands });
menu.addItem({ command: CommandIDs.create });
menu.addItem({ command: CommandIDs.update });
menu.addItem({ command: CommandIDs.newVersion });
menu.title.label = 'Share';
mainMenu.addMenu(menu, { rank: 20 });
// Add commands to Command Palette
const category = 'Sharing';
palette.addItem({ command: CommandIDs.create, category });
palette.addItem({ command: CommandIDs.update, category });
palette.addItem({ command: CommandIDs.copyDOI, category });
palette.addItem({ command: CommandIDs.newVersion, category });
// Add context menu for directories
const selectorPublished = '.jp-DirListing-item[data-isdir=true][data-doi]';
const selectorNotPublished = '.jp-DirListing-item[data-isdir=true]:not([data-doi])';
app.contextMenu.addItem({
command: CommandIDs.update,
selector: selectorPublished,
rank: 1
});
app.contextMenu.addItem({
command: CommandIDs.newVersion,
selector: selectorPublished,
rank: 2
});
app.contextMenu.addItem({
command: CommandIDs.copyDOI,
selector: selectorPublished,
rank: 3
});
app.contextMenu.addItem({
command: CommandIDs.create,
selector: selectorNotPublished,
rank: 1
});
})
.catch((reason) => {
// If something went wrong, log the error
console.error(reason.message);
});
}
/*
* Using arguments from 'activate' and the newly created widget,
* create commands for each action and add them to appropriate menus
*/
function addZenodoCommands(app, settings, restorer, browser, zenodoRegistry) {
const createLabel = settings.get('createLabel').composite;
const editLabel = settings.get('editLabel').composite;
const baseUrl = settings.get('baseUrl').composite;
const externalEditUrl = settings.get('externalEditUrl').composite;
const zenodoConfig = {
baseUrl,
externalEditUrl
};
let widget;
const tracker = new apputils_1.WidgetTracker({
namespace: 'zenodo'
});
function openWidget(formDefaults) {
if (!widget || widget.isDisposed) {
const content = new widget_1.ZenodoWidget(zenodoRegistry, zenodoConfig, formDefaults);
content.title.label = createLabel;
widget = new apputils_1.MainAreaWidget({ content });
widget.id = 'zenodo';
}
if (!widget.isAttached) {
app.shell.add(widget, 'main');
}
if (!tracker.has(widget)) {
tracker.add(widget);
}
widget.update();
app.shell.activateById(widget.id);
}
function unsupportedItem(item) {
return item && item.type !== 'directory';
}
function hasDeposition(item) {
// No item = check the root path (empty)
return zenodoRegistry.hasDepositionSync((item && item.path) || '');
}
function currentItemHasDeposition() {
const item = browser.selectedItems().next();
if (unsupportedItem(item)) {
return false;
}
return hasDeposition(item);
}
function currentItemMissingDeposition() {
const item = browser.selectedItems().next();
if (unsupportedItem(item)) {
return false;
}
return !hasDeposition(item);
}
function currentItemDeposition() {
const item = browser.selectedItems().next();
const path = (item && item.path) || '';
return zenodoRegistry.getDeposition(path).then(record => {
if (!record) {
throw Error(`No deposition exists at path "${path}"`);
}
return record;
});
}
// Command to upload any set of files
app.commands.addCommand(CommandIDs.create, {
label: createLabel,
isEnabled: currentItemMissingDeposition,
execute() {
let formDefaults;
const item = browser.selectedItems().next();
if (item && item.type === 'directory') {
formDefaults = { directory: item.path };
}
openWidget(formDefaults || {});
}
});
app.commands.addCommand(CommandIDs.update, {
label: editLabel,
isEnabled: currentItemHasDeposition,
execute() {
currentItemDeposition().then(record => {
const { externalEditUrl } = zenodoConfig;
if (externalEditUrl) {
window.open(externalEditUrl.replace('{doi}', record.doi));
}
else {
// TODO: open edit UI
throw Error('Not implemented yet');
}
});
}
});
app.commands.addCommand(CommandIDs.newVersion, {
label: 'Create new version',
isEnabled: currentItemHasDeposition,
execute() {
return __awaiter(this, void 0, void 0, function* () {
// TODO: open 'new version' UI?
const { path } = yield currentItemDeposition();
return yield zenodoRegistry.newDepositionVersion(path);
});
}
});
app.commands.addCommand(CommandIDs.copyDOI, {
label: 'Copy DOI',
isEnabled: currentItemHasDeposition,
execute() {
currentItemDeposition().then(({ doi }) => apputils_1.Clipboard.copyToSystem(doi));
}
});
restorer.restore(tracker, {
command: CommandIDs.create,
name: () => 'zenodo'
});
}
/**
* Export the plugins as default.
*/
const plugins = [
filebrowser_1.fileBrowserFactory,
zenodoRegistryPlugin,
zenodoPlugin
];
exports.default = plugins;