Files
cosmos-explorer/src/Explorer/Notebook/NotebookComponent/NotebookComponentBootstrapper.tsx
Laurent Nguyen bcd8b7229f Upgrade typescript to 4.9.5 and jest to 29.7.0 (and related packages) (#1884)
* Upgrade typescript to 4.9.5

* Fix compile issue and put back files in tsconfig.strict.json

* Update test snapshots

* Fix jest tests by upgrading jest and other related packages.

* Attempt to fix playwright test

* Revert "Attempt to fix playwright test"

This reverts commit 8293f34c9c.

* 2nd attempt to fix example test

* fix waitFor in playwright

* Remove unused describe section

* Attempt to fix e2e test

* Revert "Attempt to fix e2e test"

This reverts commit 9745bcd2ef.

* Upgrade playwright to latest

* Revert "Upgrade playwright to latest"

This reverts commit e2ea1d0189.

* Error test on e2e

* Revert "Error test on e2e"

This reverts commit 124e3764f7.

* Try to select dropdown item by xpath selector

* Revert "Try to select dropdown item by xpath selector"

This reverts commit 8eb42a64e2.

* Attempt to wait until page is fully loaded

* Revert "Attempt to wait until page is fully loaded"

This reverts commit bb43fcea6e.

* Use playwright selectOption to select dropdown option

* Revert "Use playwright selectOption to select dropdown option"

This reverts commit daa8cd0930.

* Select dropdown option with playwright api instead of manual click

* c7ab4c7ecf7b05f32a85568bce1a667ad8c62703Revert "Select dropdown option with playwright api instead of manual click"

This reverts commit c7ab4c7ecf.

* Wait for 5s after dropdown click

* Revert "Wait for 5s after dropdown click"

This reverts commit 847e9ad33f.

* Try forcing click

* Revert "Try forcing click"

This reverts commit 29b9fa1bda.

* Force click on the dropdown and set viewport size bigger.

* Force click on the dropdown and set viewport size bigger.

* try force clicking option

* Skip container test on webkit

* Add branded browsers to e2e tests

---------

Co-authored-by: Ashley Stanton-Nurse <ashleyst@microsoft.com>
2024-07-30 15:41:41 -07:00

380 lines
10 KiB
TypeScript

/* eslint-disable @typescript-eslint/no-explicit-any */
import { Link } from "@fluentui/react";
import { CellId, CellType, ImmutableNotebook } from "@nteract/commutable";
// Vendor modules
import { actions, AppState, ContentRef, KernelRef, NotebookContentRecord, selectors } from "@nteract/core";
import "@nteract/styles/editor-overrides.css";
import "@nteract/styles/global-variables.css";
import "codemirror/addon/hint/show-hint.css";
import "codemirror/lib/codemirror.css";
import { Notebook } from "Common/Constants";
import { useDialog } from "Explorer/Controls/Dialog";
import * as React from "react";
import { Provider } from "react-redux";
import "react-table/react-table.css";
import { AnyAction, Store } from "redux";
import { NotebookClientV2 } from "../NotebookClientV2";
import { NotebookContentProviderType, NotebookUtil } from "../NotebookUtil";
import * as NteractUtil from "../NTeractUtil";
import * as CdbActions from "./actions";
import { NotebookComponent } from "./NotebookComponent";
import "./NotebookComponent.less";
export interface NotebookComponentBootstrapperOptions {
notebookClient: NotebookClientV2;
contentRef: ContentRef;
}
interface IWrapModel {
name: string;
path: string;
last_modified: Date;
created: string;
content: unknown;
format: string;
mimetype: unknown;
size: number;
writeable: boolean;
type: string;
}
export class NotebookComponentBootstrapper {
public contentRef: ContentRef;
protected renderExtraComponent: () => JSX.Element;
private notebookClient: NotebookClientV2;
constructor(options: NotebookComponentBootstrapperOptions) {
this.notebookClient = options.notebookClient;
this.contentRef = options.contentRef;
}
protected static wrapModelIntoContent(name: string, path: string, content: unknown): IWrapModel {
return {
name,
path,
last_modified: new Date(),
created: "",
content,
format: "json",
mimetype: undefined,
size: 0,
writeable: false,
type: "notebook",
};
}
private renderDefaultNotebookComponent(props: any): JSX.Element {
return (
<>
{this.renderExtraComponent && this.renderExtraComponent()}
{React.createElement<{ contentRef: ContentRef }>(NotebookComponent, { contentRef: this.contentRef, ...props })}
</>
);
}
public getContent(): { name: string; content: string | ImmutableNotebook } {
const record = this.getStore().getState().core.entities.contents.byRef.get(this.contentRef);
let content: string | ImmutableNotebook;
switch (record.model.type) {
case "notebook":
content = record.model.notebook;
break;
case "file":
content = record.model.text;
break;
default:
throw new Error(`Unsupported model type ${record.model.type}`);
}
return {
name: NotebookUtil.getName(record.filepath),
content,
};
}
public getNotebookPath(): string {
return this.getStore().getState().core.entities.contents.byRef.get(this.contentRef)?.filepath;
}
public setContent(name: string, content: unknown): void {
this.getStore().dispatch(
actions.fetchContentFulfilled({
filepath: undefined,
model: NotebookComponentBootstrapper.wrapModelIntoContent(name, undefined, content),
kernelRef: undefined,
contentRef: this.contentRef,
}),
);
}
/**
* We can overload the notebook renderer here
* @param renderer
* @props additional props
*/
public renderComponent(
renderer?: any, // TODO FIX THIS React.ComponentClass<{ contentRef: ContentRef; isReadOnly?: boolean }>,
props?: any,
): JSX.Element {
return (
<Provider store={this.getStore()}>
{renderer
? React.createElement<{ contentRef: ContentRef }>(renderer, { contentRef: this.contentRef, ...props })
: this.renderDefaultNotebookComponent(props)}
</Provider>
);
}
/* Notebook operations. See nteract/packages/connected-components/src/notebook-menu/index.tsx */
public notebookSave(): void {
if (
NotebookUtil.getContentProviderType(this.getNotebookPath()) ===
NotebookContentProviderType.JupyterContentProviderType
) {
useDialog.getState().showOkCancelModalDialog(
Notebook.saveNotebookModalTitle,
undefined,
"Save",
async () => {
this.getStore().dispatch(
actions.save({
contentRef: this.contentRef,
}),
);
},
"Cancel",
undefined,
this.getSaveNotebookSubText(),
);
} else {
this.getStore().dispatch(
actions.save({
contentRef: this.contentRef,
}),
);
}
}
public notebookChangeKernel(kernelSpecName: string): void {
this.getStore().dispatch(
actions.changeKernelByName({
contentRef: this.contentRef,
kernelSpecName,
oldKernelRef: this.getCurrentKernelRef(),
}),
);
}
public notebookRunAndAdvance(): void {
this.getStore().dispatch(
CdbActions.executeFocusedCellAndFocusNext({
contentRef: this.contentRef,
}),
);
}
public notebookRunAll(): void {
this.getStore().dispatch(
actions.executeAllCells({
contentRef: this.contentRef,
}),
);
}
public notebookInterruptKernel(): void {
this.getStore().dispatch(
actions.interruptKernel({
kernelRef: this.getCurrentKernelRef(),
}),
);
}
public notebookKillKernel(): void {
this.getStore().dispatch(
actions.killKernel({
restarting: false,
kernelRef: this.getCurrentKernelRef(),
}),
);
}
public notebookRestartKernel(): void {
this.getStore().dispatch(
actions.restartKernel({
kernelRef: this.getCurrentKernelRef(),
contentRef: this.contentRef,
outputHandling: "None",
}),
);
}
public notebookClearAllOutputs(): void {
this.getStore().dispatch(
actions.clearAllOutputs({
contentRef: this.contentRef,
}),
);
}
public notebookInsertBelow(): void {
this.getStore().dispatch(
actions.createCellBelow({
cellType: "code",
contentRef: this.contentRef,
}),
);
}
public notebookChangeCellType(type: CellType): void {
const focusedCellId = this.getFocusedCellId();
if (!focusedCellId) {
console.error("No focused cell");
return;
}
this.getStore().dispatch(
actions.changeCellType({
id: focusedCellId,
contentRef: this.contentRef,
to: type,
}),
);
}
public notebokCopy(): void {
const focusedCellId = this.getFocusedCellId();
if (!focusedCellId) {
console.error("No focused cell");
return;
}
this.getStore().dispatch(
actions.copyCell({
id: focusedCellId,
contentRef: this.contentRef,
}),
);
}
public notebookCut(): void {
const focusedCellId = this.getFocusedCellId();
if (!focusedCellId) {
console.error("No focused cell");
return;
}
this.getStore().dispatch(
actions.cutCell({
id: focusedCellId,
contentRef: this.contentRef,
}),
);
}
public notebookPaste(): void {
this.getStore().dispatch(
actions.pasteCell({
contentRef: this.contentRef,
}),
);
}
public notebookShutdown(): void {
const store = this.getStore();
const kernelRef = this.getCurrentKernelRef();
if (kernelRef) {
store.dispatch(
actions.killKernel({
restarting: false,
kernelRef,
}),
);
}
store.dispatch(
CdbActions.closeNotebook({
contentRef: this.contentRef,
}),
);
}
public isContentDirty(): boolean {
const content = selectors.content(this.getStore().getState(), { contentRef: this.contentRef });
if (!content) {
return false;
}
// TODO Fix this typing here
return selectors.notebook.isDirty(content.model as never);
}
public isNotebookUntrusted(): boolean {
return NotebookUtil.isNotebookUntrusted(this.getStore().getState(), this.contentRef);
}
/**
* For display purposes, only return non-killed kernels
*/
public getCurrentKernelName(): string {
const currentKernel = selectors.kernel(this.getStore().getState(), { kernelRef: this.getCurrentKernelRef() });
return (currentKernel && currentKernel.status !== "killed" && currentKernel.kernelSpecName) || undefined;
}
// Returns the kernel name to select in the kernels dropdown
public getSelectedKernelName(): string {
const currentKernelName = this.getCurrentKernelName();
if (!currentKernelName) {
// if there's no live kernel, try to get the kernel name from the notebook metadata
const content = selectors.content(this.getStore().getState(), { contentRef: this.contentRef });
const notebook = content && (content as NotebookContentRecord).model.notebook;
if (!notebook) {
return undefined;
}
const { kernelSpecName } = NotebookUtil.extractNewKernel("", notebook);
return kernelSpecName || undefined;
}
return currentKernelName;
}
public getActiveCellTypeStr(): string {
const content = selectors.content(this.getStore().getState(), { contentRef: this.contentRef });
return NteractUtil.getCurrentCellType(content as NotebookContentRecord);
}
private getCurrentKernelRef(): KernelRef {
return selectors.kernelRefByContentRef(this.getStore().getState(), { contentRef: this.contentRef });
}
private getFocusedCellId(): CellId {
const content = selectors.content(this.getStore().getState(), { contentRef: this.contentRef });
if (!content) {
return undefined;
}
return selectors.notebook.cellFocused((content as NotebookContentRecord).model);
}
protected getStore(): Store<AppState, AnyAction> {
return this.notebookClient.getStore();
}
private getSaveNotebookSubText(): JSX.Element {
return (
<>
<p>{Notebook.saveNotebookModalContent}</p>
<br />
<p>
{Notebook.newNotebookModalContent2}
<Link href={Notebook.cosmosNotebookHomePageUrl} target="_blank">
{Notebook.learnMore}
</Link>
</p>
</>
);
}
}