mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-12-21 01:41:31 +00:00
Remove Explorer Stub and ViewModel.Explorer (#101)
This commit is contained in:
@@ -7,7 +7,7 @@ import { AutopilotTier } from "../../Contracts/DataModels";
|
||||
|
||||
describe("Add Collection Pane", () => {
|
||||
describe("isValid()", () => {
|
||||
let explorer: ViewModels.Explorer;
|
||||
let explorer: Explorer;
|
||||
const mockDatabaseAccount: ViewModels.DatabaseAccount = {
|
||||
id: "mock",
|
||||
kind: "DocumentDB",
|
||||
|
||||
@@ -5,7 +5,7 @@ import AddDatabasePane from "./AddDatabasePane";
|
||||
|
||||
describe("Add Database Pane", () => {
|
||||
describe("getSharedThroughputDefault()", () => {
|
||||
let explorer: ViewModels.Explorer;
|
||||
let explorer: Explorer;
|
||||
const mockDatabaseAccount: ViewModels.DatabaseAccount = {
|
||||
id: "mock",
|
||||
kind: "DocumentDB",
|
||||
|
||||
@@ -7,11 +7,12 @@ import { KeyCodes } from "../../Common/Constants";
|
||||
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
||||
import Explorer from "../Explorer";
|
||||
|
||||
// TODO: Use specific actions for logging telemetry data
|
||||
export abstract class ContextualPaneBase extends WaitsForTemplateViewModel implements ViewModels.ContextualPane {
|
||||
public id: string;
|
||||
public container: ViewModels.Explorer;
|
||||
public container: Explorer;
|
||||
public firstFieldHasFocus: ko.Observable<boolean>;
|
||||
public formErrorsDetails: ko.Observable<string>;
|
||||
public formErrors: ko.Observable<string>;
|
||||
|
||||
@@ -9,12 +9,12 @@ import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
||||
import Explorer from "../Explorer";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs";
|
||||
import { CollectionStub, DatabaseStub } from "../OpenActionsStubs";
|
||||
import { TreeNode } from "../../Contracts/ViewModels";
|
||||
|
||||
describe("Delete Collection Confirmation Pane", () => {
|
||||
describe("Explorer.isLastCollection()", () => {
|
||||
let explorer: ViewModels.Explorer;
|
||||
let explorer: Explorer;
|
||||
|
||||
beforeEach(() => {
|
||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
||||
@@ -59,29 +59,27 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>(
|
||||
DocumentClientUtilityBase as any
|
||||
);
|
||||
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
|
||||
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false));
|
||||
let fakeExplorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
||||
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
||||
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
||||
|
||||
let pane = new DeleteCollectionConfirmationPane({
|
||||
documentClientUtility: fakeDocumentClientUtility as any,
|
||||
id: "deletecollectionconfirmationpane",
|
||||
visible: ko.observable<boolean>(false),
|
||||
container: fakeExplorer as any
|
||||
container: fakeExplorer
|
||||
});
|
||||
|
||||
fakeExplorer.isLastCollection.returns(true);
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(false);
|
||||
pane.container = fakeExplorer as any;
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
expect(pane.shouldRecordFeedback()).toBe(true);
|
||||
|
||||
fakeExplorer.isLastCollection.returns(true);
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(true);
|
||||
pane.container = fakeExplorer as any;
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => true;
|
||||
expect(pane.shouldRecordFeedback()).toBe(false);
|
||||
|
||||
fakeExplorer.isLastCollection.returns(false);
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(false);
|
||||
pane.container = fakeExplorer as any;
|
||||
fakeExplorer.isLastCollection = () => false;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
expect(pane.shouldRecordFeedback()).toBe(false);
|
||||
});
|
||||
});
|
||||
@@ -99,38 +97,34 @@ describe("Delete Collection Confirmation Pane", () => {
|
||||
|
||||
it("it should log feedback if last collection and database is not shared", () => {
|
||||
let selectedCollectionId = "testCol";
|
||||
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>(
|
||||
DocumentClientUtilityBase as any
|
||||
);
|
||||
fakeDocumentClientUtility.deleteCollection.returns(Q.resolve(null));
|
||||
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
|
||||
fakeExplorer.findSelectedCollection.returns(
|
||||
let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
|
||||
fakeDocumentClientUtility.deleteCollection = () => Q(null);
|
||||
let fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.findSelectedCollection = () =>
|
||||
new CollectionStub({
|
||||
id: ko.observable<string>(selectedCollectionId),
|
||||
rid: "test"
|
||||
})
|
||||
);
|
||||
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false));
|
||||
sinon.stub(fakeExplorer, "selectedCollectionId").value(ko.observable<string>(selectedCollectionId));
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(false);
|
||||
});
|
||||
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
||||
fakeExplorer.selectedCollectionId = ko.computed<string>(() => selectedCollectionId);
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
const SubscriptionId = "testId";
|
||||
const AccountName = "testAccount";
|
||||
sinon.stub(fakeExplorer, "databaseAccount").value(
|
||||
ko.observable<ViewModels.DatabaseAccount>({
|
||||
id: SubscriptionId,
|
||||
name: AccountName
|
||||
} as ViewModels.DatabaseAccount)
|
||||
);
|
||||
sinon.stub(fakeExplorer, "defaultExperience").value(ko.observable<string>("DocumentDB"));
|
||||
sinon.stub(fakeExplorer, "isPreferredApiCassandra").value(
|
||||
ko.computed(() => {
|
||||
return false;
|
||||
})
|
||||
);
|
||||
sinon.stub(fakeExplorer, "documentClientUtility").value(fakeDocumentClientUtility);
|
||||
sinon.stub(fakeExplorer, "selectedNode").value(ko.observable<TreeNode>());
|
||||
fakeExplorer.isLastCollection.returns(true);
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(false);
|
||||
fakeExplorer.databaseAccount = ko.observable<ViewModels.DatabaseAccount>({
|
||||
id: SubscriptionId,
|
||||
name: AccountName
|
||||
} as ViewModels.DatabaseAccount);
|
||||
|
||||
fakeExplorer.defaultExperience = ko.observable<string>("DocumentDB");
|
||||
fakeExplorer.isPreferredApiCassandra = ko.computed(() => {
|
||||
return false;
|
||||
});
|
||||
|
||||
fakeExplorer.documentClientUtility = fakeDocumentClientUtility;
|
||||
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
||||
fakeExplorer.isLastCollection = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
||||
|
||||
let pane = new DeleteCollectionConfirmationPane({
|
||||
documentClientUtility: fakeDocumentClientUtility as any,
|
||||
|
||||
@@ -8,14 +8,14 @@ import DeleteDatabaseConfirmationPane from "./DeleteDatabaseConfirmationPane";
|
||||
import DeleteFeedback from "../../Common/DeleteFeedback";
|
||||
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
|
||||
import Explorer from "../Explorer";
|
||||
import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs";
|
||||
import { CollectionStub, DatabaseStub } from "../OpenActionsStubs";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { TreeNode } from "../../Contracts/ViewModels";
|
||||
import { TabsManager } from "../Tabs/TabsManager";
|
||||
|
||||
describe("Delete Database Confirmation Pane", () => {
|
||||
describe("Explorer.isLastDatabase() and Explorer.isLastNonEmptyDatabase()", () => {
|
||||
let explorer: ViewModels.Explorer;
|
||||
let explorer: Explorer;
|
||||
|
||||
beforeEach(() => {
|
||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
||||
@@ -50,11 +50,9 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
|
||||
describe("shouldRecordFeedback()", () => {
|
||||
it("should return true if last non empty database or is last database that has shared throughput, else false", () => {
|
||||
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>(
|
||||
DocumentClientUtilityBase as any
|
||||
);
|
||||
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
|
||||
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false));
|
||||
let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
|
||||
let fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
||||
|
||||
let pane = new DeleteDatabaseConfirmationPane({
|
||||
documentClientUtility: fakeDocumentClientUtility as any,
|
||||
@@ -63,18 +61,18 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
container: fakeExplorer as any
|
||||
});
|
||||
|
||||
fakeExplorer.isLastNonEmptyDatabase.returns(true);
|
||||
fakeExplorer.isLastNonEmptyDatabase = () => true;
|
||||
pane.container = fakeExplorer as any;
|
||||
expect(pane.shouldRecordFeedback()).toBe(true);
|
||||
|
||||
fakeExplorer.isLastDatabase.returns(true);
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(true);
|
||||
fakeExplorer.isLastDatabase = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => true;
|
||||
pane.container = fakeExplorer as any;
|
||||
expect(pane.shouldRecordFeedback()).toBe(true);
|
||||
|
||||
fakeExplorer.isLastNonEmptyDatabase.returns(false);
|
||||
fakeExplorer.isLastDatabase.returns(true);
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(false);
|
||||
fakeExplorer.isLastNonEmptyDatabase = () => false;
|
||||
fakeExplorer.isLastDatabase = () => true;
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
pane.container = fakeExplorer as any;
|
||||
expect(pane.shouldRecordFeedback()).toBe(false);
|
||||
});
|
||||
@@ -93,39 +91,33 @@ describe("Delete Database Confirmation Pane", () => {
|
||||
|
||||
it("on submit() it should log feedback if last non empty database or is last database that has shared throughput", () => {
|
||||
let selectedDatabaseId = "testDB";
|
||||
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>(
|
||||
DocumentClientUtilityBase as any
|
||||
);
|
||||
fakeDocumentClientUtility.deleteDatabase.returns(Q.resolve(null));
|
||||
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
|
||||
fakeExplorer.findSelectedDatabase.returns(
|
||||
let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
|
||||
fakeDocumentClientUtility.deleteDatabase = () => Q.resolve(null);
|
||||
let fakeExplorer = {} as Explorer;
|
||||
fakeExplorer.findSelectedDatabase = () =>
|
||||
new DatabaseStub({
|
||||
id: ko.observable<string>(selectedDatabaseId),
|
||||
rid: "test",
|
||||
collections: ko.observableArray<ViewModels.Collection>()
|
||||
})
|
||||
);
|
||||
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false));
|
||||
sinon.stub(fakeExplorer, "selectedDatabaseId").value(ko.observable<string>(selectedDatabaseId));
|
||||
fakeExplorer.isSelectedDatabaseShared.returns(false);
|
||||
});
|
||||
fakeExplorer.refreshAllDatabases = () => Q.resolve();
|
||||
fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
|
||||
fakeExplorer.selectedDatabaseId = ko.computed<string>(() => selectedDatabaseId);
|
||||
fakeExplorer.isSelectedDatabaseShared = () => false;
|
||||
const SubscriptionId = "testId";
|
||||
const AccountName = "testAccount";
|
||||
sinon.stub(fakeExplorer, "databaseAccount").value(
|
||||
ko.observable<ViewModels.DatabaseAccount>({
|
||||
id: SubscriptionId,
|
||||
name: AccountName
|
||||
} as ViewModels.DatabaseAccount)
|
||||
);
|
||||
sinon.stub(fakeExplorer, "defaultExperience").value(ko.observable<string>("DocumentDB"));
|
||||
sinon.stub(fakeExplorer, "isPreferredApiCassandra").value(
|
||||
ko.computed(() => {
|
||||
return false;
|
||||
})
|
||||
);
|
||||
sinon.stub(fakeExplorer, "documentClientUtility").value(fakeDocumentClientUtility);
|
||||
sinon.stub(fakeExplorer, "selectedNode").value(ko.observable<TreeNode>());
|
||||
sinon.stub(fakeExplorer, "tabsManager").value(new TabsManager());
|
||||
fakeExplorer.isLastNonEmptyDatabase.returns(true);
|
||||
fakeExplorer.databaseAccount = ko.observable<ViewModels.DatabaseAccount>({
|
||||
id: SubscriptionId,
|
||||
name: AccountName
|
||||
} as ViewModels.DatabaseAccount);
|
||||
fakeExplorer.defaultExperience = ko.observable<string>("DocumentDB");
|
||||
fakeExplorer.isPreferredApiCassandra = ko.computed(() => {
|
||||
return false;
|
||||
});
|
||||
fakeExplorer.documentClientUtility = fakeDocumentClientUtility;
|
||||
fakeExplorer.selectedNode = ko.observable<TreeNode>();
|
||||
fakeExplorer.tabsManager = new TabsManager();
|
||||
fakeExplorer.isLastNonEmptyDatabase = () => true;
|
||||
|
||||
let pane = new DeleteDatabaseConfirmationPane({
|
||||
documentClientUtility: fakeDocumentClientUtility as any,
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import * as React from "react";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { IconButton, PrimaryButton } from "office-ui-fabric-react/lib/Button";
|
||||
import { KeyCodes } from "../../Common/Constants";
|
||||
import { Subscription } from "knockout";
|
||||
import ErrorRedIcon from "../../../images/error_red.svg";
|
||||
import LoadingIndicatorIcon from "../../../images/LoadingIndicator_3Squares.gif";
|
||||
import Explorer from "../Explorer";
|
||||
|
||||
export interface GenericRightPaneProps {
|
||||
container: ViewModels.Explorer;
|
||||
container: Explorer;
|
||||
content: JSX.Element;
|
||||
formError: string;
|
||||
formErrorDetail: string;
|
||||
|
||||
@@ -2,9 +2,10 @@ import * as ko from "knockout";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { ContextualPaneBase } from "./ContextualPaneBase";
|
||||
import { KeyCodes } from "../../Common/Constants";
|
||||
import Explorer from "../Explorer";
|
||||
|
||||
export default class NewVertexPane extends ContextualPaneBase implements ViewModels.NewVertexPane {
|
||||
public container: ViewModels.Explorer;
|
||||
public container: Explorer;
|
||||
public visible: ko.Observable<boolean>;
|
||||
public formErrors: ko.Observable<string>;
|
||||
public formErrorsDetails: ko.Observable<string>;
|
||||
|
||||
@@ -1,156 +1,156 @@
|
||||
import ko from "knockout";
|
||||
import * as React from "react";
|
||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||
import * as Logger from "../../Common/Logger";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { JunoClient } from "../../Juno/JunoClient";
|
||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent";
|
||||
import { PublishNotebookPaneComponent, PublishNotebookPaneProps } from "./PublishNotebookPaneComponent";
|
||||
|
||||
export class PublishNotebookPaneAdapter implements ReactAdapter {
|
||||
parameters: ko.Observable<number>;
|
||||
private isOpened: boolean;
|
||||
private isExecuting: boolean;
|
||||
private formError: string;
|
||||
private formErrorDetail: string;
|
||||
|
||||
private name: string;
|
||||
private author: string;
|
||||
private content: string;
|
||||
private description: string;
|
||||
private tags: string;
|
||||
private imageSrc: string;
|
||||
|
||||
constructor(private container: ViewModels.Explorer, private junoClient: JunoClient) {
|
||||
this.parameters = ko.observable(Date.now());
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public renderComponent(): JSX.Element {
|
||||
if (!this.isOpened) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const props: GenericRightPaneProps = {
|
||||
container: this.container,
|
||||
content: this.createContent(),
|
||||
formError: this.formError,
|
||||
formErrorDetail: this.formErrorDetail,
|
||||
id: "publishnotebookpane",
|
||||
isExecuting: this.isExecuting,
|
||||
title: "Publish to gallery",
|
||||
submitButtonText: "Publish",
|
||||
onClose: () => this.close(),
|
||||
onSubmit: () => this.submit()
|
||||
};
|
||||
|
||||
return <GenericRightPaneComponent {...props} />;
|
||||
}
|
||||
|
||||
public triggerRender(): void {
|
||||
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
||||
}
|
||||
|
||||
public open(name: string, author: string, content: string): void {
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
this.content = content;
|
||||
|
||||
this.isOpened = true;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public async submit(): Promise<void> {
|
||||
const notificationId = NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.InProgress,
|
||||
`Publishing ${this.name} to gallery`
|
||||
);
|
||||
this.isExecuting = true;
|
||||
this.triggerRender();
|
||||
|
||||
try {
|
||||
if (!this.name || !this.description || !this.author) {
|
||||
throw new Error("Name, description, and author are required");
|
||||
}
|
||||
|
||||
const response = await this.junoClient.publishNotebook(
|
||||
this.name,
|
||||
this.description,
|
||||
this.tags?.split(","),
|
||||
this.author,
|
||||
this.imageSrc,
|
||||
this.content
|
||||
);
|
||||
if (!response.data) {
|
||||
throw new Error(`Received HTTP ${response.status} when publishing ${name} to gallery`);
|
||||
}
|
||||
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Published ${name} to gallery`);
|
||||
} catch (error) {
|
||||
this.formError = `Failed to publish ${this.name} to gallery`;
|
||||
this.formErrorDetail = `${error}`;
|
||||
|
||||
const message = `${this.formError}: ${this.formErrorDetail}`;
|
||||
Logger.logError(message, "PublishNotebookPaneAdapter/submit");
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
|
||||
return;
|
||||
} finally {
|
||||
NotificationConsoleUtils.clearInProgressMessageWithId(notificationId);
|
||||
this.isExecuting = false;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
this.close();
|
||||
}
|
||||
|
||||
private createFormErrorForLargeImageSelection = (formError: string, formErrorDetail: string, area: string): void => {
|
||||
this.formError = formError;
|
||||
this.formErrorDetail = formErrorDetail;
|
||||
|
||||
const message = `${this.formError}: ${this.formErrorDetail}`;
|
||||
Logger.logError(message, area);
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
|
||||
this.triggerRender();
|
||||
};
|
||||
|
||||
private clearFormError = (): void => {
|
||||
this.formError = undefined;
|
||||
this.formErrorDetail = undefined;
|
||||
this.triggerRender();
|
||||
};
|
||||
|
||||
private createContent = (): JSX.Element => {
|
||||
const publishNotebookPaneProps: PublishNotebookPaneProps = {
|
||||
notebookName: this.name,
|
||||
notebookDescription: "",
|
||||
notebookTags: "",
|
||||
notebookAuthor: this.author,
|
||||
notebookCreatedDate: new Date().toISOString(),
|
||||
onChangeDescription: (newValue: string) => (this.description = newValue),
|
||||
onChangeTags: (newValue: string) => (this.tags = newValue),
|
||||
onChangeImageSrc: (newValue: string) => (this.imageSrc = newValue),
|
||||
onError: this.createFormErrorForLargeImageSelection,
|
||||
clearFormError: this.clearFormError
|
||||
};
|
||||
|
||||
return <PublishNotebookPaneComponent {...publishNotebookPaneProps} />;
|
||||
};
|
||||
|
||||
private reset = (): void => {
|
||||
this.isOpened = false;
|
||||
this.isExecuting = false;
|
||||
this.formError = undefined;
|
||||
this.formErrorDetail = undefined;
|
||||
this.name = undefined;
|
||||
this.author = undefined;
|
||||
this.content = undefined;
|
||||
};
|
||||
}
|
||||
import ko from "knockout";
|
||||
import * as React from "react";
|
||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||
import * as Logger from "../../Common/Logger";
|
||||
import { JunoClient } from "../../Juno/JunoClient";
|
||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent";
|
||||
import Explorer from "../Explorer";
|
||||
import { PublishNotebookPaneComponent, PublishNotebookPaneProps } from "./PublishNotebookPaneComponent";
|
||||
|
||||
export class PublishNotebookPaneAdapter implements ReactAdapter {
|
||||
parameters: ko.Observable<number>;
|
||||
private isOpened: boolean;
|
||||
private isExecuting: boolean;
|
||||
private formError: string;
|
||||
private formErrorDetail: string;
|
||||
|
||||
private name: string;
|
||||
private author: string;
|
||||
private content: string;
|
||||
private description: string;
|
||||
private tags: string;
|
||||
private imageSrc: string;
|
||||
|
||||
constructor(private container: Explorer, private junoClient: JunoClient) {
|
||||
this.parameters = ko.observable(Date.now());
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public renderComponent(): JSX.Element {
|
||||
if (!this.isOpened) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const props: GenericRightPaneProps = {
|
||||
container: this.container,
|
||||
content: this.createContent(),
|
||||
formError: this.formError,
|
||||
formErrorDetail: this.formErrorDetail,
|
||||
id: "publishnotebookpane",
|
||||
isExecuting: this.isExecuting,
|
||||
title: "Publish to gallery",
|
||||
submitButtonText: "Publish",
|
||||
onClose: () => this.close(),
|
||||
onSubmit: () => this.submit()
|
||||
};
|
||||
|
||||
return <GenericRightPaneComponent {...props} />;
|
||||
}
|
||||
|
||||
public triggerRender(): void {
|
||||
window.requestAnimationFrame(() => this.parameters(Date.now()));
|
||||
}
|
||||
|
||||
public open(name: string, author: string, content: string): void {
|
||||
this.name = name;
|
||||
this.author = author;
|
||||
this.content = content;
|
||||
|
||||
this.isOpened = true;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
public async submit(): Promise<void> {
|
||||
const notificationId = NotificationConsoleUtils.logConsoleMessage(
|
||||
ConsoleDataType.InProgress,
|
||||
`Publishing ${this.name} to gallery`
|
||||
);
|
||||
this.isExecuting = true;
|
||||
this.triggerRender();
|
||||
|
||||
try {
|
||||
if (!this.name || !this.description || !this.author) {
|
||||
throw new Error("Name, description, and author are required");
|
||||
}
|
||||
|
||||
const response = await this.junoClient.publishNotebook(
|
||||
this.name,
|
||||
this.description,
|
||||
this.tags?.split(","),
|
||||
this.author,
|
||||
this.imageSrc,
|
||||
this.content
|
||||
);
|
||||
if (!response.data) {
|
||||
throw new Error(`Received HTTP ${response.status} when publishing ${name} to gallery`);
|
||||
}
|
||||
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Published ${name} to gallery`);
|
||||
} catch (error) {
|
||||
this.formError = `Failed to publish ${this.name} to gallery`;
|
||||
this.formErrorDetail = `${error}`;
|
||||
|
||||
const message = `${this.formError}: ${this.formErrorDetail}`;
|
||||
Logger.logError(message, "PublishNotebookPaneAdapter/submit");
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
|
||||
return;
|
||||
} finally {
|
||||
NotificationConsoleUtils.clearInProgressMessageWithId(notificationId);
|
||||
this.isExecuting = false;
|
||||
this.triggerRender();
|
||||
}
|
||||
|
||||
this.close();
|
||||
}
|
||||
|
||||
private createFormErrorForLargeImageSelection = (formError: string, formErrorDetail: string, area: string): void => {
|
||||
this.formError = formError;
|
||||
this.formErrorDetail = formErrorDetail;
|
||||
|
||||
const message = `${this.formError}: ${this.formErrorDetail}`;
|
||||
Logger.logError(message, area);
|
||||
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
|
||||
this.triggerRender();
|
||||
};
|
||||
|
||||
private clearFormError = (): void => {
|
||||
this.formError = undefined;
|
||||
this.formErrorDetail = undefined;
|
||||
this.triggerRender();
|
||||
};
|
||||
|
||||
private createContent = (): JSX.Element => {
|
||||
const publishNotebookPaneProps: PublishNotebookPaneProps = {
|
||||
notebookName: this.name,
|
||||
notebookDescription: "",
|
||||
notebookTags: "",
|
||||
notebookAuthor: this.author,
|
||||
notebookCreatedDate: new Date().toISOString(),
|
||||
onChangeDescription: (newValue: string) => (this.description = newValue),
|
||||
onChangeTags: (newValue: string) => (this.tags = newValue),
|
||||
onChangeImageSrc: (newValue: string) => (this.imageSrc = newValue),
|
||||
onError: this.createFormErrorForLargeImageSelection,
|
||||
clearFormError: this.clearFormError
|
||||
};
|
||||
|
||||
return <PublishNotebookPaneComponent {...publishNotebookPaneProps} />;
|
||||
};
|
||||
|
||||
private reset = (): void => {
|
||||
this.isOpened = false;
|
||||
this.isExecuting = false;
|
||||
this.formError = undefined;
|
||||
this.formErrorDetail = undefined;
|
||||
this.name = undefined;
|
||||
this.author = undefined;
|
||||
this.content = undefined;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import Explorer from "../Explorer";
|
||||
|
||||
describe("Settings Pane", () => {
|
||||
describe("shouldShowQueryPageOptions()", () => {
|
||||
let explorer: ViewModels.Explorer;
|
||||
let explorer: Explorer;
|
||||
|
||||
beforeEach(() => {
|
||||
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
|
||||
|
||||
@@ -8,9 +8,10 @@ import * as Utilities from "../../Tables/Utilities";
|
||||
import * as TableConstants from "../../Tables/Constants";
|
||||
import EntityPropertyViewModel from "./EntityPropertyViewModel";
|
||||
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
|
||||
import Explorer from "../../Explorer";
|
||||
|
||||
export default class EditTableEntityPane extends TableEntityPane implements ViewModels.EditTableEntityPane {
|
||||
container: ViewModels.Explorer;
|
||||
container: Explorer;
|
||||
visible: ko.Observable<boolean>;
|
||||
|
||||
public originEntity: Entities.ITableEntity;
|
||||
|
||||
@@ -10,6 +10,7 @@ import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
|
||||
import { UploadDetailsRecord, UploadDetails } from "../../workers/upload/definitions";
|
||||
import InfoBubbleIcon from "../../../images/info-bubble.svg";
|
||||
import Explorer from "../Explorer";
|
||||
|
||||
const UPLOAD_FILE_SIZE_LIMIT = 2097152;
|
||||
|
||||
@@ -23,7 +24,7 @@ export class UploadItemsPaneAdapter implements ReactAdapter {
|
||||
private selectedFilesTitle: string;
|
||||
private uploadFileData: UploadDetailsRecord[];
|
||||
|
||||
public constructor(private container: ViewModels.Explorer) {
|
||||
public constructor(private container: Explorer) {
|
||||
this.parameters = ko.observable(Date.now());
|
||||
this.reset();
|
||||
this.triggerRender();
|
||||
|
||||
Reference in New Issue
Block a user