Skip to content

Commit

Permalink
#6629 publish non anonymous gists
Browse files Browse the repository at this point in the history
  • Loading branch information
Mariusz Jurowicz committed Jan 30, 2018
1 parent 57f8b95 commit 4bb7087
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 50 deletions.
18 changes: 9 additions & 9 deletions js/lab/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@
"@jupyter-widgets/base": "^1.1.5",
"@jupyter-widgets/controls": "^1.1.2",
"@jupyter-widgets/output": "^1.0.10",
"@jupyterlab/application": "^0.13.0",
"@jupyterlab/codemirror": "^0.13.0",
"@jupyterlab/coreutils": "^0.13.0",
"@jupyterlab/docregistry": "^0.13.0",
"@jupyterlab/notebook": "^0.13.0",
"@jupyterlab/outputarea": "^0.13.1",
"@jupyterlab/rendermime": "^0.13.0",
"@jupyterlab/rendermime-interfaces": "^0.4.2",
"@jupyterlab/services": "^0.52.0",
"@jupyterlab/application": "^0.15.2",
"@jupyterlab/codemirror": "^0.15.2",
"@jupyterlab/coreutils": "^1.0.4",
"@jupyterlab/docregistry": "^0.15.2",
"@jupyterlab/notebook": "^0.15.2",
"@jupyterlab/outputarea": "^0.15.2",
"@jupyterlab/rendermime": "^0.15.2",
"@jupyterlab/rendermime-interfaces": "^1.0.4",
"@jupyterlab/services": "^1.1.2",
"@types/node": "^8.0.56",
"rimraf": "^2.6.2",
"typescript": "~2.6.2"
Expand Down
19 changes: 19 additions & 0 deletions js/lab/src/global.env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* 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.
*/

declare interface Window {
beakerx: any
}
3 changes: 1 addition & 2 deletions js/lab/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
* limitations under the License.
*/

declare function require(moduleName: string): any;

import './global.env';
import { IJupyterWidgetRegistry } from '@jupyter-widgets/base';
import BeakerxExtension from './plugin';
import { JupyterLab } from '@jupyterlab/application';
Expand Down
111 changes: 111 additions & 0 deletions js/lab/src/plugin/gistPublish/gistPublishModal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* 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 { Dialog } from '@jupyterlab/apputils';
import { Widget } from '@phosphor/widgets';
import { ServerConnection } from "@jupyterlab/services";
import { PageConfig } from "@jupyterlab/coreutils";
import gistPublishModalTemplate from './modalTemplate';

export default class GistPublishModal {
private settingsUrl: string;
private serverSettings: ServerConnection.ISettings;

constructor() {
this.serverSettings = ServerConnection.makeSettings();
this.settingsUrl = `${PageConfig.getBaseUrl()}beakerx/settings`;
}

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

create(submitCallback, personalAccessToken = ''): Promise<any> {
const bodyWidget = this.createBodyWidget();
const personalAccessTokenInput = bodyWidget.node.querySelector('input');
const form = bodyWidget.node.querySelector('form');
const cancelButton = Dialog.cancelButton({ label: 'Cancel' });
const publishButton = Dialog.okButton({ label: 'Publish' });

const submitHandler = (result: Dialog.IResult<any>) => {
if (result.button === cancelButton) {
return;
}

submitCallback(result.value);
this.storePersonalAccessToken(result.value);
};

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

const modal = new Dialog({
title : 'Publish to a GitHub Gist',
body: bodyWidget,
defaultButton: 1,
focusNodeSelector: 'input',
buttons: [ cancelButton, publishButton ]
});

return modal.launch().then(({ button }) => {
submitHandler({ button, value: personalAccessTokenInput.value });
});
}

createBodyWidget(): Widget {
const modalContent = document.createElement('div');

modalContent.innerHTML = gistPublishModalTemplate;

return new Widget({ node: modalContent });
}

storePersonalAccessToken(githubPersonalAccessToken = ''): Promise<any> {
return this.getStoredSettings()
.then(storedSettings =>
ServerConnection.makeRequest(
this.settingsUrl,
{
method: 'POST',
body: JSON.stringify({
...storedSettings,
githubPersonalAccessToken
})
},
this.serverSettings
).catch(reason => { console.log(reason); })
);
}

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

getStoredSettings(): Promise<any> {
return ServerConnection.makeRequest(
this.settingsUrl,
{ method: 'GET' },
this.serverSettings
)
.then(response => response.json())
.catch(reason => { console.log(reason); });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import * as $ from 'jquery';
import { NotebookPanel } from "@jupyterlab/notebook";
import { showDialog, Dialog, ToolbarButton } from '@jupyterlab/apputils';
import GistPublishModal from './gistPublishModal';

const CONFIG = {
gistsUrl: 'https://api.github.com/gists',
Expand All @@ -38,40 +39,24 @@ export function addActionButton(panel: NotebookPanel): void {
}

function openPublishDialog(panel: NotebookPanel) {
showDialog({
title : 'Publish',
body : 'Publish to an anonymous Github Gist, and open in nbviewer?',
buttons: [
Dialog.okButton({ label: 'OK' }),
Dialog.cancelButton({ label: 'Cancel' })
]
})
.then(() => savePanelState(panel))
.then(() => doPublish(panel));
}

function savePanelState(panel: NotebookPanel): Promise<any> {
return new Promise((resolve, reject) => {
panel.context.save().then(() => {
console.log("widgets state has been saved");
const gistPublishModal = new GistPublishModal();

if (!panel.isDisposed) {
resolve();
} else {
reject();
}
}, reject);
});
gistPublishModal.show(personalAccessToken => doPublish(panel, personalAccessToken));
}

function doPublish(panel: NotebookPanel): void {
function doPublish(panel: NotebookPanel, personalAccessToken: string|null): void {
const nbjson = panel.notebook.model.toJSON();
const filedata = {};

filedata[panel.context.contentsModel.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 @@ -82,16 +67,19 @@ function doPublish(panel: NotebookPanel): 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);
$.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);
});
}

function showErrorDialog(errorMsg) {
Expand Down
38 changes: 38 additions & 0 deletions js/lab/src/plugin/gistPublish/modalTemplate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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.
*/

export default `
<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>
`;
9 changes: 1 addition & 8 deletions js/lab/src/plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,7 @@ import { INotebookModel, NotebookPanel } from '@jupyterlab/notebook';
import { registerCommTargets } from './comm';
import { registerCommentOutCmd } from './codeEditor';
import { enableInitializationCellsFeature } from './initializationCells';
import { registerFeature as registerGistPublishFeature } from './gistPublish';

declare global {
interface Window {
beakerx: any,
require: Function
}
}
import { registerFeature as registerGistPublishFeature } from './gistPublish/index';

function displayHTML(widget: Widget, html: string): void {
if (!widget.node || !html) {
Expand Down
1 change: 1 addition & 0 deletions js/lab/src/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"noImplicitAny": false,
"noEmitOnError": true,
"noUnusedLocals": true,
"jsx": "preserve",
"lib": ["dom", "es5", "es2015.promise"],
"types": ["node"],
"module": "commonjs",
Expand Down

0 comments on commit 4bb7087

Please sign in to comment.