Initial Move from Azure DevOps to GitHub

This commit is contained in:
Steve Faulkner
2020-05-25 21:30:55 -05:00
commit 36581fb6d9
986 changed files with 195242 additions and 0 deletions

View File

@@ -0,0 +1,40 @@
/**
* JupyterLab applications based on jupyterLab components
*/
import { ServerConnection, TerminalSession } from "@jupyterlab/services";
import { Terminal } from "@jupyterlab/terminal";
import { Panel, Widget } from "@phosphor/widgets";
export class JupyterLabAppFactory {
public static async createTerminalApp(serverSettings: ServerConnection.ISettings) {
const session = await TerminalSession.startNew({
serverSettings: serverSettings
});
const term = new Terminal(session, { theme: "dark", shutdownOnClose: true });
if (!term) {
console.error("Failed starting terminal");
return;
}
term.title.closable = false;
term.addClass("terminalWidget");
let panel = new Panel();
panel.addWidget(term);
panel.id = "main";
// Attach the widget to the dom.
Widget.attach(panel, document.body);
// Handle resize events.
window.addEventListener("resize", () => {
panel.update();
});
// Dispose terminal when unloading.
window.addEventListener("unload", () => {
panel.dispose();
});
}
}

111
src/Terminal/NotebookAppContracts.d.ts vendored Normal file
View File

@@ -0,0 +1,111 @@
/**
* Message handling with iframe parent
*/
export interface UpdateMessage {
command: string;
arg?: any;
}
export declare type ContentType = "notebook" | "file" | "directory";
export interface ContentItem {
name: string;
path: string;
type: ContentType;
}
export interface UploadData {
filepath: string;
content: string;
}
export interface RenameFileData {
sourcePath: string;
targetPath: string;
}
export interface RenameFileResult {
source: string;
target: ContentItem;
}
export interface FromDataExplorerMessage {
type: MessageTypes;
params: any;
id: string;
}
export declare type KernelStatusStates =
| "unknown"
| "starting"
| "reconnecting"
| "idle"
| "busy"
| "restarting"
| "autorestarting"
| "dead"
| "connected";
/**
* Unsolicited message
*/
export interface FromNotebookUpdateMessage {
type: NotebookUpdateTypes;
arg?: any;
}
/**
* Response to a Data Explorer request
*/
export interface FromNotebookResponseMessage {
id: string;
data?: any;
error?: any;
}
export interface FromNotebookMessage {
actionType: ActionTypes;
message: FromNotebookUpdateMessage | FromNotebookResponseMessage;
}
export declare type KernelOption = {
name: string;
displayName: string;
};
export interface KernelSpecs {
defaultName: string;
kernelSpecs: {
[name: string]: KernelOption;
};
}
export declare enum ActionTypes {
Update = 0,
Response = 1
}
/**
* Messages Data Explorer -> JupyterLabApp
*/
export declare enum MessageTypes {
FileList = 0,
CreateInDir = 1,
DeleteFile = 2,
UploadFile = 3,
RenameFile = 4,
ReadFileContent = 5,
CreateDirectory = 6,
InsertBelow = 7,
RunAndAdvance = 8,
Copy = 9,
Cut = 10,
Paste = 11,
Undo = 12,
ClearAllOutputs = 13,
RunAll = 14,
Redo = 15,
Save = 16,
RestartKernel = 17,
ChangeCellType = 18,
SwitchKernel = 19,
ChangeKernel = 20,
Status = 21,
KernelList = 22,
IsDirty = 23,
Shutdown = 24
}
export declare enum NotebookUpdateTypes {
Ready = 0,
ClickEvent = 1,
ActiveCellType = 2,
KernelChange = 3,
FileSaved = 4,
SessionStatusChange = 5
}

76
src/Terminal/README.md Normal file
View File

@@ -0,0 +1,76 @@
# Summary
This describes how to run a custom version of the Data Explorer in the Emulator which can open a jupyter notebook from with a tab.
# Requirements
This requires:
* a running instance of CosmosDB Emulator
* a running instance of the jupyter server
* access to the cosmosdb-dataexplorer git repository
# Installation
## Install CosmosDB Emulator
* Download from https://docs.microsoft.com/en-us/azure/cosmos-db/local-emulator
* Open the Emulator and create at least one Collection
## Install Jupyter server on local machine (Windows)
We use the Anaconda distribution which comes with a packaged jupyter and python.
* Download and install Anaconda from https://www.anaconda.com/distribution/ (python3 64-bit version)
Keep all default options. Install Visual Studio Code as well.
### Verify Jupyter installation and create mynotebook
* Open an "Anaconda Prompt" (hit the Window key, type "Anaconda", select "Anaconda Prompt" hit Enter)
> cd src/jupyter-server (the notebooks will be saved in this directory)
> jupyter notebook
* It should open the browser at http://localhost:8888/ with the jupyter notebook.
* Edit the notebook and save it as "mynotebook" (This should create a file: mynotebook.ipynb).
We do this, because right now, the notebook filename is hardcoded as mynotebook.
### Modify jupyter server install
In order to serve the jupyter frontend from the emulator, we need to turn off a bunch of things.
* Stop the jupyter server (Ctrl-C twice from the Anaconda Prompt where you started jupyter notebook)
* From the Anaconda Prompt, type: juypter notebook --generate-config
* This should create the file: .jupyter/jupyter_notebook in your home directory.
* Edit this file:
Enable embedding the jupyter frontend inside an iFrame in DataExplorer:
c.NotebookApp.tornado_settings = { 'headers': { 'Content-Security-Policy': "frame-ancestors * localhost:1234 localhost:12900"} }
Enable a remotely-served jupyter frontend to still talk to the jupyter server:
c.NotebookApp.allow_origin = '*'
c.NotebookApp.allow_remote_access = True <--- not sure if this one matters
c.NotebookApp.token = ''
c.NotebookApp.disable_check_xsrf = True
## Install custom Data Explorer in Emulator
* Install git from https://git-scm.com/download/win (keep all default options)
* Install nodejs and npm from: https://nodejs.org/en/ (10.15.1 LTS)
### Download and build Data Explorer
* From the Git Bash terminal:
* cd ~/src
* git clone https://msdata.visualstudio.com/DefaultCollection/CosmosDB/_git/cosmosdb-dataexplorer
* cd cosmosdb-dataexplorer/Product/Portal
* git checkout users/languye/spark-in-dataexplorer
* cd JupyterLab
* npm i
* npm run build (this builds jupyterlab (the frontend of jupyter) and copies it into ../DataExplorer/notebookapp/)
* cd ../DataExplorer
* npm i
* npm run build (this builds and copies DataExplorer into the Emulator folder)
# How to run the setup
* Run the jupter-server by opening an Anaconda Prompt and typing: jupyter notebook
* Open the emulator at: http://localhost:8081/_explorer/index.html
* Click on any Collection
* Click on "New Notebook" button in the Command bar
* You should see the "mynotebook" jupyter notebook displayed in tab (inside an iframe).
* There is a "New Cell" button in the CommandBar outside the jupyter iframe which will add a cell inside the notebook.
# Notes
* The iframe in the Data Explorer Tab loads jupyter with the server and notebook pathname passed in the query parameters (they're hardcoded right now):
cosmosdb-dataexplorer/Product/Portal/DataExplorer/src/Explorer/Tabs/NotebookTab.html
* The Emulator is located in: C:\Program Files\Azure Cosmos DB Emulator\Packages\DataExplorer
* Running "jupyter notebook" serves the jupyter traditional frontend. There is an alternate frontend also developed by jupyter which is modular and customizable called: JupyterLab. We use their "notebook" example in this project slightly modified to pass the server and notebook pathname via iframe url's parameters:
https://github.com/jupyterlab/jupyterlab/tree/master/examples/notebook
jupyterlab uses the same communication protocol as the traditional frontend, so it can connect to any jupyter-server,
so one can use multiple frontends (at the same time) to connect to a given jupyter-server.
* The jupyter frontend and the server use websockets to communicate.

26
src/Terminal/index.css Normal file
View File

@@ -0,0 +1,26 @@
/*-----------------------------------------------------------------------------
| Copyright (c) Jupyter Development Team.
| Distributed under the terms of the Modified BSD License.
|----------------------------------------------------------------------------*/
body {
background: white;
margin: 0;
padding: 0;
}
#main {
position: absolute;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
}
.jp-NotebookPanel {
border-bottom: 1px solid #e0e0e0;
}
.terminalWidget {
height: 100%;
}

13
src/Terminal/index.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Notebook</title>
</head>
<body>
<script id="jupyter-config-data" type="application/json">
{
"terminalsAvailable": "true"
}
</script>
</body>
</html>

52
src/Terminal/index.ts Normal file
View File

@@ -0,0 +1,52 @@
import "babel-polyfill";
import "promise-polyfill/src/polyfill"; // polyfill Promise on IE
import "@jupyterlab/terminal/style/index.css";
import "./index.css";
import { ServerConnection } from "@jupyterlab/services";
import { JupyterLabAppFactory } from "./JupyterLabAppFactory";
const getUrlVars = (): { [key: string]: string } => {
const vars: { [key: string]: string } = {};
window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, (m, key, value): string => {
vars[key] = decodeURIComponent(value);
return value;
});
return vars;
};
const main = (): void => {
const urlVars = getUrlVars();
console.log("URL parameters", urlVars);
let body: BodyInit;
if (urlVars.hasOwnProperty("terminalEndpoint")) {
body = JSON.stringify({
endpoint: urlVars["terminalEndpoint"]
});
}
const server = urlVars["server"];
let options: Partial<ServerConnection.ISettings> = {
baseUrl: server,
init: { body },
fetch: window.parent.fetch
};
if (urlVars.hasOwnProperty("token")) {
options = {
baseUrl: server,
token: urlVars["token"],
init: { body },
fetch: window.parent.fetch
};
}
const serverSettings = ServerConnection.makeSettings(options);
if (urlVars.hasOwnProperty("terminal")) {
JupyterLabAppFactory.createTerminalApp(serverSettings);
return;
}
throw new Error("Only terminal is supported");
};
window.addEventListener("load", main);