Prettier 2.0 (#393)

This commit is contained in:
Steve Faulkner
2021-01-20 09:15:01 -06:00
committed by GitHub
parent c1937ca464
commit 4be53284b5
500 changed files with 41927 additions and 41838 deletions

View File

@@ -23,7 +23,7 @@ import {
HostRecord,
HostRef,
KernelspecsRef,
IContentProvider
IContentProvider,
} from "@nteract/core";
import { Media } from "@nteract/outputs";
import TransformVDOM from "@nteract/transform-vdom";
@@ -73,7 +73,7 @@ export class NotebookClientV2 {
this.getStore().dispatch(
actions.fetchKernelspecs({
hostRef: this.contentHostRef,
kernelspecsRef: this.kernelSpecsRef
kernelspecsRef: this.kernelSpecsRef,
})
);
}
@@ -101,7 +101,7 @@ export class NotebookClientV2 {
basePath: "/", // Jupyter server base URL
bookstoreEnabled: false, //!!config.bookstore.version,
showHeaderEditor: true,
crossDomain: true
crossDomain: true,
});
this.contentHostRef = createHostRef();
@@ -111,7 +111,7 @@ export class NotebookClientV2 {
const initialState: CdbAppState = {
app: makeAppRecord({
version: "dataExplorer 1.0",
host: jupyterHostRecord
host: jupyterHostRecord,
// TODO: tamitta: notificationSystem.addNotification was removed, do we need a substitute?
}),
core: makeStateRecord({
@@ -119,11 +119,11 @@ export class NotebookClientV2 {
entities: makeEntitiesRecord({
editors: makeEditorsRecord({}),
hosts: makeHostsRecord({
byRef: Immutable.Map<string, HostRecord>().set(this.contentHostRef, jupyterHostRecord)
byRef: Immutable.Map<string, HostRecord>().set(this.contentHostRef, jupyterHostRecord),
}),
comms: makeCommsRecord(),
contents: makeContentsRecord({
byRef: Immutable.Map<string, ContentRecord>()
byRef: Immutable.Map<string, ContentRecord>(),
}),
transforms: makeTransformsRecord({
displayOrder: Immutable.List([
@@ -150,7 +150,7 @@ export class NotebookClientV2 {
"image/gif",
"image/png",
"image/jpeg",
"text/plain"
"text/plain",
]),
byId: Immutable.Map({
"text/vnd.plotly.v1+html": NullTransform,
@@ -176,15 +176,15 @@ export class NotebookClientV2 {
"image/gif": Media.Image,
"image/png": Media.Image,
"image/jpeg": Media.Image,
"text/plain": Media.Plain
})
})
})
"text/plain": Media.Plain,
}),
}),
}),
}),
cdb: makeCdbRecord({
databaseAccountName: params.databaseAccountName,
defaultExperience: params.defaultExperience
})
defaultExperience: params.defaultExperience,
}),
};
/**
@@ -194,16 +194,16 @@ export class NotebookClientV2 {
*/
const cacheKernelSpecsMiddleware: Middleware = <D extends Dispatch<AnyAction>, S extends AppState>({
dispatch,
getState
getState,
}: MiddlewareAPI<D, S>) => (next: Dispatch<AnyAction>) => <A extends AnyAction>(action: A): A => {
switch (action.type) {
case actions.FETCH_KERNELSPECS_FULFILLED: {
const payload = ((action as unknown) as actions.FetchKernelspecsFulfilled).payload;
const defaultKernelName = payload.defaultKernelName;
this.kernelSpecsForDisplay = Object.keys(payload.kernelspecs)
.map(name => ({
.map((name) => ({
name,
displayName: payload.kernelspecs[name].displayName
displayName: payload.kernelspecs[name].displayName,
}))
.sort((a: KernelSpecsDisplay, b: KernelSpecsDisplay) => {
// Put default at the top, otherwise lexicographically compare
@@ -229,7 +229,7 @@ export class NotebookClientV2 {
dataExplorerArea: Constants.Areas.Notebook,
title,
message,
level: "Error"
level: "Error",
});
console.error(`${title}: ${message}`);
};
@@ -248,16 +248,16 @@ export class NotebookClientV2 {
configOption("autoSaveInterval").action(params.autoSaveInterval ?? Constants.Notebook.autoSaveIntervalMs)
);
createConfigCollection({
key: "monaco"
key: "monaco",
});
defineConfigOption({
label: "Show Line numbers",
key: "monaco.lineNumbers",
values: [
{ label: "Yes", value: true },
{ label: "No", value: false }
{ label: "No", value: false },
],
defaultValue: true
defaultValue: true,
});
}
@@ -275,7 +275,7 @@ export class NotebookClientV2 {
dataExplorerArea: Constants.Areas.Notebook,
title: msg.title,
message: msg.message,
level: msg.level
level: msg.level,
});
console.error(`${msg.title}: ${msg.message}`);
} else {

View File

@@ -25,9 +25,9 @@ export class NotebookComponentAdapter extends NotebookComponentBootstrapper impl
constructor(options: NotebookComponentAdapterOptions) {
super({
contentRef: selectors.contentRefByFilepath(options.notebookClient.getStore().getState(), {
filepath: options.contentItem.path
filepath: options.contentItem.path,
}),
notebookClient: options.notebookClient
notebookClient: options.notebookClient,
});
this.onUpdateKernelInfo = options.onUpdateKernelInfo;
@@ -42,7 +42,7 @@ export class NotebookComponentAdapter extends NotebookComponentBootstrapper impl
filepath: options.contentItem.path,
params: {},
kernelRef,
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}

View File

@@ -13,7 +13,7 @@ import {
ContentRef,
KernelRef,
NotebookContentRecord,
selectors
selectors,
} from "@nteract/core";
import * as Immutable from "immutable";
import { Provider } from "react-redux";
@@ -58,7 +58,7 @@ export class NotebookComponentBootstrapper {
mimetype: null as any,
size: 0,
writeable: false,
type: "notebook"
type: "notebook",
};
}
@@ -72,9 +72,7 @@ export class NotebookComponentBootstrapper {
}
public getContent(): { name: string; content: string | ImmutableNotebook } {
const record = this.getStore()
.getState()
.core.entities.contents.byRef.get(this.contentRef);
const record = this.getStore().getState().core.entities.contents.byRef.get(this.contentRef);
let content: string | ImmutableNotebook;
switch (record.model.type) {
case "notebook":
@@ -89,7 +87,7 @@ export class NotebookComponentBootstrapper {
return {
name: NotebookUtil.getName(record.filepath),
content
content,
};
}
@@ -99,7 +97,7 @@ export class NotebookComponentBootstrapper {
filepath: undefined,
model: NotebookComponentBootstrapper.wrapModelIntoContent(name, undefined, content),
kernelRef: undefined,
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -126,7 +124,7 @@ export class NotebookComponentBootstrapper {
public notebookSave(): void {
this.getStore().dispatch(
actions.save({
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -136,7 +134,7 @@ export class NotebookComponentBootstrapper {
actions.changeKernelByName({
contentRef: this.contentRef,
kernelSpecName,
oldKernelRef: this.getCurrentKernelRef()
oldKernelRef: this.getCurrentKernelRef(),
})
);
}
@@ -144,7 +142,7 @@ export class NotebookComponentBootstrapper {
public notebookRunAndAdvance(): void {
this.getStore().dispatch(
CdbActions.executeFocusedCellAndFocusNext({
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -152,7 +150,7 @@ export class NotebookComponentBootstrapper {
public notebookRunAll(): void {
this.getStore().dispatch(
actions.executeAllCells({
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -160,7 +158,7 @@ export class NotebookComponentBootstrapper {
public notebookInterruptKernel(): void {
this.getStore().dispatch(
actions.interruptKernel({
kernelRef: this.getCurrentKernelRef()
kernelRef: this.getCurrentKernelRef(),
})
);
}
@@ -169,7 +167,7 @@ export class NotebookComponentBootstrapper {
this.getStore().dispatch(
actions.killKernel({
restarting: false,
kernelRef: this.getCurrentKernelRef()
kernelRef: this.getCurrentKernelRef(),
})
);
}
@@ -179,7 +177,7 @@ export class NotebookComponentBootstrapper {
actions.restartKernel({
kernelRef: this.getCurrentKernelRef(),
contentRef: this.contentRef,
outputHandling: "None"
outputHandling: "None",
})
);
}
@@ -187,7 +185,7 @@ export class NotebookComponentBootstrapper {
public notebookClearAllOutputs(): void {
this.getStore().dispatch(
actions.clearAllOutputs({
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -196,7 +194,7 @@ export class NotebookComponentBootstrapper {
this.getStore().dispatch(
actions.createCellBelow({
cellType: "code",
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -212,7 +210,7 @@ export class NotebookComponentBootstrapper {
actions.changeCellType({
id: focusedCellId,
contentRef: this.contentRef,
to: type
to: type,
})
);
}
@@ -227,7 +225,7 @@ export class NotebookComponentBootstrapper {
this.getStore().dispatch(
actions.copyCell({
id: focusedCellId,
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -242,7 +240,7 @@ export class NotebookComponentBootstrapper {
this.getStore().dispatch(
actions.cutCell({
id: focusedCellId,
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -250,7 +248,7 @@ export class NotebookComponentBootstrapper {
public notebookPaste(): void {
this.getStore().dispatch(
actions.pasteCell({
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}
@@ -263,14 +261,14 @@ export class NotebookComponentBootstrapper {
store.dispatch(
actions.killKernel({
restarting: false,
kernelRef
kernelRef,
})
);
}
store.dispatch(
CdbActions.closeNotebook({
contentRef: this.contentRef
contentRef: this.contentRef,
})
);
}

View File

@@ -1,69 +1,69 @@
import { ServerConfig, IContentProvider, FileType, IContent, IGetParams } from "@nteract/core";
import { Observable } from "rxjs";
import { AjaxResponse } from "rxjs/ajax";
import { GitHubContentProvider } from "../../../GitHub/GitHubContentProvider";
import * as GitHubUtils from "../../../Utils/GitHubUtils";
export class NotebookContentProvider implements IContentProvider {
constructor(private gitHubContentProvider: GitHubContentProvider, private jupyterContentProvider: IContentProvider) {}
public remove(serverConfig: ServerConfig, path: string): Observable<AjaxResponse> {
return this.getContentProvider(path).remove(serverConfig, path);
}
public get(serverConfig: ServerConfig, path: string, params: Partial<IGetParams>): Observable<AjaxResponse> {
return this.getContentProvider(path).get(serverConfig, path, params);
}
public update<FT extends FileType>(
serverConfig: ServerConfig,
path: string,
model: Partial<IContent<FT>>
): Observable<AjaxResponse> {
return this.getContentProvider(path).update(serverConfig, path, model);
}
public create<FT extends FileType>(
serverConfig: ServerConfig,
path: string,
model: Partial<IContent<FT>> & { type: FT }
): Observable<AjaxResponse> {
return this.getContentProvider(path).create(serverConfig, path, model);
}
public save<FT extends FileType>(
serverConfig: ServerConfig,
path: string,
model: Partial<IContent<FT>>
): Observable<AjaxResponse> {
return this.getContentProvider(path).save(serverConfig, path, model);
}
public listCheckpoints(serverConfig: ServerConfig, path: string): Observable<AjaxResponse> {
return this.getContentProvider(path).listCheckpoints(serverConfig, path);
}
public createCheckpoint(serverConfig: ServerConfig, path: string): Observable<AjaxResponse> {
return this.getContentProvider(path).createCheckpoint(serverConfig, path);
}
public deleteCheckpoint(serverConfig: ServerConfig, path: string, checkpointID: string): Observable<AjaxResponse> {
return this.getContentProvider(path).deleteCheckpoint(serverConfig, path, checkpointID);
}
public restoreFromCheckpoint(
serverConfig: ServerConfig,
path: string,
checkpointID: string
): Observable<AjaxResponse> {
return this.getContentProvider(path).restoreFromCheckpoint(serverConfig, path, checkpointID);
}
private getContentProvider(path: string): IContentProvider {
if (GitHubUtils.fromContentUri(path)) {
return this.gitHubContentProvider;
}
return this.jupyterContentProvider;
}
}
import { ServerConfig, IContentProvider, FileType, IContent, IGetParams } from "@nteract/core";
import { Observable } from "rxjs";
import { AjaxResponse } from "rxjs/ajax";
import { GitHubContentProvider } from "../../../GitHub/GitHubContentProvider";
import * as GitHubUtils from "../../../Utils/GitHubUtils";
export class NotebookContentProvider implements IContentProvider {
constructor(private gitHubContentProvider: GitHubContentProvider, private jupyterContentProvider: IContentProvider) {}
public remove(serverConfig: ServerConfig, path: string): Observable<AjaxResponse> {
return this.getContentProvider(path).remove(serverConfig, path);
}
public get(serverConfig: ServerConfig, path: string, params: Partial<IGetParams>): Observable<AjaxResponse> {
return this.getContentProvider(path).get(serverConfig, path, params);
}
public update<FT extends FileType>(
serverConfig: ServerConfig,
path: string,
model: Partial<IContent<FT>>
): Observable<AjaxResponse> {
return this.getContentProvider(path).update(serverConfig, path, model);
}
public create<FT extends FileType>(
serverConfig: ServerConfig,
path: string,
model: Partial<IContent<FT>> & { type: FT }
): Observable<AjaxResponse> {
return this.getContentProvider(path).create(serverConfig, path, model);
}
public save<FT extends FileType>(
serverConfig: ServerConfig,
path: string,
model: Partial<IContent<FT>>
): Observable<AjaxResponse> {
return this.getContentProvider(path).save(serverConfig, path, model);
}
public listCheckpoints(serverConfig: ServerConfig, path: string): Observable<AjaxResponse> {
return this.getContentProvider(path).listCheckpoints(serverConfig, path);
}
public createCheckpoint(serverConfig: ServerConfig, path: string): Observable<AjaxResponse> {
return this.getContentProvider(path).createCheckpoint(serverConfig, path);
}
public deleteCheckpoint(serverConfig: ServerConfig, path: string, checkpointID: string): Observable<AjaxResponse> {
return this.getContentProvider(path).deleteCheckpoint(serverConfig, path, checkpointID);
}
public restoreFromCheckpoint(
serverConfig: ServerConfig,
path: string,
checkpointID: string
): Observable<AjaxResponse> {
return this.getContentProvider(path).restoreFromCheckpoint(serverConfig, path, checkpointID);
}
private getContentProvider(path: string): IContentProvider {
if (GitHubUtils.fromContentUri(path)) {
return this.gitHubContentProvider;
}
return this.jupyterContentProvider;
}
}

View File

@@ -49,7 +49,7 @@ const makeMapStateToProps = (
return {
kernelStatus,
kernelSpecName,
currentCellType
currentCellType,
} as VirtualCommandBarComponentProps;
}
@@ -69,7 +69,7 @@ const makeMapStateToProps = (
kernelStatus,
kernelSpecName,
currentCellType,
onRender: initialProps.onRender
onRender: initialProps.onRender,
};
};

View File

@@ -8,12 +8,12 @@ let fakeAjaxResponse: AjaxResponse = {
status: 200,
response: {},
responseText: "",
responseType: "json"
responseType: "json",
};
export const sessions = {
create: (serverConfig: unknown, body: object): Observable<AjaxResponse> => of(fakeAjaxResponse),
__setResponse: (response: AjaxResponse) => {
fakeAjaxResponse = response;
},
createSpy: undefined as any
createSpy: undefined as any,
};

View File

@@ -13,7 +13,7 @@ export interface CloseNotebookAction {
export const closeNotebook = (payload: { contentRef: ContentRef }): CloseNotebookAction => {
return {
type: CLOSE_NOTEBOOK,
payload
payload,
};
};
@@ -30,7 +30,7 @@ export const executeFocusedCellAndFocusNext = (payload: {
}): ExecuteFocusedCellAndFocusNextAction => {
return {
type: EXECUTE_FOCUSED_CELL_AND_FOCUS_NEXT,
payload
payload,
};
};
@@ -45,7 +45,7 @@ export interface UpdateKernelRestartDelayAction {
export const UpdateKernelRestartDelay = (payload: { delayMs: number }): UpdateKernelRestartDelayAction => {
return {
type: UPDATE_KERNEL_RESTART_DELAY,
payload
payload,
};
};
@@ -60,7 +60,7 @@ export interface SetHoveredCellAction {
export const setHoveredCell = (payload: { cellId: CellId }): SetHoveredCellAction => {
return {
type: SET_HOVERED_CELL,
payload
payload,
};
};
@@ -81,7 +81,7 @@ export const traceNotebookTelemetry = (payload: {
}): TraceNotebookTelemetryAction => {
return {
type: TRACE_NOTEBOOK_TELEMETRY,
payload
payload,
};
};
@@ -100,6 +100,6 @@ export const UpdateNotebookParentDomElt = (payload: {
}): UpdateNotebookParentDomEltAction => {
return {
type: UPDATE_NOTEBOOK_PARENT_DOM_ELTS,
payload
payload,
};
};

View File

@@ -85,7 +85,7 @@ const makeMapStateToProps = (initialState: AppState, initialProps: InitialProps)
return {
contentRef,
mimetype: content.mimetype,
type: content.type
type: content.type,
};
};

View File

@@ -45,7 +45,7 @@ export class TextFile extends React.PureComponent<TextFileProps, TextFileState>
constructor(props: TextFileProps) {
super(props);
this.state = {
Editor: EditorPlaceholder
Editor: EditorPlaceholder,
};
}
@@ -54,7 +54,7 @@ export class TextFile extends React.PureComponent<TextFileProps, TextFileState>
};
componentDidMount(): void {
import(/* webpackChunkName: "monaco-editor" */ "@nteract/monaco-editor").then(module => {
import(/* webpackChunkName: "monaco-editor" */ "@nteract/monaco-editor").then((module) => {
this.setState({ Editor: module.default });
});
}
@@ -99,7 +99,7 @@ function makeMapStateToTextFileProps(
return {
contentRef,
mimetype: content.mimetype != null ? content.mimetype : "text/plain",
text
text,
};
};
return mapStateToTextFileProps;
@@ -117,10 +117,10 @@ const makeMapDispatchToTextFileProps = (
dispatch(
actions.updateFileText({
contentRef,
text: source
text: source,
})
);
}
},
};
};
return mapDispatchToTextFileProps;

View File

@@ -10,7 +10,7 @@ import {
DirectoryContentRecordProps,
DummyContentRecordProps,
FileContentRecordProps,
NotebookContentRecordProps
NotebookContentRecordProps,
} from "@nteract/core";
import { RecordOf } from "immutable";
import * as React from "react";
@@ -51,7 +51,7 @@ class Contents extends React.PureComponent<ContentsProps> {
OPEN: ["ctrl+o", "meta+o"],
PASTE_CELL: ["ctrl+shift+v"],
RESTART_KERNEL: ["alt+r r", "alt+r c", "alt+r a"],
SAVE: ["ctrl+s", "ctrl+shift+s", "meta+s", "meta+shift+s"]
SAVE: ["ctrl+s", "ctrl+shift+s", "meta+s", "meta+shift+s"],
};
render(): JSX.Element {
@@ -96,7 +96,7 @@ const makeMapStateToProps: any = (initialState: AppState, initialProps: { conten
return {
contentRef: undefined,
error: undefined,
headerData: undefined
headerData: undefined,
};
}
@@ -104,7 +104,7 @@ const makeMapStateToProps: any = (initialState: AppState, initialProps: { conten
authors: [],
description: "",
tags: [],
title: ""
title: "",
};
// If a notebook, we need to read in the headerData if available
@@ -118,14 +118,14 @@ const makeMapStateToProps: any = (initialState: AppState, initialProps: { conten
authors,
description,
tags,
title
title,
});
}
return {
contentRef,
error: content.error,
headerData
headerData,
};
};
@@ -140,7 +140,7 @@ const mapDispatchToProps = (dispatch: Dispatch, ownProps: ContentsProps): object
return dispatch(
actions.overwriteMetadataFields({
...props,
contentRef: ownProps.contentRef
contentRef: ownProps.contentRef,
})
);
},
@@ -165,8 +165,8 @@ const mapDispatchToProps = (dispatch: Dispatch, ownProps: ContentsProps): object
event.key === "r" ? "None" : event.key === "a" ? "Run All" : "Clear All";
return dispatch(actions.restartKernel({ outputHandling, contentRef }));
},
SAVE: () => dispatch(actions.save({ contentRef }))
}
SAVE: () => dispatch(actions.save({ contentRef })),
},
};
};

View File

@@ -19,7 +19,7 @@ describe("Extract kernel from notebook", () => {
kernelspec: {
display_name: "Python 3",
language: "python",
name: "python3"
name: "python3",
},
language_info: {
name: "python",
@@ -27,13 +27,13 @@ describe("Extract kernel from notebook", () => {
mimetype: "text/x-python",
codemirror_mode: {
name: "ipython",
version: 3
version: 3,
},
pygments_lexer: "ipython3",
nbconvert_exporter: "python",
file_extension: ".py"
}
})
file_extension: ".py",
},
}),
});
const result = NotebookUtil.extractNewKernel("blah", fakeNotebook);
@@ -49,13 +49,13 @@ describe("Extract kernel from notebook", () => {
mimetype: "text/x-python",
codemirror_mode: {
name: "ipython",
version: 3
version: 3,
},
pygments_lexer: "ipython3",
nbconvert_exporter: "python",
file_extension: ".py"
}
})
file_extension: ".py",
},
}),
});
const result = NotebookUtil.extractNewKernel("blah", fakeNotebook);
@@ -65,8 +65,8 @@ describe("Extract kernel from notebook", () => {
it("Returns nothing if no kernelspec nor language info is found in metadata", () => {
const fakeNotebook = makeNotebookRecord({
metadata: Immutable.Map({
blah: "this should be ignored"
})
blah: "this should be ignored",
}),
});
const result = NotebookUtil.extractNewKernel("blah", fakeNotebook);
@@ -79,8 +79,8 @@ const initialState = {
host: state.makeJupyterHostRecord({
type: "jupyter",
token: "eh",
basePath: "/"
})
basePath: "/",
}),
}),
comms: state.makeCommsRecord(),
config: Immutable.Map({}),
@@ -89,8 +89,8 @@ const initialState = {
entities: state.makeEntitiesRecord({
contents: state.makeContentsRecord({
byRef: Immutable.Map({
fakeContentRef: state.makeNotebookContentRecord()
})
fakeContentRef: state.makeNotebookContentRecord(),
}),
}),
kernels: state.makeKernelsRecord({
byRef: Immutable.Map({
@@ -98,16 +98,16 @@ const initialState = {
type: "websocket",
channels: new Subject<any>(),
kernelSpecName: "fancy",
id: "0"
})
})
})
})
id: "0",
}),
}),
}),
}),
}),
cdb: makeCdbRecord({
databaseAccountName: "dbAccountName",
defaultExperience: "defaultExperience"
})
defaultExperience: "defaultExperience",
}),
};
describe("launchWebSocketKernelEpic", () => {
@@ -130,7 +130,7 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName,
cwd,
selectNextKernel: true
selectNextKernel: true,
})
);
@@ -149,20 +149,18 @@ describe("launchWebSocketKernelEpic", () => {
name: "kernel_launched",
last_activity: "2019-11-07T14:29:54.432454Z",
execution_state: "starting",
connections: 0
connections: 0,
},
notebook: {
path: "notebooks/Untitled7.ipynb",
name: ""
}
name: "",
},
},
responseText: null,
responseType: "json"
responseType: "json",
});
const responseActions = await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
const responseActions = await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(responseActions).toMatchObject([
{
@@ -177,10 +175,10 @@ describe("launchWebSocketKernelEpic", () => {
type: "websocket",
kernelSpecName,
cwd,
id: kernelId
}
}
}
id: kernelId,
},
},
},
]);
});
@@ -198,7 +196,7 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName,
cwd,
selectNextKernel: true
selectNextKernel: true,
})
);
@@ -217,25 +215,23 @@ describe("launchWebSocketKernelEpic", () => {
name: "kernel_launched",
last_activity: "2019-11-07T14:29:54.432454Z",
execution_state: "starting",
connections: 0
connections: 0,
},
notebook: {
path: "notebooks/Untitled7.ipynb",
name: ""
}
name: "",
},
},
responseText: null,
responseType: "json"
responseType: "json",
});
await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(createSpy.lastCall.args[1]).toMatchObject({
kernel: {
name: kernelSpecName
}
name: kernelSpecName,
},
});
});
@@ -253,7 +249,7 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName: undefined,
cwd,
selectNextKernel: true
selectNextKernel: true,
})
);
@@ -272,25 +268,23 @@ describe("launchWebSocketKernelEpic", () => {
name: "kernel_launched",
last_activity: "2019-11-07T14:29:54.432454Z",
execution_state: "starting",
connections: 0
connections: 0,
},
notebook: {
path: "notebooks/Untitled7.ipynb",
name: ""
}
name: "",
},
},
responseText: null,
responseType: "json"
responseType: "json",
});
const responseActions = await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
const responseActions = await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(responseActions).toMatchObject([
{
type: actions.LAUNCH_KERNEL_FAILED
}
type: actions.LAUNCH_KERNEL_FAILED,
},
]);
});
@@ -304,7 +298,7 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName: undefined,
cwd,
selectNextKernel: true
selectNextKernel: true,
})
);
@@ -315,17 +309,15 @@ describe("launchWebSocketKernelEpic", () => {
status: 500,
response: null,
responseText: null,
responseType: "json"
responseType: "json",
});
const responseActions = await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
const responseActions = await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(responseActions).toMatchObject([
{
type: actions.LAUNCH_KERNEL_FAILED
}
type: actions.LAUNCH_KERNEL_FAILED,
},
]);
});
@@ -346,7 +338,7 @@ describe("launchWebSocketKernelEpic", () => {
language: "language1",
displayName: "Kernel One",
metadata: Immutable.Map(),
resources: Immutable.Map()
resources: Immutable.Map(),
}),
kernel2: state.makeKernelspec({
name: "kernel2",
@@ -356,12 +348,12 @@ describe("launchWebSocketKernelEpic", () => {
language: "language2",
displayName: "Kernel Two",
metadata: Immutable.Map(),
resources: Immutable.Map()
})
})
})
resources: Immutable.Map(),
}),
}),
}),
}),
refs: Immutable.List(["kernelspecsref"])
refs: Immutable.List(["kernelspecsref"]),
});
initialState.core = initialState.core
.setIn(["entities", "kernelspecs"], createKernelSpecsRecord())
@@ -383,15 +375,15 @@ describe("launchWebSocketKernelEpic", () => {
name: "kernel_launched",
last_activity: "2019-11-07T14:29:54.432454Z",
execution_state: "starting",
connections: 0
connections: 0,
},
notebook: {
path: "notebooks/Untitled7.ipynb",
name: ""
}
name: "",
},
},
responseText: null,
responseType: "json"
responseType: "json",
});
});
@@ -404,17 +396,15 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName: "kernel2",
cwd: "cwd",
selectNextKernel: true
selectNextKernel: true,
})
);
await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(createSpy.lastCall.args[1]).toMatchObject({
kernel: {
name: "kernel2"
}
name: "kernel2",
},
});
});
@@ -427,18 +417,16 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName: undefined,
cwd: "cwd",
selectNextKernel: true
selectNextKernel: true,
})
);
await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(createSpy.lastCall.args[1]).toMatchObject({
kernel: {
name: "kernel2"
}
name: "kernel2",
},
});
});
@@ -451,18 +439,16 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName: "This is an unknown kernelspec",
cwd: "cwd",
selectNextKernel: true
selectNextKernel: true,
})
);
await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(createSpy.lastCall.args[1]).toMatchObject({
kernel: {
name: "kernel2"
}
name: "kernel2",
},
});
});
@@ -475,18 +461,16 @@ describe("launchWebSocketKernelEpic", () => {
kernelRef,
kernelSpecName: "ernel1",
cwd: "cwd",
selectNextKernel: true
selectNextKernel: true,
})
);
await launchWebSocketKernelEpic(action$, state$)
.pipe(toArray())
.toPromise();
await launchWebSocketKernelEpic(action$, state$).pipe(toArray()).toPromise();
expect(createSpy.lastCall.args[1]).toMatchObject({
kernel: {
name: "kernel1"
}
name: "kernel1",
},
});
});
});

View File

@@ -14,7 +14,7 @@ import {
catchError,
first,
concatMap,
timeout
timeout,
} from "rxjs/operators";
import {
AppState,
@@ -27,7 +27,7 @@ import {
ContentRef,
KernelInfo,
actions,
selectors
selectors,
} from "@nteract/core";
import { message, JupyterMessage, Channels, createMessage, childOf, ofMessageType } from "@nteract/messaging";
import { sessions, kernels } from "rx-jupyter";
@@ -58,7 +58,7 @@ const logFailureToTelemetry = (state: CdbAppState, title: string, error?: string
defaultExperience: state.cdb.defaultExperience,
dataExplorerArea: Constants.Areas.Notebook,
title,
error
error,
});
};
@@ -73,7 +73,7 @@ const addInitialCodeCellEpic = (
): Observable<{} | actions.CreateCellBelow> => {
return action$.pipe(
ofType(actions.FETCH_CONTENT_FULFILLED),
mergeMap(action => {
mergeMap((action) => {
const state = state$.value;
const contentRef = action.payload.contentRef;
const model = selectors.model(state, { contentRef });
@@ -88,7 +88,7 @@ const addInitialCodeCellEpic = (
return of(
actions.createCellAppend({
cellType: "code",
contentRef
contentRef,
})
);
}
@@ -135,8 +135,8 @@ export const acquireKernelInfoEpic = (action$: Observable<actions.NewKernelActio
payload: {
kernel: { channels },
kernelRef,
contentRef
}
contentRef,
},
} = action;
return acquireKernelInfo(channels, kernelRef, contentRef);
})
@@ -153,7 +153,7 @@ function acquireKernelInfo(channels: Channels, kernelRef: KernelRef, contentRef:
childOf(message),
ofMessageType("kernel_info_reply"),
first(),
mergeMap(msg => {
mergeMap((msg) => {
const content = msg.content;
const languageInfo = (content && content.language_info) || {
name: "",
@@ -162,7 +162,7 @@ function acquireKernelInfo(channels: Channels, kernelRef: KernelRef, contentRef:
file_extension: "",
pygments_lexer: "",
codemirror_mode: "",
nbconvert_exporter: ""
nbconvert_exporter: "",
};
switch (languageInfo.name) {
@@ -186,7 +186,7 @@ function acquireKernelInfo(channels: Channels, kernelRef: KernelRef, contentRef:
fileExtension: languageInfo.file_extension,
pygmentsLexer: languageInfo.pygments_lexer,
codemirrorMode: languageInfo.codemirror_mode,
nbconvertExporter: languageInfo.nbconvert_exporter
nbconvertExporter: languageInfo.nbconvert_exporter,
};
let result;
@@ -197,8 +197,8 @@ function acquireKernelInfo(channels: Channels, kernelRef: KernelRef, contentRef:
contentRef,
error: new Error(
"The kernel that you are attempting to launch does not support the latest version (v5) of the messaging protocol."
)
})
),
}),
];
} else {
result = [
@@ -206,12 +206,12 @@ function acquireKernelInfo(channels: Channels, kernelRef: KernelRef, contentRef:
actions.setLanguageInfo({
langInfo: msg.content.language_info,
kernelRef,
contentRef
contentRef,
}),
actions.setKernelInfo({
kernelRef,
info
})
info,
}),
];
}
@@ -236,7 +236,7 @@ function acquireKernelInfo(channels: Channels, kernelRef: KernelRef, contentRef:
const connect = (serverConfig: NotebookServiceConfig, kernelID: string, sessionID?: string): Subject<any> => {
const wsSubject = webSocket<JupyterMessage>({
url: formWebSocketURL(serverConfig, kernelID, sessionID),
protocol: serverConfig.wsProtocol
protocol: serverConfig.wsProtocol,
});
// Create a subject that does some of the handling inline for the session
@@ -249,8 +249,8 @@ const connect = (serverConfig: NotebookServiceConfig, kernelID: string, sessionI
...message,
header: {
session: sessionID,
...message.header
}
...message.header,
},
};
wsSubject.next(sessionizedMessage);
@@ -297,7 +297,7 @@ export const launchWebSocketKernelEpic = (
serverConfig.userPuid = getUserPuid();
const {
payload: { kernelSpecName, cwd, kernelRef, contentRef }
payload: { kernelSpecName, cwd, kernelRef, contentRef },
} = action;
const content = selectors.content(state, { contentRef });
@@ -321,7 +321,7 @@ export const launchWebSocketKernelEpic = (
error: new Error(
"Unable to launch kernel: no kernelspec name specified to launch and no default kernelspecs"
),
contentRef
contentRef,
})
);
}
@@ -330,7 +330,7 @@ export const launchWebSocketKernelEpic = (
// Find a kernel that best matches the kernel name
const match = currentKernelspecs.byName.find(
value => value.name.toLowerCase().indexOf(kernelSpecName.toLowerCase()) !== -1
(value) => value.name.toLowerCase().indexOf(kernelSpecName.toLowerCase()) !== -1
);
if (match) {
kernelSpecToLaunch = match.name;
@@ -346,15 +346,15 @@ export const launchWebSocketKernelEpic = (
const sessionPayload = {
kernel: {
id: null,
name: kernelSpecToLaunch
name: kernelSpecToLaunch,
} as any,
name: "",
path: content.filepath.replace(/^\/+/g, ""),
type: "notebook"
type: "notebook",
};
return sessions.create(serverConfig, sessionPayload).pipe(
mergeMap(data => {
mergeMap((data) => {
const session = data.response;
const sessionId = castToSessionId(session.id);
@@ -365,7 +365,7 @@ export const launchWebSocketKernelEpic = (
sessionId,
cwd,
channels: connect(serverConfig, session.kernel.id, sessionId),
kernelSpecName: kernelSpecToLaunch
kernelSpecName: kernelSpecToLaunch,
});
kernel.channels.next(message({ msg_type: "kernel_info_request" }));
@@ -375,11 +375,11 @@ export const launchWebSocketKernelEpic = (
kernel,
kernelRef,
contentRef: action.payload.contentRef,
selectNextKernel: true
selectNextKernel: true,
})
);
}),
catchError(error => {
catchError((error) => {
return of(actions.launchKernelFailed({ error }));
})
);
@@ -411,7 +411,7 @@ export const restartWebSocketKernelEpic = (
actions.restartKernelFailed({
error: new Error("Can't execute restart without kernel ref."),
kernelRef: "none provided",
contentRef
contentRef,
})
);
}
@@ -422,7 +422,7 @@ export const restartWebSocketKernelEpic = (
actions.restartKernelFailed({
error: new Error("Can't restart a kernel with no Jupyter host."),
kernelRef,
contentRef
contentRef,
})
);
}
@@ -433,7 +433,7 @@ export const restartWebSocketKernelEpic = (
actions.restartKernelFailed({
error: new Error("Can't restart a kernel that does not exist."),
kernelRef,
contentRef
contentRef,
})
);
}
@@ -443,7 +443,7 @@ export const restartWebSocketKernelEpic = (
actions.restartKernelFailed({
error: new Error("Can only restart Websocket kernels via API."),
kernelRef,
contentRef
contentRef,
})
);
}
@@ -451,7 +451,7 @@ export const restartWebSocketKernelEpic = (
const newKernelRef = createKernelRef();
const kill = actions.killKernel({
restarting: true,
kernelRef
kernelRef,
});
const relaunch = actions.launchKernelByName({
@@ -459,7 +459,7 @@ export const restartWebSocketKernelEpic = (
cwd: kernel.cwd,
kernelRef: newKernelRef,
selectNextKernel: true,
contentRef: contentRef
contentRef: contentRef,
});
const awaitKernelReady = action$.pipe(
@@ -470,7 +470,7 @@ export const restartWebSocketKernelEpic = (
concatMap(() => {
const restartSuccess = actions.restartKernelSuccessful({
kernelRef: newKernelRef,
contentRef
contentRef,
});
if ((action as actions.RestartKernel).payload.outputHandling === "Run All") {
@@ -479,12 +479,12 @@ export const restartWebSocketKernelEpic = (
return of(restartSuccess);
}
}),
catchError(error => {
catchError((error) => {
return of(
actions.restartKernelFailed({
error,
kernelRef: newKernelRef,
contentRef
contentRef,
})
);
})
@@ -511,7 +511,7 @@ const changeWebSocketKernelEpic = (
filter(() => selectors.isCurrentHostJupyter(state$.value)),
switchMap((action: actions.ChangeKernelByName) => {
const {
payload: { contentRef, oldKernelRef, kernelSpecName }
payload: { contentRef, oldKernelRef, kernelSpecName },
} = action;
const state = state$.value;
const host = selectors.currentHost(state);
@@ -539,7 +539,7 @@ const changeWebSocketKernelEpic = (
}
const {
filepath,
model: { notebook }
model: { notebook },
} = content;
const { cwd } = NotebookUtil.extractNewKernel(filepath, notebook);
@@ -548,7 +548,7 @@ const changeWebSocketKernelEpic = (
mergeMap(({ response }) => {
const { id: kernelId } = response;
const sessionPayload = {
kernel: { id: kernelId, name: kernelSpecName }
kernel: { id: kernelId, name: kernelSpecName },
};
// The sessions API will close down the old kernel for us if it is on this session
return sessions.update(serverConfig, sessionId, sessionPayload).pipe(
@@ -558,21 +558,21 @@ const changeWebSocketKernelEpic = (
sessionId,
cwd,
channels: connect(serverConfig, session.kernel.id, sessionId),
kernelSpecName
kernelSpecName,
});
return of(
actions.launchKernelSuccessful({
kernel,
kernelRef,
contentRef: action.payload.contentRef,
selectNextKernel: true
selectNextKernel: true,
})
);
}),
catchError(error => of(actions.launchKernelFailed({ error, kernelRef, contentRef })))
catchError((error) => of(actions.launchKernelFailed({ error, kernelRef, contentRef })))
);
}),
catchError(error => of(actions.launchKernelFailed({ error, kernelRef, contentRef })))
catchError((error) => of(actions.launchKernelFailed({ error, kernelRef, contentRef })))
);
})
);
@@ -589,7 +589,7 @@ const focusInitialCodeCellEpic = (
): Observable<{} | actions.FocusCell> => {
return action$.pipe(
ofType(actions.CREATE_CELL_APPEND),
mergeMap(action => {
mergeMap((action) => {
const state = state$.value;
const contentRef = action.payload.contentRef;
const model = selectors.model(state, { contentRef });
@@ -606,7 +606,7 @@ const focusInitialCodeCellEpic = (
return of(
actions.focusCell({
id,
contentRef
contentRef,
})
);
}
@@ -631,7 +631,7 @@ const notificationsToUserEpic = (action$: Observable<any>, state$: StateObservab
actions.SAVE_FAILED,
actions.FETCH_CONTENT_FAILED
),
mergeMap(action => {
mergeMap((action) => {
switch (action.type) {
case actions.RESTART_KERNEL_SUCCESSFUL: {
const title = "Kernel restart";
@@ -677,7 +677,7 @@ const handleKernelConnectionLostEpic = (
): Observable<CdbActions.UpdateKernelRestartDelayAction | actions.RestartKernel | {}> => {
return action$.pipe(
ofType(actions.UPDATE_DISPLAY_FAILED),
mergeMap(action => {
mergeMap((action) => {
const state = state$.value;
const msg = "Notebook was disconnected from kernel";
@@ -708,14 +708,14 @@ const handleKernelConnectionLostEpic = (
of(CdbActions.UpdateKernelRestartDelay({ delayMs: delayMs * 1.5 })),
sessions.list(serverConfig).pipe(
delayWhen(() => timer(delayMs)),
map(xhr => {
map((xhr) => {
return actions.restartKernel({
outputHandling: "None",
kernelRef,
contentRef
contentRef,
});
}),
retryWhen(errors => {
retryWhen((errors) => {
return errors.pipe(
delayWhen(() => timer(Constants.Notebook.heartbeatDelayMs)),
tap(() => console.log("retrying...")) // TODO: Send new action?
@@ -738,12 +738,12 @@ export const cleanKernelOnConnectionLostEpic = (
): Observable<actions.KillKernelSuccessful> => {
return action$.pipe(
ofType(actions.UPDATE_DISPLAY_FAILED),
switchMap(action => {
switchMap((action) => {
const contentRef = action.payload.contentRef;
const kernelRef = selectors.kernelRefByContentRef(state$.value, { contentRef });
return of(
actions.killKernelSuccessful({
kernelRef
kernelRef,
})
);
})
@@ -761,7 +761,7 @@ const executeFocusedCellAndFocusNextEpic = (
): Observable<{} | actions.FocusNextCellEditor> => {
return action$.pipe(
ofType(CdbActions.EXECUTE_FOCUSED_CELL_AND_FOCUS_NEXT),
mergeMap(action => {
mergeMap((action) => {
const contentRef = action.payload.contentRef;
return concat(
of(actions.executeFocusedCell({ contentRef })),
@@ -801,7 +801,7 @@ const closeUnsupportedMimetypesEpic = (
): Observable<{}> => {
return action$.pipe(
ofType(actions.FETCH_CONTENT_FULFILLED),
mergeMap(action => {
mergeMap((action) => {
const mimetype = action.payload.model.mimetype;
const explorer = window.dataExplorer;
if (explorer && !TextFile.handles(mimetype)) {
@@ -830,7 +830,7 @@ const closeContentFailedToFetchEpic = (
): Observable<{}> => {
return action$.pipe(
ofType(actions.FETCH_CONTENT_FAILED),
mergeMap(action => {
mergeMap((action) => {
const explorer = window.dataExplorer;
if (explorer) {
const filepath = action.payload.filepath;
@@ -860,7 +860,7 @@ const traceNotebookTelemetryEpic = (
...action.payload.data,
databaseAccountName: state.cdb.databaseAccountName,
defaultExperience: state.cdb.defaultExperience,
dataExplorerArea: Areas.Notebook
dataExplorerArea: Areas.Notebook,
});
return EMPTY;
})
@@ -893,7 +893,7 @@ const traceNotebookInfoEpic = (
nbCodeCells: 0,
nbRawCells: 0,
nbMarkdownCells: 0,
nbCells: 0
nbCells: 0,
};
for (let [id, cell] of selectors.notebook.cellMap(model)) {
switch (cell.cell_type) {
@@ -914,7 +914,7 @@ const traceNotebookInfoEpic = (
cdbActions.traceNotebookTelemetry({
action: TelemetryAction.NotebooksFetched,
actionModifier: ActionModifiers.Mark,
data: dataToLog
data: dataToLog,
})
);
})
@@ -938,8 +938,8 @@ const traceNotebookKernelEpic = (
action: TelemetryAction.NotebooksKernelSpecName,
actionModifier: ActionModifiers.Mark,
data: {
kernelSpecName: action.payload.kernel.name
}
kernelSpecName: action.payload.kernel.name,
},
})
);
})
@@ -961,5 +961,5 @@ export const allEpics = [
restartWebSocketKernelEpic,
traceNotebookTelemetryEpic,
traceNotebookInfoEpic,
traceNotebookKernelEpic
traceNotebookKernelEpic,
];

View File

@@ -2,24 +2,24 @@
// https://github.com/nteract/nteract/blob/master/applications/jupyter-extension/nteract_on_jupyter/app/contents/notebook.tsx
export default (props: { addTransform: (component: any) => void }) => {
import(/* webpackChunkName: "plotly" */ "@nteract/transform-plotly").then(module => {
import(/* webpackChunkName: "plotly" */ "@nteract/transform-plotly").then((module) => {
props.addTransform(module.default);
props.addTransform(module.PlotlyNullTransform);
});
import(/* webpackChunkName: "tabular-dataresource" */ "@nteract/data-explorer").then(module => {
import(/* webpackChunkName: "tabular-dataresource" */ "@nteract/data-explorer").then((module) => {
props.addTransform(module.default);
});
import(/* webpackChunkName: "jupyter-widgets" */ "@nteract/jupyter-widgets").then(module => {
import(/* webpackChunkName: "jupyter-widgets" */ "@nteract/jupyter-widgets").then((module) => {
props.addTransform(module.WidgetDisplay);
});
import("@nteract/transform-model-debug").then(module => {
import("@nteract/transform-model-debug").then((module) => {
props.addTransform(module.default);
});
import(/* webpackChunkName: "vega-transform" */ "@nteract/transform-vega").then(module => {
import(/* webpackChunkName: "vega-transform" */ "@nteract/transform-vega").then((module) => {
props.addTransform(module.VegaLite1);
props.addTransform(module.VegaLite2);
props.addTransform(module.VegaLite3);

View File

@@ -41,7 +41,7 @@ export const coreReducer = (state: CoreRecord, action: Action) => {
"model",
"notebook",
"metadata",
"kernelspec"
"kernelspec",
];
// Update metadata
return state

View File

@@ -23,7 +23,7 @@ export default function configureStore(
*/
const catchErrorMiddleware: Middleware = <D extends Dispatch<AnyAction>, S extends AppState>({
dispatch,
getState
getState,
}: MiddlewareAPI<D, S>) => (next: Dispatch<AnyAction>) => <A extends AnyAction>(action: A): any => {
try {
next(action);
@@ -52,7 +52,7 @@ export default function configureStore(
};
const protectEpics = (epics: Epic[]): Epic[] => {
return epics.map(epic => protect(epic));
return epics.map((epic) => protect(epic));
};
const filteredCoreEpics = getCoreEpics(autoStartKernelOnNotebookOpen);
@@ -62,12 +62,12 @@ export default function configureStore(
reducers: {
app: reducers.app,
core: coreReducer as any,
cdb: cdbReducer
cdb: cdbReducer,
},
epics: protectEpics([...filteredCoreEpics, ...allEpics]),
epicDependencies: { contentProvider },
epicMiddleware: customMiddlewares.concat(catchErrorMiddleware),
enhancer: composeEnhancers
enhancer: composeEnhancers,
});
const store = mythConfigureStore(initialState as any);
@@ -100,7 +100,7 @@ export const getCoreEpics = (autoStartKernelOnNotebookOpen: boolean): Epic[] =>
coreEpics.saveContentEpic,
coreEpics.publishToBookstore,
coreEpics.publishToBookstoreAfterSave,
coreEpics.sendInputReplyEpic
coreEpics.sendInputReplyEpic,
];
if (autoStartKernelOnNotebookOpen) {

View File

@@ -23,5 +23,5 @@ export const makeCdbRecord = Immutable.Record<CdbRecordProps>({
defaultExperience: undefined,
kernelRestartDelayMs: Notebook.kernelRestartInitialDelayMs,
hoveredCellId: undefined,
currentNotebookParentElements: new Map<ContentRef, HTMLElement>()
currentNotebookParentElements: new Map<ContentRef, HTMLElement>(),
});

View File

@@ -35,7 +35,7 @@ export class NotebookContainerClient {
private scheduleHeartbeat(delayMs: number): void {
setTimeout(() => {
this.getMemoryUsage()
.then(memoryUsageInfo => this.onMemoryUsageInfoUpdate(memoryUsageInfo))
.then((memoryUsageInfo) => this.onMemoryUsageInfoUpdate(memoryUsageInfo))
.finally(() => this.scheduleHeartbeat(Constants.Notebook.heartbeatDelayMs));
}, delayMs);
}
@@ -57,8 +57,8 @@ export class NotebookContainerClient {
method: "GET",
headers: {
Authorization: authToken,
"content-type": "application/json"
}
"content-type": "application/json",
},
});
if (response.ok) {
if (this.reconnectingNotificationId) {
@@ -69,7 +69,7 @@ export class NotebookContainerClient {
if (memoryUsageInfo) {
return {
totalKB: memoryUsageInfo.total,
freeKB: memoryUsageInfo.free
freeKB: memoryUsageInfo.free,
};
}
}
@@ -108,7 +108,7 @@ export class NotebookContainerClient {
try {
await fetch(`${notebookServerEndpoint}/api/shutdown`, {
method: "POST",
headers: { Authorization: authToken }
headers: { Authorization: authToken },
});
} catch (error) {
Logger.logError(getErrorMessage(error), "NotebookContainerClient/resetWorkspace");
@@ -126,7 +126,7 @@ export class NotebookContainerClient {
return {
notebookServerEndpoint,
authToken
authToken,
};
}

View File

@@ -20,9 +20,9 @@ export class NotebookContentClient {
* @param item
*/
public updateItemChildren(item: NotebookContentItem): Promise<void> {
return this.fetchNotebookFiles(item.path).then(subItems => {
return this.fetchNotebookFiles(item.path).then((subItems) => {
item.children = subItems;
subItems.forEach(subItem => (subItem.parent = item));
subItems.forEach((subItem) => (subItem.parent = item));
});
}
@@ -68,7 +68,7 @@ export class NotebookContentClient {
if (item.parent && item.parent.children) {
// Remove deleted child
const newChildren = item.parent.children.filter(child => child.path !== path);
const newChildren = item.parent.children.filter((child) => child.path !== path);
item.parent.children = newChildren;
}
});
@@ -98,7 +98,7 @@ export class NotebookContentClient {
content,
format: "text",
name,
type: "file"
type: "file",
};
return this.contentProvider
@@ -119,7 +119,7 @@ export class NotebookContentClient {
const parentDirPath = NotebookUtil.getParentPath(filepath);
if (parentDirPath) {
const items = await this.fetchNotebookFiles(parentDirPath);
return items.some(value => FileSystemUtil.isPathEqual(value.path, filepath));
return items.some((value) => FileSystemUtil.isPathEqual(value.path, filepath));
}
return false;
}
@@ -142,7 +142,7 @@ export class NotebookContentClient {
return this.contentProvider
.update<"file" | "notebook" | "directory">(this.getServerConfig(), sourcePath, { path: targetPath })
.toPromise()
.then(xhr => {
.then((xhr) => {
if (typeof xhr.response === "string") {
throw new Error(`jupyter server response invalid: ${xhr.response}`);
}
@@ -244,10 +244,10 @@ export class NotebookContentClient {
private fetchNotebookFiles(path: string): Promise<NotebookContentItem[]> {
return this.contentProvider
.get(this.getServerConfig(), path, {
type: "directory"
type: "directory",
})
.toPromise()
.then(xhr => {
.then((xhr) => {
if (xhr.status !== 200) {
throw new Error(JSON.stringify(xhr.response));
}
@@ -265,7 +265,7 @@ export class NotebookContentClient {
(item: IEmptyContent<FileType>): NotebookContentItem => ({
name: item.name,
path: item.path,
type: NotebookUtil.getType(item.type)
type: NotebookUtil.getType(item.type),
})
);
});
@@ -275,7 +275,7 @@ export class NotebookContentClient {
return {
endpoint: this.notebookServerInfo().notebookServerEndpoint,
token: this.notebookServerInfo().authToken,
crossDomain: true
crossDomain: true,
};
}
}

View File

@@ -10,5 +10,5 @@ export interface NotebookContentItem {
export enum NotebookContentItemType {
Notebook,
File,
Directory
Directory,
}

View File

@@ -1,194 +1,194 @@
/*
* Contains all notebook related stuff meant to be dynamically loaded by explorer
*/
import { JunoClient } from "../../Juno/JunoClient";
import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService";
import { GitHubClient } from "../../GitHub/GitHubClient";
import * as Logger from "../../Common/Logger";
import { HttpStatusCodes, Areas } from "../../Common/Constants";
import { GitHubReposPane } from "../Panes/GitHubReposPane";
import ko from "knockout";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { IContentProvider } from "@nteract/core";
import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider";
import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider";
import { contents } from "rx-jupyter";
import { NotebookContainerClient } from "./NotebookContainerClient";
import { MemoryUsageInfo } from "../../Contracts/DataModels";
import { NotebookContentClient } from "./NotebookContentClient";
import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent";
import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter";
import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter";
import { getFullName } from "../../Utils/UserUtils";
import { ImmutableNotebook } from "@nteract/commutable";
import Explorer from "../Explorer";
import { ContextualPaneBase } from "../Panes/ContextualPaneBase";
import { CopyNotebookPaneAdapter } from "../Panes/CopyNotebookPane";
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
export interface NotebookManagerOptions {
container: Explorer;
notebookBasePath: ko.Observable<string>;
dialogProps: ko.Observable<DialogProps>;
resourceTree: ResourceTreeAdapter;
refreshCommandBarButtons: () => void;
refreshNotebookList: () => void;
}
export default class NotebookManager {
private params: NotebookManagerOptions;
public junoClient: JunoClient;
public notebookContentProvider: IContentProvider;
public notebookClient: NotebookContainerClient;
public notebookContentClient: NotebookContentClient;
private gitHubContentProvider: GitHubContentProvider;
public gitHubOAuthService: GitHubOAuthService;
private gitHubClient: GitHubClient;
public gitHubReposPane: ContextualPaneBase;
public publishNotebookPaneAdapter: PublishNotebookPaneAdapter;
public copyNotebookPaneAdapter: CopyNotebookPaneAdapter;
public initialize(params: NotebookManagerOptions): void {
this.params = params;
this.junoClient = new JunoClient(this.params.container.databaseAccount);
this.gitHubOAuthService = new GitHubOAuthService(this.junoClient);
this.gitHubClient = new GitHubClient(this.onGitHubClientError);
this.gitHubReposPane = new GitHubReposPane({
id: "gitHubReposPane",
visible: ko.observable<boolean>(false),
container: this.params.container,
junoClient: this.junoClient,
gitHubClient: this.gitHubClient
});
this.gitHubContentProvider = new GitHubContentProvider({
gitHubClient: this.gitHubClient,
promptForCommitMsg: this.promptForCommitMsg
});
this.notebookContentProvider = new NotebookContentProvider(
this.gitHubContentProvider,
contents.JupyterContentProvider
);
this.notebookClient = new NotebookContainerClient(
this.params.container.notebookServerInfo,
() => this.params.container.initNotebooks(this.params.container.databaseAccount()),
(update: MemoryUsageInfo) => this.params.container.memoryUsageInfo(update)
);
this.notebookContentClient = new NotebookContentClient(
this.params.container.notebookServerInfo,
this.params.notebookBasePath,
this.notebookContentProvider
);
if (this.params.container.isGalleryPublishEnabled()) {
this.publishNotebookPaneAdapter = new PublishNotebookPaneAdapter(this.params.container, this.junoClient);
}
this.copyNotebookPaneAdapter = new CopyNotebookPaneAdapter(
this.params.container,
this.junoClient,
this.gitHubOAuthService
);
this.gitHubOAuthService.getTokenObservable().subscribe(token => {
this.gitHubClient.setToken(token?.access_token);
if (this.gitHubReposPane.visible()) {
this.gitHubReposPane.open();
}
this.params.refreshCommandBarButtons();
this.params.refreshNotebookList();
});
this.junoClient.subscribeToPinnedRepos(pinnedRepos => {
this.params.resourceTree.initializeGitHubRepos(pinnedRepos);
this.params.resourceTree.triggerRender();
});
this.refreshPinnedRepos();
}
public refreshPinnedRepos(): void {
const token = this.gitHubOAuthService.getTokenObservable()();
if (token) {
this.junoClient.getPinnedRepos(token.scope);
}
}
public async openPublishNotebookPane(
name: string,
content: string | ImmutableNotebook,
parentDomElement: HTMLElement,
isLinkInjectionEnabled: boolean
): Promise<void> {
await this.publishNotebookPaneAdapter.open(name, getFullName(), content, parentDomElement, isLinkInjectionEnabled);
}
public openCopyNotebookPane(name: string, content: string): void {
this.copyNotebookPaneAdapter.open(name, content);
}
// Octokit's error handler uses any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private onGitHubClientError = (error: any): void => {
Logger.logError(getErrorMessage(error), "NotebookManager/onGitHubClientError");
if (error.status === HttpStatusCodes.Unauthorized) {
this.gitHubOAuthService.resetToken();
this.params.container.showOkCancelModalDialog(
undefined,
"Cosmos DB cannot access your Github account anymore. Please connect to GitHub again.",
"Connect to GitHub",
() => this.gitHubReposPane.open(),
"Cancel",
undefined
);
}
};
private promptForCommitMsg = (title: string, primaryButtonLabel: string) => {
return new Promise<string>((resolve, reject) => {
let commitMsg = "Committed from Azure Cosmos DB Notebooks";
this.params.container.showOkCancelModalDialog(
title || "Commit",
undefined,
primaryButtonLabel || "Commit",
() => {
TelemetryProcessor.trace(Action.NotebooksGitHubCommit, ActionModifiers.Mark, {
databaseAccountName:
this.params.container.databaseAccount() && this.params.container.databaseAccount().name,
defaultExperience: this.params.container.defaultExperience && this.params.container.defaultExperience(),
dataExplorerArea: Areas.Notebook
});
resolve(commitMsg);
},
"Cancel",
() => reject(new Error("Commit dialog canceled")),
undefined,
{
label: "Commit message",
autoAdjustHeight: true,
multiline: true,
defaultValue: commitMsg,
rows: 3,
onChange: (_, newValue: string) => {
commitMsg = newValue;
this.params.dialogProps().primaryButtonDisabled = !commitMsg;
this.params.dialogProps.valueHasMutated();
}
},
!commitMsg
);
});
};
}
/*
* Contains all notebook related stuff meant to be dynamically loaded by explorer
*/
import { JunoClient } from "../../Juno/JunoClient";
import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService";
import { GitHubClient } from "../../GitHub/GitHubClient";
import * as Logger from "../../Common/Logger";
import { HttpStatusCodes, Areas } from "../../Common/Constants";
import { GitHubReposPane } from "../Panes/GitHubReposPane";
import ko from "knockout";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import { IContentProvider } from "@nteract/core";
import { NotebookContentProvider } from "./NotebookComponent/NotebookContentProvider";
import { GitHubContentProvider } from "../../GitHub/GitHubContentProvider";
import { contents } from "rx-jupyter";
import { NotebookContainerClient } from "./NotebookContainerClient";
import { MemoryUsageInfo } from "../../Contracts/DataModels";
import { NotebookContentClient } from "./NotebookContentClient";
import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent";
import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter";
import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter";
import { getFullName } from "../../Utils/UserUtils";
import { ImmutableNotebook } from "@nteract/commutable";
import Explorer from "../Explorer";
import { ContextualPaneBase } from "../Panes/ContextualPaneBase";
import { CopyNotebookPaneAdapter } from "../Panes/CopyNotebookPane";
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
export interface NotebookManagerOptions {
container: Explorer;
notebookBasePath: ko.Observable<string>;
dialogProps: ko.Observable<DialogProps>;
resourceTree: ResourceTreeAdapter;
refreshCommandBarButtons: () => void;
refreshNotebookList: () => void;
}
export default class NotebookManager {
private params: NotebookManagerOptions;
public junoClient: JunoClient;
public notebookContentProvider: IContentProvider;
public notebookClient: NotebookContainerClient;
public notebookContentClient: NotebookContentClient;
private gitHubContentProvider: GitHubContentProvider;
public gitHubOAuthService: GitHubOAuthService;
private gitHubClient: GitHubClient;
public gitHubReposPane: ContextualPaneBase;
public publishNotebookPaneAdapter: PublishNotebookPaneAdapter;
public copyNotebookPaneAdapter: CopyNotebookPaneAdapter;
public initialize(params: NotebookManagerOptions): void {
this.params = params;
this.junoClient = new JunoClient(this.params.container.databaseAccount);
this.gitHubOAuthService = new GitHubOAuthService(this.junoClient);
this.gitHubClient = new GitHubClient(this.onGitHubClientError);
this.gitHubReposPane = new GitHubReposPane({
id: "gitHubReposPane",
visible: ko.observable<boolean>(false),
container: this.params.container,
junoClient: this.junoClient,
gitHubClient: this.gitHubClient,
});
this.gitHubContentProvider = new GitHubContentProvider({
gitHubClient: this.gitHubClient,
promptForCommitMsg: this.promptForCommitMsg,
});
this.notebookContentProvider = new NotebookContentProvider(
this.gitHubContentProvider,
contents.JupyterContentProvider
);
this.notebookClient = new NotebookContainerClient(
this.params.container.notebookServerInfo,
() => this.params.container.initNotebooks(this.params.container.databaseAccount()),
(update: MemoryUsageInfo) => this.params.container.memoryUsageInfo(update)
);
this.notebookContentClient = new NotebookContentClient(
this.params.container.notebookServerInfo,
this.params.notebookBasePath,
this.notebookContentProvider
);
if (this.params.container.isGalleryPublishEnabled()) {
this.publishNotebookPaneAdapter = new PublishNotebookPaneAdapter(this.params.container, this.junoClient);
}
this.copyNotebookPaneAdapter = new CopyNotebookPaneAdapter(
this.params.container,
this.junoClient,
this.gitHubOAuthService
);
this.gitHubOAuthService.getTokenObservable().subscribe((token) => {
this.gitHubClient.setToken(token?.access_token);
if (this.gitHubReposPane.visible()) {
this.gitHubReposPane.open();
}
this.params.refreshCommandBarButtons();
this.params.refreshNotebookList();
});
this.junoClient.subscribeToPinnedRepos((pinnedRepos) => {
this.params.resourceTree.initializeGitHubRepos(pinnedRepos);
this.params.resourceTree.triggerRender();
});
this.refreshPinnedRepos();
}
public refreshPinnedRepos(): void {
const token = this.gitHubOAuthService.getTokenObservable()();
if (token) {
this.junoClient.getPinnedRepos(token.scope);
}
}
public async openPublishNotebookPane(
name: string,
content: string | ImmutableNotebook,
parentDomElement: HTMLElement,
isLinkInjectionEnabled: boolean
): Promise<void> {
await this.publishNotebookPaneAdapter.open(name, getFullName(), content, parentDomElement, isLinkInjectionEnabled);
}
public openCopyNotebookPane(name: string, content: string): void {
this.copyNotebookPaneAdapter.open(name, content);
}
// Octokit's error handler uses any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private onGitHubClientError = (error: any): void => {
Logger.logError(getErrorMessage(error), "NotebookManager/onGitHubClientError");
if (error.status === HttpStatusCodes.Unauthorized) {
this.gitHubOAuthService.resetToken();
this.params.container.showOkCancelModalDialog(
undefined,
"Cosmos DB cannot access your Github account anymore. Please connect to GitHub again.",
"Connect to GitHub",
() => this.gitHubReposPane.open(),
"Cancel",
undefined
);
}
};
private promptForCommitMsg = (title: string, primaryButtonLabel: string) => {
return new Promise<string>((resolve, reject) => {
let commitMsg = "Committed from Azure Cosmos DB Notebooks";
this.params.container.showOkCancelModalDialog(
title || "Commit",
undefined,
primaryButtonLabel || "Commit",
() => {
TelemetryProcessor.trace(Action.NotebooksGitHubCommit, ActionModifiers.Mark, {
databaseAccountName:
this.params.container.databaseAccount() && this.params.container.databaseAccount().name,
defaultExperience: this.params.container.defaultExperience && this.params.container.defaultExperience(),
dataExplorerArea: Areas.Notebook,
});
resolve(commitMsg);
},
"Cancel",
() => reject(new Error("Commit dialog canceled")),
undefined,
{
label: "Commit message",
autoAdjustHeight: true,
multiline: true,
defaultValue: commitMsg,
rows: 3,
onChange: (_, newValue: string) => {
commitMsg = newValue;
this.params.dialogProps().primaryButtonDisabled = !commitMsg;
this.params.dialogProps.valueHasMutated();
},
},
!commitMsg
);
});
};
}

View File

@@ -62,15 +62,15 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
prompt: (props: { id: string; contentRef: string }) => this.renderPrompt(props.id, props.contentRef),
editor: {
monaco: (props: PassedEditorProps) =>
this.props.hideInputs ? <></> : <MonacoEditor readOnly={true} {...props} editorType={"monaco"} />
}
this.props.hideInputs ? <></> : <MonacoEditor readOnly={true} {...props} editorType={"monaco"} />,
},
}}
</CodeCell>
),
markdown: ({ id, contentRef }: { id: any; contentRef: ContentRef }) => (
<MarkdownCell id={id} contentRef={contentRef} cell_type="markdown">
{{
editor: {}
editor: {},
}}
</MarkdownCell>
),
@@ -79,11 +79,11 @@ class NotebookReadOnlyRenderer extends React.Component<NotebookRendererProps> {
{{
editor: {
monaco: (props: PassedEditorProps) =>
this.props.hideInputs ? <></> : <MonacoEditor {...props} readOnly={true} editorType={"monaco"} />
}
this.props.hideInputs ? <></> : <MonacoEditor {...props} readOnly={true} editorType={"monaco"} />,
},
}}
</RawCell>
)
),
}}
</Cells>
<AzureTheme />
@@ -99,10 +99,10 @@ const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: Noteboo
return dispatch(
actions.addTransform({
mediaType: transform.MIMETYPE,
component: transform
component: transform,
})
);
}
},
};
};
return mapDispatchToProps;

View File

@@ -69,7 +69,7 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
super(props);
this.state = {
hoveredCellId: undefined
hoveredCellId: undefined,
};
}
@@ -103,14 +103,14 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
<CodeCell id={id} contentRef={contentRef} cell_type="code">
{{
editor: {
monaco: (props: PassedEditorProps) => <MonacoEditor {...props} editorType={"monaco"} />
monaco: (props: PassedEditorProps) => <MonacoEditor {...props} editorType={"monaco"} />,
},
prompt: ({ id, contentRef }: { id: CellId; contentRef: ContentRef }) => (
<Prompt id={id} contentRef={contentRef} isHovered={false}>
{promptContent}
</Prompt>
),
toolbar: () => <CellToolbar id={id} contentRef={contentRef} />
toolbar: () => <CellToolbar id={id} contentRef={contentRef} />,
}}
</CodeCell>
),
@@ -122,9 +122,9 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
<MarkdownCell id={id} contentRef={contentRef} cell_type="markdown">
{{
editor: {
monaco: (props: PassedEditorProps) => <MonacoEditor {...props} editorType={"monaco"} />
monaco: (props: PassedEditorProps) => <MonacoEditor {...props} editorType={"monaco"} />,
},
toolbar: () => <CellToolbar id={id} contentRef={contentRef} />
toolbar: () => <CellToolbar id={id} contentRef={contentRef} />,
}}
</MarkdownCell>
),
@@ -137,12 +137,12 @@ class BaseNotebookRenderer extends React.Component<NotebookRendererProps> {
<RawCell id={id} contentRef={contentRef} cell_type="raw">
{{
editor: {
monaco: (props: PassedEditorProps) => <MonacoEditor {...props} editorType={"monaco"} />
monaco: (props: PassedEditorProps) => <MonacoEditor {...props} editorType={"monaco"} />,
},
toolbar: () => <CellToolbar id={id} contentRef={contentRef} />
toolbar: () => <CellToolbar id={id} contentRef={contentRef} />,
}}
</RawCell>
)
),
}}
</Cells>
</KeyboardShortcuts>
@@ -163,7 +163,7 @@ const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: Noteboo
return dispatch(
actions.addTransform({
mediaType: transform.MIMETYPE,
component: transform
component: transform,
})
);
},
@@ -171,10 +171,10 @@ const makeMapDispatchToProps = (initialDispatch: Dispatch, initialProps: Noteboo
return dispatch(
cdbActions.UpdateNotebookParentDomElt({
contentRef,
parentElt
parentElt,
})
);
}
},
};
};
return mapDispatchToProps;

View File

@@ -46,7 +46,7 @@ export class PromptPure extends React.Component<Props> {
executionCount: this.props.executionCount,
runCell: this.props.executeCell,
stopCell: this.props.stopExecution,
isHovered: this.props.isHovered
isHovered: this.props.isHovered,
})}
</div>
);
@@ -74,7 +74,7 @@ const makeMapStateToProps = (state: CdbAppState, ownProps: ComponentProps): ((st
return {
status,
executionCount,
isHovered
isHovered,
};
};
return mapStateToProps;
@@ -89,11 +89,11 @@ const mapDispatchToProps = (
dispatch(
cdbActions.traceNotebookTelemetry({
action: Action.ExecuteCellPromptBtn,
actionModifier: ActionModifiers.Mark
actionModifier: ActionModifiers.Mark,
})
);
},
stopExecution: () => dispatch(actions.interruptKernel({}))
stopExecution: () => dispatch(actions.interruptKernel({})),
});
export default connect(makeMapStateToProps, mapDispatchToProps)(PromptPure);

View File

@@ -26,7 +26,7 @@ describe("StatusBar", () => {
{
lastSaved,
kernelSpecDisplayName: "javascript",
kernelStatus: "kernelStatus"
kernelStatus: "kernelStatus",
},
null,
null
@@ -45,7 +45,7 @@ describe("StatusBar", () => {
{
lastSaved: new Date(),
kernelSpecDisplayName: "python3",
kernelStatus: "kernelStatus"
kernelStatus: "kernelStatus",
},
null,
null

View File

@@ -90,7 +90,7 @@ const makeMapStateToProps = (initialState: AppState, initialProps: InitialProps)
return {
kernelStatus: NOT_CONNECTED,
kernelSpecDisplayName: "no kernel",
lastSaved: null
lastSaved: null,
};
}
@@ -118,7 +118,7 @@ const makeMapStateToProps = (initialState: AppState, initialProps: InitialProps)
return {
kernelSpecDisplayName,
kernelStatus,
lastSaved
lastSaved,
};
};

View File

@@ -7,7 +7,7 @@ import { IconButton } from "office-ui-fabric-react/lib/Button";
import {
DirectionalHint,
IContextualMenuItem,
ContextualMenuItemType
ContextualMenuItemType,
} from "office-ui-fabric-react/lib/ContextualMenu";
import { actions, AppState, DocumentRecordProps } from "@nteract/core";
import { CellToolbarContext } from "@nteract/stateful-components";
@@ -54,7 +54,7 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.executeCell();
this.props.traceNotebookTelemetry(Action.NotebooksExecuteCellFromMenu, ActionModifiers.Mark);
}
},
},
{
key: "Clear Outputs",
@@ -62,19 +62,19 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.clearOutputs();
this.props.traceNotebookTelemetry(Action.NotebooksClearOutputsFromMenu, ActionModifiers.Mark);
}
},
},
{
key: "Divider",
itemType: ContextualMenuItemType.Divider
}
itemType: ContextualMenuItemType.Divider,
},
]);
}
items = items.concat([
{
key: "Divider2",
itemType: ContextualMenuItemType.Divider
itemType: ContextualMenuItemType.Divider,
},
{
key: "Insert Code Cell Above",
@@ -82,7 +82,7 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.insertCodeCellAbove();
this.props.traceNotebookTelemetry(Action.NotebooksInsertCodeCellAboveFromMenu, ActionModifiers.Mark);
}
},
},
{
key: "Insert Code Cell Below",
@@ -90,7 +90,7 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.insertCodeCellBelow();
this.props.traceNotebookTelemetry(Action.NotebooksInsertCodeCellBelowFromMenu, ActionModifiers.Mark);
}
},
},
{
key: "Insert Text Cell Above",
@@ -98,7 +98,7 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.insertTextCellAbove();
this.props.traceNotebookTelemetry(Action.NotebooksInsertTextCellAboveFromMenu, ActionModifiers.Mark);
}
},
},
{
key: "Insert Text Cell Below",
@@ -106,12 +106,12 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.insertTextCellBelow();
this.props.traceNotebookTelemetry(Action.NotebooksInsertTextCellBelowFromMenu, ActionModifiers.Mark);
}
},
},
{
key: "Divider3",
itemType: ContextualMenuItemType.Divider
}
itemType: ContextualMenuItemType.Divider,
},
]);
const moveItems: IContextualMenuItem[] = [];
@@ -122,7 +122,7 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.moveCell(this.props.cellIdAbove, true);
this.props.traceNotebookTelemetry(Action.NotebooksMoveCellUpFromMenu, ActionModifiers.Mark);
}
},
});
}
@@ -133,14 +133,14 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.moveCell(this.props.cellIdBelow, false);
this.props.traceNotebookTelemetry(Action.NotebooksMoveCellDownFromMenu, ActionModifiers.Mark);
}
},
});
}
if (moveItems.length > 0) {
moveItems.push({
key: "Divider4",
itemType: ContextualMenuItemType.Divider
itemType: ContextualMenuItemType.Divider,
});
items = items.concat(moveItems);
}
@@ -151,7 +151,7 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
onClick: () => {
this.props.deleteCell();
this.props.traceNotebookTelemetry(Action.DeleteCellFromMenu, ActionModifiers.Mark);
}
},
});
const menuItemLabel = "More";
@@ -162,12 +162,12 @@ class BaseToolbar extends React.PureComponent<ComponentProps & DispatchProps & S
ariaLabel={menuItemLabel}
menuIconProps={{
iconName: menuItemLabel,
styles: { root: { fontSize: "18px", fontWeight: "bold" } }
styles: { root: { fontSize: "18px", fontWeight: "bold" } },
}}
menuProps={{
isBeakVisible: false,
directionalHint: DirectionalHint.bottomRightEdge,
items
items,
}}
/>
);
@@ -188,7 +188,7 @@ const mapDispatchToProps = (
clearOutputs: () => dispatch(actions.clearOutputs({ id, contentRef })),
deleteCell: () => dispatch(actions.deleteCell({ id, contentRef })),
traceNotebookTelemetry: (action: Action, actionModifier?: string, data?: any) =>
dispatch(cdbActions.traceNotebookTelemetry({ action, actionModifier, data }))
dispatch(cdbActions.traceNotebookTelemetry({ action, actionModifier, data })),
});
const makeMapStateToProps = (state: AppState, ownProps: ComponentProps): ((state: AppState) => StateProps) => {
@@ -204,7 +204,7 @@ const makeMapStateToProps = (state: AppState, ownProps: ComponentProps): ((state
return {
cellType,
cellIdAbove,
cellIdBelow
cellIdBelow,
};
};
return mapStateToProps;

View File

@@ -193,12 +193,12 @@ const mapStateToProps = (state: AppState, ownProps: ComponentProps) => {
if (model && model.type === "notebook") {
const cellOrder = selectors.notebook.cellOrder(model);
const cellIndex = cellOrder.findIndex(cellId => cellId === id);
const cellIndex = cellOrder.findIndex((cellId) => cellId === id);
isFirstCell = cellIndex === 0;
}
return {
isFirstCell
isFirstCell,
};
};
@@ -208,7 +208,7 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
createCellAppend: (payload: { cellType: CellType; contentRef: ContentRef }) =>
dispatch(actions.createCellAppend(payload)),
createCellBelow: (payload: { cellType: CellType; id?: string; source: string; contentRef: ContentRef }) =>
dispatch(actions.createCellBelow(payload))
dispatch(actions.createCellBelow(payload)),
});
export default connect(mapStateToProps, mapDispatchToProps)(CellCreator);

View File

@@ -36,7 +36,7 @@ const makeMapStateToProps = (state: AppState, ownProps: ComponentProps): ((state
const cellIndex = cellOrder.indexOf(ownProps.id);
return {
cellIndex
cellIndex,
};
};
return mapStateToProps;

View File

@@ -34,7 +34,7 @@ const mapDispatchToProps = (
{ id, contentRef }: { id: string; contentRef: ContentRef }
): DispatchProps => ({
hover: () => dispatch(actions.setHoveredCell({ cellId: id })),
unHover: () => dispatch(actions.setHoveredCell({ cellId: undefined }))
unHover: () => dispatch(actions.setHoveredCell({ cellId: undefined })),
});
export default connect(undefined, mapDispatchToProps)(HoverableCell);

View File

@@ -9,7 +9,7 @@ import {
DragSourceMonitor,
DropTarget,
DropTargetConnector,
DropTargetMonitor
DropTargetMonitor,
} from "react-dnd";
import { connect } from "react-redux";
@@ -43,7 +43,7 @@ const cellDragPreviewImage = [
"s46mRlWqQiudxebVV3gAj7C9hXsmgZeztnfe/91YODEr3IoF/JY/sE2gbGaVLci3",
"hh0tRtWNvsm16JmNcOs6N9dW72LP7yOtWbEhjAUkZ+icoJ5HbE6+NSxMjKWe6cKb",
"GkUWgMwiFbXSlRpFkXelUlF4F70rVd7Bd4oZ/LL8xiDmtPV2Nwyf2zOlTfHERY7i",
"Haa1+w2+iFqx0aIgvgAAAABJRU5ErkJggg=="
"Haa1+w2+iFqx0aIgvgAAAABJRU5ErkJggg==",
].join("");
interface Props {
@@ -72,13 +72,13 @@ interface State {
const cellSource = {
beginDrag(props: Props) {
return {
id: props.id
id: props.id,
};
}
},
};
const DragHandle = styled.div.attrs({
role: "presentation"
role: "presentation",
})`
position: absolute;
z-index: 200;
@@ -93,12 +93,12 @@ interface DragAreaProps {
hoverUpperHalf: boolean;
}
const DragArea = styled.div.attrs<DragAreaProps>(props => ({
const DragArea = styled.div.attrs<DragAreaProps>((props) => ({
style: {
opacity: props.isDragging ? 0.25 : 1,
borderTop: props.isOver && props.hoverUpperHalf ? "3px lightgray solid" : "3px transparent solid",
borderBottom: props.isOver && !props.hoverUpperHalf ? "3px lightgray solid" : "3px transparent solid"
}
borderBottom: props.isOver && !props.hoverUpperHalf ? "3px lightgray solid" : "3px transparent solid",
},
}))`
padding: 10px;
margin-top: -15px;
@@ -128,7 +128,7 @@ export const cellTarget = {
id: monitor.getItem().id,
destinationId: props.id,
above: hoverUpperHalf,
contentRef: props.contentRef
contentRef: props.contentRef,
});
}
},
@@ -136,10 +136,10 @@ export const cellTarget = {
hover(props: Props, monitor: DropTargetMonitor, component: any): void {
if (monitor) {
component.setState({
hoverUpperHalf: isDragUpper(props, monitor, component.el)
hoverUpperHalf: isDragUpper(props, monitor, component.el),
});
}
}
},
};
function collectSource(
@@ -153,7 +153,7 @@ function collectSource(
return {
connectDragSource: connect.dragSource(),
isDragging: monitor.isDragging(),
connectDragPreview: connect.dragPreview()
connectDragPreview: connect.dragPreview(),
};
}
@@ -166,7 +166,7 @@ function collectTarget(
} {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver()
isOver: monitor.isOver(),
};
}
@@ -174,7 +174,7 @@ export class DraggableCellView extends React.Component<Props & DnDSourceProps &
el?: HTMLDivElement | null;
state = {
hoverUpperHalf: true
hoverUpperHalf: true,
};
componentDidMount(): void {
@@ -201,7 +201,7 @@ export class DraggableCellView extends React.Component<Props & DnDSourceProps &
isDragging={this.props.isDragging}
hoverUpperHalf={this.state.hoverUpperHalf}
isOver={this.props.isOver}
ref={el => {
ref={(el) => {
this.el = el;
}}
>
@@ -226,7 +226,7 @@ const target = DropTarget<Props, DnDTargetProps>("CELL", cellTarget, collectTarg
export const makeMapDispatchToProps = (initialDispatch: Dispatch) => {
const mapDispatchToProps = (dispatch: Dispatch) => ({
moveCell: (payload: actions.MoveCell["payload"]) => dispatch(actions.moveCell(payload)),
focusCell: (payload: actions.FocusCell["payload"]) => dispatch(actions.focusCell(payload))
focusCell: (payload: actions.FocusCell["payload"]) => dispatch(actions.focusCell(payload)),
});
return mapDispatchToProps;
};

View File

@@ -60,7 +60,7 @@ export class HijackScroll extends React.Component<Props> {
<div
onClick={this.props.selectCell}
role="presentation"
ref={el => {
ref={(el) => {
this.el = el;
}}
>
@@ -81,7 +81,7 @@ const makeMapStateToProps = (initialState: AppState, ownProps: ComponentProps) =
}
return {
focused
focused,
};
};
return mapStateToProps;
@@ -89,7 +89,7 @@ const makeMapStateToProps = (initialState: AppState, ownProps: ComponentProps) =
const makeMapDispatchToProps = (initialDispatch: Dispatch, ownProps: ComponentProps) => {
const mapDispatchToProps = (dispatch: Dispatch) => ({
selectCell: () => dispatch(actions.focusCell({ id: ownProps.id, contentRef: ownProps.contentRef }))
selectCell: () => dispatch(actions.focusCell({ id: ownProps.id, contentRef: ownProps.contentRef })),
});
return mapDispatchToProps;
};

View File

@@ -59,7 +59,7 @@ export class KeyboardShortcuts extends React.Component<Props> {
contentRef,
cellOrder,
focusedCell,
cellMap
cellMap,
} = this.props;
let ctrlKeyPressed = e.ctrlKey;
@@ -90,7 +90,7 @@ export class KeyboardShortcuts extends React.Component<Props> {
focusNextCell({
id: undefined,
createCellIfUndefined: true,
contentRef
contentRef,
});
/** Only focus the next editor if it is a code cell or a cell
@@ -125,7 +125,7 @@ export const makeMapStateToProps = (state: AppState, ownProps: ComponentProps) =
return {
cellOrder,
cellMap,
focusedCell
focusedCell,
};
};
return mapStateToProps;
@@ -136,7 +136,7 @@ export const mapDispatchToProps = (dispatch: Dispatch) => ({
focusNextCell: (payload: { id?: CellId; createCellIfUndefined: boolean; contentRef: ContentRef }) =>
dispatch(actions.focusNextCell(payload)),
focusNextCellEditor: (payload: { id?: CellId; contentRef: ContentRef }) =>
dispatch(actions.focusNextCellEditor(payload))
dispatch(actions.focusNextCellEditor(payload)),
});
export default connect(makeMapStateToProps, mapDispatchToProps)(KeyboardShortcuts);

View File

@@ -1,137 +1,137 @@
import { NotebookUtil } from "./NotebookUtil";
import * as GitHubUtils from "../../Utils/GitHubUtils";
import {
ImmutableNotebook,
MediaBundle,
CodeCellParams,
MarkdownCellParams,
makeCodeCell,
makeMarkdownCell,
makeNotebookRecord
} from "@nteract/commutable";
import { List, Map } from "immutable";
const fileName = "file";
const notebookName = "file.ipynb";
const folderPath = "folder";
const filePath = `${folderPath}/${fileName}`;
const notebookPath = `${folderPath}/${notebookName}`;
const gitHubFolderUri = GitHubUtils.toContentUri("owner", "repo", "branch", folderPath);
const gitHubFileUri = GitHubUtils.toContentUri("owner", "repo", "branch", filePath);
const gitHubNotebookUri = GitHubUtils.toContentUri("owner", "repo", "branch", notebookPath);
const notebookRecord = makeNotebookRecord({
cellOrder: List.of("0", "1", "2", "3"),
cellMap: Map({
"0": makeMarkdownCell({
cell_type: "markdown",
source: "abc",
metadata: undefined
} as MarkdownCellParams),
"1": makeCodeCell({
cell_type: "code",
execution_count: undefined,
metadata: undefined,
source: "print(5)",
outputs: List.of({
name: "stdout",
output_type: "stream",
text: "5"
})
} as CodeCellParams),
"2": makeCodeCell({
cell_type: "code",
execution_count: undefined,
metadata: undefined,
source: 'display(HTML("<h1>Sample html</h1>"))',
outputs: List.of({
data: Object.freeze({
"text/html": "<h1>Sample output</h1>",
"text/plain": "<IPython.core.display.HTML object>"
} as MediaBundle),
output_type: "display_data",
metadata: undefined
})
} as CodeCellParams),
"3": makeCodeCell({
cell_type: "code",
execution_count: undefined,
metadata: undefined,
source: 'print("hello world")',
outputs: List.of({
name: "stdout",
output_type: "stream",
text: "hello world"
})
} as CodeCellParams)
}),
nbformat_minor: 2,
nbformat: 2,
metadata: undefined
});
describe("NotebookUtil", () => {
describe("isNotebookFile", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.isNotebookFile(filePath)).toBeFalsy();
expect(NotebookUtil.isNotebookFile(notebookPath)).toBeTruthy();
});
it("works for github file uris", () => {
expect(NotebookUtil.isNotebookFile(gitHubFileUri)).toBeFalsy();
expect(NotebookUtil.isNotebookFile(gitHubNotebookUri)).toBeTruthy();
});
});
describe("getFilePath", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.getFilePath(folderPath, fileName)).toEqual(filePath);
});
it("works for github file uris", () => {
expect(NotebookUtil.getFilePath(gitHubFolderUri, fileName)).toEqual(gitHubFileUri);
});
});
describe("getParentPath", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.getParentPath(filePath)).toEqual(folderPath);
});
it("works for github file uris", () => {
expect(NotebookUtil.getParentPath(gitHubFileUri)).toEqual(gitHubFolderUri);
});
});
describe("getName", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.getName(filePath)).toEqual(fileName);
expect(NotebookUtil.getName(notebookPath)).toEqual(notebookName);
});
it("works for github file uris", () => {
expect(NotebookUtil.getName(gitHubFileUri)).toEqual(fileName);
expect(NotebookUtil.getName(gitHubNotebookUri)).toEqual(notebookName);
});
});
describe("replaceName", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.replaceName(filePath, "newName")).toEqual(filePath.replace(fileName, "newName"));
expect(NotebookUtil.replaceName(notebookPath, "newName")).toEqual(notebookPath.replace(notebookName, "newName"));
});
it("works for github file uris", () => {
expect(NotebookUtil.replaceName(gitHubFileUri, "newName")).toEqual(gitHubFileUri.replace(fileName, "newName"));
expect(NotebookUtil.replaceName(gitHubNotebookUri, "newName")).toEqual(
gitHubNotebookUri.replace(notebookName, "newName")
);
});
});
describe("findFirstCodeCellWithDisplay", () => {
it("works for Notebook file", () => {
const notebookObject = notebookRecord as ImmutableNotebook;
expect(NotebookUtil.findFirstCodeCellWithDisplay(notebookObject)).toEqual(1);
});
});
});
import { NotebookUtil } from "./NotebookUtil";
import * as GitHubUtils from "../../Utils/GitHubUtils";
import {
ImmutableNotebook,
MediaBundle,
CodeCellParams,
MarkdownCellParams,
makeCodeCell,
makeMarkdownCell,
makeNotebookRecord,
} from "@nteract/commutable";
import { List, Map } from "immutable";
const fileName = "file";
const notebookName = "file.ipynb";
const folderPath = "folder";
const filePath = `${folderPath}/${fileName}`;
const notebookPath = `${folderPath}/${notebookName}`;
const gitHubFolderUri = GitHubUtils.toContentUri("owner", "repo", "branch", folderPath);
const gitHubFileUri = GitHubUtils.toContentUri("owner", "repo", "branch", filePath);
const gitHubNotebookUri = GitHubUtils.toContentUri("owner", "repo", "branch", notebookPath);
const notebookRecord = makeNotebookRecord({
cellOrder: List.of("0", "1", "2", "3"),
cellMap: Map({
"0": makeMarkdownCell({
cell_type: "markdown",
source: "abc",
metadata: undefined,
} as MarkdownCellParams),
"1": makeCodeCell({
cell_type: "code",
execution_count: undefined,
metadata: undefined,
source: "print(5)",
outputs: List.of({
name: "stdout",
output_type: "stream",
text: "5",
}),
} as CodeCellParams),
"2": makeCodeCell({
cell_type: "code",
execution_count: undefined,
metadata: undefined,
source: 'display(HTML("<h1>Sample html</h1>"))',
outputs: List.of({
data: Object.freeze({
"text/html": "<h1>Sample output</h1>",
"text/plain": "<IPython.core.display.HTML object>",
} as MediaBundle),
output_type: "display_data",
metadata: undefined,
}),
} as CodeCellParams),
"3": makeCodeCell({
cell_type: "code",
execution_count: undefined,
metadata: undefined,
source: 'print("hello world")',
outputs: List.of({
name: "stdout",
output_type: "stream",
text: "hello world",
}),
} as CodeCellParams),
}),
nbformat_minor: 2,
nbformat: 2,
metadata: undefined,
});
describe("NotebookUtil", () => {
describe("isNotebookFile", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.isNotebookFile(filePath)).toBeFalsy();
expect(NotebookUtil.isNotebookFile(notebookPath)).toBeTruthy();
});
it("works for github file uris", () => {
expect(NotebookUtil.isNotebookFile(gitHubFileUri)).toBeFalsy();
expect(NotebookUtil.isNotebookFile(gitHubNotebookUri)).toBeTruthy();
});
});
describe("getFilePath", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.getFilePath(folderPath, fileName)).toEqual(filePath);
});
it("works for github file uris", () => {
expect(NotebookUtil.getFilePath(gitHubFolderUri, fileName)).toEqual(gitHubFileUri);
});
});
describe("getParentPath", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.getParentPath(filePath)).toEqual(folderPath);
});
it("works for github file uris", () => {
expect(NotebookUtil.getParentPath(gitHubFileUri)).toEqual(gitHubFolderUri);
});
});
describe("getName", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.getName(filePath)).toEqual(fileName);
expect(NotebookUtil.getName(notebookPath)).toEqual(notebookName);
});
it("works for github file uris", () => {
expect(NotebookUtil.getName(gitHubFileUri)).toEqual(fileName);
expect(NotebookUtil.getName(gitHubNotebookUri)).toEqual(notebookName);
});
});
describe("replaceName", () => {
it("works for jupyter file paths", () => {
expect(NotebookUtil.replaceName(filePath, "newName")).toEqual(filePath.replace(fileName, "newName"));
expect(NotebookUtil.replaceName(notebookPath, "newName")).toEqual(notebookPath.replace(notebookName, "newName"));
});
it("works for github file uris", () => {
expect(NotebookUtil.replaceName(gitHubFileUri, "newName")).toEqual(gitHubFileUri.replace(fileName, "newName"));
expect(NotebookUtil.replaceName(gitHubNotebookUri, "newName")).toEqual(
gitHubNotebookUri.replace(notebookName, "newName")
);
});
});
describe("findFirstCodeCellWithDisplay", () => {
it("works for Notebook file", () => {
const notebookObject = notebookRecord as ImmutableNotebook;
expect(NotebookUtil.findFirstCodeCellWithDisplay(notebookObject)).toEqual(1);
});
});
});

View File

@@ -26,7 +26,7 @@ export class NotebookUtil {
name,
path,
type: NotebookUtil.getType(type),
timestamp: NotebookUtil.getCurrentTimestamp()
timestamp: NotebookUtil.getCurrentTimestamp(),
};
}
@@ -66,7 +66,7 @@ export class NotebookUtil {
return {
cwd,
kernelSpecName
kernelSpecName,
};
}
@@ -149,7 +149,7 @@ export class NotebookUtil {
const cell = notebookObject.cellMap.get(cellId);
if (cell?.cell_type === "code") {
const displayOutput = (cell as ImmutableCodeCell)?.outputs?.find(
output => output.output_type === "display_data" || output.output_type === "execute_result"
(output) => output.output_type === "display_data" || output.output_type === "execute_result"
);
if (displayOutput) {
return codeCellIndex;

View File

@@ -9,31 +9,31 @@ describe("auto start kernel", () => {
(configureStore as jest.Mock).mockReturnValue({
dispatch: () => {
/* noop */
}
},
});
defineConfigOption({
label: "editorType",
key: "editorType",
defaultValue: "foo"
defaultValue: "foo",
});
defineConfigOption({
label: "autoSaveInterval",
key: "autoSaveInterval",
defaultValue: 1234
defaultValue: 1234,
});
[true, false].forEach(isReadOnly => {
[true, false].forEach((isReadOnly) => {
new NotebookClientV2({
connectionInfo: {
authToken: "autToken",
notebookServerEndpoint: "notebookServerEndpoint"
notebookServerEndpoint: "notebookServerEndpoint",
},
databaseAccountName: undefined,
defaultExperience: undefined,
isReadOnly,
contentProvider: undefined
contentProvider: undefined,
});
expect(configureStore).toHaveBeenCalledWith(