Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#6594 allow to publish personal gists #6637

Merged
merged 12 commits into from
Jan 19, 2018
2 changes: 1 addition & 1 deletion js/notebook/src/Plot.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ var PlotView = widgets.DOMWidgetView.extend({
scope.destroy();
});
}
that._currentScope.destroy();
that._currentScope && that._currentScope.destroy();

setTimeout(function() { that._currentScope = null; });
});
Expand Down
2 changes: 1 addition & 1 deletion js/notebook/src/extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ define([
'./plot/plotApi',
'./shared/bkCoreManager',
'big.js',
'./extension/GistPublish'
'./extension/gistPublish/index'
], function(
configmod,
comm,
Expand Down
103 changes: 103 additions & 0 deletions js/notebook/src/extension/gistPublish/gistPublishModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2017 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import * as _ from 'underscore';

const dialog = require('base/js/dialog');
const utils = require('base/js/utils');

export default class GistPublishModal {
static template = _.template(require('./modalTemplate.html'))();
static settingsUrl = `${(Jupyter.notebook_list || Jupyter.notebook).base_url}beakerx/settings`;

static show(submitCallback: Function): void {
GistPublishModal.getGithubPersonalAccessToken()
.then(personalAccessToken => {
GistPublishModal.create(submitCallback, personalAccessToken);
});
}

static create(submitCallback, personalAccessToken = '') {
const modalContent = GistPublishModal.createModalContent();
const personalAccessTokenInput = modalContent.querySelector('input');
const form = modalContent.querySelector('form');

const submitHandler = (event) => {
const personalAccessToken = personalAccessTokenInput ? personalAccessTokenInput.value : '';

event.preventDefault();
submitCallback(personalAccessToken);
GistPublishModal.storePersonalAccessToken(personalAccessToken);
};

if (personalAccessTokenInput && form) {
personalAccessTokenInput.value = personalAccessToken;
}

const modal = dialog.modal({
keyboard_manager: Jupyter.notebook.keyboard_manager,
title : 'Publish to a GitHub Gist',
body : modalContent,
default_button: 'Publish',
buttons: {
'Publish': {
'class' : 'btn-primary',
'click': submitHandler
},
'Cancel': {}
}
});

if (form) {
form.onsubmit = (event) => {
modal.modal('hide');
submitHandler(event);
}
}
}

static createModalContent(): HTMLElement {
const modalContent = document.createElement('div');

modalContent.innerHTML = GistPublishModal.template;

return modalContent;
}

static storePersonalAccessToken(githubPersonalAccessToken = ''): Promise<any> {
return GistPublishModal.getStoredSettings()
.then(storedSettings =>
utils.ajax(GistPublishModal.settingsUrl, {
type: 'POST',
data: JSON.stringify({
...storedSettings,
githubPersonalAccessToken
})
}).fail(reason => { console.log(reason); })
);
}

static getGithubPersonalAccessToken(): Promise<any> {
return GistPublishModal.getStoredSettings()
.then(settings => settings.githubPersonalAccessToken || '');
}

static getStoredSettings(): Promise<any> {
return utils.ajax(GistPublishModal.settingsUrl, {
method: 'GET'
}).fail(reason => { console.log(reason); });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
* limitations under the License.
*/

import $ from 'jquery';
import * as $ from 'jquery';
import GistPublishModal from './gistPublishModal';

const dialog = require('base/js/dialog');
const CONFIG = {
Expand Down Expand Up @@ -44,19 +45,9 @@ export function registerFeature(): void {
}

function beforePublish(): void {
dialog.modal({
title : 'Publish',
body : 'Publish to an anonymous Github Gist, and open in nbviewer?',
buttons: {
'OK': {
'class' : 'btn-primary',
'click': function() {
saveWidgetsState().then(doPublish);
}
},
'Cancel': {}
}
});
GistPublishModal.show(personalAccessToken => saveWidgetsState().then(
() => doPublish(personalAccessToken)
));
}

function showErrorDialog(errorMsg) {
Expand Down Expand Up @@ -84,14 +75,19 @@ function saveWidgetsState(): Promise<any> {
});
}

function doPublish(): void {
function doPublish(personalAccessToken): void {
const nbjson = Jupyter.notebook.toJSON();
const filedata = {};

filedata[Jupyter.notebook.notebook_name] = {
content : JSON.stringify(nbjson, undefined, 1)
};

let gistsUrl = CONFIG.gistsUrl;
if (personalAccessToken) {
gistsUrl = `${gistsUrl}?oauth_token=${personalAccessToken}`;
}

const settings = {
type : 'POST',
headers : {},
Expand All @@ -102,14 +98,17 @@ function doPublish(): void {
success : (data, status) => {
console.log("gist successfully published: " + data.id);
window.open(CONFIG.nbviewerBaseUrl + data.id);
},
error : (jqXHR, status, err) => {
const errorMsg = jqXHR.readyState === 0 && !err ? 'NETWORK ERROR!' : err;

console.log(errorMsg);
showErrorDialog(errorMsg);
}
};

$.ajax(CONFIG.gistsUrl, settings);
return $.ajax(gistsUrl, settings).catch((jqXHR, status, err) => {
let errorMsg = jqXHR.readyState === 0 && !err ? 'NETWORK ERROR!' : err;

if (jqXHR.responseJSON && jqXHR.responseJSON.message) {
errorMsg = jqXHR.responseJSON.message;
}

console.log(errorMsg);
showErrorDialog(errorMsg);
});
}
36 changes: 36 additions & 0 deletions js/notebook/src/extension/gistPublish/modalTemplate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!--
Copyright 2017 TWO SIGMA OPEN SOURCE, LLC

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<div>
<p class="alert alert-primary bg-info">
<strong>Leave the Personal Access Token field empty to publish as an anonymous gist.</strong>
<br>
<strong>Press enter or click the "Publish" button below. A
window will open with the results, which you can share like
any URL.</strong>
</p>
<form>
<div class="form-group">
<label>Personal Access Token</label>
<input type="password" class="form-control">
</div>
</form>
<p class="help-block">
<span>Enter a <a target="_blank" href="https://github.com/settings/tokens">Personal Access Token</a> to publish the notebook as a gist in your GitHub account.</span><br>
<span>We recommend your Personal Access Token have only the <strong><i>gists</i></strong> scope.</span><br>
<span>You can read about scopes <a href="https://developer.github.com/apps/building-oauth-apps/scopes-for-oauth-apps/">here</a></span>
</p>
</div>
2 changes: 1 addition & 1 deletion js/notebook/src/plot/plotScope.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ define([
moment
) {

var CONTEXT_MENU_DEBOUNCE_TIME = 250;
var CONTEXT_MENU_DEBOUNCE_TIME = 350;

function PlotScope(wrapperId) {
this.wrapperId = wrapperId;
Expand Down