From eab6506940b7018378c1e200358c80be0288d6f2 Mon Sep 17 00:00:00 2001 From: Steve Faulkner Date: Mon, 20 Jul 2020 12:59:40 -0500 Subject: [PATCH] Remove Explorer Stub and ViewModel.Explorer (#101) --- .github/workflows/ci.yml | 1 + src/Common/EnvironmentUtility.ts | 3 +- src/Common/QueriesClient.ts | 3 +- src/Contracts/ViewModels.ts | 221 +-------- src/Explorer/ContextMenuButtonFactory.ts | 14 +- .../Controls/GitHub/AddRepoComponent.tsx | 4 +- .../GalleryAndNotebookViewerComponent.tsx | 4 +- .../GalleryViewerComponent.tsx | 4 +- .../NotebookViewerComponent.tsx | 3 +- .../QueriesGridComponent.tsx | 2 +- .../QueriesGridComponentAdapter.tsx | 3 +- .../ContainerSampleGenerator.test.ts | 7 +- .../DataSamples/ContainerSampleGenerator.ts | 5 +- .../DataSamples/DataSamplesUtil.test.ts | 5 +- src/Explorer/DataSamples/DataSamplesUtil.ts | 3 +- src/Explorer/Explorer.ts | 4 +- .../CommandBar/CommandBarComponentAdapter.tsx | 5 +- .../CommandBarComponentButtonFactory.test.ts | 20 +- .../CommandBarComponentButtonFactory.ts | 45 +- .../NotificationConsoleComponentAdapter.tsx | 5 +- .../MostRecentActivity/MostRecentActivity.ts | 3 +- .../Notebook/NotebookContainerClient.ts | 2 +- src/Explorer/Notebook/NotebookManager.ts | 3 +- src/Explorer/OpenActions.test.ts | 15 +- src/Explorer/OpenActions.ts | 7 +- src/Explorer/OpenActionsStubs.ts | 420 +----------------- src/Explorer/Panes/AddCollectionPane.test.ts | 2 +- src/Explorer/Panes/AddDatabasePane.test.ts | 2 +- src/Explorer/Panes/ContextualPaneBase.ts | 3 +- .../DeleteCollectionConfirmationPane.test.ts | 76 ++-- .../DeleteDatabaseConfirmationPane.test.ts | 72 ++- .../Panes/GenericRightPaneComponent.tsx | 4 +- src/Explorer/Panes/NewVertexPane.ts | 3 +- .../Panes/PublishNotebookPaneAdapter.tsx | 312 ++++++------- src/Explorer/Panes/SettingsPane.test.ts | 2 +- .../Panes/Tables/EditTableEntityPane.ts | 3 +- src/Explorer/Panes/UploadItemsPaneAdapter.tsx | 3 +- .../SplashScreenComponentApdapter.tsx | 3 +- .../DataTable/DataTableBindingManager.ts | 2 +- .../Tables/DataTable/TableCommands.ts | 5 +- src/Explorer/Tables/TableDataClient.ts | 9 +- src/Explorer/Tabs/ConflictsTab.ts | 3 +- src/Explorer/Tabs/DatabaseSettingsTab.ts | 3 +- src/Explorer/Tabs/DocumentsTab.ts | 3 +- src/Explorer/Tabs/GalleryTab.tsx | 5 +- src/Explorer/Tabs/MongoShellTab.ts | 3 +- src/Explorer/Tabs/NotebookV2Tab.ts | 5 +- src/Explorer/Tabs/NotebookViewerTab.tsx | 5 +- src/Explorer/Tabs/QueryTab.test.ts | 6 +- src/Explorer/Tabs/QueryTab.ts | 2 +- src/Explorer/Tabs/QueryTablesTab.ts | 3 +- src/Explorer/Tabs/SettingsTab.test.ts | 4 +- src/Explorer/Tabs/SettingsTab.ts | 3 +- src/Explorer/Tabs/SparkMasterTab.ts | 3 +- src/Explorer/Tabs/TabsBase.ts | 5 +- src/Explorer/Tabs/TabsManager.test.ts | 2 +- src/Explorer/Tabs/TabsManager.ts | 3 +- src/Explorer/Tabs/TerminalTab.tsx | 5 +- src/Explorer/Tree/Collection.test.ts | 9 +- src/Explorer/Tree/Collection.ts | 5 +- src/Explorer/Tree/Database.ts | 5 +- src/Explorer/Tree/ResourceTokenCollection.ts | 5 +- src/Explorer/Tree/ResourceTreeAdapter.tsx | 5 +- ...sourceTreeAdapterForResourceToken.test.tsx | 9 +- .../ResourceTreeAdapterForResourceToken.tsx | 3 +- src/Explorer/Tree/StoredProcedure.ts | 5 +- src/Explorer/Tree/Trigger.ts | 5 +- src/Explorer/Tree/UserDefinedFunction.ts | 5 +- src/GitHub/GitHubOAuthService.test.ts | 5 +- src/Main.ts | 5 +- src/Platform/Emulator/ExplorerFactory.ts | 3 +- src/Platform/Emulator/Main.ts | 7 +- src/Platform/Hosted/Authorization.ts | 2 +- src/Platform/Hosted/ExplorerFactory.ts | 4 +- src/Platform/Hosted/Main.ts | 29 +- src/Platform/Portal/DataAccessUtility.ts | 2 +- src/Platform/Portal/ExplorerFactory.ts | 2 +- src/Platform/Portal/Main.ts | 4 +- src/RouteHandlers/TabRouteHandler.ts | 14 +- src/Shared/AddCollectionUtility.ts | 8 +- src/Utils/AuthorizationUtils.ts | 4 +- src/Utils/GalleryUtils.test.ts | 10 +- src/Utils/GalleryUtils.ts | 10 +- src/Utils/NotebookConfigurationUtils.ts | 4 +- src/applyExplorerBindings.ts | 2 +- src/global.d.ts | 2 +- 86 files changed, 469 insertions(+), 1079 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd3558ff8..8c29fa13a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: CI on: push: + branches: [master] pull_request: branches: [master] jobs: diff --git a/src/Common/EnvironmentUtility.ts b/src/Common/EnvironmentUtility.ts index 781ecae7b..3d9925503 100644 --- a/src/Common/EnvironmentUtility.ts +++ b/src/Common/EnvironmentUtility.ts @@ -2,6 +2,7 @@ import * as Constants from "../Common/Constants"; import * as ViewModels from "../Contracts/ViewModels"; import { AuthType } from "../AuthType"; import { StringUtils } from "../Utils/StringUtils"; +import Explorer from "../Explorer/Explorer"; export default class EnvironmentUtility { public static getMongoBackendEndpoint(serverId: string, location: string, extensionEndpoint: string = ""): string { @@ -26,7 +27,7 @@ export default class EnvironmentUtility { return window.authType === AuthType.AAD; } - public static getCassandraBackendEndpoint(explorer: ViewModels.Explorer): string { + public static getCassandraBackendEndpoint(explorer: Explorer): string { const defaultLocation: string = "default"; const location: string = EnvironmentUtility.normalizeRegionName(explorer.databaseAccount().location); return ( diff --git a/src/Common/QueriesClient.ts b/src/Common/QueriesClient.ts index 889308e5d..a957f29bc 100644 --- a/src/Common/QueriesClient.ts +++ b/src/Common/QueriesClient.ts @@ -10,6 +10,7 @@ import { ItemDefinition, QueryIterator, Resource } from "@azure/cosmos"; import * as Logger from "./Logger"; import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils"; import { QueryUtils } from "../Utils/QueryUtils"; +import Explorer from "../Explorer/Explorer"; export class QueriesClient implements ViewModels.QueriesClient { private static readonly PartitionKey: DataModels.PartitionKey = { @@ -20,7 +21,7 @@ export class QueriesClient implements ViewModels.QueriesClient { private static readonly FetchQuery: string = "SELECT * FROM c"; private static readonly FetchMongoQuery: string = "{}"; - public constructor(private container: ViewModels.Explorer) {} + public constructor(private container: Explorer) {} public async setupQueriesCollection(): Promise { const queriesCollection: ViewModels.Collection = this.findQueriesCollection(); diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index 34061d385..ee8b3b680 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -6,27 +6,17 @@ import Q from "q"; import QueryViewModel from "../Explorer/Tables/QueryBuilder/QueryViewModel"; import TableEntityListViewModel from "../Explorer/Tables/DataTable/TableEntityListViewModel"; import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList"; -import { ArcadiaWorkspaceItem } from "../Explorer/Controls/Arcadia/ArcadiaMenuPicker"; -import { CassandraTableKey, CassandraTableKeys, TableDataClient } from "../Explorer/Tables/TableDataClient"; +import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient"; import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent"; import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { ExecuteSprocParam } from "../Explorer/Panes/ExecuteSprocParamsPane"; import { GitHubClient } from "../GitHub/GitHubClient"; import { IColumnSetting } from "../Explorer/Panes/Tables/TableColumnOptionsPane"; import { JunoClient, IGalleryItem } from "../Juno/JunoClient"; -import { Library } from "./DataModels"; -import { MostRecentActivity } from "../Explorer/MostRecentActivity/MostRecentActivity"; import { NotebookContentItem } from "../Explorer/Notebook/NotebookContentItem"; -import { PlatformType } from "../PlatformType"; import { QueryMetrics } from "@azure/cosmos"; -import { SetupNotebooksPane } from "../Explorer/Panes/SetupNotebooksPane"; -import { Splitter } from "../Common/Splitter"; -import { StringInputPane } from "../Explorer/Panes/StringInputPane"; -import { TabsManager } from "../Explorer/Tabs/TabsManager"; -import { TextFieldProps } from "../Explorer/Controls/DialogReactComponent/DialogComponent"; import { UploadDetails } from "../workers/upload/definitions"; -import { UploadItemsPaneAdapter } from "../Explorer/Panes/UploadItemsPaneAdapter"; -import { ReactAdapter } from "../Bindings/ReactBindingHandler"; +import Explorer from "../Explorer/Explorer"; export interface ExplorerOptions { documentClientUtility: DocumentClientUtilityBase; @@ -42,213 +32,6 @@ export interface NavbarButtonConfig extends CommandButtonComponentProps {} export interface DatabaseAccount extends DataModels.DatabaseAccount {} -export interface Explorer { - flight: ko.Observable; - handleMessage(event: MessageEvent): void; - isRefreshingExplorer: ko.Observable; - - databaseAccount: ko.Observable; - subscriptionType: ko.Observable; - quotaId: ko.Observable; - hasWriteAccess: ko.Observable; - - defaultExperience: ko.Observable; - isPreferredApiDocumentDB: ko.Computed; - isPreferredApiCassandra: ko.Computed; - isPreferredApiTable: ko.Computed; - isPreferredApiGraph: ko.Computed; - isPreferredApiMongoDB: ko.Computed; - - isFixedCollectionWithSharedThroughputSupported: ko.Computed; - - isDatabaseNodeOrNoneSelected(): boolean; - isDatabaseNodeSelected(): boolean; - isNodeKindSelected(nodeKind: string): boolean; - isNoneSelected(): boolean; - isSelectedDatabaseShared(): boolean; - deleteDatabaseText: ko.Observable; - deleteCollectionText: ko.Subscribable; // Our code assigns to a ko.Observable, but unit test assigns to ko.Computed - - addCollectionText: ko.Observable; - addDatabaseText: ko.Observable; - collectionTitle: ko.Observable; - collectionTreeNodeAltText: ko.Observable; - refreshTreeTitle: ko.Observable; - - isAccountReady: ko.Observable; - - collectionCreationDefaults: CollectionCreationDefaults; - isEmulator: boolean; - features: ko.Observable; - serverId: ko.Observable; - extensionEndpoint: ko.Observable; - armEndpoint: ko.Observable; - isFeatureEnabled: (feature: string) => boolean; - isGalleryPublishEnabled: ko.Computed; - isGitHubPaneEnabled: ko.Observable; - isPublishNotebookPaneEnabled: ko.Observable; - isRightPanelV2Enabled: ko.Computed; - canExceedMaximumValue: ko.Computed; - hasAutoPilotV2FeatureFlag: ko.Computed; - isHostedDataExplorerEnabled: ko.Computed; - isNotificationConsoleExpanded: ko.Observable; - isTryCosmosDBSubscription: ko.Observable; - canSaveQueries: ko.Computed; - parentFrameDataExplorerVersion: ko.Observable; - - documentClientUtility: DocumentClientUtilityBase; - notificationsClient: NotificationsClient; - queriesClient: QueriesClient; - tableDataClient: TableDataClient; - splitter: Splitter; - notificationConsoleData: ko.ObservableArray; - - // Selection - selectedNode: ko.Observable; - - // Tree - databases: ko.ObservableArray; - nonSystemDatabases: ko.Computed; - selectedDatabaseId: ko.Computed; - selectedCollectionId: ko.Computed; - isLeftPaneExpanded: ko.Observable; - - // Resource Token - resourceTokenDatabaseId: ko.Observable; - resourceTokenCollectionId: ko.Observable; - resourceTokenCollection: ko.Observable; - resourceTokenPartitionKey: ko.Observable; - isAuthWithResourceToken: ko.Observable; - isResourceTokenCollectionNodeSelected: ko.Computed; - - // Tabs - isTabsContentExpanded: ko.Observable; - tabsManager: TabsManager; - - // Contextual Panes - addDatabasePane: AddDatabasePane; - addCollectionPane: AddCollectionPane; - deleteCollectionConfirmationPane: DeleteCollectionConfirmationPane; - deleteDatabaseConfirmationPane: DeleteDatabaseConfirmationPane; - graphStylingPane: GraphStylingPane; - addTableEntityPane: AddTableEntityPane; - editTableEntityPane: EditTableEntityPane; - tableColumnOptionsPane: TableColumnOptionsPane; - querySelectPane: QuerySelectPane; - newVertexPane: NewVertexPane; - cassandraAddCollectionPane: CassandraAddCollectionPane; - settingsPane: SettingsPane; - executeSprocParamsPane: ExecuteSprocParamsPane; - renewAdHocAccessPane: RenewAdHocAccessPane; - uploadItemsPane: UploadItemsPane; - uploadItemsPaneAdapter: UploadItemsPaneAdapter; - loadQueryPane: LoadQueryPane; - saveQueryPane: ContextualPane; - browseQueriesPane: BrowseQueriesPane; - uploadFilePane: UploadFilePane; - stringInputPane: StringInputPane; - setupNotebooksPane: SetupNotebooksPane; - gitHubReposPane: ContextualPane; - publishNotebookPaneAdapter: ReactAdapter; - - // Facade - logConsoleData(data: ConsoleData): void; - isNodeKindSelected(nodeKind: string): boolean; - initDataExplorerWithFrameInputs(inputs: DataExplorerInputsFrame): Q.Promise; - toggleLeftPaneExpanded(): void; - refreshDatabaseForResourceToken(): Q.Promise; - refreshAllDatabases(isInitialLoad?: boolean): Q.Promise; - closeAllPanes(): void; - findSelectedDatabase(): Database; - findDatabaseWithId(databaseRid: string): Database; - isLastDatabase(): boolean; - isLastNonEmptyDatabase(): boolean; - findSelectedCollection(): Collection; - isLastCollection(): boolean; - findSelectedStoredProcedure(): StoredProcedure; - findSelectedUDF(): UserDefinedFunction; - findSelectedTrigger(): Trigger; - findCollection(rid: string): Collection; - provideFeedbackEmail(): void; - expandConsole: () => void; - collapseConsole: () => void; - generateSharedAccessData(): void; - getPlatformType(): PlatformType; - isConnectExplorerVisible(): boolean; - isRunningOnNationalCloud(): boolean; - displayConnectExplorerForm(): void; - hideConnectExplorerForm(): void; - displayContextSwitchPromptForConnectionString(connectionString: string): void; - displayGuestAccessTokenRenewalPrompt(): void; - rebindDocumentClientUtility(documentClientUtility: DocumentClientUtilityBase): void; - renewExplorerShareAccess: (explorer: Explorer, token: string) => Q.Promise; - renewShareAccess(accessInput: string): Q.Promise; - onUpdateTabsButtons: (buttons: NavbarButtonConfig[]) => void; - onNewCollectionClicked: () => void; - showOkModalDialog: (title: string, msg: string) => void; - showOkCancelModalDialog: ( - title: string, - msg: string, - okLabel: string, - onOk: () => void, - cancelLabel: string, - onCancel: () => void - ) => void; - showOkCancelTextFieldModalDialog: ( - title: string, - msg: string, - okLabel: string, - onOk: () => void, - cancelLabel: string, - onCancel: () => void, - textFiledProps: TextFieldProps, - isPrimaryButtonDisabled?: boolean - ) => void; - - // Analytics - isNotebookEnabled: ko.Observable; - isSparkEnabled: ko.Observable; - isNotebooksEnabledForAccount: ko.Observable; - isSparkEnabledForAccount: ko.Observable; - hasStorageAnalyticsAfecFeature: ko.Observable; - openEnableSynapseLinkDialog(): void; - isSynapseLinkUpdating: ko.Observable; - notebookServerInfo: ko.Observable; - sparkClusterConnectionInfo: ko.Observable; - arcadiaToken: ko.Observable; - arcadiaWorkspaces: ko.ObservableArray; - memoryUsageInfo: ko.Observable; - notebookManager?: any; // This is dynamically loaded - openNotebook(notebookContentItem: NotebookContentItem): Promise; // True if it was opened, false otherwise - resetNotebookWorkspace(): void; - importAndOpen: (path: string) => Promise; - importAndOpenContent: (name: string, content: string) => Promise; - publishNotebook: (name: string, content: string) => void; - openNotebookTerminal: (kind: TerminalKind) => void; - openGallery: (notebookUrl?: string, galleryItem?: IGalleryItem, isFavorite?: boolean) => void; - openNotebookViewer: (notebookUrl: string) => void; - notebookWorkspaceManager: NotebookWorkspaceManager; - mostRecentActivity: MostRecentActivity; - initNotebooks: (databaseAccount: DataModels.DatabaseAccount) => Promise; - handleOpenFileAction(path: string): Promise; - - // Notebook operations - openNotebook(notebookContentItem: NotebookContentItem): Promise; // True if it was opened, false otherwise - deleteNotebookFile: (item: NotebookContentItem) => Promise; - onCreateDirectory(parent: NotebookContentItem): Q.Promise; - onNewNotebookClicked: (parent?: NotebookContentItem) => void; - onUploadToNotebookServerClicked: (parent?: NotebookContentItem) => void; - renameNotebook: (notebookFile: NotebookContentItem) => Q.Promise; - readFile: (notebookFile: NotebookContentItem) => Promise; - downloadFile: (notebookFile: NotebookContentItem) => Promise; - createNotebookContentItemFile: (name: string, filepath: string) => NotebookContentItem; - refreshContentItem(item: NotebookContentItem): Promise; - getNotebookBasePath(): string; - - createWorkspace(): Promise; - createSparkPool(workspaceId: string): Promise; -} - export interface NotebookWorkspaceManager { getNotebookWorkspacesAsync(cosmosAccountResourceId: string): Promise; getNotebookWorkspaceAsync( diff --git a/src/Explorer/ContextMenuButtonFactory.ts b/src/Explorer/ContextMenuButtonFactory.ts index 211b0232f..7b99409f0 100644 --- a/src/Explorer/ContextMenuButtonFactory.ts +++ b/src/Explorer/ContextMenuButtonFactory.ts @@ -12,6 +12,7 @@ import AddTriggerIcon from "../../images/AddTrigger.svg"; import DeleteTriggerIcon from "../../images/DeleteTrigger.svg"; import DeleteUDFIcon from "../../images/DeleteUDF.svg"; import DeleteSprocIcon from "../../images/DeleteSproc.svg"; +import Explorer from "./Explorer"; export interface CollectionContextMenuButtonParams { databaseId: string; @@ -26,7 +27,7 @@ export interface DatabaseContextMenuButtonParams { */ export class ResourceTreeContextMenuButtonFactory { public static createDatabaseContextMenu( - container: ViewModels.Explorer, + container: Explorer, selectedDatabase: ViewModels.Database ): TreeNodeMenuItem[] { const newCollectionMenuItem: TreeNodeMenuItem = { @@ -44,7 +45,7 @@ export class ResourceTreeContextMenuButtonFactory { } public static createCollectionContextMenuButton( - container: ViewModels.Explorer, + container: Explorer, selectedCollection: ViewModels.Collection ): TreeNodeMenuItem[] { const items: TreeNodeMenuItem[] = []; @@ -115,7 +116,7 @@ export class ResourceTreeContextMenuButtonFactory { } public static createStoreProcedureContextMenuItems( - container: ViewModels.Explorer, + container: Explorer, storedProcedure: ViewModels.StoredProcedure ): TreeNodeMenuItem[] { if (container.isPreferredApiCassandra()) { @@ -131,10 +132,7 @@ export class ResourceTreeContextMenuButtonFactory { ]; } - public static createTriggerContextMenuItems( - container: ViewModels.Explorer, - trigger: ViewModels.Trigger - ): TreeNodeMenuItem[] { + public static createTriggerContextMenuItems(container: Explorer, trigger: ViewModels.Trigger): TreeNodeMenuItem[] { if (container.isPreferredApiCassandra()) { return []; } @@ -149,7 +147,7 @@ export class ResourceTreeContextMenuButtonFactory { } public static createUserDefinedFunctionContextMenuItems( - container: ViewModels.Explorer, + container: Explorer, userDefinedFunction: ViewModels.UserDefinedFunction ): TreeNodeMenuItem[] { if (container.isPreferredApiCassandra()) { diff --git a/src/Explorer/Controls/GitHub/AddRepoComponent.tsx b/src/Explorer/Controls/GitHub/AddRepoComponent.tsx index 603920540..76914ef99 100644 --- a/src/Explorer/Controls/GitHub/AddRepoComponent.tsx +++ b/src/Explorer/Controls/GitHub/AddRepoComponent.tsx @@ -1,6 +1,5 @@ import { DefaultButton, IButtonProps, ITextFieldProps, TextField } from "office-ui-fabric-react"; import * as React from "react"; -import * as ViewModels from "../../../Contracts/ViewModels"; import * as Constants from "../../../Common/Constants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import { RepoListItem } from "./GitHubReposComponent"; @@ -9,9 +8,10 @@ import * as GitHubUtils from "../../../Utils/GitHubUtils"; import { IGitHubRepo } from "../../../GitHub/GitHubClient"; import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import UrlUtility from "../../../Common/UrlUtility"; +import Explorer from "../../Explorer"; export interface AddRepoComponentProps { - container: ViewModels.Explorer; + container: Explorer; getRepo: (owner: string, repo: string) => Promise; pinRepo: (item: RepoListItem) => void; } diff --git a/src/Explorer/Controls/NotebookGallery/GalleryAndNotebookViewerComponent.tsx b/src/Explorer/Controls/NotebookGallery/GalleryAndNotebookViewerComponent.tsx index 34165af57..84cd9ae83 100644 --- a/src/Explorer/Controls/NotebookGallery/GalleryAndNotebookViewerComponent.tsx +++ b/src/Explorer/Controls/NotebookGallery/GalleryAndNotebookViewerComponent.tsx @@ -1,12 +1,12 @@ import * as React from "react"; -import * as ViewModels from "../../../Contracts/ViewModels"; import { JunoClient, IGalleryItem } from "../../../Juno/JunoClient"; import { GalleryTab, SortBy, GalleryViewerComponentProps, GalleryViewerComponent } from "./GalleryViewerComponent"; import { NotebookViewerComponentProps, NotebookViewerComponent } from "../NotebookViewer/NotebookViewerComponent"; import * as GalleryUtils from "../../../Utils/GalleryUtils"; +import Explorer from "../../Explorer"; export interface GalleryAndNotebookViewerComponentProps { - container?: ViewModels.Explorer; + container?: Explorer; junoClient: JunoClient; notebookUrl?: string; galleryItem?: IGalleryItem; diff --git a/src/Explorer/Controls/NotebookGallery/GalleryViewerComponent.tsx b/src/Explorer/Controls/NotebookGallery/GalleryViewerComponent.tsx index d65a69b46..6ca1c4fd8 100644 --- a/src/Explorer/Controls/NotebookGallery/GalleryViewerComponent.tsx +++ b/src/Explorer/Controls/NotebookGallery/GalleryViewerComponent.tsx @@ -15,7 +15,6 @@ import { } from "office-ui-fabric-react"; import * as React from "react"; import * as Logger from "../../../Common/Logger"; -import * as ViewModels from "../../../Contracts/ViewModels"; import { IGalleryItem, JunoClient } from "../../../Juno/JunoClient"; import * as GalleryUtils from "../../../Utils/GalleryUtils"; import { NotificationConsoleUtils } from "../../../Utils/NotificationConsoleUtils"; @@ -24,9 +23,10 @@ import { DialogComponent, DialogProps } from "../DialogReactComponent/DialogComp import { GalleryCardComponent, GalleryCardComponentProps } from "./Cards/GalleryCardComponent"; import "./GalleryViewerComponent.less"; import { HttpStatusCodes } from "../../../Common/Constants"; +import Explorer from "../../Explorer"; export interface GalleryViewerComponentProps { - container?: ViewModels.Explorer; + container?: Explorer; junoClient: JunoClient; selectedTab: GalleryTab; sortBy: SortBy; diff --git a/src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx b/src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx index 0e3f2c91f..6658bca43 100644 --- a/src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx +++ b/src/Explorer/Controls/NotebookViewer/NotebookViewerComponent.tsx @@ -18,9 +18,10 @@ import NotebookReadOnlyRenderer from "../../Notebook/NotebookRenderer/NotebookRe import { DialogComponent, DialogProps } from "../DialogReactComponent/DialogComponent"; import { NotebookMetadataComponent } from "./NotebookMetadataComponent"; import "./NotebookViewerComponent.less"; +import Explorer from "../../Explorer"; export interface NotebookViewerComponentProps { - container?: ViewModels.Explorer; + container?: Explorer; junoClient?: JunoClient; notebookUrl: string; galleryItem?: IGalleryItem; diff --git a/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx b/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx index 54db59938..ae1d548d1 100644 --- a/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx +++ b/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx @@ -217,7 +217,7 @@ export class QueriesGridComponent extends React.Component { if (window.confirm("Are you sure you want to delete this query?")) { - const container: ViewModels.Explorer = window.dataExplorer; + const container = window.dataExplorer; const startKey: number = TelemetryProcessor.traceStart(Action.DeleteSavedQuery, { databaseAccountName: container && container.databaseAccount().name, defaultExperience: container && container.defaultExperience(), diff --git a/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx b/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx index 26701e183..76bb303a5 100644 --- a/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx +++ b/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponentAdapter.tsx @@ -8,11 +8,12 @@ import * as React from "react"; import * as ViewModels from "../../../Contracts/ViewModels"; import { QueriesGridComponent, QueriesGridComponentProps } from "./QueriesGridComponent"; import { ReactAdapter } from "../../../Bindings/ReactBindingHandler"; +import Explorer from "../../Explorer"; export class QueriesGridComponentAdapter implements ReactAdapter { public parameters: ko.Observable; - constructor(private container: ViewModels.Explorer) { + constructor(private container: Explorer) { this.parameters = ko.observable(Date.now()); } diff --git a/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts b/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts index 5369d84fa..94cc9c67b 100644 --- a/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts +++ b/src/Explorer/DataSamples/ContainerSampleGenerator.test.ts @@ -3,14 +3,15 @@ import * as sinon from "sinon"; import * as ViewModels from "../../Contracts/ViewModels"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import Q from "q"; -import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs"; +import { CollectionStub, DatabaseStub } from "../OpenActionsStubs"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; import { CosmosClient } from "../../Common/CosmosClient"; import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient"; +import Explorer from "../Explorer"; describe("ContainerSampleGenerator", () => { - const createExplorerStub = (database: ViewModels.Database): ExplorerStub => { - const explorerStub = new ExplorerStub(); + const createExplorerStub = (database: ViewModels.Database): Explorer => { + const explorerStub = {} as Explorer; explorerStub.nonSystemDatabases = ko.computed(() => [database]); explorerStub.isPreferredApiGraph = ko.computed(() => false); explorerStub.isPreferredApiMongoDB = ko.computed(() => false); diff --git a/src/Explorer/DataSamples/ContainerSampleGenerator.ts b/src/Explorer/DataSamples/ContainerSampleGenerator.ts index 45238e8e2..5a12e8a71 100644 --- a/src/Explorer/DataSamples/ContainerSampleGenerator.ts +++ b/src/Explorer/DataSamples/ContainerSampleGenerator.ts @@ -6,6 +6,7 @@ import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsol import { CosmosClient } from "../../Common/CosmosClient"; import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; +import Explorer from "../Explorer"; interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest { data: any[]; @@ -14,12 +15,12 @@ interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest { export class ContainerSampleGenerator { private sampleDataFile: SampleDataFile; - private constructor(private container: ViewModels.Explorer) {} + private constructor(private container: Explorer) {} /** * Factory function to load the json data file */ - public static async createSampleGeneratorAsync(container: ViewModels.Explorer): Promise { + public static async createSampleGeneratorAsync(container: Explorer): Promise { const generator = new ContainerSampleGenerator(container); let dataFileContent: any; if (container.isPreferredApiGraph()) { diff --git a/src/Explorer/DataSamples/DataSamplesUtil.test.ts b/src/Explorer/DataSamples/DataSamplesUtil.test.ts index 02ca82106..946a60939 100644 --- a/src/Explorer/DataSamples/DataSamplesUtil.test.ts +++ b/src/Explorer/DataSamples/DataSamplesUtil.test.ts @@ -1,8 +1,9 @@ -import { ExplorerStub, DatabaseStub, CollectionStub } from "../OpenActionsStubs"; +import { DatabaseStub, CollectionStub } from "../OpenActionsStubs"; import { DataSamplesUtil } from "./DataSamplesUtil"; import * as sinon from "sinon"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; import * as ko from "knockout"; +import Explorer from "../Explorer"; describe("DataSampleUtils", () => { const sampleCollectionId = "sampleCollectionId"; @@ -14,7 +15,7 @@ describe("DataSampleUtils", () => { id: ko.observable(sampleDatabaseId), collections: ko.observableArray([collection]) }); - const explorer = new ExplorerStub(); + const explorer = {} as Explorer; explorer.nonSystemDatabases = ko.computed(() => [database]); explorer.showOkModalDialog = () => {}; const dataSamplesUtil = new DataSamplesUtil(explorer); diff --git a/src/Explorer/DataSamples/DataSamplesUtil.ts b/src/Explorer/DataSamples/DataSamplesUtil.ts index f5dc87c10..78c2bc14d 100644 --- a/src/Explorer/DataSamples/DataSamplesUtil.ts +++ b/src/Explorer/DataSamples/DataSamplesUtil.ts @@ -2,10 +2,11 @@ import * as ViewModels from "../../Contracts/ViewModels"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; +import Explorer from "../Explorer"; export class DataSamplesUtil { private static readonly DialogTitle = "Create Sample Container"; - constructor(private container: ViewModels.Explorer) {} + constructor(private container: Explorer) {} /** * Check if Database/Container is already there: if so, show modal to delete diff --git a/src/Explorer/Explorer.ts b/src/Explorer/Explorer.ts index c7a76e823..ee5f99017 100644 --- a/src/Explorer/Explorer.ts +++ b/src/Explorer/Explorer.ts @@ -89,7 +89,7 @@ enum ShareAccessToggleState { Read } -export default class Explorer implements ViewModels.Explorer { +export default class Explorer { public flight: ko.Observable = ko.observable( SharedConstants.CollectionCreation.DefaultAddCollectionDefaultFlight ); @@ -200,7 +200,7 @@ export default class Explorer implements ViewModels.Explorer { public shouldShowShareDialogContents: ko.Observable; public shareAccessData: ko.Observable; - public renewExplorerShareAccess: (explorer: ViewModels.Explorer, token: string) => Q.Promise; + public renewExplorerShareAccess: (explorer: Explorer, token: string) => Q.Promise; public renewTokenError: ko.Observable; public tokenForRenewal: ko.Observable; public shareAccessToggleState: ko.Observable; diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx index d40095699..f0e009ad0 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx @@ -11,14 +11,15 @@ import { CommandBarComponentButtonFactory } from "./CommandBarComponentButtonFac import { CommandBar, ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar"; import { StyleConstants } from "../../../Common/Constants"; import { CommandBarUtil } from "./CommandBarUtil"; +import Explorer from "../../Explorer"; export class CommandBarComponentAdapter implements ReactAdapter { public parameters: ko.Observable; - public container: ViewModels.Explorer; + public container: Explorer; private tabsButtons: ViewModels.NavbarButtonConfig[]; private isNotebookTabActive: ko.Computed; - constructor(container: ViewModels.Explorer) { + constructor(container: Explorer) { this.container = container; this.tabsButtons = []; this.isNotebookTabActive = ko.computed(() => diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts index b7eb74b36..8a7f94d1d 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.test.ts @@ -1,24 +1,25 @@ import * as ko from "knockout"; -import * as ViewModels from "../../../Contracts/ViewModels"; import { CommandBarComponentButtonFactory } from "./CommandBarComponentButtonFactory"; -import { ExplorerStub } from "../../OpenActionsStubs"; import { GitHubOAuthService } from "../../../GitHub/GitHubOAuthService"; import NotebookManager from "../../Notebook/NotebookManager"; +import Explorer from "../../Explorer"; describe("CommandBarComponentButtonFactory tests", () => { - let mockExplorer: ViewModels.Explorer; + let mockExplorer: Explorer; describe("Enable notebook button", () => { const enableNotebookBtnLabel = "Enable Notebooks (Preview)"; beforeAll(() => { - mockExplorer = new ExplorerStub(); + mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); mockExplorer.isPreferredApiCassandra = ko.computed(() => false); + mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isSparkEnabled = ko.observable(true); + mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isGalleryPublishEnabled = ko.computed(() => false); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed(() => true); mockExplorer.isDatabaseNodeOrNoneSelected = () => true; @@ -75,12 +76,13 @@ describe("CommandBarComponentButtonFactory tests", () => { const openMongoShellBtnLabel = "Open Mongo Shell"; beforeAll(() => { - mockExplorer = new ExplorerStub(); + mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiCassandra = ko.computed(() => false); mockExplorer.isSparkEnabled = ko.observable(true); + mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isGalleryPublishEnabled = ko.computed(() => false); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed(() => true); mockExplorer.isDatabaseNodeOrNoneSelected = () => true; @@ -155,11 +157,12 @@ describe("CommandBarComponentButtonFactory tests", () => { const openCassandraShellBtnLabel = "Open Cassandra Shell"; beforeAll(() => { - mockExplorer = new ExplorerStub(); + mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); + mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isGalleryPublishEnabled = ko.computed(() => false); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed(() => true); @@ -236,13 +239,14 @@ describe("CommandBarComponentButtonFactory tests", () => { const manageGitHubSettingsBtnLabel = "Manage GitHub settings"; beforeAll(() => { - mockExplorer = new ExplorerStub(); + mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiMongoDB = ko.computed(() => false); mockExplorer.isPreferredApiCassandra = ko.computed(() => false); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed(() => true); + mockExplorer.isSynapseLinkUpdating = ko.observable(false); mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isDatabaseNodeOrNoneSelected = () => true; mockExplorer.isNotebooksEnabledForAccount = ko.observable(false); @@ -294,7 +298,7 @@ describe("CommandBarComponentButtonFactory tests", () => { describe("Resource token", () => { beforeAll(() => { - mockExplorer = new ExplorerStub(); + mockExplorer = {} as Explorer; mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.isAuthWithResourceToken = ko.observable(true); mockExplorer.isPreferredApiDocumentDB = ko.computed(() => true); diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts index 202932bfd..c672cc51a 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts @@ -25,11 +25,12 @@ import ResetWorkspaceIcon from "../../../../images/notebook/Notebook-reset-works import GitHubIcon from "../../../../images/github.svg"; import SynapseIcon from "../../../../images/synapse-link.svg"; import { config, Platform } from "../../../Config"; +import Explorer from "../../Explorer"; export class CommandBarComponentButtonFactory { private static counter: number = 0; - public static createStaticCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { + public static createStaticCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { if (container.isAuthWithResourceToken()) { return CommandBarComponentButtonFactory.createStaticCommandBarButtonsForResourceToken(container); } @@ -132,7 +133,7 @@ export class CommandBarComponentButtonFactory { return buttons; } - public static createContextCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { + public static createContextCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { const buttons: ViewModels.NavbarButtonConfig[] = []; if (!container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()) { @@ -155,7 +156,7 @@ export class CommandBarComponentButtonFactory { return buttons; } - public static createControlCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { + public static createControlCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { const buttons: ViewModels.NavbarButtonConfig[] = []; if (window.dataExplorerPlatform === PlatformType.Hosted) { return buttons; @@ -223,11 +224,11 @@ export class CommandBarComponentButtonFactory { }; } - private static areScriptsSupported(container: ViewModels.Explorer): boolean { + private static areScriptsSupported(container: Explorer): boolean { return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph(); } - private static createNewCollectionGroup(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createNewCollectionGroup(container: Explorer): ViewModels.NavbarButtonConfig { const label = container.addCollectionText(); return { iconSrc: AddCollectionIcon, @@ -240,7 +241,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenSynapseLinkDialogButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createOpenSynapseLinkDialogButton(container: Explorer): ViewModels.NavbarButtonConfig { if (config.platform === Platform.Emulator) { return null; } @@ -275,7 +276,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNewDatabase(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createNewDatabase(container: Explorer): ViewModels.NavbarButtonConfig { const label = container.addDatabaseText(); return { iconSrc: AddDatabaseIcon, @@ -290,7 +291,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNewSQLQueryButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createNewSQLQueryButton(container: Explorer): ViewModels.NavbarButtonConfig { if (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph()) { const label = "New SQL Query"; return { @@ -324,7 +325,7 @@ export class CommandBarComponentButtonFactory { return null; } - public static createScriptCommandButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { + public static createScriptCommandButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { const buttons: ViewModels.NavbarButtonConfig[] = []; const shouldEnableScriptsCommands: boolean = @@ -384,7 +385,7 @@ export class CommandBarComponentButtonFactory { return buttons; } - private static createScaleAndSettingsButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createScaleAndSettingsButton(container: Explorer): ViewModels.NavbarButtonConfig { let isShared = false; if (container.isDatabaseNodeSelected()) { isShared = container.findSelectedDatabase().isDatabaseShared(); @@ -409,7 +410,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNewNotebookButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createNewNotebookButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "New Notebook"; return { iconSrc: NewNotebookIcon, @@ -422,7 +423,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createuploadNotebookButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createuploadNotebookButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Upload to Notebook Server"; return { iconSrc: NewNotebookIcon, @@ -435,7 +436,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenQueryButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createOpenQueryButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Open Query"; return { iconSrc: BrowseQueriesIcon, @@ -448,7 +449,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenQueryFromDiskButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createOpenQueryFromDiskButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Open Query From Disk"; return { iconSrc: OpenQueryFromDiskIcon, @@ -461,7 +462,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createEnableNotebooksButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createEnableNotebooksButton(container: Explorer): ViewModels.NavbarButtonConfig { if (config.platform === Platform.Emulator) { return null; } @@ -482,7 +483,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenTerminalButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createOpenTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Open Terminal"; return { iconSrc: CosmosTerminalIcon, @@ -495,7 +496,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenMongoTerminalButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createOpenMongoTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Open Mongo Shell"; const tooltip = "This feature is not yet available in your account's region. View supported regions here: https://aka.ms/cosmos-enable-notebooks."; @@ -521,7 +522,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenCassandraTerminalButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createOpenCassandraTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Open Cassandra Shell"; const tooltip = "This feature is not yet available in your account's region. View supported regions here: https://aka.ms/cosmos-enable-notebooks."; @@ -547,7 +548,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNotebookWorkspaceResetButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createNotebookWorkspaceResetButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Reset Workspace"; return { iconSrc: ResetWorkspaceIcon, @@ -560,7 +561,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createManageGitHubAccountButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + private static createManageGitHubAccountButton(container: Explorer): ViewModels.NavbarButtonConfig { let connectedToGitHub: boolean = container.notebookManager?.gitHubOAuthService.isLoggedIn(); const label = connectedToGitHub ? "Manage GitHub settings" : "Connect to GitHub"; return { @@ -583,9 +584,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createStaticCommandBarButtonsForResourceToken( - container: ViewModels.Explorer - ): ViewModels.NavbarButtonConfig[] { + private static createStaticCommandBarButtonsForResourceToken(container: Explorer): ViewModels.NavbarButtonConfig[] { const newSqlQueryBtn = CommandBarComponentButtonFactory.createNewSQLQueryButton(container); const openQueryBtn = CommandBarComponentButtonFactory.createOpenQueryButton(container); diff --git a/src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx b/src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx index b424bb730..db1eae4b0 100644 --- a/src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx +++ b/src/Explorer/Menus/NotificationConsole/NotificationConsoleComponentAdapter.tsx @@ -4,13 +4,14 @@ import { ReactAdapter } from "../../../Bindings/ReactBindingHandler"; import * as ViewModels from "../../../Contracts/ViewModels"; import { NotificationConsoleComponent } from "./NotificationConsoleComponent"; import { ConsoleData } from "./NotificationConsoleComponent"; +import Explorer from "../../Explorer"; export class NotificationConsoleComponentAdapter implements ReactAdapter { public parameters: ko.Observable; - public container: ViewModels.Explorer; + public container: Explorer; private consoleData: ko.ObservableArray; - constructor(container: ViewModels.Explorer) { + constructor(container: Explorer) { this.container = container; this.consoleData = container.notificationConsoleData; diff --git a/src/Explorer/MostRecentActivity/MostRecentActivity.ts b/src/Explorer/MostRecentActivity/MostRecentActivity.ts index 18286d3c6..894c0c535 100644 --- a/src/Explorer/MostRecentActivity/MostRecentActivity.ts +++ b/src/Explorer/MostRecentActivity/MostRecentActivity.ts @@ -3,6 +3,7 @@ import { StorageKey, LocalStorageUtility } from "../../Shared/StorageUtility"; import CollectionIcon from "../../../images/tree-collection.svg"; import NotebookIcon from "../../../images/notebook/Notebook-resource.svg"; +import Explorer from "../Explorer"; export enum Type { OpenCollection, @@ -36,7 +37,7 @@ export class MostRecentActivity { private static readonly schemaVersion: string = "1"; private static itemsMaxNumber: number = 5; private storedData: StoredData; - constructor(private container: ViewModels.Explorer) { + constructor(private container: Explorer) { // Retrieve from local storage if (LocalStorageUtility.hasItem(StorageKey.MostRecentActivity)) { const rawData = LocalStorageUtility.getEntryString(StorageKey.MostRecentActivity); diff --git a/src/Explorer/Notebook/NotebookContainerClient.ts b/src/Explorer/Notebook/NotebookContainerClient.ts index 619a8e6eb..017ace6b5 100644 --- a/src/Explorer/Notebook/NotebookContainerClient.ts +++ b/src/Explorer/Notebook/NotebookContainerClient.ts @@ -131,7 +131,7 @@ export class NotebookContainerClient implements ViewModels.INotebookContainerCli } private async recreateNotebookWorkspaceAsync(): Promise { - const explorer = window.dataExplorer as ViewModels.Explorer; + const explorer = window.dataExplorer; if (!explorer || !explorer.databaseAccount() || !explorer.databaseAccount().id) { throw new Error("DataExplorer not initialized"); } diff --git a/src/Explorer/Notebook/NotebookManager.ts b/src/Explorer/Notebook/NotebookManager.ts index 292898d48..2e4d5fe87 100644 --- a/src/Explorer/Notebook/NotebookManager.ts +++ b/src/Explorer/Notebook/NotebookManager.ts @@ -23,9 +23,10 @@ import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent"; import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter"; import { getFullName } from "../../Utils/UserUtils"; +import Explorer from "../Explorer"; export interface NotebookManagerOptions { - container: ViewModels.Explorer; + container: Explorer; notebookBasePath: ko.Observable; dialogProps: ko.Observable; resourceTree: ResourceTreeAdapter; diff --git a/src/Explorer/OpenActions.test.ts b/src/Explorer/OpenActions.test.ts index 0e9a68848..f1a620bb5 100644 --- a/src/Explorer/OpenActions.test.ts +++ b/src/Explorer/OpenActions.test.ts @@ -1,18 +1,13 @@ import * as ko from "knockout"; import { handleOpenAction } from "./OpenActions"; import * as ViewModels from "../Contracts/ViewModels"; -import { - ExplorerStub, - DatabaseStub, - CollectionStub, - AddCollectionPaneStub, - CassandraAddCollectionPane -} from "./OpenActionsStubs"; +import { DatabaseStub, CollectionStub, AddCollectionPaneStub, CassandraAddCollectionPane } from "./OpenActionsStubs"; import { ActionContracts } from "../Contracts/ExplorerContracts"; +import Explorer from "./Explorer"; describe("OpenActions", () => { describe("handleOpenAction", () => { - let explorer: ViewModels.Explorer; + let explorer: Explorer; let database: ViewModels.Database; let collection: ViewModels.Collection; let databases: ViewModels.Database[]; @@ -28,9 +23,11 @@ describe("OpenActions", () => { let openCassandraAddCollectionPane: jasmine.Spy; beforeEach(() => { - explorer = new ExplorerStub(); + explorer = {} as Explorer; explorer.addCollectionPane = new AddCollectionPaneStub(); explorer.cassandraAddCollectionPane = new CassandraAddCollectionPane(); + explorer.closeAllPanes = () => {}; + explorer.isConnectExplorerVisible = () => false; database = new DatabaseStub({ id: ko.observable("db"), diff --git a/src/Explorer/OpenActions.ts b/src/Explorer/OpenActions.ts index a692d09a4..051e40010 100644 --- a/src/Explorer/OpenActions.ts +++ b/src/Explorer/OpenActions.ts @@ -2,11 +2,12 @@ import * as ViewModels from "../Contracts/ViewModels"; import { ActionContracts } from "../Contracts/ExplorerContracts"; +import Explorer from "./Explorer"; export function handleOpenAction( action: ActionContracts.DataExplorerAction, databases: ViewModels.Database[], - explorer: ViewModels.Explorer + explorer: Explorer ): boolean { if ( action.actionType === ActionContracts.ActionType.OpenCollectionTab || @@ -126,7 +127,7 @@ function openCollectionTab( } } -function openPane(action: ActionContracts.OpenPane, explorer: ViewModels.Explorer) { +function openPane(action: ActionContracts.OpenPane, explorer: Explorer) { if ( action.paneKind === ActionContracts.PaneKind.AddCollection || (action).paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.AddCollection] @@ -154,7 +155,7 @@ function openPane(action: ActionContracts.OpenPane, explorer: ViewModels.Explore } } -function openFile(action: ActionContracts.OpenSampleNotebook, explorer: ViewModels.Explorer) { +function openFile(action: ActionContracts.OpenSampleNotebook, explorer: Explorer) { explorer.handleOpenFileAction(decodeURIComponent(action.path)); } diff --git a/src/Explorer/OpenActionsStubs.ts b/src/Explorer/OpenActionsStubs.ts index d930ac051..2b128a23b 100644 --- a/src/Explorer/OpenActionsStubs.ts +++ b/src/Explorer/OpenActionsStubs.ts @@ -3,425 +3,13 @@ import * as ko from "knockout"; import * as ViewModels from "../../src/Contracts/ViewModels"; import DocumentClientUtilityBase from "../Common/DocumentClientUtilityBase"; import Q from "q"; -import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker"; -import { CassandraTableKey, CassandraTableKeys, TableDataClient } from "../../src/Explorer/Tables/TableDataClient"; -import { ConsoleData } from "../../src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; -import { MostRecentActivity } from "./MostRecentActivity/MostRecentActivity"; -import { NotebookContentItem } from "./Notebook/NotebookContentItem"; -import { PlatformType } from "../../src/PlatformType"; -import { QuerySelectPane } from "../../src/Explorer/Panes/Tables/QuerySelectPane"; -import { SetupNotebooksPane } from "./Panes/SetupNotebooksPane"; -import { Splitter } from "../../src/Common/Splitter"; -import { StringInputPane } from "./Panes/StringInputPane"; -import { TableColumnOptionsPane } from "../../src/Explorer/Panes/Tables/TableColumnOptionsPane"; -import { TextFieldProps } from "./Controls/DialogReactComponent/DialogComponent"; +import { CassandraTableKey, CassandraTableKeys } from "../../src/Explorer/Tables/TableDataClient"; import { UploadDetails } from "../workers/upload/definitions"; -import { UploadFilePane } from "./Panes/UploadFilePane"; -import { UploadItemsPaneAdapter } from "./Panes/UploadItemsPaneAdapter"; -import { Versions } from "../../src/Contracts/ExplorerContracts"; -import { CollectionCreationDefaults } from "../Shared/Constants"; -import { IGalleryItem } from "../Juno/JunoClient"; -import { ReactAdapter } from "../Bindings/ReactBindingHandler"; -import { TabsManager } from "./Tabs/TabsManager"; - -export class ExplorerStub implements ViewModels.Explorer { - public flight: ko.Observable; - public addCollectionText: ko.Observable; - public hasAutoPilotV2FeatureFlag: ko.Computed; - public addDatabaseText: ko.Observable; - public collectionTitle: ko.Observable; - public deleteCollectionText: ko.Observable; - public deleteDatabaseText: ko.Observable; - public collectionTreeNodeAltText: ko.Observable; - public refreshTreeTitle: ko.Observable; - public collapsedResourceTreeWidth: number; - public collectionCreationDefaults: ViewModels.CollectionCreationDefaults = CollectionCreationDefaults; - public hasWriteAccess: ko.Observable = ko.observable(false); - public databaseAccount: ko.Observable; - public subscriptionType: ko.Observable; - public quotaId: ko.Observable; - public defaultExperience: ko.Observable; - public isPreferredApiDocumentDB: ko.Computed; - public isPreferredApiCassandra: ko.Computed; - public isPreferredApiMongoDB: ko.Computed; - public isPreferredApiGraph: ko.Computed; - public isPreferredApiTable: ko.Computed; - public isFixedCollectionWithSharedThroughputSupported: ko.Computed; - public isEmulator: boolean; - public isAccountReady: ko.Observable; - public canSaveQueries: ko.Computed; - public features: ko.Observable; - public serverId: ko.Observable; - public extensionEndpoint: ko.Observable = ko.observable(undefined); - public armEndpoint: ko.Observable; - public isTryCosmosDBSubscription: ko.Observable; - public documentClientUtility: DocumentClientUtilityBase; - public notificationsClient: ViewModels.NotificationsClient; - public queriesClient: ViewModels.QueriesClient; - public tableDataClient: TableDataClient; - public splitter: Splitter; - public notificationConsoleData: ko.ObservableArray; - public isNotificationConsoleExpanded: ko.Observable; - public contextPanes: ViewModels.ContextualPane[]; - public databases: ko.ObservableArray; - public nonSystemDatabases: ko.Computed; - public selectedDatabaseId: ko.Computed; - public selectedCollectionId: ko.Computed; - public isLeftPaneExpanded: ko.Observable; - public selectedNode: ko.Observable; - public isRefreshingExplorer: ko.Observable; - public isTabsContentExpanded: ko.Observable; - public addCollectionPane: ViewModels.AddCollectionPane; - public addDatabasePane: ViewModels.AddDatabasePane; - public deleteCollectionConfirmationPane: ViewModels.DeleteCollectionConfirmationPane; - public deleteDatabaseConfirmationPane: ViewModels.DeleteDatabaseConfirmationPane; - public graphStylingPane: ViewModels.GraphStylingPane; - public addTableEntityPane: ViewModels.AddTableEntityPane; - public editTableEntityPane: ViewModels.EditTableEntityPane; - public tableColumnOptionsPane: TableColumnOptionsPane; - public querySelectPane: QuerySelectPane; - public newVertexPane: ViewModels.NewVertexPane; - public cassandraAddCollectionPane: ViewModels.CassandraAddCollectionPane; - public renewAdHocAccessPane: ViewModels.RenewAdHocAccessPane; - public renewExplorerShareAccess: (explorer: ViewModels.Explorer, token: string) => Q.Promise; - public settingsPane: ViewModels.SettingsPane; - public executeSprocParamsPane: ViewModels.ExecuteSprocParamsPane; - public uploadItemsPane: ViewModels.UploadItemsPane; - public uploadItemsPaneAdapter: UploadItemsPaneAdapter; - public loadQueryPane: ViewModels.LoadQueryPane; - public saveQueryPane: ViewModels.ContextualPane; - public browseQueriesPane: ViewModels.BrowseQueriesPane; - public uploadFilePane: UploadFilePane; - public stringInputPane: StringInputPane; - public setupNotebooksPane: SetupNotebooksPane; - public isGalleryPublishEnabled: ko.Computed; - public isGitHubPaneEnabled: ko.Observable; - public isPublishNotebookPaneEnabled: ko.Observable; - public isRightPanelV2Enabled: ko.Computed; - public canExceedMaximumValue: ko.Computed; - public isHostedDataExplorerEnabled: ko.Computed; - public parentFrameDataExplorerVersion: ko.Observable = ko.observable(Versions.DataExplorer); - public mostRecentActivity: MostRecentActivity; - public isNotebookEnabled: ko.Observable; - public isSparkEnabled: ko.Observable; - public isNotebooksEnabledForAccount: ko.Observable; - public isSparkEnabledForAccount: ko.Observable; - public arcadiaToken: ko.Observable; - public notebookWorkspaceManager: ViewModels.NotebookWorkspaceManager; - public notebookServerInfo: ko.Observable; - public sparkClusterConnectionInfo: ko.Observable; - public gitHubReposPane: ViewModels.ContextualPane; - public publishNotebookPaneAdapter: ReactAdapter; - public arcadiaWorkspaces: ko.ObservableArray; - public hasStorageAnalyticsAfecFeature: ko.Observable; - public isSynapseLinkUpdating: ko.Observable; - public memoryUsageInfo: ko.Observable; - public notebookManager?: any; - public openGallery: (notebookUrl?: string, galleryItem?: IGalleryItem, isFavorite?: boolean) => void; - public openNotebookViewer: (notebookUrl: string) => void; - public resourceTokenDatabaseId: ko.Observable; - public resourceTokenCollectionId: ko.Observable; - public resourceTokenCollection: ko.Observable; - public resourceTokenPartitionKey: ko.Observable; - public isAuthWithResourceToken: ko.Observable; - public isResourceTokenCollectionNodeSelected: ko.Computed; - public tabsManager: TabsManager; - - private _featureEnabledReturnValue: boolean; - - constructor(options?: any) { - options = options || {}; - this._featureEnabledReturnValue = options.featureEnabledReturnValue || false; - this.isSynapseLinkUpdating = ko.observable(options.isSynapseLinkUpdating || false); - } - - public openEnableSynapseLinkDialog() { - throw new Error("Not implemented"); - } - - public createWorkspace(): Promise { - throw new Error("Not implemented"); - } - - public createSparkPool(workspaceId: string): Promise { - throw new Error("Not implemented"); - } - - public isDatabaseNodeOrNoneSelected(): boolean { - throw new Error("Not implemented"); - } - - public isDatabaseNodeSelected(): boolean { - throw new Error("Not implemented"); - } - - public isNodeKindSelected(nodeKind: string): boolean { - throw new Error("Not implemented"); - } - - public isNoneSelected(): boolean { - throw new Error("Not implemented"); - } - - public isFeatureEnabled(feature: string): boolean { - return this._featureEnabledReturnValue; - } - - public isSelectedDatabaseShared(): boolean { - throw new Error("Not implemented"); - } - - public logConsoleData(consoleData: ConsoleData): void { - throw new Error("Not implemented"); - } - - public deleteInProgressConsoleDataWithId(id: string): void { - throw new Error("Not implemented"); - } - - public toggleLeftPaneExpanded() { - throw new Error("Not implemented"); - } - - public refreshAllDatabases(): Q.Promise { - throw new Error("Not implemented"); - } - - public refreshDatabaseForResourceToken(): Q.Promise { - throw new Error("Note impplemented"); - } - - public onRefreshDatabasesKeyPress = (source: any, event: KeyboardEvent): boolean => { - throw new Error("Not implemented"); - }; - - public onRefreshResourcesClick = (source: any, event: MouseEvent): boolean => { - throw new Error("Not implemented"); - }; - - public toggleLeftPaneExpandedKeyPress = (source: any, event: KeyboardEvent): boolean => { - throw new Error("Not implemented"); - }; - - // Facade - public provideFeedbackEmail = () => { - throw new Error("Not implemented"); - }; - - public handleMessage(event: MessageEvent) { - throw new Error("Not implemented"); - } - - public findSelectedDatabase(): ViewModels.Database { - throw new Error("Not implemented"); - } - - public findDatabaseWithId(databaseId: string): ViewModels.Database { - throw new Error("Not implemented"); - } - - public isLastDatabase(): boolean { - throw new Error("Not implemented"); - } - - public isLastNonEmptyDatabase(): boolean { - throw new Error("Not implemented"); - } - - public initDataExplorerWithFrameInputs(inputs: ViewModels.DataExplorerInputsFrame): Q.Promise { - throw new Error("Not implemented"); - } - - public findSelectedCollection(): ViewModels.Collection { - throw new Error("Not implemented"); - } - - public findCollection(rid: string): ViewModels.Collection { - throw new Error("Not implemented"); - } - - public isLastCollection(): boolean { - throw new Error("Not implemented"); - } - - public findSelectedStoredProcedure(): ViewModels.StoredProcedure { - throw new Error("Not implemented"); - } - - public findSelectedUDF(): ViewModels.UserDefinedFunction { - throw new Error("Not implemented"); - } - - public findSelectedTrigger(): ViewModels.Trigger { - throw new Error("Not implemented"); - } - - public generateSharedAccessData(): void { - throw new Error("Not implemented"); - } - - public displayConnectExplorerForm(): void { - throw new Error("Not implemented"); - } - - public displayContextSwitchPromptForConnectionString(connectionString: string): void { - throw new Error("Not implemented"); - } - - public hideConnectExplorerForm(): void { - throw new Error("Not implemented"); - } - - public displayGuestAccessTokenRenewalPrompt(): void { - throw new Error("Not implemented"); - } - - public expandConsole(): void { - throw new Error("Not implemented"); - } - - public collapseConsole(): void { - throw new Error("Not implemented"); - } - - public rebindDocumentClientUtility(documentClientUtility: any) { - throw new Error("Not implemented"); - } - - public renewShareAccess(token: string): Q.Promise { - throw new Error("Not implemented"); - } - - public getPlatformType(): PlatformType { - throw new Error("Not implemented"); - } - - public isRunningOnNationalCloud(): boolean { - throw new Error("Not implemented"); - } - - public isConnectExplorerVisible(): boolean { - return false; - } - - public closeAllPanes(): void { - // return for now so tests dont break - // TODO: implement once we start testing pane close - return; - } - - public onUpdateTabsButtons(buttons: ViewModels.NavbarButtonConfig[]): void { - throw new Error("Not implemented"); - } - - public importAndOpen(path: string): Promise { - throw new Error("Not implemented"); - } - - public importAndOpenContent(name: string, content: string): Promise { - throw new Error("Not implemented"); - } - - public publishNotebook(name: string, content: string): void { - throw new Error("Not implemented"); - } - - public async openNotebook(notebookContentItem: NotebookContentItem): Promise { - throw new Error("Not implemented"); - } - - public deleteNotebookFile(item: NotebookContentItem): Promise { - throw new Error("Not implemented"); - } - - public onCreateDirectory(parent: NotebookContentItem): Q.Promise { - throw new Error("Not implemented"); - } - - public onNewNotebookClicked(parent?: NotebookContentItem): void { - throw new Error("Not implemented"); - } - - public openNotebookTerminal(): void { - throw new Error("Not implemented"); - } - - public resetNotebookWorkspace(): void { - throw new Error("Not implemented"); - } - - public onNewCollectionClicked(): void { - throw new Error("Not implemented"); - } - - public onUploadToNotebookServerClicked(parent?: NotebookContentItem): void { - throw new Error("Not implemented"); - } - - public renameNotebook(notebookFile: NotebookContentItem): Q.Promise { - throw new Error("Not implemented"); - } - - public readFile(notebookFile: NotebookContentItem): Promise { - throw new Error("Not implemented"); - } - - public downloadFile(notebookFile: NotebookContentItem): Promise { - throw new Error("Not implemented"); - } - - public initNotebooks(databaseAccount: DataModels.DatabaseAccount): Promise { - throw new Error("Not implemented"); - } - - public showOkModalDialog(title: string, msg: string): void { - throw new Error("Not implemented"); - } - - public showOkCancelModalDialog( - title: string, - msg: string, - okLabel: string, - onOk: () => void, - cancelLabel: string, - onCancel: () => void - ): void { - throw new Error("Not implemented"); - } - - public showOkCancelTextFieldModalDialog( - title: string, - msg: string, - okLabel: string, - onOk: () => void, - cancelLabel: string, - onCancel: () => void, - textFieldProps: TextFieldProps, - isPrimaryButtonDisabled?: boolean - ): void { - throw new Error("Not implemented"); - } - - public createNotebookContentItemFile(name: string, filepath: string): NotebookContentItem { - throw new Error("Not implemented"); - } - - public refreshContentItem(item: NotebookContentItem): Promise { - throw new Error("Not implemented"); - } - - public getNotebookBasePath(): string { - throw new Error("Not implemented"); - } - - public handleOpenFileAction(): Promise { - throw new Error("Not implemented"); - } -} +import Explorer from "./Explorer"; export class DatabaseStub implements ViewModels.Database { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public self: string; public rid: string; public id: ko.Observable; @@ -498,7 +86,7 @@ export class DatabaseStub implements ViewModels.Database { export class CollectionStub implements ViewModels.Collection { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public rawDataModel: DataModels.Collection; public self: string; public rid: string; diff --git a/src/Explorer/Panes/AddCollectionPane.test.ts b/src/Explorer/Panes/AddCollectionPane.test.ts index abdf7194f..68f4fc587 100644 --- a/src/Explorer/Panes/AddCollectionPane.test.ts +++ b/src/Explorer/Panes/AddCollectionPane.test.ts @@ -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", diff --git a/src/Explorer/Panes/AddDatabasePane.test.ts b/src/Explorer/Panes/AddDatabasePane.test.ts index bee4e9f06..ce9a03af2 100644 --- a/src/Explorer/Panes/AddDatabasePane.test.ts +++ b/src/Explorer/Panes/AddDatabasePane.test.ts @@ -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", diff --git a/src/Explorer/Panes/ContextualPaneBase.ts b/src/Explorer/Panes/ContextualPaneBase.ts index ee1b93232..8eadbbd12 100644 --- a/src/Explorer/Panes/ContextualPaneBase.ts +++ b/src/Explorer/Panes/ContextualPaneBase.ts @@ -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; public formErrorsDetails: ko.Observable; public formErrors: ko.Observable; diff --git a/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts b/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts index 398e28855..b45b4155a 100644 --- a/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts +++ b/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts @@ -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 as any ); - let fakeExplorer = sinon.createStubInstance(ExplorerStub as any); - sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable(false)); + let fakeExplorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); + fakeExplorer.isNotificationConsoleExpanded = ko.observable(false); + fakeExplorer.refreshAllDatabases = () => Q.resolve(); let pane = new DeleteCollectionConfirmationPane({ documentClientUtility: fakeDocumentClientUtility as any, id: "deletecollectionconfirmationpane", visible: ko.observable(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 as any - ); - fakeDocumentClientUtility.deleteCollection.returns(Q.resolve(null)); - let fakeExplorer = sinon.createStubInstance(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(selectedCollectionId), rid: "test" - }) - ); - sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable(false)); - sinon.stub(fakeExplorer, "selectedCollectionId").value(ko.observable(selectedCollectionId)); - fakeExplorer.isSelectedDatabaseShared.returns(false); + }); + fakeExplorer.isNotificationConsoleExpanded = ko.observable(false); + fakeExplorer.selectedCollectionId = ko.computed(() => selectedCollectionId); + fakeExplorer.isSelectedDatabaseShared = () => false; const SubscriptionId = "testId"; const AccountName = "testAccount"; - sinon.stub(fakeExplorer, "databaseAccount").value( - ko.observable({ - id: SubscriptionId, - name: AccountName - } as ViewModels.DatabaseAccount) - ); - sinon.stub(fakeExplorer, "defaultExperience").value(ko.observable("DocumentDB")); - sinon.stub(fakeExplorer, "isPreferredApiCassandra").value( - ko.computed(() => { - return false; - }) - ); - sinon.stub(fakeExplorer, "documentClientUtility").value(fakeDocumentClientUtility); - sinon.stub(fakeExplorer, "selectedNode").value(ko.observable()); - fakeExplorer.isLastCollection.returns(true); - fakeExplorer.isSelectedDatabaseShared.returns(false); + fakeExplorer.databaseAccount = ko.observable({ + id: SubscriptionId, + name: AccountName + } as ViewModels.DatabaseAccount); + + fakeExplorer.defaultExperience = ko.observable("DocumentDB"); + fakeExplorer.isPreferredApiCassandra = ko.computed(() => { + return false; + }); + + fakeExplorer.documentClientUtility = fakeDocumentClientUtility; + fakeExplorer.selectedNode = ko.observable(); + fakeExplorer.isLastCollection = () => true; + fakeExplorer.isSelectedDatabaseShared = () => false; + fakeExplorer.refreshAllDatabases = () => Q.resolve(); let pane = new DeleteCollectionConfirmationPane({ documentClientUtility: fakeDocumentClientUtility as any, diff --git a/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts b/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts index d47637e2d..c7a34693f 100644 --- a/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts +++ b/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts @@ -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 as any - ); - let fakeExplorer = sinon.createStubInstance(ExplorerStub as any); - sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable(false)); + let fakeDocumentClientUtility = {} as DocumentClientUtilityBase; + let fakeExplorer = {} as Explorer; + fakeExplorer.isNotificationConsoleExpanded = ko.observable(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 as any - ); - fakeDocumentClientUtility.deleteDatabase.returns(Q.resolve(null)); - let fakeExplorer = sinon.createStubInstance(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(selectedDatabaseId), rid: "test", collections: ko.observableArray() - }) - ); - sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable(false)); - sinon.stub(fakeExplorer, "selectedDatabaseId").value(ko.observable(selectedDatabaseId)); - fakeExplorer.isSelectedDatabaseShared.returns(false); + }); + fakeExplorer.refreshAllDatabases = () => Q.resolve(); + fakeExplorer.isNotificationConsoleExpanded = ko.observable(false); + fakeExplorer.selectedDatabaseId = ko.computed(() => selectedDatabaseId); + fakeExplorer.isSelectedDatabaseShared = () => false; const SubscriptionId = "testId"; const AccountName = "testAccount"; - sinon.stub(fakeExplorer, "databaseAccount").value( - ko.observable({ - id: SubscriptionId, - name: AccountName - } as ViewModels.DatabaseAccount) - ); - sinon.stub(fakeExplorer, "defaultExperience").value(ko.observable("DocumentDB")); - sinon.stub(fakeExplorer, "isPreferredApiCassandra").value( - ko.computed(() => { - return false; - }) - ); - sinon.stub(fakeExplorer, "documentClientUtility").value(fakeDocumentClientUtility); - sinon.stub(fakeExplorer, "selectedNode").value(ko.observable()); - sinon.stub(fakeExplorer, "tabsManager").value(new TabsManager()); - fakeExplorer.isLastNonEmptyDatabase.returns(true); + fakeExplorer.databaseAccount = ko.observable({ + id: SubscriptionId, + name: AccountName + } as ViewModels.DatabaseAccount); + fakeExplorer.defaultExperience = ko.observable("DocumentDB"); + fakeExplorer.isPreferredApiCassandra = ko.computed(() => { + return false; + }); + fakeExplorer.documentClientUtility = fakeDocumentClientUtility; + fakeExplorer.selectedNode = ko.observable(); + fakeExplorer.tabsManager = new TabsManager(); + fakeExplorer.isLastNonEmptyDatabase = () => true; let pane = new DeleteDatabaseConfirmationPane({ documentClientUtility: fakeDocumentClientUtility as any, diff --git a/src/Explorer/Panes/GenericRightPaneComponent.tsx b/src/Explorer/Panes/GenericRightPaneComponent.tsx index 753119ccf..4b17bdc8f 100644 --- a/src/Explorer/Panes/GenericRightPaneComponent.tsx +++ b/src/Explorer/Panes/GenericRightPaneComponent.tsx @@ -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; diff --git a/src/Explorer/Panes/NewVertexPane.ts b/src/Explorer/Panes/NewVertexPane.ts index edccddf48..e1c96fcd1 100644 --- a/src/Explorer/Panes/NewVertexPane.ts +++ b/src/Explorer/Panes/NewVertexPane.ts @@ -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; public formErrors: ko.Observable; public formErrorsDetails: ko.Observable; diff --git a/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx b/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx index 4fa84141e..2dac1fe9a 100644 --- a/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx +++ b/src/Explorer/Panes/PublishNotebookPaneAdapter.tsx @@ -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; - 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 ; - } - - 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 { - 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 ; - }; - - 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; + 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 ; + } + + 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 { + 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 ; + }; + + private reset = (): void => { + this.isOpened = false; + this.isExecuting = false; + this.formError = undefined; + this.formErrorDetail = undefined; + this.name = undefined; + this.author = undefined; + this.content = undefined; + }; +} diff --git a/src/Explorer/Panes/SettingsPane.test.ts b/src/Explorer/Panes/SettingsPane.test.ts index 1f444c02e..3bf87f26f 100644 --- a/src/Explorer/Panes/SettingsPane.test.ts +++ b/src/Explorer/Panes/SettingsPane.test.ts @@ -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 }); diff --git a/src/Explorer/Panes/Tables/EditTableEntityPane.ts b/src/Explorer/Panes/Tables/EditTableEntityPane.ts index db846f63b..b7bff3565 100644 --- a/src/Explorer/Panes/Tables/EditTableEntityPane.ts +++ b/src/Explorer/Panes/Tables/EditTableEntityPane.ts @@ -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; public originEntity: Entities.ITableEntity; diff --git a/src/Explorer/Panes/UploadItemsPaneAdapter.tsx b/src/Explorer/Panes/UploadItemsPaneAdapter.tsx index 99f35c495..fd63e1a73 100644 --- a/src/Explorer/Panes/UploadItemsPaneAdapter.tsx +++ b/src/Explorer/Panes/UploadItemsPaneAdapter.tsx @@ -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(); diff --git a/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx b/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx index a244275e3..bd2f381b8 100644 --- a/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx +++ b/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx @@ -18,6 +18,7 @@ import * as MostRecentActivity from "../MostRecentActivity/MostRecentActivity"; import AddDatabaseIcon from "../../../images/AddDatabase.svg"; import SampleIcon from "../../../images/Hero-sample.svg"; import { DataSamplesUtil } from "../DataSamples/DataSamplesUtil"; +import Explorer from "../Explorer"; /** * TODO Remove this when fully ported to ReactJS @@ -29,7 +30,7 @@ export class SplashScreenComponentAdapter implements ReactAdapter { public parameters: ko.Observable; - constructor(private container: ViewModels.Explorer) { + constructor(private container: Explorer) { this.parameters = ko.observable(Date.now()); this.container.tabsManager.openedTabs.subscribe((tabs: ViewModels.Tab[]) => { if (tabs.length === 0) { diff --git a/src/Explorer/Tables/DataTable/DataTableBindingManager.ts b/src/Explorer/Tables/DataTable/DataTableBindingManager.ts index a12516e7e..ecbd4dc32 100644 --- a/src/Explorer/Tables/DataTable/DataTableBindingManager.ts +++ b/src/Explorer/Tables/DataTable/DataTableBindingManager.ts @@ -237,7 +237,7 @@ function updateTableScrollableRegionHeight(): void { .offset().top; var dataTablesInfoElem = $(tabElement).find(".dataTables_info"); var dataTablesPaginateElem = $(tabElement).find(".dataTables_paginate"); - const explorer = window.dataExplorer as ViewModels.Explorer; + const explorer = window.dataExplorer; const notificationConsoleHeight = explorer.isNotificationConsoleExpanded() ? 252 /** 32px(header) + 220px(content height) **/ : 32 /** Header height **/; diff --git a/src/Explorer/Tables/DataTable/TableCommands.ts b/src/Explorer/Tables/DataTable/TableCommands.ts index bfda7f1ae..70226fc62 100644 --- a/src/Explorer/Tables/DataTable/TableCommands.ts +++ b/src/Explorer/Tables/DataTable/TableCommands.ts @@ -6,6 +6,7 @@ import TableEntityListViewModel from "./TableEntityListViewModel"; import * as Entities from "../Entities"; import * as ViewModels from "../../../Contracts/ViewModels"; import * as TableColumnOptionsPane from "../../Panes/Tables/TableColumnOptionsPane"; +import Explorer from "../../Explorer"; export default class TableCommands { // Command Ids @@ -15,9 +16,9 @@ export default class TableCommands { public static resetColumnsCommand: string = "reset"; public static customizeColumnsCommand: string = "customizeColumns"; - private _container: ViewModels.Explorer; + private _container: Explorer; - constructor(container: ViewModels.Explorer) { + constructor(container: Explorer) { this._container = container; } diff --git a/src/Explorer/Tables/TableDataClient.ts b/src/Explorer/Tables/TableDataClient.ts index 3de9b558a..224dc2289 100644 --- a/src/Explorer/Tables/TableDataClient.ts +++ b/src/Explorer/Tables/TableDataClient.ts @@ -16,6 +16,7 @@ import * as ViewModels from "../../Contracts/ViewModels"; import { MessageTypes } from "../../Contracts/ExplorerContracts"; import { MessageHandler } from "../../Common/MessageHandler"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; +import Explorer from "../Explorer"; export interface CassandraTableKeys { partitionKeys: CassandraTableKey[]; @@ -405,7 +406,7 @@ export class CassandraAPIDataClient extends TableDataClient { public createKeyspace( cassandraEndpoint: string, resourceId: string, - explorer: ViewModels.Explorer, + explorer: Explorer, createKeyspaceQuery: string ): Q.Promise { if (!createKeyspaceQuery) { @@ -446,7 +447,7 @@ export class CassandraAPIDataClient extends TableDataClient { public createTableAndKeyspace( cassandraEndpoint: string, resourceId: string, - explorer: ViewModels.Explorer, + explorer: Explorer, createTableQuery: string, createKeyspaceQuery?: string ): Q.Promise { @@ -506,7 +507,7 @@ export class CassandraAPIDataClient extends TableDataClient { cassandraEndpoint: string, resourceId: string, deleteQuery: string, - explorer: ViewModels.Explorer + explorer: Explorer ): Q.Promise { const deferred = Q.defer(); const notificationId = NotificationConsoleUtils.logConsoleMessage( @@ -660,7 +661,7 @@ export class CassandraAPIDataClient extends TableDataClient { cassandraEndpoint: string, resourceId: string, query: string, - explorer: ViewModels.Explorer + explorer: Explorer ): Q.Promise { const deferred = Q.defer(); const authType = window.authType; diff --git a/src/Explorer/Tabs/ConflictsTab.ts b/src/Explorer/Tabs/ConflictsTab.ts index d2394e239..bb76b53aa 100644 --- a/src/Explorer/Tabs/ConflictsTab.ts +++ b/src/Explorer/Tabs/ConflictsTab.ts @@ -20,6 +20,7 @@ import DiscardIcon from "../../../images/discard.svg"; import DeleteIcon from "../../../images/delete.svg"; import { QueryIterator, ItemDefinition, Resource, ConflictDefinition } from "@azure/cosmos"; import { MinimalQueryIterator } from "../../Common/IteratorUtilities"; +import Explorer from "../Explorer"; export default class ConflictsTab extends TabsBase implements ViewModels.ConflictsTab { public selectedConflictId: ko.Observable; @@ -49,7 +50,7 @@ export default class ConflictsTab extends TabsBase implements ViewModels.Conflic public conflictIds: ko.ObservableArray; private _documentsIterator: MinimalQueryIterator; - private _container: ViewModels.Explorer; + private _container: Explorer; private _acceptButtonLabel: ko.Observable = ko.observable("Save"); protected _selfLink: string; diff --git a/src/Explorer/Tabs/DatabaseSettingsTab.ts b/src/Explorer/Tabs/DatabaseSettingsTab.ts index 4ac2066ba..bdce3dfab 100644 --- a/src/Explorer/Tabs/DatabaseSettingsTab.ts +++ b/src/Explorer/Tabs/DatabaseSettingsTab.ts @@ -17,6 +17,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { CosmosClient } from "../../Common/CosmosClient"; import { PlatformType } from "../../PlatformType"; import { RequestOptions } from "@azure/cosmos/dist-esm"; +import Explorer from "../Explorer"; const updateThroughputBeyondLimitWarningMessage: string = ` You are about to request an increase in throughput beyond the pre-allocated capacity. @@ -94,7 +95,7 @@ export default class DatabaseSettingsTab extends TabsBase private _hasProvisioningTypeChanged: ko.Computed; private _wasAutopilotOriginallySet: ko.Observable; private _offerReplacePending: ko.Computed; - private container: ViewModels.Explorer; + private container: Explorer; constructor(options: ViewModels.TabOptions) { super(options); diff --git a/src/Explorer/Tabs/DocumentsTab.ts b/src/Explorer/Tabs/DocumentsTab.ts index 4eda49040..87142bbd2 100644 --- a/src/Explorer/Tabs/DocumentsTab.ts +++ b/src/Explorer/Tabs/DocumentsTab.ts @@ -25,6 +25,7 @@ import SynapseIcon from "../../../images/synapse-link.svg"; import { extractPartitionKey, PartitionKeyDefinition, QueryIterator, ItemDefinition, Resource } from "@azure/cosmos"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; +import Explorer from "../Explorer"; export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab { public selectedDocumentId: ko.Observable; @@ -957,7 +958,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen ); } - public static _createUploadButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { + public static _createUploadButton(container: Explorer): ViewModels.NavbarButtonConfig { const label = "Upload Item"; return { iconSrc: UploadIcon, diff --git a/src/Explorer/Tabs/GalleryTab.tsx b/src/Explorer/Tabs/GalleryTab.tsx index 58645522b..0820adbea 100644 --- a/src/Explorer/Tabs/GalleryTab.tsx +++ b/src/Explorer/Tabs/GalleryTab.tsx @@ -3,12 +3,13 @@ import { GalleryAndNotebookViewerComponentProps } from "../Controls/NotebookGall import { GalleryAndNotebookViewerComponentAdapter } from "../Controls/NotebookGallery/GalleryAndNotebookViewerComponentAdapter"; import { GalleryTab as GalleryViewerTab, SortBy } from "../Controls/NotebookGallery/GalleryViewerComponent"; import TabsBase from "./TabsBase"; +import Explorer from "../Explorer"; /** * Notebook gallery tab */ export default class GalleryTab extends TabsBase implements ViewModels.Tab { - private container: ViewModels.Explorer; + private container: Explorer; public galleryAndNotebookViewerComponentAdapter: GalleryAndNotebookViewerComponentAdapter; constructor(options: ViewModels.GalleryTabOptions) { @@ -29,7 +30,7 @@ export default class GalleryTab extends TabsBase implements ViewModels.Tab { this.galleryAndNotebookViewerComponentAdapter = new GalleryAndNotebookViewerComponentAdapter(props); } - protected getContainer(): ViewModels.Explorer { + protected getContainer(): Explorer { return this.container; } } diff --git a/src/Explorer/Tabs/MongoShellTab.ts b/src/Explorer/Tabs/MongoShellTab.ts index 6120c6c65..dbeda93cc 100644 --- a/src/Explorer/Tabs/MongoShellTab.ts +++ b/src/Explorer/Tabs/MongoShellTab.ts @@ -13,10 +13,11 @@ import { CosmosClient } from "../../Common/CosmosClient"; import { HashMap } from "../../Common/HashMap"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { PlatformType } from "../../PlatformType"; +import Explorer from "../Explorer"; export default class MongoShellTab extends TabsBase implements ViewModels.MongoShellTab { public url: ko.Computed; - private _container: ViewModels.Explorer; + private _container: Explorer; private _runtimeEndpoint: string; private _logTraces: HashMap; diff --git a/src/Explorer/Tabs/NotebookV2Tab.ts b/src/Explorer/Tabs/NotebookV2Tab.ts index 5d4ab0602..4e96ef453 100644 --- a/src/Explorer/Tabs/NotebookV2Tab.ts +++ b/src/Explorer/Tabs/NotebookV2Tab.ts @@ -27,10 +27,11 @@ import { NotebookComponentAdapter } from "../Notebook/NotebookComponent/Notebook import { NotebookConfigurationUtils } from "../../Utils/NotebookConfigurationUtils"; import { KernelSpecsDisplay, NotebookClientV2 } from "../Notebook/NotebookClientV2"; import { config } from "../../Config"; +import Explorer from "../Explorer"; export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { private static clientManager: NotebookClientV2; - private container: ViewModels.Explorer; + private container: Explorer; public notebookPath: ko.Observable; private selectedSparkPool: ko.Observable; private notebookComponentAdapter: NotebookComponentAdapter; @@ -104,7 +105,7 @@ export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { return await this.configureServiceEndpoints(this.notebookComponentAdapter.getCurrentKernelName()); } - protected getContainer(): ViewModels.Explorer { + protected getContainer(): Explorer { return this.container; } diff --git a/src/Explorer/Tabs/NotebookViewerTab.tsx b/src/Explorer/Tabs/NotebookViewerTab.tsx index ee9b31089..f9b573e42 100644 --- a/src/Explorer/Tabs/NotebookViewerTab.tsx +++ b/src/Explorer/Tabs/NotebookViewerTab.tsx @@ -7,6 +7,7 @@ import { NotebookViewerComponentProps } from "../Controls/NotebookViewer/NotebookViewerComponent"; import TabsBase from "./TabsBase"; +import Explorer from "../Explorer"; /** * Notebook Viewer tab @@ -29,7 +30,7 @@ class NotebookViewerComponentAdapter implements ReactAdapter { } export default class NotebookViewerTab extends TabsBase implements ViewModels.Tab { - private container: ViewModels.Explorer; + private container: Explorer; public notebookUrl: string; public notebookViewerComponentAdapter: NotebookViewerComponentAdapter; @@ -49,7 +50,7 @@ export default class NotebookViewerTab extends TabsBase implements ViewModels.Ta }); } - protected getContainer(): ViewModels.Explorer { + protected getContainer(): Explorer { return this.container; } diff --git a/src/Explorer/Tabs/QueryTab.test.ts b/src/Explorer/Tabs/QueryTab.test.ts index e75226d14..e22d6c2d6 100644 --- a/src/Explorer/Tabs/QueryTab.test.ts +++ b/src/Explorer/Tabs/QueryTab.test.ts @@ -6,7 +6,7 @@ import { CollectionStub, DatabaseStub } from "../../Explorer/OpenActionsStubs"; import QueryTab from "./QueryTab"; describe("Query Tab", () => { - function getNewQueryTabForContainer(container: ViewModels.Explorer): ViewModels.QueryTab { + function getNewQueryTabForContainer(container: Explorer): ViewModels.QueryTab { const database: ViewModels.Database = new DatabaseStub({ container: container, id: ko.observable("test"), @@ -54,7 +54,7 @@ describe("Query Tab", () => { }); describe("isQueryMetricsEnabled()", () => { - let explorer: ViewModels.Explorer; + let explorer: Explorer; beforeEach(() => { explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); @@ -74,7 +74,7 @@ describe("Query Tab", () => { }); describe("Save Queries command button", () => { - let explorer: ViewModels.Explorer; + let explorer: Explorer; beforeEach(() => { explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); diff --git a/src/Explorer/Tabs/QueryTab.ts b/src/Explorer/Tabs/QueryTab.ts index 70811be2a..988c65004 100644 --- a/src/Explorer/Tabs/QueryTab.ts +++ b/src/Explorer/Tabs/QueryTab.ts @@ -115,7 +115,7 @@ export default class QueryTab extends TabsBase implements ViewModels.QueryTab, V }; this._isSaveQueriesEnabled = ko.computed(() => { - const container: ViewModels.Explorer = this.collection && this.collection.container; + const container = this.collection && this.collection.container; return (container && (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph())) || false; }); diff --git a/src/Explorer/Tabs/QueryTablesTab.ts b/src/Explorer/Tabs/QueryTablesTab.ts index 69a387c8d..626e641c5 100644 --- a/src/Explorer/Tabs/QueryTablesTab.ts +++ b/src/Explorer/Tabs/QueryTablesTab.ts @@ -13,6 +13,7 @@ import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg"; import AddEntityIcon from "../../../images/AddEntity.svg"; import EditEntityIcon from "../../../images/Edit-entity.svg"; import DeleteEntitiesIcon from "../../../images/DeleteEntities.svg"; +import Explorer from "../Explorer"; // Will act as table explorer class export default class QueryTablesTab extends TabsBase { @@ -31,7 +32,7 @@ export default class QueryTablesTab extends TabsBase { public deleteEntityButton: ViewModels.Button; public queryBuilderButton: ViewModels.Button; public queryTextButton: ViewModels.Button; - public container: ViewModels.Explorer; + public container: Explorer; constructor(options: ViewModels.TabOptions) { super(options); diff --git a/src/Explorer/Tabs/SettingsTab.test.ts b/src/Explorer/Tabs/SettingsTab.test.ts index 6a28211ba..b2214fd7c 100644 --- a/src/Explorer/Tabs/SettingsTab.test.ts +++ b/src/Explorer/Tabs/SettingsTab.test.ts @@ -177,7 +177,7 @@ describe("Settings tab", () => { }); describe("Should update collection", () => { - let explorer: ViewModels.Explorer; + let explorer: Explorer; beforeEach(() => { explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); @@ -259,7 +259,7 @@ describe("Settings tab", () => { }); describe("Get Conflict Resolution configuration from user", () => { - let explorer: ViewModels.Explorer; + let explorer: Explorer; beforeEach(() => { explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); diff --git a/src/Explorer/Tabs/SettingsTab.ts b/src/Explorer/Tabs/SettingsTab.ts index e1d60e52d..53b4989ac 100644 --- a/src/Explorer/Tabs/SettingsTab.ts +++ b/src/Explorer/Tabs/SettingsTab.ts @@ -17,6 +17,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants"; import { CosmosClient } from "../../Common/CosmosClient"; import { PlatformType } from "../../PlatformType"; import { RequestOptions } from "@azure/cosmos/dist-esm"; +import Explorer from "../Explorer"; const ttlWarning: string = ` The system will automatically delete items based on the TTL value (in seconds) you provide, without needing a delete operation explicitly issued by a client application. @@ -218,7 +219,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.Settings public throughputModeRadioName: string; private _offerReplacePending: ko.PureComputed; - private container: ViewModels.Explorer; + private container: Explorer; private _wasAutopilotOriginallySet: ko.Observable; private _isAutoPilotDirty: ko.Computed; private _hasProvisioningTypeChanged: ko.Computed; diff --git a/src/Explorer/Tabs/SparkMasterTab.ts b/src/Explorer/Tabs/SparkMasterTab.ts index 52cf0f75f..3469f7240 100644 --- a/src/Explorer/Tabs/SparkMasterTab.ts +++ b/src/Explorer/Tabs/SparkMasterTab.ts @@ -2,12 +2,13 @@ import * as ko from "knockout"; import * as DataModels from "../../Contracts/DataModels"; import * as ViewModels from "../../Contracts/ViewModels"; import TabsBase from "./TabsBase"; +import Explorer from "../Explorer"; export default class SparkMasterTab extends TabsBase { public sparkMasterSrc: ko.Observable; private _clusterConnectionInfo: DataModels.SparkClusterConnectionInfo; - private _container: ViewModels.Explorer; + private _container: Explorer; constructor(options: ViewModels.SparkMasterTabOptions) { super(options); diff --git a/src/Explorer/Tabs/TabsBase.ts b/src/Explorer/Tabs/TabsBase.ts index c3c0390d6..6711f3441 100644 --- a/src/Explorer/Tabs/TabsBase.ts +++ b/src/Explorer/Tabs/TabsBase.ts @@ -8,6 +8,7 @@ import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import ThemeUtility from "../../Common/ThemeUtility"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; +import Explorer from "../Explorer"; // TODO: Use specific actions for logging telemetry data export default class TabsBase extends WaitsForTemplateViewModel implements ViewModels.Tab { @@ -79,7 +80,7 @@ export default class TabsBase extends WaitsForTemplateViewModel implements ViewM } public onCloseTabButtonClick(): void { - const explorer: ViewModels.Explorer = this.getContainer(); + const explorer = this.getContainer(); explorer.tabsManager.closeTab(this.tabId, explorer); TelemetryProcessor.trace(Action.Tab, ActionModifiers.Close, { @@ -173,7 +174,7 @@ export default class TabsBase extends WaitsForTemplateViewModel implements ViewM return Q(); } - protected getContainer(): ViewModels.Explorer { + protected getContainer(): Explorer { return (this.collection && this.collection.container) || (this.database && this.database.container); } diff --git a/src/Explorer/Tabs/TabsManager.test.ts b/src/Explorer/Tabs/TabsManager.test.ts index 64ecae9a3..c1ea0f383 100644 --- a/src/Explorer/Tabs/TabsManager.test.ts +++ b/src/Explorer/Tabs/TabsManager.test.ts @@ -10,7 +10,7 @@ import QueryTab from "./QueryTab"; describe("Tabs manager tests", () => { let tabsManager: TabsManager; - let explorer: ViewModels.Explorer; + let explorer: Explorer; let database: ViewModels.Database; let collection: ViewModels.Collection; let queryTab: QueryTab; diff --git a/src/Explorer/Tabs/TabsManager.ts b/src/Explorer/Tabs/TabsManager.ts index e8f48fe06..2d8746c2f 100644 --- a/src/Explorer/Tabs/TabsManager.ts +++ b/src/Explorer/Tabs/TabsManager.ts @@ -1,6 +1,7 @@ import * as ko from "knockout"; import * as ViewModels from "../../Contracts/ViewModels"; import TabsManagerTemplate from "./TabsManager.html"; +import Explorer from "../Explorer"; export class TabsManager { public openedTabs: ko.ObservableArray; @@ -62,7 +63,7 @@ export class TabsManager { this.openedTabs([]); } - public closeTab(tabId: string, explorer: ViewModels.Explorer): void { + public closeTab(tabId: string, explorer: Explorer): void { const tabIndex: number = this.openedTabs().findIndex((tab: ViewModels.Tab) => tab.tabId === tabId); if (tabIndex !== -1) { const tabToActive: ViewModels.Tab = this.openedTabs()[tabIndex + 1] || this.openedTabs()[tabIndex - 1]; diff --git a/src/Explorer/Tabs/TerminalTab.tsx b/src/Explorer/Tabs/TerminalTab.tsx index de0db416e..a2c8bac2c 100644 --- a/src/Explorer/Tabs/TerminalTab.tsx +++ b/src/Explorer/Tabs/TerminalTab.tsx @@ -5,6 +5,7 @@ import TabsBase from "./TabsBase"; import * as React from "react"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { NotebookTerminalComponent } from "../Controls/Notebook/NotebookTerminalComponent"; +import Explorer from "../Explorer"; /** * Notebook terminal tab @@ -30,7 +31,7 @@ class NotebookTerminalComponentAdapter implements ReactAdapter { } export default class TerminalTab extends TabsBase implements ViewModels.Tab { - private container: ViewModels.Explorer; + private container: Explorer; private notebookTerminalComponentAdapter: NotebookTerminalComponentAdapter; constructor(options: ViewModels.TerminalTabOptions) { @@ -48,7 +49,7 @@ export default class TerminalTab extends TabsBase implements ViewModels.Tab { }); } - protected getContainer(): ViewModels.Explorer { + protected getContainer(): Explorer { return this.container; } diff --git a/src/Explorer/Tree/Collection.test.ts b/src/Explorer/Tree/Collection.test.ts index 58b1235f7..c95d41e94 100644 --- a/src/Explorer/Tree/Collection.test.ts +++ b/src/Explorer/Tree/Collection.test.ts @@ -2,11 +2,12 @@ import * as DataModels from "../../Contracts/DataModels"; import * as ko from "knockout"; import * as ViewModels from "../../Contracts/ViewModels"; import Collection from "./Collection"; +import Explorer from "../Explorer"; jest.mock("monaco-editor"); describe("Collection", () => { function generateCollection( - container: ViewModels.Explorer, + container: Explorer, databaseId: string, data: DataModels.Collection, quotaInfo: DataModels.CollectionQuotaInfo, @@ -31,7 +32,7 @@ describe("Collection", () => { } function generateMockCollectionWithDataModel(data: DataModels.Collection): Collection { - const mockContainer = {} as ViewModels.Explorer; + const mockContainer = {} as Explorer; mockContainer.isPreferredApiMongoDB = ko.computed(() => { return false; }); @@ -47,9 +48,7 @@ describe("Collection", () => { mockContainer.isPreferredApiGraph = ko.computed(() => { return false; }); - mockContainer.deleteCollectionText = ko.computed(() => { - return "delete collection"; - }); + mockContainer.deleteCollectionText = ko.observable("delete collection"); return generateCollection(mockContainer, "abc", data, {} as DataModels.CollectionQuotaInfo, {} as DataModels.Offer); } diff --git a/src/Explorer/Tree/Collection.ts b/src/Explorer/Tree/Collection.ts index 1b8217f36..75b4dea84 100644 --- a/src/Explorer/Tree/Collection.ts +++ b/src/Explorer/Tree/Collection.ts @@ -32,10 +32,11 @@ import StoredProcedure from "./StoredProcedure"; import Trigger from "./Trigger"; import UserDefinedFunction from "./UserDefinedFunction"; import { config } from "../../Config"; +import Explorer from "../Explorer"; export default class Collection implements ViewModels.Collection { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public self: string; public rid: string; public databaseId: string; @@ -86,7 +87,7 @@ export default class Collection implements ViewModels.Collection { public triggersFocused: ko.Observable; constructor( - container: ViewModels.Explorer, + container: Explorer, databaseId: string, data: DataModels.Collection, quotaInfo: DataModels.CollectionQuotaInfo, diff --git a/src/Explorer/Tree/Database.ts b/src/Explorer/Tree/Database.ts index aa1c263f3..3e72f4ffa 100644 --- a/src/Explorer/Tree/Database.ts +++ b/src/Explorer/Tree/Database.ts @@ -11,10 +11,11 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import * as Logger from "../../Common/Logger"; +import Explorer from "../Explorer"; export default class Database implements ViewModels.Database { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public self: string; public rid: string; public id: ko.Observable; @@ -24,7 +25,7 @@ export default class Database implements ViewModels.Database { public isDatabaseShared: ko.Computed; public selectedSubnodeKind: ko.Observable; - constructor(container: ViewModels.Explorer, data: any, offer: DataModels.Offer) { + constructor(container: Explorer, data: any, offer: DataModels.Offer) { this.nodeKind = "Database"; this.container = container; this.self = data._self; diff --git a/src/Explorer/Tree/ResourceTokenCollection.ts b/src/Explorer/Tree/ResourceTokenCollection.ts index 42788263e..b12e4b86a 100644 --- a/src/Explorer/Tree/ResourceTokenCollection.ts +++ b/src/Explorer/Tree/ResourceTokenCollection.ts @@ -8,10 +8,11 @@ import DocumentsTab from "../Tabs/DocumentsTab"; import Q from "q"; import QueryTab from "../Tabs/QueryTab"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import Explorer from "../Explorer"; export default class ResourceTokenCollection implements ViewModels.CollectionBase { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public databaseId: string; public self: string; public rid: string; @@ -24,7 +25,7 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas public selectedSubnodeKind: ko.Observable; public isCollectionExpanded: ko.Observable; - constructor(container: ViewModels.Explorer, databaseId: string, data: DataModels.Collection) { + constructor(container: Explorer, databaseId: string, data: DataModels.Collection) { this.nodeKind = "Collection"; this.container = container; this.databaseId = databaseId; diff --git a/src/Explorer/Tree/ResourceTreeAdapter.tsx b/src/Explorer/Tree/ResourceTreeAdapter.tsx index 5f884ef58..b95a5e699 100644 --- a/src/Explorer/Tree/ResourceTreeAdapter.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapter.tsx @@ -26,6 +26,7 @@ import * as GitHubUtils from "../../Utils/GitHubUtils"; import GalleryIcon from "../../../images/GalleryIcon.svg"; import { Callout, Text, Link, DirectionalHint, Stack, ICalloutProps, ILinkProps } from "office-ui-fabric-react"; import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility"; +import Explorer from "../Explorer"; export class ResourceTreeAdapter implements ReactAdapter { private static readonly DataTitle = "DATA"; @@ -42,7 +43,7 @@ export class ResourceTreeAdapter implements ReactAdapter { private koSubsCollectionIdMap: ArrayHashMap; // collection id -> ko subs private databaseCollectionIdMap: ArrayHashMap; // database id -> collection ids - public constructor(private container: ViewModels.Explorer) { + public constructor(private container: Explorer) { this.parameters = ko.observable(Date.now()); this.container.selectedNode.subscribe((newValue: any) => this.triggerRender()); @@ -208,7 +209,7 @@ export class ResourceTreeAdapter implements ReactAdapter { * This is a rewrite of Collection.ts : showScriptsMenu, showStoredProcedures, showTriggers, showUserDefinedFunctions * @param container */ - private static showScriptNodes(container: ViewModels.Explorer): boolean { + private static showScriptNodes(container: Explorer): boolean { return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph(); } diff --git a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx index 2b41ef020..0f37de89a 100644 --- a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.test.tsx @@ -7,9 +7,10 @@ import ResourceTokenCollection from "./ResourceTokenCollection"; import { ResourceTreeAdapterForResourceToken } from "./ResourceTreeAdapterForResourceToken"; import { shallow } from "enzyme"; import { TreeComponent, TreeNode, TreeComponentProps } from "../Controls/TreeComponent/TreeComponent"; +import Explorer from "../Explorer"; -const createMockContainer = (): ViewModels.Explorer => { - let mockContainer = {} as ViewModels.Explorer; +const createMockContainer = (): Explorer => { + let mockContainer = {} as Explorer; mockContainer.resourceTokenCollection = createMockCollection(mockContainer); mockContainer.selectedNode = ko.observable(); mockContainer.mostRecentActivity = new MostRecentActivity.MostRecentActivity(mockContainer); @@ -18,7 +19,7 @@ const createMockContainer = (): ViewModels.Explorer => { return mockContainer; }; -const createMockCollection = (container: ViewModels.Explorer): ko.Observable => { +const createMockCollection = (container: Explorer): ko.Observable => { let mockCollection = {} as DataModels.Collection; mockCollection._rid = "fakeRid"; mockCollection._self = "fakeSelf"; @@ -33,7 +34,7 @@ const createMockCollection = (container: ViewModels.Explorer): ko.Observable { - const mockContainer: ViewModels.Explorer = createMockContainer(); + const mockContainer: Explorer = createMockContainer(); const resourceTree = new ResourceTreeAdapterForResourceToken(mockContainer); it("should render", () => { diff --git a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx index 91d945dd4..625d83968 100644 --- a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx @@ -7,12 +7,13 @@ import { NotebookContentItem } from "../Notebook/NotebookContentItem"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { TreeComponent, TreeNode } from "../Controls/TreeComponent/TreeComponent"; import CollectionIcon from "../../../images/tree-collection.svg"; +import Explorer from "../Explorer"; export class ResourceTreeAdapterForResourceToken implements ReactAdapter { public parameters: ko.Observable; public myNotebooksContentRoot: NotebookContentItem; - public constructor(private container: ViewModels.Explorer) { + public constructor(private container: Explorer) { this.parameters = ko.observable(Date.now()); this.container.resourceTokenCollection.subscribe((collection: ViewModels.CollectionBase) => this.triggerRender()); diff --git a/src/Explorer/Tree/StoredProcedure.ts b/src/Explorer/Tree/StoredProcedure.ts index 5980c408c..c6474eb45 100644 --- a/src/Explorer/Tree/StoredProcedure.ts +++ b/src/Explorer/Tree/StoredProcedure.ts @@ -6,6 +6,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan import StoredProcedureTab from "../Tabs/StoredProcedureTab"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import Explorer from "../Explorer"; const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE function sample(prefix) { @@ -36,7 +37,7 @@ function sample(prefix) { export default class StoredProcedure implements ViewModels.StoredProcedure { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public collection: ViewModels.Collection; public self: string; public rid: string; @@ -44,7 +45,7 @@ export default class StoredProcedure implements ViewModels.StoredProcedure { public body: ko.Observable; public isExecuteEnabled: boolean; - constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: DataModels.StoredProcedure) { + constructor(container: Explorer, collection: ViewModels.Collection, data: DataModels.StoredProcedure) { this.nodeKind = "StoredProcedure"; this.container = container; this.collection = collection; diff --git a/src/Explorer/Tree/Trigger.ts b/src/Explorer/Tree/Trigger.ts index 2202f6cc1..33f3f3ae1 100644 --- a/src/Explorer/Tree/Trigger.ts +++ b/src/Explorer/Tree/Trigger.ts @@ -5,10 +5,11 @@ import * as DataModels from "../../Contracts/DataModels"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import TriggerTab from "../Tabs/TriggerTab"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import Explorer from "../Explorer"; export default class Trigger implements ViewModels.Trigger { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public collection: ViewModels.Collection; public self: string; public rid: string; @@ -17,7 +18,7 @@ export default class Trigger implements ViewModels.Trigger { public triggerType: ko.Observable; public triggerOperation: ko.Observable; - constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: any) { + constructor(container: Explorer, collection: ViewModels.Collection, data: any) { this.nodeKind = "Trigger"; this.container = container; this.collection = collection; diff --git a/src/Explorer/Tree/UserDefinedFunction.ts b/src/Explorer/Tree/UserDefinedFunction.ts index 14c66be1c..04e778138 100644 --- a/src/Explorer/Tree/UserDefinedFunction.ts +++ b/src/Explorer/Tree/UserDefinedFunction.ts @@ -5,17 +5,18 @@ import * as DataModels from "../../Contracts/DataModels"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import Explorer from "../Explorer"; export default class UserDefinedFunction implements ViewModels.UserDefinedFunction { public nodeKind: string; - public container: ViewModels.Explorer; + public container: Explorer; public collection: ViewModels.Collection; public self: string; public rid: string; public id: ko.Observable; public body: ko.Observable; - constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: DataModels.UserDefinedFunction) { + constructor(container: Explorer, collection: ViewModels.Collection, data: DataModels.UserDefinedFunction) { this.nodeKind = "UserDefinedFunction"; this.container = container; diff --git a/src/GitHub/GitHubOAuthService.test.ts b/src/GitHub/GitHubOAuthService.test.ts index 2327dc18f..2e914867b 100644 --- a/src/GitHub/GitHubOAuthService.test.ts +++ b/src/GitHub/GitHubOAuthService.test.ts @@ -6,6 +6,7 @@ import { GitHubConnector, IGitHubConnectorParams } from "./GitHubConnector"; import { GitHubOAuthService } from "./GitHubOAuthService"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import NotebookManager from "../Explorer/Notebook/NotebookManager"; +import Explorer from "../Explorer/Explorer"; const sampleDatabaseAccount: ViewModels.DatabaseAccount = { id: "id", @@ -25,7 +26,7 @@ const sampleDatabaseAccount: ViewModels.DatabaseAccount = { describe("GitHubOAuthService", () => { let junoClient: JunoClient; let gitHubOAuthService: GitHubOAuthService; - let originalDataExplorer: ViewModels.Explorer; + let originalDataExplorer: Explorer; beforeEach(() => { junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); @@ -35,7 +36,7 @@ describe("GitHubOAuthService", () => { ...originalDataExplorer, logConsoleData: (data): void => data.type === ConsoleDataType.Error ? console.error(data.message) : console.log(data.message) - } as ViewModels.Explorer; + } as Explorer; window.dataExplorer.notebookManager = new NotebookManager(); window.dataExplorer.notebookManager.junoClient = junoClient; window.dataExplorer.notebookManager.gitHubOAuthService = gitHubOAuthService; diff --git a/src/Main.ts b/src/Main.ts index 8af1aaaca..46e4e28d8 100644 --- a/src/Main.ts +++ b/src/Main.ts @@ -74,6 +74,7 @@ import { AuthType } from "./AuthType"; import { initializeIcons } from "office-ui-fabric-react/lib/Icons"; import { applyExplorerBindings } from "./applyExplorerBindings"; import { initializeConfiguration, Platform } from "./Config"; +import Explorer from "./Explorer/Explorer"; initializeIcons(/* optional base url */); @@ -86,13 +87,13 @@ initializeConfiguration().then(config => { // TODO Remove. All window variables should move to src/Config file window.dataExplorerPlatform = PlatformType.Hosted; Hosted.initializeExplorer().then( - (explorer: ViewModels.Explorer) => { + (explorer: Explorer) => { applyExplorerBindings(explorer); Hosted.configureTokenValidationDisplayPrompt(explorer); }, (error: any) => { try { - const uninitializedExplorer: ViewModels.Explorer = Hosted.getUninitializedExplorerForGuestAccess(); + const uninitializedExplorer: Explorer = Hosted.getUninitializedExplorerForGuestAccess(); window.dataExplorer = uninitializedExplorer; ko.applyBindings(uninitializedExplorer); BindingHandlersRegisterer.registerBindingHandlers(); diff --git a/src/Platform/Emulator/ExplorerFactory.ts b/src/Platform/Emulator/ExplorerFactory.ts index dd6c591d9..7a58e11e2 100644 --- a/src/Platform/Emulator/ExplorerFactory.ts +++ b/src/Platform/Emulator/ExplorerFactory.ts @@ -1,4 +1,3 @@ -import * as ViewModels from "../../Contracts/ViewModels"; import { AccountKind, TagNames, DefaultAccountExperience } from "../../Common/Constants"; import Explorer from "../../Explorer/Explorer"; @@ -8,7 +7,7 @@ import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import { DataAccessUtility } from "./DataAccessUtility"; export default class EmulatorExplorerFactory { - public static createExplorer(): ViewModels.Explorer { + public static createExplorer(): Explorer { DocumentClientUtilityBase; const documentClientUtility: DocumentClientUtilityBase = new DocumentClientUtilityBase(new DataAccessUtility()); diff --git a/src/Platform/Emulator/Main.ts b/src/Platform/Emulator/Main.ts index f86a385df..08b32237d 100644 --- a/src/Platform/Emulator/Main.ts +++ b/src/Platform/Emulator/Main.ts @@ -1,7 +1,6 @@ -import * as ViewModels from "../../Contracts/ViewModels"; import EmulatorExplorerFactory from "./ExplorerFactory"; +import Explorer from "../../Explorer/Explorer"; -export function initializeExplorer(): ViewModels.Explorer { - const explorer = EmulatorExplorerFactory.createExplorer(); - return explorer; +export function initializeExplorer(): Explorer { + return EmulatorExplorerFactory.createExplorer(); } diff --git a/src/Platform/Hosted/Authorization.ts b/src/Platform/Hosted/Authorization.ts index 96f77c22b..215f1cf20 100644 --- a/src/Platform/Hosted/Authorization.ts +++ b/src/Platform/Hosted/Authorization.ts @@ -90,7 +90,7 @@ export default class AuthHeadersUtil { const url: string = `${ AuthHeadersUtil.extensionEndpoint }/api/tokens/generateToken${AuthHeadersUtil._generateResourceUrl()}`; - const explorer: ViewModels.Explorer = (window).dataExplorer; + const explorer = window.dataExplorer; const headers: any = { authorization: CosmosClient.authorizationToken() }; headers[Constants.HttpHeaders.getReadOnlyKey] = !explorer.hasWriteAccess(); diff --git a/src/Platform/Hosted/ExplorerFactory.ts b/src/Platform/Hosted/ExplorerFactory.ts index 8d128307d..69ea6caab 100644 --- a/src/Platform/Hosted/ExplorerFactory.ts +++ b/src/Platform/Hosted/ExplorerFactory.ts @@ -5,7 +5,7 @@ import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import { DataAccessUtility } from "./DataAccessUtility"; export default class HostedExplorerFactory { - public createExplorer(): ViewModels.Explorer { + public createExplorer(): Explorer { var documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility()); const explorer = new Explorer({ @@ -17,7 +17,7 @@ export default class HostedExplorerFactory { return explorer; } - public static reInitializeDocumentClientUtilityForExplorer(explorer: ViewModels.Explorer): void { + public static reInitializeDocumentClientUtilityForExplorer(explorer: Explorer): void { if (!!explorer) { const documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility()); explorer.rebindDocumentClientUtility(documentClientUtility); diff --git a/src/Platform/Hosted/Main.ts b/src/Platform/Hosted/Main.ts index 5bb361d3c..a7f83163c 100644 --- a/src/Platform/Hosted/Main.ts +++ b/src/Platform/Hosted/Main.ts @@ -23,6 +23,7 @@ import { MessageTypes } from "../../Contracts/ExplorerContracts"; import { SessionStorageUtility, StorageKey } from "../../Shared/StorageUtility"; import { SubscriptionUtilMappings } from "../../Shared/Constants"; import "../../Explorer/Tables/DataTable/DataTableBindingManager"; +import Explorer from "../../Explorer/Explorer"; export default class Main { private static _databaseAccountId: string; @@ -32,8 +33,8 @@ export default class Main { private static _features: { [key: string]: string }; // For AAD, Need to post message to hosted frame to do the auth // Use local deferred variable as work around until we find better solution - private static _getAadAccessDeferred: Q.Deferred; - private static _explorer: ViewModels.Explorer; + private static _getAadAccessDeferred: Q.Deferred; + private static _explorer: Explorer; public static isUsingEncryptionToken(): boolean { const params = new URLSearchParams(window.parent.location.search); @@ -43,11 +44,11 @@ export default class Main { return false; } - public static initializeExplorer(): Q.Promise { + public static initializeExplorer(): Q.Promise { window.addEventListener("message", this._handleMessage.bind(this), false); this._features = {}; const params = new URLSearchParams(window.parent.location.search); - const deferred: Q.Deferred = Q.defer(); + const deferred: Q.Deferred = Q.defer(); let authType: string = null; // Encrypted token flow @@ -74,7 +75,7 @@ export default class Main { return Q.reject("Sign in needed"); } - const explorer: ViewModels.Explorer = this._instantiateExplorer(); + const explorer: Explorer = this._instantiateExplorer(); if (authType === AuthType.EncryptedToken) { MessageHandler.sendMessage({ type: MessageTypes.UpdateAccountSwitch, @@ -109,7 +110,7 @@ export default class Main { return Q(null); } this._explorer = explorer; - this._getAadAccessDeferred = Q.defer(); + this._getAadAccessDeferred = Q.defer(); return this._getAadAccessDeferred.promise.finally(() => { this._getAadAccessDeferred = null; }); @@ -135,7 +136,7 @@ export default class Main { return features; } - public static configureTokenValidationDisplayPrompt(explorer: ViewModels.Explorer): void { + public static configureTokenValidationDisplayPrompt(explorer: Explorer): void { const authType: AuthType = (window).authType; if ( !explorer || @@ -182,7 +183,7 @@ export default class Main { }; } - public static renewExplorerAccess = (explorer: ViewModels.Explorer, connectionString: string): Q.Promise => { + public static renewExplorerAccess = (explorer: Explorer, connectionString: string): Q.Promise => { if (!connectionString) { console.error("Missing or invalid connection string input"); Q.reject("Missing or invalid connection string input"); @@ -249,7 +250,7 @@ export default class Main { return deferred.promise.timeout(Constants.ClientDefaults.requestTimeoutMs); }; - public static getUninitializedExplorerForGuestAccess(): ViewModels.Explorer { + public static getUninitializedExplorerForGuestAccess(): Explorer { const explorer = Main._instantiateExplorer(); if (window.authType === AuthType.AAD) { this._explorer = explorer; @@ -260,7 +261,7 @@ export default class Main { } private static _initDataExplorerFrameInputs( - explorer: ViewModels.Explorer, + explorer: Explorer, masterKey?: string /* master key extracted from connection string if available */, account?: DatabaseAccount, authorizationToken?: string /* access key */ @@ -372,7 +373,7 @@ export default class Main { return Q.reject(`Unsupported AuthType ${authType}`); } - private static _instantiateExplorer(): ViewModels.Explorer { + private static _instantiateExplorer(): Explorer { const hostedExplorerFactory = new HostedExplorerFactory(); const explorer = hostedExplorerFactory.createExplorer(); // workaround to resolve cyclic refs with view @@ -395,7 +396,7 @@ export default class Main { return explorer; } - private static _showGuestAccessTokenRenewalPromptInMs(explorer: ViewModels.Explorer, interval: number): void { + private static _showGuestAccessTokenRenewalPromptInMs(explorer: Explorer, interval: number): void { if (interval != null && !isNaN(interval)) { setTimeout(() => { explorer.displayGuestAccessTokenRenewalPrompt(); @@ -454,7 +455,7 @@ export default class Main { } private static _renewExplorerAccessWithResourceToken = ( - explorer: ViewModels.Explorer, + explorer: Explorer, connectionString: string ): Q.Promise => { window.authType = AuthType.ResourceToken; @@ -506,7 +507,7 @@ export default class Main { }; private static _setExplorerReady( - explorer: ViewModels.Explorer, + explorer: Explorer, masterKey?: string, account?: DatabaseAccount, authorizationToken?: string diff --git a/src/Platform/Portal/DataAccessUtility.ts b/src/Platform/Portal/DataAccessUtility.ts index 11a7585be..724ccd39b 100644 --- a/src/Platform/Portal/DataAccessUtility.ts +++ b/src/Platform/Portal/DataAccessUtility.ts @@ -70,7 +70,7 @@ export class DataAccessUtility extends DataAccessUtilityBase { options: any ): Q.Promise { const deferred: Q.Deferred = Q.defer(); - const explorer: ViewModels.Explorer = (window).dataExplorer; + const explorer = window.dataExplorer; const url: string = `${explorer.extensionEndpoint()}/api/offerthroughputrequest/updatebeyondspecifiedlimit`; const authorizationHeader: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader(); const requestOptions: any = _.extend({}, options, {}); diff --git a/src/Platform/Portal/ExplorerFactory.ts b/src/Platform/Portal/ExplorerFactory.ts index bdaf95440..bf38ffcf1 100644 --- a/src/Platform/Portal/ExplorerFactory.ts +++ b/src/Platform/Portal/ExplorerFactory.ts @@ -6,7 +6,7 @@ import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import { DataAccessUtility } from "./DataAccessUtility"; export default class PortalExplorerFactory { - public createExplorer(): ViewModels.Explorer { + public createExplorer(): Explorer { var documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility()); var explorer = new Explorer({ diff --git a/src/Platform/Portal/Main.ts b/src/Platform/Portal/Main.ts index 46dfdfefc..cfce9ac2f 100644 --- a/src/Platform/Portal/Main.ts +++ b/src/Platform/Portal/Main.ts @@ -1,8 +1,8 @@ -import * as ViewModels from "../../Contracts/ViewModels"; import PortalExplorerFactory from "./ExplorerFactory"; import "../../Explorer/Tables/DataTable/DataTableBindingManager"; +import Explorer from "../../Explorer/Explorer"; -export function initializeExplorer(): ViewModels.Explorer { +export function initializeExplorer(): Explorer { const portalExplorerFactory = new PortalExplorerFactory(); const explorer = portalExplorerFactory.createExplorer(); diff --git a/src/RouteHandlers/TabRouteHandler.ts b/src/RouteHandlers/TabRouteHandler.ts index e30212e05..54ef68463 100644 --- a/src/RouteHandlers/TabRouteHandler.ts +++ b/src/RouteHandlers/TabRouteHandler.ts @@ -183,7 +183,6 @@ export class TabRouteHandler { private _openQueryTabForResource(databaseId: string, collectionId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( databaseId, collectionId @@ -203,7 +202,6 @@ export class TabRouteHandler { private _openMongoQueryTabForResource(databaseId: string, collectionId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( databaseId, collectionId @@ -226,7 +224,6 @@ export class TabRouteHandler { private _openMongoShellTabForResource(databaseId: string, collectionId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( databaseId, collectionId @@ -249,7 +246,7 @@ export class TabRouteHandler { private _openDatabaseSettingsTabForResource(databaseId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; + const explorer = window.dataExplorer; const database: ViewModels.Database = _.find( explorer.databases(), (database: ViewModels.Database) => database.id() === databaseId @@ -270,7 +267,6 @@ export class TabRouteHandler { private _openNewSprocTabForResource(databaseId: string, collectionId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( databaseId, collectionId @@ -303,7 +299,6 @@ export class TabRouteHandler { private _openNewTriggerTabForResource(databaseId: string, collectionId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( databaseId, collectionId @@ -335,7 +330,6 @@ export class TabRouteHandler { private _openNewUserDefinedFunctionTabForResource(databaseId: string, collectionId: string): void { this._executeActionHelper(() => { - const explorer: ViewModels.Explorer = (window).dataExplorer; const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( databaseId, collectionId @@ -389,7 +383,7 @@ export class TabRouteHandler { tabKind: ViewModels.CollectionTabKind, isNewScriptTab?: boolean ): ViewModels.Tab { - const explorer: ViewModels.Explorer = (window).dataExplorer; + const explorer = window.dataExplorer; const matchingTabs: ViewModels.Tab[] = explorer.tabsManager.getTabs( tabKind, (tab: ViewModels.Tab) => @@ -402,7 +396,7 @@ export class TabRouteHandler { } private _findMatchingCollectionForResource(databaseId: string, collectionId: string): ViewModels.Collection { - const explorer: ViewModels.Explorer = (window).dataExplorer; + const explorer = window.dataExplorer; const matchedDatabase: ViewModels.Database = explorer.findDatabaseWithId(databaseId); const matchedCollection: ViewModels.Collection = matchedDatabase && matchedDatabase.findCollectionWithId(collectionId); @@ -411,7 +405,7 @@ export class TabRouteHandler { } private _executeActionHelper(action: () => void): void { - const explorer: ViewModels.Explorer = (window).dataExplorer; + const explorer = window.dataExplorer; if (!!explorer && (explorer.isRefreshingExplorer() || !explorer.isAccountReady())) { const refreshSubscription = explorer.isRefreshingExplorer.subscribe((isRefreshing: boolean) => { if (!isRefreshing) { diff --git a/src/Shared/AddCollectionUtility.ts b/src/Shared/AddCollectionUtility.ts index 563c4470a..3dbc4b7af 100644 --- a/src/Shared/AddCollectionUtility.ts +++ b/src/Shared/AddCollectionUtility.ts @@ -11,6 +11,7 @@ import { MessageHandler } from "../Common/MessageHandler"; import { MessageTypes } from "../Contracts/ExplorerContracts"; import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils"; import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient"; +import Explorer from "../Explorer/Explorer"; export class CreateSqlCollectionUtilities { public static createSqlCollection( @@ -276,10 +277,7 @@ export class Utilities { return defaults.throughput.unlimitedmin; } - public static getMaxThroughput( - defaults: ViewModels.CollectionCreationDefaults, - container: ViewModels.Explorer - ): number { + public static getMaxThroughput(defaults: ViewModels.CollectionCreationDefaults, container: Explorer): number { const throughput = defaults.throughput.unlimited; if (typeof throughput === "number") { return throughput; @@ -290,7 +288,7 @@ export class Utilities { } } - private static _exceedsThreshold(unlimitedThreshold: number, container: ViewModels.Explorer): boolean { + private static _exceedsThreshold(unlimitedThreshold: number, container: Explorer): boolean { const databases = (container && container.databases && container.databases()) || []; return _.any( databases, diff --git a/src/Utils/AuthorizationUtils.ts b/src/Utils/AuthorizationUtils.ts index e2b728da7..7293ddaeb 100644 --- a/src/Utils/AuthorizationUtils.ts +++ b/src/Utils/AuthorizationUtils.ts @@ -57,8 +57,8 @@ export function decryptJWTToken(token: string) { } export function displayTokenRenewalPromptForStatus(httpStatusCode: number): void { - const platformType: PlatformType = window.dataExplorerPlatform; - const explorer: ViewModels.Explorer = window.dataExplorer; + const platformType = window.dataExplorerPlatform; + const explorer = window.dataExplorer; if ( httpStatusCode == null || diff --git a/src/Utils/GalleryUtils.test.ts b/src/Utils/GalleryUtils.test.ts index 5babfb746..1a95147e3 100644 --- a/src/Utils/GalleryUtils.test.ts +++ b/src/Utils/GalleryUtils.test.ts @@ -1,8 +1,8 @@ import * as GalleryUtils from "./GalleryUtils"; import { JunoClient, IGalleryItem } from "../Juno/JunoClient"; -import { ExplorerStub } from "../Explorer/OpenActionsStubs"; import { HttpStatusCodes } from "../Common/Constants"; import { GalleryTab, SortBy } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent"; +import Explorer from "../Explorer/Explorer"; const galleryItem: IGalleryItem = { id: "id", @@ -25,7 +25,7 @@ describe("GalleryUtils", () => { }); it("downloadItem shows dialog in data explorer", () => { - const container = new ExplorerStub(); + const container = {} as Explorer; container.showOkCancelModalDialog = jest.fn().mockImplementation(); GalleryUtils.downloadItem(container, undefined, galleryItem, undefined); @@ -34,7 +34,7 @@ describe("GalleryUtils", () => { }); it("favoriteItem favorites item", async () => { - const container = new ExplorerStub(); + const container = {} as Explorer; const junoClient = new JunoClient(); junoClient.favoriteNotebook = jest .fn() @@ -48,7 +48,7 @@ describe("GalleryUtils", () => { }); it("unfavoriteItem unfavorites item", async () => { - const container = new ExplorerStub(); + const container = {} as Explorer; const junoClient = new JunoClient(); junoClient.unfavoriteNotebook = jest .fn() @@ -62,7 +62,7 @@ describe("GalleryUtils", () => { }); it("deleteItem shows dialog in data explorer", () => { - const container = new ExplorerStub(); + const container = {} as Explorer; container.showOkCancelModalDialog = jest.fn().mockImplementation(); GalleryUtils.deleteItem(container, undefined, galleryItem, undefined); diff --git a/src/Utils/GalleryUtils.ts b/src/Utils/GalleryUtils.ts index 076893c1e..b170f20d4 100644 --- a/src/Utils/GalleryUtils.ts +++ b/src/Utils/GalleryUtils.ts @@ -1,5 +1,4 @@ import { IGalleryItem, JunoClient } from "../Juno/JunoClient"; -import * as ViewModels from "../Contracts/ViewModels"; import { NotificationConsoleUtils } from "./NotificationConsoleUtils"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import * as Logger from "../Common/Logger"; @@ -8,6 +7,7 @@ import { SortBy, GalleryViewerComponent } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent"; +import Explorer from "../Explorer/Explorer"; export enum NotebookViewerParams { NotebookUrl = "notebookUrl", @@ -34,7 +34,7 @@ export interface GalleryViewerProps { } export function downloadItem( - container: ViewModels.Explorer, + container: Explorer, junoClient: JunoClient, data: IGalleryItem, onComplete: (item: IGalleryItem) => void @@ -80,7 +80,7 @@ export function downloadItem( } export async function favoriteItem( - container: ViewModels.Explorer, + container: Explorer, junoClient: JunoClient, data: IGalleryItem, onComplete: (item: IGalleryItem) => void @@ -102,7 +102,7 @@ export async function favoriteItem( } export async function unfavoriteItem( - container: ViewModels.Explorer, + container: Explorer, junoClient: JunoClient, data: IGalleryItem, onComplete: (item: IGalleryItem) => void @@ -124,7 +124,7 @@ export async function unfavoriteItem( } export function deleteItem( - container: ViewModels.Explorer, + container: Explorer, junoClient: JunoClient, data: IGalleryItem, onComplete: (item: IGalleryItem) => void diff --git a/src/Utils/NotebookConfigurationUtils.ts b/src/Utils/NotebookConfigurationUtils.ts index cab19d4c6..cfaae70ba 100644 --- a/src/Utils/NotebookConfigurationUtils.ts +++ b/src/Utils/NotebookConfigurationUtils.ts @@ -1,5 +1,5 @@ import * as DataModels from "../Contracts/DataModels"; -import { Explorer, KernelConnectionMetadata } from "../Contracts/ViewModels"; +import { KernelConnectionMetadata } from "../Contracts/ViewModels"; import * as Logger from "../Common/Logger"; export class NotebookConfigurationUtils { @@ -27,7 +27,7 @@ export class NotebookConfigurationUtils { return Promise.reject("Invalid or missing cluster connection info"); } - const dataExplorer = window.dataExplorer as Explorer; + const dataExplorer = window.dataExplorer; const notebookEndpointInfo: DataModels.NotebookConfigurationEndpointInfo[] = clusterConnectionInfo.endpoints.map( clusterEndpoint => ({ type: clusterEndpoint.kind.toLowerCase(), diff --git a/src/applyExplorerBindings.ts b/src/applyExplorerBindings.ts index bf22b9c9d..a74dd0b40 100644 --- a/src/applyExplorerBindings.ts +++ b/src/applyExplorerBindings.ts @@ -1,7 +1,7 @@ import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer"; import { MessageHandler } from "./Common/MessageHandler"; import * as ko from "knockout"; -import { Explorer } from "./Contracts/ViewModels"; +import Explorer from "./Explorer/Explorer"; export const applyExplorerBindings = (explorer: Explorer) => { if (!!explorer) { diff --git a/src/global.d.ts b/src/global.d.ts index de68855d8..3b55f9dd2 100644 --- a/src/global.d.ts +++ b/src/global.d.ts @@ -1,6 +1,6 @@ import { AuthType } from "./AuthType"; import { PlatformType } from "./PlatformType"; -import { Explorer } from "./Contracts/ViewModels"; +import Explorer from "./Explorer/Explorer"; declare global { interface Window {