Remove Explorer Stub and ViewModel.Explorer (#101)

This commit is contained in:
Steve Faulkner 2020-07-20 12:59:40 -05:00 committed by GitHub
parent 050da28d6e
commit eab6506940
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 469 additions and 1079 deletions

View File

@ -1,6 +1,7 @@
name: CI name: CI
on: on:
push: push:
branches: [master]
pull_request: pull_request:
branches: [master] branches: [master]
jobs: jobs:

View File

@ -2,6 +2,7 @@ import * as Constants from "../Common/Constants";
import * as ViewModels from "../Contracts/ViewModels"; import * as ViewModels from "../Contracts/ViewModels";
import { AuthType } from "../AuthType"; import { AuthType } from "../AuthType";
import { StringUtils } from "../Utils/StringUtils"; import { StringUtils } from "../Utils/StringUtils";
import Explorer from "../Explorer/Explorer";
export default class EnvironmentUtility { export default class EnvironmentUtility {
public static getMongoBackendEndpoint(serverId: string, location: string, extensionEndpoint: string = ""): string { public static getMongoBackendEndpoint(serverId: string, location: string, extensionEndpoint: string = ""): string {
@ -26,7 +27,7 @@ export default class EnvironmentUtility {
return window.authType === AuthType.AAD; return window.authType === AuthType.AAD;
} }
public static getCassandraBackendEndpoint(explorer: ViewModels.Explorer): string { public static getCassandraBackendEndpoint(explorer: Explorer): string {
const defaultLocation: string = "default"; const defaultLocation: string = "default";
const location: string = EnvironmentUtility.normalizeRegionName(explorer.databaseAccount().location); const location: string = EnvironmentUtility.normalizeRegionName(explorer.databaseAccount().location);
return ( return (

View File

@ -10,6 +10,7 @@ import { ItemDefinition, QueryIterator, Resource } from "@azure/cosmos";
import * as Logger from "./Logger"; import * as Logger from "./Logger";
import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils";
import { QueryUtils } from "../Utils/QueryUtils"; import { QueryUtils } from "../Utils/QueryUtils";
import Explorer from "../Explorer/Explorer";
export class QueriesClient implements ViewModels.QueriesClient { export class QueriesClient implements ViewModels.QueriesClient {
private static readonly PartitionKey: DataModels.PartitionKey = { 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 FetchQuery: string = "SELECT * FROM c";
private static readonly FetchMongoQuery: string = "{}"; private static readonly FetchMongoQuery: string = "{}";
public constructor(private container: ViewModels.Explorer) {} public constructor(private container: Explorer) {}
public async setupQueriesCollection(): Promise<DataModels.Collection> { public async setupQueriesCollection(): Promise<DataModels.Collection> {
const queriesCollection: ViewModels.Collection = this.findQueriesCollection(); const queriesCollection: ViewModels.Collection = this.findQueriesCollection();

View File

@ -6,27 +6,17 @@ import Q from "q";
import QueryViewModel from "../Explorer/Tables/QueryBuilder/QueryViewModel"; import QueryViewModel from "../Explorer/Tables/QueryBuilder/QueryViewModel";
import TableEntityListViewModel from "../Explorer/Tables/DataTable/TableEntityListViewModel"; import TableEntityListViewModel from "../Explorer/Tables/DataTable/TableEntityListViewModel";
import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList"; import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList";
import { ArcadiaWorkspaceItem } from "../Explorer/Controls/Arcadia/ArcadiaMenuPicker"; import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
import { CassandraTableKey, CassandraTableKeys, TableDataClient } from "../Explorer/Tables/TableDataClient";
import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent"; import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent";
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import { ExecuteSprocParam } from "../Explorer/Panes/ExecuteSprocParamsPane"; import { ExecuteSprocParam } from "../Explorer/Panes/ExecuteSprocParamsPane";
import { GitHubClient } from "../GitHub/GitHubClient"; import { GitHubClient } from "../GitHub/GitHubClient";
import { IColumnSetting } from "../Explorer/Panes/Tables/TableColumnOptionsPane"; import { IColumnSetting } from "../Explorer/Panes/Tables/TableColumnOptionsPane";
import { JunoClient, IGalleryItem } from "../Juno/JunoClient"; import { JunoClient, IGalleryItem } from "../Juno/JunoClient";
import { Library } from "./DataModels";
import { MostRecentActivity } from "../Explorer/MostRecentActivity/MostRecentActivity";
import { NotebookContentItem } from "../Explorer/Notebook/NotebookContentItem"; import { NotebookContentItem } from "../Explorer/Notebook/NotebookContentItem";
import { PlatformType } from "../PlatformType";
import { QueryMetrics } from "@azure/cosmos"; 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 { UploadDetails } from "../workers/upload/definitions";
import { UploadItemsPaneAdapter } from "../Explorer/Panes/UploadItemsPaneAdapter"; import Explorer from "../Explorer/Explorer";
import { ReactAdapter } from "../Bindings/ReactBindingHandler";
export interface ExplorerOptions { export interface ExplorerOptions {
documentClientUtility: DocumentClientUtilityBase; documentClientUtility: DocumentClientUtilityBase;
@ -42,213 +32,6 @@ export interface NavbarButtonConfig extends CommandButtonComponentProps {}
export interface DatabaseAccount extends DataModels.DatabaseAccount {} export interface DatabaseAccount extends DataModels.DatabaseAccount {}
export interface Explorer {
flight: ko.Observable<string>;
handleMessage(event: MessageEvent): void;
isRefreshingExplorer: ko.Observable<boolean>;
databaseAccount: ko.Observable<DatabaseAccount>;
subscriptionType: ko.Observable<SubscriptionType>;
quotaId: ko.Observable<string>;
hasWriteAccess: ko.Observable<boolean>;
defaultExperience: ko.Observable<string>;
isPreferredApiDocumentDB: ko.Computed<boolean>;
isPreferredApiCassandra: ko.Computed<boolean>;
isPreferredApiTable: ko.Computed<boolean>;
isPreferredApiGraph: ko.Computed<boolean>;
isPreferredApiMongoDB: ko.Computed<boolean>;
isFixedCollectionWithSharedThroughputSupported: ko.Computed<boolean>;
isDatabaseNodeOrNoneSelected(): boolean;
isDatabaseNodeSelected(): boolean;
isNodeKindSelected(nodeKind: string): boolean;
isNoneSelected(): boolean;
isSelectedDatabaseShared(): boolean;
deleteDatabaseText: ko.Observable<string>;
deleteCollectionText: ko.Subscribable<string>; // Our code assigns to a ko.Observable, but unit test assigns to ko.Computed
addCollectionText: ko.Observable<string>;
addDatabaseText: ko.Observable<string>;
collectionTitle: ko.Observable<string>;
collectionTreeNodeAltText: ko.Observable<string>;
refreshTreeTitle: ko.Observable<string>;
isAccountReady: ko.Observable<boolean>;
collectionCreationDefaults: CollectionCreationDefaults;
isEmulator: boolean;
features: ko.Observable<any>;
serverId: ko.Observable<string>;
extensionEndpoint: ko.Observable<string>;
armEndpoint: ko.Observable<string>;
isFeatureEnabled: (feature: string) => boolean;
isGalleryPublishEnabled: ko.Computed<boolean>;
isGitHubPaneEnabled: ko.Observable<boolean>;
isPublishNotebookPaneEnabled: ko.Observable<boolean>;
isRightPanelV2Enabled: ko.Computed<boolean>;
canExceedMaximumValue: ko.Computed<boolean>;
hasAutoPilotV2FeatureFlag: ko.Computed<boolean>;
isHostedDataExplorerEnabled: ko.Computed<boolean>;
isNotificationConsoleExpanded: ko.Observable<boolean>;
isTryCosmosDBSubscription: ko.Observable<boolean>;
canSaveQueries: ko.Computed<boolean>;
parentFrameDataExplorerVersion: ko.Observable<string>;
documentClientUtility: DocumentClientUtilityBase;
notificationsClient: NotificationsClient;
queriesClient: QueriesClient;
tableDataClient: TableDataClient;
splitter: Splitter;
notificationConsoleData: ko.ObservableArray<ConsoleData>;
// Selection
selectedNode: ko.Observable<TreeNode>;
// Tree
databases: ko.ObservableArray<Database>;
nonSystemDatabases: ko.Computed<Database[]>;
selectedDatabaseId: ko.Computed<string>;
selectedCollectionId: ko.Computed<string>;
isLeftPaneExpanded: ko.Observable<boolean>;
// Resource Token
resourceTokenDatabaseId: ko.Observable<string>;
resourceTokenCollectionId: ko.Observable<string>;
resourceTokenCollection: ko.Observable<CollectionBase>;
resourceTokenPartitionKey: ko.Observable<string>;
isAuthWithResourceToken: ko.Observable<boolean>;
isResourceTokenCollectionNodeSelected: ko.Computed<boolean>;
// Tabs
isTabsContentExpanded: ko.Observable<boolean>;
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<void>;
toggleLeftPaneExpanded(): void;
refreshDatabaseForResourceToken(): Q.Promise<void>;
refreshAllDatabases(isInitialLoad?: boolean): Q.Promise<any>;
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<void>;
renewShareAccess(accessInput: string): Q.Promise<void>;
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<boolean>;
isSparkEnabled: ko.Observable<boolean>;
isNotebooksEnabledForAccount: ko.Observable<boolean>;
isSparkEnabledForAccount: ko.Observable<boolean>;
hasStorageAnalyticsAfecFeature: ko.Observable<boolean>;
openEnableSynapseLinkDialog(): void;
isSynapseLinkUpdating: ko.Observable<boolean>;
notebookServerInfo: ko.Observable<DataModels.NotebookWorkspaceConnectionInfo>;
sparkClusterConnectionInfo: ko.Observable<DataModels.SparkClusterConnectionInfo>;
arcadiaToken: ko.Observable<string>;
arcadiaWorkspaces: ko.ObservableArray<ArcadiaWorkspaceItem>;
memoryUsageInfo: ko.Observable<DataModels.MemoryUsageInfo>;
notebookManager?: any; // This is dynamically loaded
openNotebook(notebookContentItem: NotebookContentItem): Promise<boolean>; // True if it was opened, false otherwise
resetNotebookWorkspace(): void;
importAndOpen: (path: string) => Promise<boolean>;
importAndOpenContent: (name: string, content: string) => Promise<boolean>;
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<void>;
handleOpenFileAction(path: string): Promise<void>;
// Notebook operations
openNotebook(notebookContentItem: NotebookContentItem): Promise<boolean>; // True if it was opened, false otherwise
deleteNotebookFile: (item: NotebookContentItem) => Promise<void>;
onCreateDirectory(parent: NotebookContentItem): Q.Promise<NotebookContentItem>;
onNewNotebookClicked: (parent?: NotebookContentItem) => void;
onUploadToNotebookServerClicked: (parent?: NotebookContentItem) => void;
renameNotebook: (notebookFile: NotebookContentItem) => Q.Promise<NotebookContentItem>;
readFile: (notebookFile: NotebookContentItem) => Promise<string>;
downloadFile: (notebookFile: NotebookContentItem) => Promise<void>;
createNotebookContentItemFile: (name: string, filepath: string) => NotebookContentItem;
refreshContentItem(item: NotebookContentItem): Promise<void>;
getNotebookBasePath(): string;
createWorkspace(): Promise<string>;
createSparkPool(workspaceId: string): Promise<string>;
}
export interface NotebookWorkspaceManager { export interface NotebookWorkspaceManager {
getNotebookWorkspacesAsync(cosmosAccountResourceId: string): Promise<DataModels.NotebookWorkspace[]>; getNotebookWorkspacesAsync(cosmosAccountResourceId: string): Promise<DataModels.NotebookWorkspace[]>;
getNotebookWorkspaceAsync( getNotebookWorkspaceAsync(

View File

@ -12,6 +12,7 @@ import AddTriggerIcon from "../../images/AddTrigger.svg";
import DeleteTriggerIcon from "../../images/DeleteTrigger.svg"; import DeleteTriggerIcon from "../../images/DeleteTrigger.svg";
import DeleteUDFIcon from "../../images/DeleteUDF.svg"; import DeleteUDFIcon from "../../images/DeleteUDF.svg";
import DeleteSprocIcon from "../../images/DeleteSproc.svg"; import DeleteSprocIcon from "../../images/DeleteSproc.svg";
import Explorer from "./Explorer";
export interface CollectionContextMenuButtonParams { export interface CollectionContextMenuButtonParams {
databaseId: string; databaseId: string;
@ -26,7 +27,7 @@ export interface DatabaseContextMenuButtonParams {
*/ */
export class ResourceTreeContextMenuButtonFactory { export class ResourceTreeContextMenuButtonFactory {
public static createDatabaseContextMenu( public static createDatabaseContextMenu(
container: ViewModels.Explorer, container: Explorer,
selectedDatabase: ViewModels.Database selectedDatabase: ViewModels.Database
): TreeNodeMenuItem[] { ): TreeNodeMenuItem[] {
const newCollectionMenuItem: TreeNodeMenuItem = { const newCollectionMenuItem: TreeNodeMenuItem = {
@ -44,7 +45,7 @@ export class ResourceTreeContextMenuButtonFactory {
} }
public static createCollectionContextMenuButton( public static createCollectionContextMenuButton(
container: ViewModels.Explorer, container: Explorer,
selectedCollection: ViewModels.Collection selectedCollection: ViewModels.Collection
): TreeNodeMenuItem[] { ): TreeNodeMenuItem[] {
const items: TreeNodeMenuItem[] = []; const items: TreeNodeMenuItem[] = [];
@ -115,7 +116,7 @@ export class ResourceTreeContextMenuButtonFactory {
} }
public static createStoreProcedureContextMenuItems( public static createStoreProcedureContextMenuItems(
container: ViewModels.Explorer, container: Explorer,
storedProcedure: ViewModels.StoredProcedure storedProcedure: ViewModels.StoredProcedure
): TreeNodeMenuItem[] { ): TreeNodeMenuItem[] {
if (container.isPreferredApiCassandra()) { if (container.isPreferredApiCassandra()) {
@ -131,10 +132,7 @@ export class ResourceTreeContextMenuButtonFactory {
]; ];
} }
public static createTriggerContextMenuItems( public static createTriggerContextMenuItems(container: Explorer, trigger: ViewModels.Trigger): TreeNodeMenuItem[] {
container: ViewModels.Explorer,
trigger: ViewModels.Trigger
): TreeNodeMenuItem[] {
if (container.isPreferredApiCassandra()) { if (container.isPreferredApiCassandra()) {
return []; return [];
} }
@ -149,7 +147,7 @@ export class ResourceTreeContextMenuButtonFactory {
} }
public static createUserDefinedFunctionContextMenuItems( public static createUserDefinedFunctionContextMenuItems(
container: ViewModels.Explorer, container: Explorer,
userDefinedFunction: ViewModels.UserDefinedFunction userDefinedFunction: ViewModels.UserDefinedFunction
): TreeNodeMenuItem[] { ): TreeNodeMenuItem[] {
if (container.isPreferredApiCassandra()) { if (container.isPreferredApiCassandra()) {

View File

@ -1,6 +1,5 @@
import { DefaultButton, IButtonProps, ITextFieldProps, TextField } from "office-ui-fabric-react"; import { DefaultButton, IButtonProps, ITextFieldProps, TextField } from "office-ui-fabric-react";
import * as React from "react"; import * as React from "react";
import * as ViewModels from "../../../Contracts/ViewModels";
import * as Constants from "../../../Common/Constants"; import * as Constants from "../../../Common/Constants";
import { Action } from "../../../Shared/Telemetry/TelemetryConstants"; import { Action } from "../../../Shared/Telemetry/TelemetryConstants";
import { RepoListItem } from "./GitHubReposComponent"; import { RepoListItem } from "./GitHubReposComponent";
@ -9,9 +8,10 @@ import * as GitHubUtils from "../../../Utils/GitHubUtils";
import { IGitHubRepo } from "../../../GitHub/GitHubClient"; import { IGitHubRepo } from "../../../GitHub/GitHubClient";
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import UrlUtility from "../../../Common/UrlUtility"; import UrlUtility from "../../../Common/UrlUtility";
import Explorer from "../../Explorer";
export interface AddRepoComponentProps { export interface AddRepoComponentProps {
container: ViewModels.Explorer; container: Explorer;
getRepo: (owner: string, repo: string) => Promise<IGitHubRepo>; getRepo: (owner: string, repo: string) => Promise<IGitHubRepo>;
pinRepo: (item: RepoListItem) => void; pinRepo: (item: RepoListItem) => void;
} }

View File

@ -1,12 +1,12 @@
import * as React from "react"; import * as React from "react";
import * as ViewModels from "../../../Contracts/ViewModels";
import { JunoClient, IGalleryItem } from "../../../Juno/JunoClient"; import { JunoClient, IGalleryItem } from "../../../Juno/JunoClient";
import { GalleryTab, SortBy, GalleryViewerComponentProps, GalleryViewerComponent } from "./GalleryViewerComponent"; import { GalleryTab, SortBy, GalleryViewerComponentProps, GalleryViewerComponent } from "./GalleryViewerComponent";
import { NotebookViewerComponentProps, NotebookViewerComponent } from "../NotebookViewer/NotebookViewerComponent"; import { NotebookViewerComponentProps, NotebookViewerComponent } from "../NotebookViewer/NotebookViewerComponent";
import * as GalleryUtils from "../../../Utils/GalleryUtils"; import * as GalleryUtils from "../../../Utils/GalleryUtils";
import Explorer from "../../Explorer";
export interface GalleryAndNotebookViewerComponentProps { export interface GalleryAndNotebookViewerComponentProps {
container?: ViewModels.Explorer; container?: Explorer;
junoClient: JunoClient; junoClient: JunoClient;
notebookUrl?: string; notebookUrl?: string;
galleryItem?: IGalleryItem; galleryItem?: IGalleryItem;

View File

@ -15,7 +15,6 @@ import {
} from "office-ui-fabric-react"; } from "office-ui-fabric-react";
import * as React from "react"; import * as React from "react";
import * as Logger from "../../../Common/Logger"; import * as Logger from "../../../Common/Logger";
import * as ViewModels from "../../../Contracts/ViewModels";
import { IGalleryItem, JunoClient } from "../../../Juno/JunoClient"; import { IGalleryItem, JunoClient } from "../../../Juno/JunoClient";
import * as GalleryUtils from "../../../Utils/GalleryUtils"; import * as GalleryUtils from "../../../Utils/GalleryUtils";
import { NotificationConsoleUtils } from "../../../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../../../Utils/NotificationConsoleUtils";
@ -24,9 +23,10 @@ import { DialogComponent, DialogProps } from "../DialogReactComponent/DialogComp
import { GalleryCardComponent, GalleryCardComponentProps } from "./Cards/GalleryCardComponent"; import { GalleryCardComponent, GalleryCardComponentProps } from "./Cards/GalleryCardComponent";
import "./GalleryViewerComponent.less"; import "./GalleryViewerComponent.less";
import { HttpStatusCodes } from "../../../Common/Constants"; import { HttpStatusCodes } from "../../../Common/Constants";
import Explorer from "../../Explorer";
export interface GalleryViewerComponentProps { export interface GalleryViewerComponentProps {
container?: ViewModels.Explorer; container?: Explorer;
junoClient: JunoClient; junoClient: JunoClient;
selectedTab: GalleryTab; selectedTab: GalleryTab;
sortBy: SortBy; sortBy: SortBy;

View File

@ -18,9 +18,10 @@ import NotebookReadOnlyRenderer from "../../Notebook/NotebookRenderer/NotebookRe
import { DialogComponent, DialogProps } from "../DialogReactComponent/DialogComponent"; import { DialogComponent, DialogProps } from "../DialogReactComponent/DialogComponent";
import { NotebookMetadataComponent } from "./NotebookMetadataComponent"; import { NotebookMetadataComponent } from "./NotebookMetadataComponent";
import "./NotebookViewerComponent.less"; import "./NotebookViewerComponent.less";
import Explorer from "../../Explorer";
export interface NotebookViewerComponentProps { export interface NotebookViewerComponentProps {
container?: ViewModels.Explorer; container?: Explorer;
junoClient?: JunoClient; junoClient?: JunoClient;
notebookUrl: string; notebookUrl: string;
galleryItem?: IGalleryItem; galleryItem?: IGalleryItem;

View File

@ -217,7 +217,7 @@ export class QueriesGridComponent extends React.Component<QueriesGridComponentPr
menuItem: any menuItem: any
) => { ) => {
if (window.confirm("Are you sure you want to delete this query?")) { 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, { const startKey: number = TelemetryProcessor.traceStart(Action.DeleteSavedQuery, {
databaseAccountName: container && container.databaseAccount().name, databaseAccountName: container && container.databaseAccount().name,
defaultExperience: container && container.defaultExperience(), defaultExperience: container && container.defaultExperience(),

View File

@ -8,11 +8,12 @@ import * as React from "react";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import { QueriesGridComponent, QueriesGridComponentProps } from "./QueriesGridComponent"; import { QueriesGridComponent, QueriesGridComponentProps } from "./QueriesGridComponent";
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler"; import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import Explorer from "../../Explorer";
export class QueriesGridComponentAdapter implements ReactAdapter { export class QueriesGridComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>; public parameters: ko.Observable<number>;
constructor(private container: ViewModels.Explorer) { constructor(private container: Explorer) {
this.parameters = ko.observable<number>(Date.now()); this.parameters = ko.observable<number>(Date.now());
} }

View File

@ -3,14 +3,15 @@ import * as sinon from "sinon";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Q from "q"; import Q from "q";
import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs"; import { CollectionStub, DatabaseStub } from "../OpenActionsStubs";
import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
import { CosmosClient } from "../../Common/CosmosClient"; import { CosmosClient } from "../../Common/CosmosClient";
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient"; import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
import Explorer from "../Explorer";
describe("ContainerSampleGenerator", () => { describe("ContainerSampleGenerator", () => {
const createExplorerStub = (database: ViewModels.Database): ExplorerStub => { const createExplorerStub = (database: ViewModels.Database): Explorer => {
const explorerStub = new ExplorerStub(); const explorerStub = {} as Explorer;
explorerStub.nonSystemDatabases = ko.computed(() => [database]); explorerStub.nonSystemDatabases = ko.computed(() => [database]);
explorerStub.isPreferredApiGraph = ko.computed<boolean>(() => false); explorerStub.isPreferredApiGraph = ko.computed<boolean>(() => false);
explorerStub.isPreferredApiMongoDB = ko.computed<boolean>(() => false); explorerStub.isPreferredApiMongoDB = ko.computed<boolean>(() => false);

View File

@ -6,6 +6,7 @@ import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsol
import { CosmosClient } from "../../Common/CosmosClient"; import { CosmosClient } from "../../Common/CosmosClient";
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient"; import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import Explorer from "../Explorer";
interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest { interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
data: any[]; data: any[];
@ -14,12 +15,12 @@ interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
export class ContainerSampleGenerator { export class ContainerSampleGenerator {
private sampleDataFile: SampleDataFile; private sampleDataFile: SampleDataFile;
private constructor(private container: ViewModels.Explorer) {} private constructor(private container: Explorer) {}
/** /**
* Factory function to load the json data file * Factory function to load the json data file
*/ */
public static async createSampleGeneratorAsync(container: ViewModels.Explorer): Promise<ContainerSampleGenerator> { public static async createSampleGeneratorAsync(container: Explorer): Promise<ContainerSampleGenerator> {
const generator = new ContainerSampleGenerator(container); const generator = new ContainerSampleGenerator(container);
let dataFileContent: any; let dataFileContent: any;
if (container.isPreferredApiGraph()) { if (container.isPreferredApiGraph()) {

View File

@ -1,8 +1,9 @@
import { ExplorerStub, DatabaseStub, CollectionStub } from "../OpenActionsStubs"; import { DatabaseStub, CollectionStub } from "../OpenActionsStubs";
import { DataSamplesUtil } from "./DataSamplesUtil"; import { DataSamplesUtil } from "./DataSamplesUtil";
import * as sinon from "sinon"; import * as sinon from "sinon";
import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
import * as ko from "knockout"; import * as ko from "knockout";
import Explorer from "../Explorer";
describe("DataSampleUtils", () => { describe("DataSampleUtils", () => {
const sampleCollectionId = "sampleCollectionId"; const sampleCollectionId = "sampleCollectionId";
@ -14,7 +15,7 @@ describe("DataSampleUtils", () => {
id: ko.observable(sampleDatabaseId), id: ko.observable(sampleDatabaseId),
collections: ko.observableArray([collection]) collections: ko.observableArray([collection])
}); });
const explorer = new ExplorerStub(); const explorer = {} as Explorer;
explorer.nonSystemDatabases = ko.computed(() => [database]); explorer.nonSystemDatabases = ko.computed(() => [database]);
explorer.showOkModalDialog = () => {}; explorer.showOkModalDialog = () => {};
const dataSamplesUtil = new DataSamplesUtil(explorer); const dataSamplesUtil = new DataSamplesUtil(explorer);

View File

@ -2,10 +2,11 @@ import * as ViewModels from "../../Contracts/ViewModels";
import { ContainerSampleGenerator } from "./ContainerSampleGenerator"; import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import Explorer from "../Explorer";
export class DataSamplesUtil { export class DataSamplesUtil {
private static readonly DialogTitle = "Create Sample Container"; 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 * Check if Database/Container is already there: if so, show modal to delete

View File

@ -89,7 +89,7 @@ enum ShareAccessToggleState {
Read Read
} }
export default class Explorer implements ViewModels.Explorer { export default class Explorer {
public flight: ko.Observable<string> = ko.observable<string>( public flight: ko.Observable<string> = ko.observable<string>(
SharedConstants.CollectionCreation.DefaultAddCollectionDefaultFlight SharedConstants.CollectionCreation.DefaultAddCollectionDefaultFlight
); );
@ -200,7 +200,7 @@ export default class Explorer implements ViewModels.Explorer {
public shouldShowShareDialogContents: ko.Observable<boolean>; public shouldShowShareDialogContents: ko.Observable<boolean>;
public shareAccessData: ko.Observable<ViewModels.AdHocAccessData>; public shareAccessData: ko.Observable<ViewModels.AdHocAccessData>;
public renewExplorerShareAccess: (explorer: ViewModels.Explorer, token: string) => Q.Promise<void>; public renewExplorerShareAccess: (explorer: Explorer, token: string) => Q.Promise<void>;
public renewTokenError: ko.Observable<string>; public renewTokenError: ko.Observable<string>;
public tokenForRenewal: ko.Observable<string>; public tokenForRenewal: ko.Observable<string>;
public shareAccessToggleState: ko.Observable<ShareAccessToggleState>; public shareAccessToggleState: ko.Observable<ShareAccessToggleState>;

View File

@ -11,14 +11,15 @@ import { CommandBarComponentButtonFactory } from "./CommandBarComponentButtonFac
import { CommandBar, ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar"; import { CommandBar, ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar";
import { StyleConstants } from "../../../Common/Constants"; import { StyleConstants } from "../../../Common/Constants";
import { CommandBarUtil } from "./CommandBarUtil"; import { CommandBarUtil } from "./CommandBarUtil";
import Explorer from "../../Explorer";
export class CommandBarComponentAdapter implements ReactAdapter { export class CommandBarComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>; public parameters: ko.Observable<number>;
public container: ViewModels.Explorer; public container: Explorer;
private tabsButtons: ViewModels.NavbarButtonConfig[]; private tabsButtons: ViewModels.NavbarButtonConfig[];
private isNotebookTabActive: ko.Computed<boolean>; private isNotebookTabActive: ko.Computed<boolean>;
constructor(container: ViewModels.Explorer) { constructor(container: Explorer) {
this.container = container; this.container = container;
this.tabsButtons = []; this.tabsButtons = [];
this.isNotebookTabActive = ko.computed(() => this.isNotebookTabActive = ko.computed(() =>

View File

@ -1,24 +1,25 @@
import * as ko from "knockout"; import * as ko from "knockout";
import * as ViewModels from "../../../Contracts/ViewModels";
import { CommandBarComponentButtonFactory } from "./CommandBarComponentButtonFactory"; import { CommandBarComponentButtonFactory } from "./CommandBarComponentButtonFactory";
import { ExplorerStub } from "../../OpenActionsStubs";
import { GitHubOAuthService } from "../../../GitHub/GitHubOAuthService"; import { GitHubOAuthService } from "../../../GitHub/GitHubOAuthService";
import NotebookManager from "../../Notebook/NotebookManager"; import NotebookManager from "../../Notebook/NotebookManager";
import Explorer from "../../Explorer";
describe("CommandBarComponentButtonFactory tests", () => { describe("CommandBarComponentButtonFactory tests", () => {
let mockExplorer: ViewModels.Explorer; let mockExplorer: Explorer;
describe("Enable notebook button", () => { describe("Enable notebook button", () => {
const enableNotebookBtnLabel = "Enable Notebooks (Preview)"; const enableNotebookBtnLabel = "Enable Notebooks (Preview)";
beforeAll(() => { beforeAll(() => {
mockExplorer = new ExplorerStub(); mockExplorer = {} as Explorer;
mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.addCollectionText = ko.observable("mockText");
mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isAuthWithResourceToken = ko.observable(false);
mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiTable = ko.computed(() => true);
mockExplorer.isPreferredApiMongoDB = ko.computed<boolean>(() => false); mockExplorer.isPreferredApiMongoDB = ko.computed<boolean>(() => false);
mockExplorer.isPreferredApiCassandra = ko.computed<boolean>(() => false); mockExplorer.isPreferredApiCassandra = ko.computed<boolean>(() => false);
mockExplorer.isSynapseLinkUpdating = ko.observable(false);
mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSparkEnabled = ko.observable(true);
mockExplorer.isSynapseLinkUpdating = ko.observable(false);
mockExplorer.isGalleryPublishEnabled = ko.computed<boolean>(() => false); mockExplorer.isGalleryPublishEnabled = ko.computed<boolean>(() => false);
mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
mockExplorer.isDatabaseNodeOrNoneSelected = () => true; mockExplorer.isDatabaseNodeOrNoneSelected = () => true;
@ -75,12 +76,13 @@ describe("CommandBarComponentButtonFactory tests", () => {
const openMongoShellBtnLabel = "Open Mongo Shell"; const openMongoShellBtnLabel = "Open Mongo Shell";
beforeAll(() => { beforeAll(() => {
mockExplorer = new ExplorerStub(); mockExplorer = {} as Explorer;
mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.addCollectionText = ko.observable("mockText");
mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isAuthWithResourceToken = ko.observable(false);
mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiTable = ko.computed(() => true);
mockExplorer.isPreferredApiCassandra = ko.computed<boolean>(() => false); mockExplorer.isPreferredApiCassandra = ko.computed<boolean>(() => false);
mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSparkEnabled = ko.observable(true);
mockExplorer.isSynapseLinkUpdating = ko.observable(false);
mockExplorer.isGalleryPublishEnabled = ko.computed<boolean>(() => false); mockExplorer.isGalleryPublishEnabled = ko.computed<boolean>(() => false);
mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
mockExplorer.isDatabaseNodeOrNoneSelected = () => true; mockExplorer.isDatabaseNodeOrNoneSelected = () => true;
@ -155,11 +157,12 @@ describe("CommandBarComponentButtonFactory tests", () => {
const openCassandraShellBtnLabel = "Open Cassandra Shell"; const openCassandraShellBtnLabel = "Open Cassandra Shell";
beforeAll(() => { beforeAll(() => {
mockExplorer = new ExplorerStub(); mockExplorer = {} as Explorer;
mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.addCollectionText = ko.observable("mockText");
mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isAuthWithResourceToken = ko.observable(false);
mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiTable = ko.computed(() => true);
mockExplorer.isPreferredApiMongoDB = ko.computed<boolean>(() => false); mockExplorer.isPreferredApiMongoDB = ko.computed<boolean>(() => false);
mockExplorer.isSynapseLinkUpdating = ko.observable(false);
mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSparkEnabled = ko.observable(true);
mockExplorer.isGalleryPublishEnabled = ko.computed<boolean>(() => false); mockExplorer.isGalleryPublishEnabled = ko.computed<boolean>(() => false);
mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
@ -236,13 +239,14 @@ describe("CommandBarComponentButtonFactory tests", () => {
const manageGitHubSettingsBtnLabel = "Manage GitHub settings"; const manageGitHubSettingsBtnLabel = "Manage GitHub settings";
beforeAll(() => { beforeAll(() => {
mockExplorer = new ExplorerStub(); mockExplorer = {} as Explorer;
mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.addCollectionText = ko.observable("mockText");
mockExplorer.isAuthWithResourceToken = ko.observable(false); mockExplorer.isAuthWithResourceToken = ko.observable(false);
mockExplorer.isPreferredApiTable = ko.computed(() => true); mockExplorer.isPreferredApiTable = ko.computed(() => true);
mockExplorer.isPreferredApiMongoDB = ko.computed<boolean>(() => false); mockExplorer.isPreferredApiMongoDB = ko.computed<boolean>(() => false);
mockExplorer.isPreferredApiCassandra = ko.computed<boolean>(() => false); mockExplorer.isPreferredApiCassandra = ko.computed<boolean>(() => false);
mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true); mockExplorer.hasAutoPilotV2FeatureFlag = ko.computed<boolean>(() => true);
mockExplorer.isSynapseLinkUpdating = ko.observable(false);
mockExplorer.isSparkEnabled = ko.observable(true); mockExplorer.isSparkEnabled = ko.observable(true);
mockExplorer.isDatabaseNodeOrNoneSelected = () => true; mockExplorer.isDatabaseNodeOrNoneSelected = () => true;
mockExplorer.isNotebooksEnabledForAccount = ko.observable(false); mockExplorer.isNotebooksEnabledForAccount = ko.observable(false);
@ -294,7 +298,7 @@ describe("CommandBarComponentButtonFactory tests", () => {
describe("Resource token", () => { describe("Resource token", () => {
beforeAll(() => { beforeAll(() => {
mockExplorer = new ExplorerStub(); mockExplorer = {} as Explorer;
mockExplorer.addCollectionText = ko.observable("mockText"); mockExplorer.addCollectionText = ko.observable("mockText");
mockExplorer.isAuthWithResourceToken = ko.observable(true); mockExplorer.isAuthWithResourceToken = ko.observable(true);
mockExplorer.isPreferredApiDocumentDB = ko.computed(() => true); mockExplorer.isPreferredApiDocumentDB = ko.computed(() => true);

View File

@ -25,11 +25,12 @@ import ResetWorkspaceIcon from "../../../../images/notebook/Notebook-reset-works
import GitHubIcon from "../../../../images/github.svg"; import GitHubIcon from "../../../../images/github.svg";
import SynapseIcon from "../../../../images/synapse-link.svg"; import SynapseIcon from "../../../../images/synapse-link.svg";
import { config, Platform } from "../../../Config"; import { config, Platform } from "../../../Config";
import Explorer from "../../Explorer";
export class CommandBarComponentButtonFactory { export class CommandBarComponentButtonFactory {
private static counter: number = 0; private static counter: number = 0;
public static createStaticCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { public static createStaticCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
if (container.isAuthWithResourceToken()) { if (container.isAuthWithResourceToken()) {
return CommandBarComponentButtonFactory.createStaticCommandBarButtonsForResourceToken(container); return CommandBarComponentButtonFactory.createStaticCommandBarButtonsForResourceToken(container);
} }
@ -132,7 +133,7 @@ export class CommandBarComponentButtonFactory {
return buttons; return buttons;
} }
public static createContextCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { public static createContextCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
const buttons: ViewModels.NavbarButtonConfig[] = []; const buttons: ViewModels.NavbarButtonConfig[] = [];
if (!container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()) { if (!container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()) {
@ -155,7 +156,7 @@ export class CommandBarComponentButtonFactory {
return buttons; return buttons;
} }
public static createControlCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { public static createControlCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
const buttons: ViewModels.NavbarButtonConfig[] = []; const buttons: ViewModels.NavbarButtonConfig[] = [];
if (window.dataExplorerPlatform === PlatformType.Hosted) { if (window.dataExplorerPlatform === PlatformType.Hosted) {
return buttons; 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(); return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph();
} }
private static createNewCollectionGroup(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { private static createNewCollectionGroup(container: Explorer): ViewModels.NavbarButtonConfig {
const label = container.addCollectionText(); const label = container.addCollectionText();
return { return {
iconSrc: AddCollectionIcon, 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) { if (config.platform === Platform.Emulator) {
return null; 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(); const label = container.addDatabaseText();
return { return {
iconSrc: AddDatabaseIcon, 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()) { if (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph()) {
const label = "New SQL Query"; const label = "New SQL Query";
return { return {
@ -324,7 +325,7 @@ export class CommandBarComponentButtonFactory {
return null; return null;
} }
public static createScriptCommandButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] { public static createScriptCommandButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
const buttons: ViewModels.NavbarButtonConfig[] = []; const buttons: ViewModels.NavbarButtonConfig[] = [];
const shouldEnableScriptsCommands: boolean = const shouldEnableScriptsCommands: boolean =
@ -384,7 +385,7 @@ export class CommandBarComponentButtonFactory {
return buttons; return buttons;
} }
private static createScaleAndSettingsButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig { private static createScaleAndSettingsButton(container: Explorer): ViewModels.NavbarButtonConfig {
let isShared = false; let isShared = false;
if (container.isDatabaseNodeSelected()) { if (container.isDatabaseNodeSelected()) {
isShared = container.findSelectedDatabase().isDatabaseShared(); 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"; const label = "New Notebook";
return { return {
iconSrc: NewNotebookIcon, 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"; const label = "Upload to Notebook Server";
return { return {
iconSrc: NewNotebookIcon, 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"; const label = "Open Query";
return { return {
iconSrc: BrowseQueriesIcon, 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"; const label = "Open Query From Disk";
return { return {
iconSrc: OpenQueryFromDiskIcon, 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) { if (config.platform === Platform.Emulator) {
return null; 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"; const label = "Open Terminal";
return { return {
iconSrc: CosmosTerminalIcon, 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 label = "Open Mongo Shell";
const tooltip = const tooltip =
"This feature is not yet available in your account's region. View supported regions here: https://aka.ms/cosmos-enable-notebooks."; "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 label = "Open Cassandra Shell";
const tooltip = const tooltip =
"This feature is not yet available in your account's region. View supported regions here: https://aka.ms/cosmos-enable-notebooks."; "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"; const label = "Reset Workspace";
return { return {
iconSrc: ResetWorkspaceIcon, 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(); let connectedToGitHub: boolean = container.notebookManager?.gitHubOAuthService.isLoggedIn();
const label = connectedToGitHub ? "Manage GitHub settings" : "Connect to GitHub"; const label = connectedToGitHub ? "Manage GitHub settings" : "Connect to GitHub";
return { return {
@ -583,9 +584,7 @@ export class CommandBarComponentButtonFactory {
}; };
} }
private static createStaticCommandBarButtonsForResourceToken( private static createStaticCommandBarButtonsForResourceToken(container: Explorer): ViewModels.NavbarButtonConfig[] {
container: ViewModels.Explorer
): ViewModels.NavbarButtonConfig[] {
const newSqlQueryBtn = CommandBarComponentButtonFactory.createNewSQLQueryButton(container); const newSqlQueryBtn = CommandBarComponentButtonFactory.createNewSQLQueryButton(container);
const openQueryBtn = CommandBarComponentButtonFactory.createOpenQueryButton(container); const openQueryBtn = CommandBarComponentButtonFactory.createOpenQueryButton(container);

View File

@ -4,13 +4,14 @@ import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import { NotificationConsoleComponent } from "./NotificationConsoleComponent"; import { NotificationConsoleComponent } from "./NotificationConsoleComponent";
import { ConsoleData } from "./NotificationConsoleComponent"; import { ConsoleData } from "./NotificationConsoleComponent";
import Explorer from "../../Explorer";
export class NotificationConsoleComponentAdapter implements ReactAdapter { export class NotificationConsoleComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>; public parameters: ko.Observable<number>;
public container: ViewModels.Explorer; public container: Explorer;
private consoleData: ko.ObservableArray<ConsoleData>; private consoleData: ko.ObservableArray<ConsoleData>;
constructor(container: ViewModels.Explorer) { constructor(container: Explorer) {
this.container = container; this.container = container;
this.consoleData = container.notificationConsoleData; this.consoleData = container.notificationConsoleData;

View File

@ -3,6 +3,7 @@ import { StorageKey, LocalStorageUtility } from "../../Shared/StorageUtility";
import CollectionIcon from "../../../images/tree-collection.svg"; import CollectionIcon from "../../../images/tree-collection.svg";
import NotebookIcon from "../../../images/notebook/Notebook-resource.svg"; import NotebookIcon from "../../../images/notebook/Notebook-resource.svg";
import Explorer from "../Explorer";
export enum Type { export enum Type {
OpenCollection, OpenCollection,
@ -36,7 +37,7 @@ export class MostRecentActivity {
private static readonly schemaVersion: string = "1"; private static readonly schemaVersion: string = "1";
private static itemsMaxNumber: number = 5; private static itemsMaxNumber: number = 5;
private storedData: StoredData; private storedData: StoredData;
constructor(private container: ViewModels.Explorer) { constructor(private container: Explorer) {
// Retrieve from local storage // Retrieve from local storage
if (LocalStorageUtility.hasItem(StorageKey.MostRecentActivity)) { if (LocalStorageUtility.hasItem(StorageKey.MostRecentActivity)) {
const rawData = LocalStorageUtility.getEntryString(StorageKey.MostRecentActivity); const rawData = LocalStorageUtility.getEntryString(StorageKey.MostRecentActivity);

View File

@ -131,7 +131,7 @@ export class NotebookContainerClient implements ViewModels.INotebookContainerCli
} }
private async recreateNotebookWorkspaceAsync(): Promise<void> { private async recreateNotebookWorkspaceAsync(): Promise<void> {
const explorer = window.dataExplorer as ViewModels.Explorer; const explorer = window.dataExplorer;
if (!explorer || !explorer.databaseAccount() || !explorer.databaseAccount().id) { if (!explorer || !explorer.databaseAccount() || !explorer.databaseAccount().id) {
throw new Error("DataExplorer not initialized"); throw new Error("DataExplorer not initialized");
} }

View File

@ -23,9 +23,10 @@ import { DialogProps } from "../Controls/DialogReactComponent/DialogComponent";
import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter"; import { ResourceTreeAdapter } from "../Tree/ResourceTreeAdapter";
import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter"; import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter";
import { getFullName } from "../../Utils/UserUtils"; import { getFullName } from "../../Utils/UserUtils";
import Explorer from "../Explorer";
export interface NotebookManagerOptions { export interface NotebookManagerOptions {
container: ViewModels.Explorer; container: Explorer;
notebookBasePath: ko.Observable<string>; notebookBasePath: ko.Observable<string>;
dialogProps: ko.Observable<DialogProps>; dialogProps: ko.Observable<DialogProps>;
resourceTree: ResourceTreeAdapter; resourceTree: ResourceTreeAdapter;

View File

@ -1,18 +1,13 @@
import * as ko from "knockout"; import * as ko from "knockout";
import { handleOpenAction } from "./OpenActions"; import { handleOpenAction } from "./OpenActions";
import * as ViewModels from "../Contracts/ViewModels"; import * as ViewModels from "../Contracts/ViewModels";
import { import { DatabaseStub, CollectionStub, AddCollectionPaneStub, CassandraAddCollectionPane } from "./OpenActionsStubs";
ExplorerStub,
DatabaseStub,
CollectionStub,
AddCollectionPaneStub,
CassandraAddCollectionPane
} from "./OpenActionsStubs";
import { ActionContracts } from "../Contracts/ExplorerContracts"; import { ActionContracts } from "../Contracts/ExplorerContracts";
import Explorer from "./Explorer";
describe("OpenActions", () => { describe("OpenActions", () => {
describe("handleOpenAction", () => { describe("handleOpenAction", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
let database: ViewModels.Database; let database: ViewModels.Database;
let collection: ViewModels.Collection; let collection: ViewModels.Collection;
let databases: ViewModels.Database[]; let databases: ViewModels.Database[];
@ -28,9 +23,11 @@ describe("OpenActions", () => {
let openCassandraAddCollectionPane: jasmine.Spy; let openCassandraAddCollectionPane: jasmine.Spy;
beforeEach(() => { beforeEach(() => {
explorer = new ExplorerStub(); explorer = {} as Explorer;
explorer.addCollectionPane = new AddCollectionPaneStub(); explorer.addCollectionPane = new AddCollectionPaneStub();
explorer.cassandraAddCollectionPane = new CassandraAddCollectionPane(); explorer.cassandraAddCollectionPane = new CassandraAddCollectionPane();
explorer.closeAllPanes = () => {};
explorer.isConnectExplorerVisible = () => false;
database = new DatabaseStub({ database = new DatabaseStub({
id: ko.observable("db"), id: ko.observable("db"),

View File

@ -2,11 +2,12 @@
import * as ViewModels from "../Contracts/ViewModels"; import * as ViewModels from "../Contracts/ViewModels";
import { ActionContracts } from "../Contracts/ExplorerContracts"; import { ActionContracts } from "../Contracts/ExplorerContracts";
import Explorer from "./Explorer";
export function handleOpenAction( export function handleOpenAction(
action: ActionContracts.DataExplorerAction, action: ActionContracts.DataExplorerAction,
databases: ViewModels.Database[], databases: ViewModels.Database[],
explorer: ViewModels.Explorer explorer: Explorer
): boolean { ): boolean {
if ( if (
action.actionType === ActionContracts.ActionType.OpenCollectionTab || 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 ( if (
action.paneKind === ActionContracts.PaneKind.AddCollection || action.paneKind === ActionContracts.PaneKind.AddCollection ||
(<any>action).paneKind === ActionContracts.PaneKind[ActionContracts.PaneKind.AddCollection] (<any>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)); explorer.handleOpenFileAction(decodeURIComponent(action.path));
} }

View File

@ -3,425 +3,13 @@ import * as ko from "knockout";
import * as ViewModels from "../../src/Contracts/ViewModels"; import * as ViewModels from "../../src/Contracts/ViewModels";
import DocumentClientUtilityBase from "../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../Common/DocumentClientUtilityBase";
import Q from "q"; import Q from "q";
import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker"; import { CassandraTableKey, CassandraTableKeys } from "../../src/Explorer/Tables/TableDataClient";
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 { UploadDetails } from "../workers/upload/definitions"; import { UploadDetails } from "../workers/upload/definitions";
import { UploadFilePane } from "./Panes/UploadFilePane"; import Explorer from "./Explorer";
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<string>;
public addCollectionText: ko.Observable<string>;
public hasAutoPilotV2FeatureFlag: ko.Computed<boolean>;
public addDatabaseText: ko.Observable<string>;
public collectionTitle: ko.Observable<string>;
public deleteCollectionText: ko.Observable<string>;
public deleteDatabaseText: ko.Observable<string>;
public collectionTreeNodeAltText: ko.Observable<string>;
public refreshTreeTitle: ko.Observable<string>;
public collapsedResourceTreeWidth: number;
public collectionCreationDefaults: ViewModels.CollectionCreationDefaults = CollectionCreationDefaults;
public hasWriteAccess: ko.Observable<boolean> = ko.observable<boolean>(false);
public databaseAccount: ko.Observable<ViewModels.DatabaseAccount>;
public subscriptionType: ko.Observable<ViewModels.SubscriptionType>;
public quotaId: ko.Observable<string>;
public defaultExperience: ko.Observable<string>;
public isPreferredApiDocumentDB: ko.Computed<boolean>;
public isPreferredApiCassandra: ko.Computed<boolean>;
public isPreferredApiMongoDB: ko.Computed<boolean>;
public isPreferredApiGraph: ko.Computed<boolean>;
public isPreferredApiTable: ko.Computed<boolean>;
public isFixedCollectionWithSharedThroughputSupported: ko.Computed<boolean>;
public isEmulator: boolean;
public isAccountReady: ko.Observable<boolean>;
public canSaveQueries: ko.Computed<boolean>;
public features: ko.Observable<any>;
public serverId: ko.Observable<string>;
public extensionEndpoint: ko.Observable<string> = ko.observable<string>(undefined);
public armEndpoint: ko.Observable<string>;
public isTryCosmosDBSubscription: ko.Observable<boolean>;
public documentClientUtility: DocumentClientUtilityBase;
public notificationsClient: ViewModels.NotificationsClient;
public queriesClient: ViewModels.QueriesClient;
public tableDataClient: TableDataClient;
public splitter: Splitter;
public notificationConsoleData: ko.ObservableArray<ConsoleData>;
public isNotificationConsoleExpanded: ko.Observable<boolean>;
public contextPanes: ViewModels.ContextualPane[];
public databases: ko.ObservableArray<ViewModels.Database>;
public nonSystemDatabases: ko.Computed<ViewModels.Database[]>;
public selectedDatabaseId: ko.Computed<string>;
public selectedCollectionId: ko.Computed<string>;
public isLeftPaneExpanded: ko.Observable<boolean>;
public selectedNode: ko.Observable<ViewModels.TreeNode>;
public isRefreshingExplorer: ko.Observable<boolean>;
public isTabsContentExpanded: ko.Observable<boolean>;
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<void>;
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<boolean>;
public isGitHubPaneEnabled: ko.Observable<boolean>;
public isPublishNotebookPaneEnabled: ko.Observable<boolean>;
public isRightPanelV2Enabled: ko.Computed<boolean>;
public canExceedMaximumValue: ko.Computed<boolean>;
public isHostedDataExplorerEnabled: ko.Computed<boolean>;
public parentFrameDataExplorerVersion: ko.Observable<string> = ko.observable<string>(Versions.DataExplorer);
public mostRecentActivity: MostRecentActivity;
public isNotebookEnabled: ko.Observable<boolean>;
public isSparkEnabled: ko.Observable<boolean>;
public isNotebooksEnabledForAccount: ko.Observable<boolean>;
public isSparkEnabledForAccount: ko.Observable<boolean>;
public arcadiaToken: ko.Observable<string>;
public notebookWorkspaceManager: ViewModels.NotebookWorkspaceManager;
public notebookServerInfo: ko.Observable<DataModels.NotebookWorkspaceConnectionInfo>;
public sparkClusterConnectionInfo: ko.Observable<DataModels.SparkClusterConnectionInfo>;
public gitHubReposPane: ViewModels.ContextualPane;
public publishNotebookPaneAdapter: ReactAdapter;
public arcadiaWorkspaces: ko.ObservableArray<ArcadiaWorkspaceItem>;
public hasStorageAnalyticsAfecFeature: ko.Observable<boolean>;
public isSynapseLinkUpdating: ko.Observable<boolean>;
public memoryUsageInfo: ko.Observable<DataModels.MemoryUsageInfo>;
public notebookManager?: any;
public openGallery: (notebookUrl?: string, galleryItem?: IGalleryItem, isFavorite?: boolean) => void;
public openNotebookViewer: (notebookUrl: string) => void;
public resourceTokenDatabaseId: ko.Observable<string>;
public resourceTokenCollectionId: ko.Observable<string>;
public resourceTokenCollection: ko.Observable<ViewModels.CollectionBase>;
public resourceTokenPartitionKey: ko.Observable<string>;
public isAuthWithResourceToken: ko.Observable<boolean>;
public isResourceTokenCollectionNodeSelected: ko.Computed<boolean>;
public tabsManager: TabsManager;
private _featureEnabledReturnValue: boolean;
constructor(options?: any) {
options = options || {};
this._featureEnabledReturnValue = options.featureEnabledReturnValue || false;
this.isSynapseLinkUpdating = ko.observable<boolean>(options.isSynapseLinkUpdating || false);
}
public openEnableSynapseLinkDialog() {
throw new Error("Not implemented");
}
public createWorkspace(): Promise<string> {
throw new Error("Not implemented");
}
public createSparkPool(workspaceId: string): Promise<string> {
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<any> {
throw new Error("Not implemented");
}
public refreshDatabaseForResourceToken(): Q.Promise<void> {
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<void> {
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<void> {
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<boolean> {
throw new Error("Not implemented");
}
public importAndOpenContent(name: string, content: string): Promise<boolean> {
throw new Error("Not implemented");
}
public publishNotebook(name: string, content: string): void {
throw new Error("Not implemented");
}
public async openNotebook(notebookContentItem: NotebookContentItem): Promise<boolean> {
throw new Error("Not implemented");
}
public deleteNotebookFile(item: NotebookContentItem): Promise<void> {
throw new Error("Not implemented");
}
public onCreateDirectory(parent: NotebookContentItem): Q.Promise<NotebookContentItem> {
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<NotebookContentItem> {
throw new Error("Not implemented");
}
public readFile(notebookFile: NotebookContentItem): Promise<string> {
throw new Error("Not implemented");
}
public downloadFile(notebookFile: NotebookContentItem): Promise<void> {
throw new Error("Not implemented");
}
public initNotebooks(databaseAccount: DataModels.DatabaseAccount): Promise<void> {
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<void> {
throw new Error("Not implemented");
}
public getNotebookBasePath(): string {
throw new Error("Not implemented");
}
public handleOpenFileAction(): Promise<void> {
throw new Error("Not implemented");
}
}
export class DatabaseStub implements ViewModels.Database { export class DatabaseStub implements ViewModels.Database {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public self: string; public self: string;
public rid: string; public rid: string;
public id: ko.Observable<string>; public id: ko.Observable<string>;
@ -498,7 +86,7 @@ export class DatabaseStub implements ViewModels.Database {
export class CollectionStub implements ViewModels.Collection { export class CollectionStub implements ViewModels.Collection {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public rawDataModel: DataModels.Collection; public rawDataModel: DataModels.Collection;
public self: string; public self: string;
public rid: string; public rid: string;

View File

@ -7,7 +7,7 @@ import { AutopilotTier } from "../../Contracts/DataModels";
describe("Add Collection Pane", () => { describe("Add Collection Pane", () => {
describe("isValid()", () => { describe("isValid()", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
const mockDatabaseAccount: ViewModels.DatabaseAccount = { const mockDatabaseAccount: ViewModels.DatabaseAccount = {
id: "mock", id: "mock",
kind: "DocumentDB", kind: "DocumentDB",

View File

@ -5,7 +5,7 @@ import AddDatabasePane from "./AddDatabasePane";
describe("Add Database Pane", () => { describe("Add Database Pane", () => {
describe("getSharedThroughputDefault()", () => { describe("getSharedThroughputDefault()", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
const mockDatabaseAccount: ViewModels.DatabaseAccount = { const mockDatabaseAccount: ViewModels.DatabaseAccount = {
id: "mock", id: "mock",
kind: "DocumentDB", kind: "DocumentDB",

View File

@ -7,11 +7,12 @@ import { KeyCodes } from "../../Common/Constants";
import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel"; import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Explorer from "../Explorer";
// TODO: Use specific actions for logging telemetry data // TODO: Use specific actions for logging telemetry data
export abstract class ContextualPaneBase extends WaitsForTemplateViewModel implements ViewModels.ContextualPane { export abstract class ContextualPaneBase extends WaitsForTemplateViewModel implements ViewModels.ContextualPane {
public id: string; public id: string;
public container: ViewModels.Explorer; public container: Explorer;
public firstFieldHasFocus: ko.Observable<boolean>; public firstFieldHasFocus: ko.Observable<boolean>;
public formErrorsDetails: ko.Observable<string>; public formErrorsDetails: ko.Observable<string>;
public formErrors: ko.Observable<string>; public formErrors: ko.Observable<string>;

View File

@ -9,12 +9,12 @@ import DeleteFeedback from "../../Common/DeleteFeedback";
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs"; import { CollectionStub, DatabaseStub } from "../OpenActionsStubs";
import { TreeNode } from "../../Contracts/ViewModels"; import { TreeNode } from "../../Contracts/ViewModels";
describe("Delete Collection Confirmation Pane", () => { describe("Delete Collection Confirmation Pane", () => {
describe("Explorer.isLastCollection()", () => { describe("Explorer.isLastCollection()", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
@ -59,29 +59,27 @@ describe("Delete Collection Confirmation Pane", () => {
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>( let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>(
DocumentClientUtilityBase as any DocumentClientUtilityBase as any
); );
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any); let fakeExplorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false)); fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
fakeExplorer.refreshAllDatabases = () => Q.resolve();
let pane = new DeleteCollectionConfirmationPane({ let pane = new DeleteCollectionConfirmationPane({
documentClientUtility: fakeDocumentClientUtility as any, documentClientUtility: fakeDocumentClientUtility as any,
id: "deletecollectionconfirmationpane", id: "deletecollectionconfirmationpane",
visible: ko.observable<boolean>(false), visible: ko.observable<boolean>(false),
container: fakeExplorer as any container: fakeExplorer
}); });
fakeExplorer.isLastCollection.returns(true); fakeExplorer.isLastCollection = () => true;
fakeExplorer.isSelectedDatabaseShared.returns(false); fakeExplorer.isSelectedDatabaseShared = () => false;
pane.container = fakeExplorer as any;
expect(pane.shouldRecordFeedback()).toBe(true); expect(pane.shouldRecordFeedback()).toBe(true);
fakeExplorer.isLastCollection.returns(true); fakeExplorer.isLastCollection = () => true;
fakeExplorer.isSelectedDatabaseShared.returns(true); fakeExplorer.isSelectedDatabaseShared = () => true;
pane.container = fakeExplorer as any;
expect(pane.shouldRecordFeedback()).toBe(false); expect(pane.shouldRecordFeedback()).toBe(false);
fakeExplorer.isLastCollection.returns(false); fakeExplorer.isLastCollection = () => false;
fakeExplorer.isSelectedDatabaseShared.returns(false); fakeExplorer.isSelectedDatabaseShared = () => false;
pane.container = fakeExplorer as any;
expect(pane.shouldRecordFeedback()).toBe(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", () => { it("it should log feedback if last collection and database is not shared", () => {
let selectedCollectionId = "testCol"; let selectedCollectionId = "testCol";
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>( let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
DocumentClientUtilityBase as any fakeDocumentClientUtility.deleteCollection = () => Q(null);
); let fakeExplorer = {} as Explorer;
fakeDocumentClientUtility.deleteCollection.returns(Q.resolve(null)); fakeExplorer.findSelectedCollection = () =>
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
fakeExplorer.findSelectedCollection.returns(
new CollectionStub({ new CollectionStub({
id: ko.observable<string>(selectedCollectionId), id: ko.observable<string>(selectedCollectionId),
rid: "test" rid: "test"
}) });
); fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false)); fakeExplorer.selectedCollectionId = ko.computed<string>(() => selectedCollectionId);
sinon.stub(fakeExplorer, "selectedCollectionId").value(ko.observable<string>(selectedCollectionId)); fakeExplorer.isSelectedDatabaseShared = () => false;
fakeExplorer.isSelectedDatabaseShared.returns(false);
const SubscriptionId = "testId"; const SubscriptionId = "testId";
const AccountName = "testAccount"; const AccountName = "testAccount";
sinon.stub(fakeExplorer, "databaseAccount").value( fakeExplorer.databaseAccount = ko.observable<ViewModels.DatabaseAccount>({
ko.observable<ViewModels.DatabaseAccount>({ id: SubscriptionId,
id: SubscriptionId, name: AccountName
name: AccountName } as ViewModels.DatabaseAccount);
} as ViewModels.DatabaseAccount)
); fakeExplorer.defaultExperience = ko.observable<string>("DocumentDB");
sinon.stub(fakeExplorer, "defaultExperience").value(ko.observable<string>("DocumentDB")); fakeExplorer.isPreferredApiCassandra = ko.computed(() => {
sinon.stub(fakeExplorer, "isPreferredApiCassandra").value( return false;
ko.computed(() => { });
return false;
}) fakeExplorer.documentClientUtility = fakeDocumentClientUtility;
); fakeExplorer.selectedNode = ko.observable<TreeNode>();
sinon.stub(fakeExplorer, "documentClientUtility").value(fakeDocumentClientUtility); fakeExplorer.isLastCollection = () => true;
sinon.stub(fakeExplorer, "selectedNode").value(ko.observable<TreeNode>()); fakeExplorer.isSelectedDatabaseShared = () => false;
fakeExplorer.isLastCollection.returns(true); fakeExplorer.refreshAllDatabases = () => Q.resolve();
fakeExplorer.isSelectedDatabaseShared.returns(false);
let pane = new DeleteCollectionConfirmationPane({ let pane = new DeleteCollectionConfirmationPane({
documentClientUtility: fakeDocumentClientUtility as any, documentClientUtility: fakeDocumentClientUtility as any,

View File

@ -8,14 +8,14 @@ import DeleteDatabaseConfirmationPane from "./DeleteDatabaseConfirmationPane";
import DeleteFeedback from "../../Common/DeleteFeedback"; import DeleteFeedback from "../../Common/DeleteFeedback";
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Explorer from "../Explorer"; import Explorer from "../Explorer";
import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs"; import { CollectionStub, DatabaseStub } from "../OpenActionsStubs";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { TreeNode } from "../../Contracts/ViewModels"; import { TreeNode } from "../../Contracts/ViewModels";
import { TabsManager } from "../Tabs/TabsManager"; import { TabsManager } from "../Tabs/TabsManager";
describe("Delete Database Confirmation Pane", () => { describe("Delete Database Confirmation Pane", () => {
describe("Explorer.isLastDatabase() and Explorer.isLastNonEmptyDatabase()", () => { describe("Explorer.isLastDatabase() and Explorer.isLastNonEmptyDatabase()", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
@ -50,11 +50,9 @@ describe("Delete Database Confirmation Pane", () => {
describe("shouldRecordFeedback()", () => { describe("shouldRecordFeedback()", () => {
it("should return true if last non empty database or is last database that has shared throughput, else false", () => { it("should return true if last non empty database or is last database that has shared throughput, else false", () => {
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>( let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
DocumentClientUtilityBase as any let fakeExplorer = {} as Explorer;
); fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false));
let pane = new DeleteDatabaseConfirmationPane({ let pane = new DeleteDatabaseConfirmationPane({
documentClientUtility: fakeDocumentClientUtility as any, documentClientUtility: fakeDocumentClientUtility as any,
@ -63,18 +61,18 @@ describe("Delete Database Confirmation Pane", () => {
container: fakeExplorer as any container: fakeExplorer as any
}); });
fakeExplorer.isLastNonEmptyDatabase.returns(true); fakeExplorer.isLastNonEmptyDatabase = () => true;
pane.container = fakeExplorer as any; pane.container = fakeExplorer as any;
expect(pane.shouldRecordFeedback()).toBe(true); expect(pane.shouldRecordFeedback()).toBe(true);
fakeExplorer.isLastDatabase.returns(true); fakeExplorer.isLastDatabase = () => true;
fakeExplorer.isSelectedDatabaseShared.returns(true); fakeExplorer.isSelectedDatabaseShared = () => true;
pane.container = fakeExplorer as any; pane.container = fakeExplorer as any;
expect(pane.shouldRecordFeedback()).toBe(true); expect(pane.shouldRecordFeedback()).toBe(true);
fakeExplorer.isLastNonEmptyDatabase.returns(false); fakeExplorer.isLastNonEmptyDatabase = () => false;
fakeExplorer.isLastDatabase.returns(true); fakeExplorer.isLastDatabase = () => true;
fakeExplorer.isSelectedDatabaseShared.returns(false); fakeExplorer.isSelectedDatabaseShared = () => false;
pane.container = fakeExplorer as any; pane.container = fakeExplorer as any;
expect(pane.shouldRecordFeedback()).toBe(false); 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", () => { it("on submit() it should log feedback if last non empty database or is last database that has shared throughput", () => {
let selectedDatabaseId = "testDB"; let selectedDatabaseId = "testDB";
let fakeDocumentClientUtility = sinon.createStubInstance<DocumentClientUtilityBase>( let fakeDocumentClientUtility = {} as DocumentClientUtilityBase;
DocumentClientUtilityBase as any fakeDocumentClientUtility.deleteDatabase = () => Q.resolve(null);
); let fakeExplorer = {} as Explorer;
fakeDocumentClientUtility.deleteDatabase.returns(Q.resolve(null)); fakeExplorer.findSelectedDatabase = () =>
let fakeExplorer = sinon.createStubInstance<ExplorerStub>(ExplorerStub as any);
fakeExplorer.findSelectedDatabase.returns(
new DatabaseStub({ new DatabaseStub({
id: ko.observable<string>(selectedDatabaseId), id: ko.observable<string>(selectedDatabaseId),
rid: "test", rid: "test",
collections: ko.observableArray<ViewModels.Collection>() collections: ko.observableArray<ViewModels.Collection>()
}) });
); fakeExplorer.refreshAllDatabases = () => Q.resolve();
sinon.stub(fakeExplorer, "isNotificationConsoleExpanded").value(ko.observable<boolean>(false)); fakeExplorer.isNotificationConsoleExpanded = ko.observable<boolean>(false);
sinon.stub(fakeExplorer, "selectedDatabaseId").value(ko.observable<string>(selectedDatabaseId)); fakeExplorer.selectedDatabaseId = ko.computed<string>(() => selectedDatabaseId);
fakeExplorer.isSelectedDatabaseShared.returns(false); fakeExplorer.isSelectedDatabaseShared = () => false;
const SubscriptionId = "testId"; const SubscriptionId = "testId";
const AccountName = "testAccount"; const AccountName = "testAccount";
sinon.stub(fakeExplorer, "databaseAccount").value( fakeExplorer.databaseAccount = ko.observable<ViewModels.DatabaseAccount>({
ko.observable<ViewModels.DatabaseAccount>({ id: SubscriptionId,
id: SubscriptionId, name: AccountName
name: AccountName } as ViewModels.DatabaseAccount);
} as ViewModels.DatabaseAccount) fakeExplorer.defaultExperience = ko.observable<string>("DocumentDB");
); fakeExplorer.isPreferredApiCassandra = ko.computed(() => {
sinon.stub(fakeExplorer, "defaultExperience").value(ko.observable<string>("DocumentDB")); return false;
sinon.stub(fakeExplorer, "isPreferredApiCassandra").value( });
ko.computed(() => { fakeExplorer.documentClientUtility = fakeDocumentClientUtility;
return false; fakeExplorer.selectedNode = ko.observable<TreeNode>();
}) fakeExplorer.tabsManager = new TabsManager();
); fakeExplorer.isLastNonEmptyDatabase = () => true;
sinon.stub(fakeExplorer, "documentClientUtility").value(fakeDocumentClientUtility);
sinon.stub(fakeExplorer, "selectedNode").value(ko.observable<TreeNode>());
sinon.stub(fakeExplorer, "tabsManager").value(new TabsManager());
fakeExplorer.isLastNonEmptyDatabase.returns(true);
let pane = new DeleteDatabaseConfirmationPane({ let pane = new DeleteDatabaseConfirmationPane({
documentClientUtility: fakeDocumentClientUtility as any, documentClientUtility: fakeDocumentClientUtility as any,

View File

@ -1,13 +1,13 @@
import * as React from "react"; import * as React from "react";
import * as ViewModels from "../../Contracts/ViewModels";
import { IconButton, PrimaryButton } from "office-ui-fabric-react/lib/Button"; import { IconButton, PrimaryButton } from "office-ui-fabric-react/lib/Button";
import { KeyCodes } from "../../Common/Constants"; import { KeyCodes } from "../../Common/Constants";
import { Subscription } from "knockout"; import { Subscription } from "knockout";
import ErrorRedIcon from "../../../images/error_red.svg"; import ErrorRedIcon from "../../../images/error_red.svg";
import LoadingIndicatorIcon from "../../../images/LoadingIndicator_3Squares.gif"; import LoadingIndicatorIcon from "../../../images/LoadingIndicator_3Squares.gif";
import Explorer from "../Explorer";
export interface GenericRightPaneProps { export interface GenericRightPaneProps {
container: ViewModels.Explorer; container: Explorer;
content: JSX.Element; content: JSX.Element;
formError: string; formError: string;
formErrorDetail: string; formErrorDetail: string;

View File

@ -2,9 +2,10 @@ import * as ko from "knockout";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import { ContextualPaneBase } from "./ContextualPaneBase"; import { ContextualPaneBase } from "./ContextualPaneBase";
import { KeyCodes } from "../../Common/Constants"; import { KeyCodes } from "../../Common/Constants";
import Explorer from "../Explorer";
export default class NewVertexPane extends ContextualPaneBase implements ViewModels.NewVertexPane { export default class NewVertexPane extends ContextualPaneBase implements ViewModels.NewVertexPane {
public container: ViewModels.Explorer; public container: Explorer;
public visible: ko.Observable<boolean>; public visible: ko.Observable<boolean>;
public formErrors: ko.Observable<string>; public formErrors: ko.Observable<string>;
public formErrorsDetails: ko.Observable<string>; public formErrorsDetails: ko.Observable<string>;

View File

@ -1,156 +1,156 @@
import ko from "knockout"; import ko from "knockout";
import * as React from "react"; import * as React from "react";
import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
import * as Logger from "../../Common/Logger"; import * as Logger from "../../Common/Logger";
import * as ViewModels from "../../Contracts/ViewModels"; import { JunoClient } from "../../Juno/JunoClient";
import { JunoClient } from "../../Juno/JunoClient"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent";
import { GenericRightPaneComponent, GenericRightPaneProps } from "./GenericRightPaneComponent"; import Explorer from "../Explorer";
import { PublishNotebookPaneComponent, PublishNotebookPaneProps } from "./PublishNotebookPaneComponent"; import { PublishNotebookPaneComponent, PublishNotebookPaneProps } from "./PublishNotebookPaneComponent";
export class PublishNotebookPaneAdapter implements ReactAdapter { export class PublishNotebookPaneAdapter implements ReactAdapter {
parameters: ko.Observable<number>; parameters: ko.Observable<number>;
private isOpened: boolean; private isOpened: boolean;
private isExecuting: boolean; private isExecuting: boolean;
private formError: string; private formError: string;
private formErrorDetail: string; private formErrorDetail: string;
private name: string; private name: string;
private author: string; private author: string;
private content: string; private content: string;
private description: string; private description: string;
private tags: string; private tags: string;
private imageSrc: string; private imageSrc: string;
constructor(private container: ViewModels.Explorer, private junoClient: JunoClient) { constructor(private container: Explorer, private junoClient: JunoClient) {
this.parameters = ko.observable(Date.now()); this.parameters = ko.observable(Date.now());
this.reset(); this.reset();
this.triggerRender(); this.triggerRender();
} }
public renderComponent(): JSX.Element { public renderComponent(): JSX.Element {
if (!this.isOpened) { if (!this.isOpened) {
return undefined; return undefined;
} }
const props: GenericRightPaneProps = { const props: GenericRightPaneProps = {
container: this.container, container: this.container,
content: this.createContent(), content: this.createContent(),
formError: this.formError, formError: this.formError,
formErrorDetail: this.formErrorDetail, formErrorDetail: this.formErrorDetail,
id: "publishnotebookpane", id: "publishnotebookpane",
isExecuting: this.isExecuting, isExecuting: this.isExecuting,
title: "Publish to gallery", title: "Publish to gallery",
submitButtonText: "Publish", submitButtonText: "Publish",
onClose: () => this.close(), onClose: () => this.close(),
onSubmit: () => this.submit() onSubmit: () => this.submit()
}; };
return <GenericRightPaneComponent {...props} />; return <GenericRightPaneComponent {...props} />;
} }
public triggerRender(): void { public triggerRender(): void {
window.requestAnimationFrame(() => this.parameters(Date.now())); window.requestAnimationFrame(() => this.parameters(Date.now()));
} }
public open(name: string, author: string, content: string): void { public open(name: string, author: string, content: string): void {
this.name = name; this.name = name;
this.author = author; this.author = author;
this.content = content; this.content = content;
this.isOpened = true; this.isOpened = true;
this.triggerRender(); this.triggerRender();
} }
public close(): void { public close(): void {
this.reset(); this.reset();
this.triggerRender(); this.triggerRender();
} }
public async submit(): Promise<void> { public async submit(): Promise<void> {
const notificationId = NotificationConsoleUtils.logConsoleMessage( const notificationId = NotificationConsoleUtils.logConsoleMessage(
ConsoleDataType.InProgress, ConsoleDataType.InProgress,
`Publishing ${this.name} to gallery` `Publishing ${this.name} to gallery`
); );
this.isExecuting = true; this.isExecuting = true;
this.triggerRender(); this.triggerRender();
try { try {
if (!this.name || !this.description || !this.author) { if (!this.name || !this.description || !this.author) {
throw new Error("Name, description, and author are required"); throw new Error("Name, description, and author are required");
} }
const response = await this.junoClient.publishNotebook( const response = await this.junoClient.publishNotebook(
this.name, this.name,
this.description, this.description,
this.tags?.split(","), this.tags?.split(","),
this.author, this.author,
this.imageSrc, this.imageSrc,
this.content this.content
); );
if (!response.data) { if (!response.data) {
throw new Error(`Received HTTP ${response.status} when publishing ${name} to gallery`); throw new Error(`Received HTTP ${response.status} when publishing ${name} to gallery`);
} }
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Published ${name} to gallery`); NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Info, `Published ${name} to gallery`);
} catch (error) { } catch (error) {
this.formError = `Failed to publish ${this.name} to gallery`; this.formError = `Failed to publish ${this.name} to gallery`;
this.formErrorDetail = `${error}`; this.formErrorDetail = `${error}`;
const message = `${this.formError}: ${this.formErrorDetail}`; const message = `${this.formError}: ${this.formErrorDetail}`;
Logger.logError(message, "PublishNotebookPaneAdapter/submit"); Logger.logError(message, "PublishNotebookPaneAdapter/submit");
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
return; return;
} finally { } finally {
NotificationConsoleUtils.clearInProgressMessageWithId(notificationId); NotificationConsoleUtils.clearInProgressMessageWithId(notificationId);
this.isExecuting = false; this.isExecuting = false;
this.triggerRender(); this.triggerRender();
} }
this.close(); this.close();
} }
private createFormErrorForLargeImageSelection = (formError: string, formErrorDetail: string, area: string): void => { private createFormErrorForLargeImageSelection = (formError: string, formErrorDetail: string, area: string): void => {
this.formError = formError; this.formError = formError;
this.formErrorDetail = formErrorDetail; this.formErrorDetail = formErrorDetail;
const message = `${this.formError}: ${this.formErrorDetail}`; const message = `${this.formError}: ${this.formErrorDetail}`;
Logger.logError(message, area); Logger.logError(message, area);
NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message); NotificationConsoleUtils.logConsoleMessage(ConsoleDataType.Error, message);
this.triggerRender(); this.triggerRender();
}; };
private clearFormError = (): void => { private clearFormError = (): void => {
this.formError = undefined; this.formError = undefined;
this.formErrorDetail = undefined; this.formErrorDetail = undefined;
this.triggerRender(); this.triggerRender();
}; };
private createContent = (): JSX.Element => { private createContent = (): JSX.Element => {
const publishNotebookPaneProps: PublishNotebookPaneProps = { const publishNotebookPaneProps: PublishNotebookPaneProps = {
notebookName: this.name, notebookName: this.name,
notebookDescription: "", notebookDescription: "",
notebookTags: "", notebookTags: "",
notebookAuthor: this.author, notebookAuthor: this.author,
notebookCreatedDate: new Date().toISOString(), notebookCreatedDate: new Date().toISOString(),
onChangeDescription: (newValue: string) => (this.description = newValue), onChangeDescription: (newValue: string) => (this.description = newValue),
onChangeTags: (newValue: string) => (this.tags = newValue), onChangeTags: (newValue: string) => (this.tags = newValue),
onChangeImageSrc: (newValue: string) => (this.imageSrc = newValue), onChangeImageSrc: (newValue: string) => (this.imageSrc = newValue),
onError: this.createFormErrorForLargeImageSelection, onError: this.createFormErrorForLargeImageSelection,
clearFormError: this.clearFormError clearFormError: this.clearFormError
}; };
return <PublishNotebookPaneComponent {...publishNotebookPaneProps} />; return <PublishNotebookPaneComponent {...publishNotebookPaneProps} />;
}; };
private reset = (): void => { private reset = (): void => {
this.isOpened = false; this.isOpened = false;
this.isExecuting = false; this.isExecuting = false;
this.formError = undefined; this.formError = undefined;
this.formErrorDetail = undefined; this.formErrorDetail = undefined;
this.name = undefined; this.name = undefined;
this.author = undefined; this.author = undefined;
this.content = undefined; this.content = undefined;
}; };
} }

View File

@ -4,7 +4,7 @@ import Explorer from "../Explorer";
describe("Settings Pane", () => { describe("Settings Pane", () => {
describe("shouldShowQueryPageOptions()", () => { describe("shouldShowQueryPageOptions()", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });

View File

@ -8,9 +8,10 @@ import * as Utilities from "../../Tables/Utilities";
import * as TableConstants from "../../Tables/Constants"; import * as TableConstants from "../../Tables/Constants";
import EntityPropertyViewModel from "./EntityPropertyViewModel"; import EntityPropertyViewModel from "./EntityPropertyViewModel";
import * as TableEntityProcessor from "../../Tables/TableEntityProcessor"; import * as TableEntityProcessor from "../../Tables/TableEntityProcessor";
import Explorer from "../../Explorer";
export default class EditTableEntityPane extends TableEntityPane implements ViewModels.EditTableEntityPane { export default class EditTableEntityPane extends TableEntityPane implements ViewModels.EditTableEntityPane {
container: ViewModels.Explorer; container: Explorer;
visible: ko.Observable<boolean>; visible: ko.Observable<boolean>;
public originEntity: Entities.ITableEntity; public originEntity: Entities.ITableEntity;

View File

@ -10,6 +10,7 @@ import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
import { UploadDetailsRecord, UploadDetails } from "../../workers/upload/definitions"; import { UploadDetailsRecord, UploadDetails } from "../../workers/upload/definitions";
import InfoBubbleIcon from "../../../images/info-bubble.svg"; import InfoBubbleIcon from "../../../images/info-bubble.svg";
import Explorer from "../Explorer";
const UPLOAD_FILE_SIZE_LIMIT = 2097152; const UPLOAD_FILE_SIZE_LIMIT = 2097152;
@ -23,7 +24,7 @@ export class UploadItemsPaneAdapter implements ReactAdapter {
private selectedFilesTitle: string; private selectedFilesTitle: string;
private uploadFileData: UploadDetailsRecord[]; private uploadFileData: UploadDetailsRecord[];
public constructor(private container: ViewModels.Explorer) { public constructor(private container: Explorer) {
this.parameters = ko.observable(Date.now()); this.parameters = ko.observable(Date.now());
this.reset(); this.reset();
this.triggerRender(); this.triggerRender();

View File

@ -18,6 +18,7 @@ import * as MostRecentActivity from "../MostRecentActivity/MostRecentActivity";
import AddDatabaseIcon from "../../../images/AddDatabase.svg"; import AddDatabaseIcon from "../../../images/AddDatabase.svg";
import SampleIcon from "../../../images/Hero-sample.svg"; import SampleIcon from "../../../images/Hero-sample.svg";
import { DataSamplesUtil } from "../DataSamples/DataSamplesUtil"; import { DataSamplesUtil } from "../DataSamples/DataSamplesUtil";
import Explorer from "../Explorer";
/** /**
* TODO Remove this when fully ported to ReactJS * TODO Remove this when fully ported to ReactJS
@ -29,7 +30,7 @@ export class SplashScreenComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>; public parameters: ko.Observable<number>;
constructor(private container: ViewModels.Explorer) { constructor(private container: Explorer) {
this.parameters = ko.observable<number>(Date.now()); this.parameters = ko.observable<number>(Date.now());
this.container.tabsManager.openedTabs.subscribe((tabs: ViewModels.Tab[]) => { this.container.tabsManager.openedTabs.subscribe((tabs: ViewModels.Tab[]) => {
if (tabs.length === 0) { if (tabs.length === 0) {

View File

@ -237,7 +237,7 @@ function updateTableScrollableRegionHeight(): void {
.offset().top; .offset().top;
var dataTablesInfoElem = $(tabElement).find(".dataTables_info"); var dataTablesInfoElem = $(tabElement).find(".dataTables_info");
var dataTablesPaginateElem = $(tabElement).find(".dataTables_paginate"); var dataTablesPaginateElem = $(tabElement).find(".dataTables_paginate");
const explorer = window.dataExplorer as ViewModels.Explorer; const explorer = window.dataExplorer;
const notificationConsoleHeight = explorer.isNotificationConsoleExpanded() const notificationConsoleHeight = explorer.isNotificationConsoleExpanded()
? 252 /** 32px(header) + 220px(content height) **/ ? 252 /** 32px(header) + 220px(content height) **/
: 32 /** Header height **/; : 32 /** Header height **/;

View File

@ -6,6 +6,7 @@ import TableEntityListViewModel from "./TableEntityListViewModel";
import * as Entities from "../Entities"; import * as Entities from "../Entities";
import * as ViewModels from "../../../Contracts/ViewModels"; import * as ViewModels from "../../../Contracts/ViewModels";
import * as TableColumnOptionsPane from "../../Panes/Tables/TableColumnOptionsPane"; import * as TableColumnOptionsPane from "../../Panes/Tables/TableColumnOptionsPane";
import Explorer from "../../Explorer";
export default class TableCommands { export default class TableCommands {
// Command Ids // Command Ids
@ -15,9 +16,9 @@ export default class TableCommands {
public static resetColumnsCommand: string = "reset"; public static resetColumnsCommand: string = "reset";
public static customizeColumnsCommand: string = "customizeColumns"; public static customizeColumnsCommand: string = "customizeColumns";
private _container: ViewModels.Explorer; private _container: Explorer;
constructor(container: ViewModels.Explorer) { constructor(container: Explorer) {
this._container = container; this._container = container;
} }

View File

@ -16,6 +16,7 @@ import * as ViewModels from "../../Contracts/ViewModels";
import { MessageTypes } from "../../Contracts/ExplorerContracts"; import { MessageTypes } from "../../Contracts/ExplorerContracts";
import { MessageHandler } from "../../Common/MessageHandler"; import { MessageHandler } from "../../Common/MessageHandler";
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Explorer from "../Explorer";
export interface CassandraTableKeys { export interface CassandraTableKeys {
partitionKeys: CassandraTableKey[]; partitionKeys: CassandraTableKey[];
@ -405,7 +406,7 @@ export class CassandraAPIDataClient extends TableDataClient {
public createKeyspace( public createKeyspace(
cassandraEndpoint: string, cassandraEndpoint: string,
resourceId: string, resourceId: string,
explorer: ViewModels.Explorer, explorer: Explorer,
createKeyspaceQuery: string createKeyspaceQuery: string
): Q.Promise<any> { ): Q.Promise<any> {
if (!createKeyspaceQuery) { if (!createKeyspaceQuery) {
@ -446,7 +447,7 @@ export class CassandraAPIDataClient extends TableDataClient {
public createTableAndKeyspace( public createTableAndKeyspace(
cassandraEndpoint: string, cassandraEndpoint: string,
resourceId: string, resourceId: string,
explorer: ViewModels.Explorer, explorer: Explorer,
createTableQuery: string, createTableQuery: string,
createKeyspaceQuery?: string createKeyspaceQuery?: string
): Q.Promise<any> { ): Q.Promise<any> {
@ -506,7 +507,7 @@ export class CassandraAPIDataClient extends TableDataClient {
cassandraEndpoint: string, cassandraEndpoint: string,
resourceId: string, resourceId: string,
deleteQuery: string, deleteQuery: string,
explorer: ViewModels.Explorer explorer: Explorer
): Q.Promise<any> { ): Q.Promise<any> {
const deferred = Q.defer<any>(); const deferred = Q.defer<any>();
const notificationId = NotificationConsoleUtils.logConsoleMessage( const notificationId = NotificationConsoleUtils.logConsoleMessage(
@ -660,7 +661,7 @@ export class CassandraAPIDataClient extends TableDataClient {
cassandraEndpoint: string, cassandraEndpoint: string,
resourceId: string, resourceId: string,
query: string, query: string,
explorer: ViewModels.Explorer explorer: Explorer
): Q.Promise<any> { ): Q.Promise<any> {
const deferred = Q.defer(); const deferred = Q.defer();
const authType = window.authType; const authType = window.authType;

View File

@ -20,6 +20,7 @@ import DiscardIcon from "../../../images/discard.svg";
import DeleteIcon from "../../../images/delete.svg"; import DeleteIcon from "../../../images/delete.svg";
import { QueryIterator, ItemDefinition, Resource, ConflictDefinition } from "@azure/cosmos"; import { QueryIterator, ItemDefinition, Resource, ConflictDefinition } from "@azure/cosmos";
import { MinimalQueryIterator } from "../../Common/IteratorUtilities"; import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
import Explorer from "../Explorer";
export default class ConflictsTab extends TabsBase implements ViewModels.ConflictsTab { export default class ConflictsTab extends TabsBase implements ViewModels.ConflictsTab {
public selectedConflictId: ko.Observable<ViewModels.ConflictId>; public selectedConflictId: ko.Observable<ViewModels.ConflictId>;
@ -49,7 +50,7 @@ export default class ConflictsTab extends TabsBase implements ViewModels.Conflic
public conflictIds: ko.ObservableArray<ViewModels.ConflictId>; public conflictIds: ko.ObservableArray<ViewModels.ConflictId>;
private _documentsIterator: MinimalQueryIterator; private _documentsIterator: MinimalQueryIterator;
private _container: ViewModels.Explorer; private _container: Explorer;
private _acceptButtonLabel: ko.Observable<string> = ko.observable("Save"); private _acceptButtonLabel: ko.Observable<string> = ko.observable("Save");
protected _selfLink: string; protected _selfLink: string;

View File

@ -17,6 +17,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { CosmosClient } from "../../Common/CosmosClient"; import { CosmosClient } from "../../Common/CosmosClient";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";
import Explorer from "../Explorer";
const updateThroughputBeyondLimitWarningMessage: string = ` const updateThroughputBeyondLimitWarningMessage: string = `
You are about to request an increase in throughput beyond the pre-allocated capacity. 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<boolean>; private _hasProvisioningTypeChanged: ko.Computed<boolean>;
private _wasAutopilotOriginallySet: ko.Observable<boolean>; private _wasAutopilotOriginallySet: ko.Observable<boolean>;
private _offerReplacePending: ko.Computed<boolean>; private _offerReplacePending: ko.Computed<boolean>;
private container: ViewModels.Explorer; private container: Explorer;
constructor(options: ViewModels.TabOptions) { constructor(options: ViewModels.TabOptions) {
super(options); super(options);

View File

@ -25,6 +25,7 @@ import SynapseIcon from "../../../images/synapse-link.svg";
import { extractPartitionKey, PartitionKeyDefinition, QueryIterator, ItemDefinition, Resource } from "@azure/cosmos"; import { extractPartitionKey, PartitionKeyDefinition, QueryIterator, ItemDefinition, Resource } from "@azure/cosmos";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import Explorer from "../Explorer";
export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab { export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab {
public selectedDocumentId: ko.Observable<ViewModels.DocumentId>; public selectedDocumentId: ko.Observable<ViewModels.DocumentId>;
@ -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"; const label = "Upload Item";
return { return {
iconSrc: UploadIcon, iconSrc: UploadIcon,

View File

@ -3,12 +3,13 @@ import { GalleryAndNotebookViewerComponentProps } from "../Controls/NotebookGall
import { GalleryAndNotebookViewerComponentAdapter } from "../Controls/NotebookGallery/GalleryAndNotebookViewerComponentAdapter"; import { GalleryAndNotebookViewerComponentAdapter } from "../Controls/NotebookGallery/GalleryAndNotebookViewerComponentAdapter";
import { GalleryTab as GalleryViewerTab, SortBy } from "../Controls/NotebookGallery/GalleryViewerComponent"; import { GalleryTab as GalleryViewerTab, SortBy } from "../Controls/NotebookGallery/GalleryViewerComponent";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import Explorer from "../Explorer";
/** /**
* Notebook gallery tab * Notebook gallery tab
*/ */
export default class GalleryTab extends TabsBase implements ViewModels.Tab { export default class GalleryTab extends TabsBase implements ViewModels.Tab {
private container: ViewModels.Explorer; private container: Explorer;
public galleryAndNotebookViewerComponentAdapter: GalleryAndNotebookViewerComponentAdapter; public galleryAndNotebookViewerComponentAdapter: GalleryAndNotebookViewerComponentAdapter;
constructor(options: ViewModels.GalleryTabOptions) { constructor(options: ViewModels.GalleryTabOptions) {
@ -29,7 +30,7 @@ export default class GalleryTab extends TabsBase implements ViewModels.Tab {
this.galleryAndNotebookViewerComponentAdapter = new GalleryAndNotebookViewerComponentAdapter(props); this.galleryAndNotebookViewerComponentAdapter = new GalleryAndNotebookViewerComponentAdapter(props);
} }
protected getContainer(): ViewModels.Explorer { protected getContainer(): Explorer {
return this.container; return this.container;
} }
} }

View File

@ -13,10 +13,11 @@ import { CosmosClient } from "../../Common/CosmosClient";
import { HashMap } from "../../Common/HashMap"; import { HashMap } from "../../Common/HashMap";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import Explorer from "../Explorer";
export default class MongoShellTab extends TabsBase implements ViewModels.MongoShellTab { export default class MongoShellTab extends TabsBase implements ViewModels.MongoShellTab {
public url: ko.Computed<string>; public url: ko.Computed<string>;
private _container: ViewModels.Explorer; private _container: Explorer;
private _runtimeEndpoint: string; private _runtimeEndpoint: string;
private _logTraces: HashMap<number>; private _logTraces: HashMap<number>;

View File

@ -27,10 +27,11 @@ import { NotebookComponentAdapter } from "../Notebook/NotebookComponent/Notebook
import { NotebookConfigurationUtils } from "../../Utils/NotebookConfigurationUtils"; import { NotebookConfigurationUtils } from "../../Utils/NotebookConfigurationUtils";
import { KernelSpecsDisplay, NotebookClientV2 } from "../Notebook/NotebookClientV2"; import { KernelSpecsDisplay, NotebookClientV2 } from "../Notebook/NotebookClientV2";
import { config } from "../../Config"; import { config } from "../../Config";
import Explorer from "../Explorer";
export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab {
private static clientManager: NotebookClientV2; private static clientManager: NotebookClientV2;
private container: ViewModels.Explorer; private container: Explorer;
public notebookPath: ko.Observable<string>; public notebookPath: ko.Observable<string>;
private selectedSparkPool: ko.Observable<string>; private selectedSparkPool: ko.Observable<string>;
private notebookComponentAdapter: NotebookComponentAdapter; private notebookComponentAdapter: NotebookComponentAdapter;
@ -104,7 +105,7 @@ export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab {
return await this.configureServiceEndpoints(this.notebookComponentAdapter.getCurrentKernelName()); return await this.configureServiceEndpoints(this.notebookComponentAdapter.getCurrentKernelName());
} }
protected getContainer(): ViewModels.Explorer { protected getContainer(): Explorer {
return this.container; return this.container;
} }

View File

@ -7,6 +7,7 @@ import {
NotebookViewerComponentProps NotebookViewerComponentProps
} from "../Controls/NotebookViewer/NotebookViewerComponent"; } from "../Controls/NotebookViewer/NotebookViewerComponent";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import Explorer from "../Explorer";
/** /**
* Notebook Viewer tab * Notebook Viewer tab
@ -29,7 +30,7 @@ class NotebookViewerComponentAdapter implements ReactAdapter {
} }
export default class NotebookViewerTab extends TabsBase implements ViewModels.Tab { export default class NotebookViewerTab extends TabsBase implements ViewModels.Tab {
private container: ViewModels.Explorer; private container: Explorer;
public notebookUrl: string; public notebookUrl: string;
public notebookViewerComponentAdapter: NotebookViewerComponentAdapter; 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; return this.container;
} }

View File

@ -6,7 +6,7 @@ import { CollectionStub, DatabaseStub } from "../../Explorer/OpenActionsStubs";
import QueryTab from "./QueryTab"; import QueryTab from "./QueryTab";
describe("Query Tab", () => { describe("Query Tab", () => {
function getNewQueryTabForContainer(container: ViewModels.Explorer): ViewModels.QueryTab { function getNewQueryTabForContainer(container: Explorer): ViewModels.QueryTab {
const database: ViewModels.Database = new DatabaseStub({ const database: ViewModels.Database = new DatabaseStub({
container: container, container: container,
id: ko.observable<string>("test"), id: ko.observable<string>("test"),
@ -54,7 +54,7 @@ describe("Query Tab", () => {
}); });
describe("isQueryMetricsEnabled()", () => { describe("isQueryMetricsEnabled()", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
@ -74,7 +74,7 @@ describe("Query Tab", () => {
}); });
describe("Save Queries command button", () => { describe("Save Queries command button", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });

View File

@ -115,7 +115,7 @@ export default class QueryTab extends TabsBase implements ViewModels.QueryTab, V
}; };
this._isSaveQueriesEnabled = ko.computed<boolean>(() => { this._isSaveQueriesEnabled = ko.computed<boolean>(() => {
const container: ViewModels.Explorer = this.collection && this.collection.container; const container = this.collection && this.collection.container;
return (container && (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph())) || false; return (container && (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph())) || false;
}); });

View File

@ -13,6 +13,7 @@ import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg";
import AddEntityIcon from "../../../images/AddEntity.svg"; import AddEntityIcon from "../../../images/AddEntity.svg";
import EditEntityIcon from "../../../images/Edit-entity.svg"; import EditEntityIcon from "../../../images/Edit-entity.svg";
import DeleteEntitiesIcon from "../../../images/DeleteEntities.svg"; import DeleteEntitiesIcon from "../../../images/DeleteEntities.svg";
import Explorer from "../Explorer";
// Will act as table explorer class // Will act as table explorer class
export default class QueryTablesTab extends TabsBase { export default class QueryTablesTab extends TabsBase {
@ -31,7 +32,7 @@ export default class QueryTablesTab extends TabsBase {
public deleteEntityButton: ViewModels.Button; public deleteEntityButton: ViewModels.Button;
public queryBuilderButton: ViewModels.Button; public queryBuilderButton: ViewModels.Button;
public queryTextButton: ViewModels.Button; public queryTextButton: ViewModels.Button;
public container: ViewModels.Explorer; public container: Explorer;
constructor(options: ViewModels.TabOptions) { constructor(options: ViewModels.TabOptions) {
super(options); super(options);

View File

@ -177,7 +177,7 @@ describe("Settings tab", () => {
}); });
describe("Should update collection", () => { describe("Should update collection", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });
@ -259,7 +259,7 @@ describe("Settings tab", () => {
}); });
describe("Get Conflict Resolution configuration from user", () => { describe("Get Conflict Resolution configuration from user", () => {
let explorer: ViewModels.Explorer; let explorer: Explorer;
beforeEach(() => { beforeEach(() => {
explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false }); explorer = new Explorer({ documentClientUtility: null, notificationsClient: null, isEmulator: false });

View File

@ -17,6 +17,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { CosmosClient } from "../../Common/CosmosClient"; import { CosmosClient } from "../../Common/CosmosClient";
import { PlatformType } from "../../PlatformType"; import { PlatformType } from "../../PlatformType";
import { RequestOptions } from "@azure/cosmos/dist-esm"; import { RequestOptions } from "@azure/cosmos/dist-esm";
import Explorer from "../Explorer";
const ttlWarning: string = ` 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. 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; public throughputModeRadioName: string;
private _offerReplacePending: ko.PureComputed<boolean>; private _offerReplacePending: ko.PureComputed<boolean>;
private container: ViewModels.Explorer; private container: Explorer;
private _wasAutopilotOriginallySet: ko.Observable<boolean>; private _wasAutopilotOriginallySet: ko.Observable<boolean>;
private _isAutoPilotDirty: ko.Computed<boolean>; private _isAutoPilotDirty: ko.Computed<boolean>;
private _hasProvisioningTypeChanged: ko.Computed<boolean>; private _hasProvisioningTypeChanged: ko.Computed<boolean>;

View File

@ -2,12 +2,13 @@ import * as ko from "knockout";
import * as DataModels from "../../Contracts/DataModels"; import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import TabsBase from "./TabsBase"; import TabsBase from "./TabsBase";
import Explorer from "../Explorer";
export default class SparkMasterTab extends TabsBase { export default class SparkMasterTab extends TabsBase {
public sparkMasterSrc: ko.Observable<string>; public sparkMasterSrc: ko.Observable<string>;
private _clusterConnectionInfo: DataModels.SparkClusterConnectionInfo; private _clusterConnectionInfo: DataModels.SparkClusterConnectionInfo;
private _container: ViewModels.Explorer; private _container: Explorer;
constructor(options: ViewModels.SparkMasterTabOptions) { constructor(options: ViewModels.SparkMasterTabOptions) {
super(options); super(options);

View File

@ -8,6 +8,7 @@ import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import ThemeUtility from "../../Common/ThemeUtility"; import ThemeUtility from "../../Common/ThemeUtility";
import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase"; import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Explorer from "../Explorer";
// TODO: Use specific actions for logging telemetry data // TODO: Use specific actions for logging telemetry data
export default class TabsBase extends WaitsForTemplateViewModel implements ViewModels.Tab { export default class TabsBase extends WaitsForTemplateViewModel implements ViewModels.Tab {
@ -79,7 +80,7 @@ export default class TabsBase extends WaitsForTemplateViewModel implements ViewM
} }
public onCloseTabButtonClick(): void { public onCloseTabButtonClick(): void {
const explorer: ViewModels.Explorer = this.getContainer(); const explorer = this.getContainer();
explorer.tabsManager.closeTab(this.tabId, explorer); explorer.tabsManager.closeTab(this.tabId, explorer);
TelemetryProcessor.trace(Action.Tab, ActionModifiers.Close, { TelemetryProcessor.trace(Action.Tab, ActionModifiers.Close, {
@ -173,7 +174,7 @@ export default class TabsBase extends WaitsForTemplateViewModel implements ViewM
return Q(); return Q();
} }
protected getContainer(): ViewModels.Explorer { protected getContainer(): Explorer {
return (this.collection && this.collection.container) || (this.database && this.database.container); return (this.collection && this.collection.container) || (this.database && this.database.container);
} }

View File

@ -10,7 +10,7 @@ import QueryTab from "./QueryTab";
describe("Tabs manager tests", () => { describe("Tabs manager tests", () => {
let tabsManager: TabsManager; let tabsManager: TabsManager;
let explorer: ViewModels.Explorer; let explorer: Explorer;
let database: ViewModels.Database; let database: ViewModels.Database;
let collection: ViewModels.Collection; let collection: ViewModels.Collection;
let queryTab: QueryTab; let queryTab: QueryTab;

View File

@ -1,6 +1,7 @@
import * as ko from "knockout"; import * as ko from "knockout";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import TabsManagerTemplate from "./TabsManager.html"; import TabsManagerTemplate from "./TabsManager.html";
import Explorer from "../Explorer";
export class TabsManager { export class TabsManager {
public openedTabs: ko.ObservableArray<ViewModels.Tab>; public openedTabs: ko.ObservableArray<ViewModels.Tab>;
@ -62,7 +63,7 @@ export class TabsManager {
this.openedTabs([]); 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); const tabIndex: number = this.openedTabs().findIndex((tab: ViewModels.Tab) => tab.tabId === tabId);
if (tabIndex !== -1) { if (tabIndex !== -1) {
const tabToActive: ViewModels.Tab = this.openedTabs()[tabIndex + 1] || this.openedTabs()[tabIndex - 1]; const tabToActive: ViewModels.Tab = this.openedTabs()[tabIndex + 1] || this.openedTabs()[tabIndex - 1];

View File

@ -5,6 +5,7 @@ import TabsBase from "./TabsBase";
import * as React from "react"; import * as React from "react";
import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
import { NotebookTerminalComponent } from "../Controls/Notebook/NotebookTerminalComponent"; import { NotebookTerminalComponent } from "../Controls/Notebook/NotebookTerminalComponent";
import Explorer from "../Explorer";
/** /**
* Notebook terminal tab * Notebook terminal tab
@ -30,7 +31,7 @@ class NotebookTerminalComponentAdapter implements ReactAdapter {
} }
export default class TerminalTab extends TabsBase implements ViewModels.Tab { export default class TerminalTab extends TabsBase implements ViewModels.Tab {
private container: ViewModels.Explorer; private container: Explorer;
private notebookTerminalComponentAdapter: NotebookTerminalComponentAdapter; private notebookTerminalComponentAdapter: NotebookTerminalComponentAdapter;
constructor(options: ViewModels.TerminalTabOptions) { 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; return this.container;
} }

View File

@ -2,11 +2,12 @@ import * as DataModels from "../../Contracts/DataModels";
import * as ko from "knockout"; import * as ko from "knockout";
import * as ViewModels from "../../Contracts/ViewModels"; import * as ViewModels from "../../Contracts/ViewModels";
import Collection from "./Collection"; import Collection from "./Collection";
import Explorer from "../Explorer";
jest.mock("monaco-editor"); jest.mock("monaco-editor");
describe("Collection", () => { describe("Collection", () => {
function generateCollection( function generateCollection(
container: ViewModels.Explorer, container: Explorer,
databaseId: string, databaseId: string,
data: DataModels.Collection, data: DataModels.Collection,
quotaInfo: DataModels.CollectionQuotaInfo, quotaInfo: DataModels.CollectionQuotaInfo,
@ -31,7 +32,7 @@ describe("Collection", () => {
} }
function generateMockCollectionWithDataModel(data: DataModels.Collection): Collection { function generateMockCollectionWithDataModel(data: DataModels.Collection): Collection {
const mockContainer = {} as ViewModels.Explorer; const mockContainer = {} as Explorer;
mockContainer.isPreferredApiMongoDB = ko.computed(() => { mockContainer.isPreferredApiMongoDB = ko.computed(() => {
return false; return false;
}); });
@ -47,9 +48,7 @@ describe("Collection", () => {
mockContainer.isPreferredApiGraph = ko.computed(() => { mockContainer.isPreferredApiGraph = ko.computed(() => {
return false; return false;
}); });
mockContainer.deleteCollectionText = ko.computed(() => { mockContainer.deleteCollectionText = ko.observable<string>("delete collection");
return "delete collection";
});
return generateCollection(mockContainer, "abc", data, {} as DataModels.CollectionQuotaInfo, {} as DataModels.Offer); return generateCollection(mockContainer, "abc", data, {} as DataModels.CollectionQuotaInfo, {} as DataModels.Offer);
} }

View File

@ -32,10 +32,11 @@ import StoredProcedure from "./StoredProcedure";
import Trigger from "./Trigger"; import Trigger from "./Trigger";
import UserDefinedFunction from "./UserDefinedFunction"; import UserDefinedFunction from "./UserDefinedFunction";
import { config } from "../../Config"; import { config } from "../../Config";
import Explorer from "../Explorer";
export default class Collection implements ViewModels.Collection { export default class Collection implements ViewModels.Collection {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public self: string; public self: string;
public rid: string; public rid: string;
public databaseId: string; public databaseId: string;
@ -86,7 +87,7 @@ export default class Collection implements ViewModels.Collection {
public triggersFocused: ko.Observable<boolean>; public triggersFocused: ko.Observable<boolean>;
constructor( constructor(
container: ViewModels.Explorer, container: Explorer,
databaseId: string, databaseId: string,
data: DataModels.Collection, data: DataModels.Collection,
quotaInfo: DataModels.CollectionQuotaInfo, quotaInfo: DataModels.CollectionQuotaInfo,

View File

@ -11,10 +11,11 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import * as Logger from "../../Common/Logger"; import * as Logger from "../../Common/Logger";
import Explorer from "../Explorer";
export default class Database implements ViewModels.Database { export default class Database implements ViewModels.Database {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public self: string; public self: string;
public rid: string; public rid: string;
public id: ko.Observable<string>; public id: ko.Observable<string>;
@ -24,7 +25,7 @@ export default class Database implements ViewModels.Database {
public isDatabaseShared: ko.Computed<boolean>; public isDatabaseShared: ko.Computed<boolean>;
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>; public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
constructor(container: ViewModels.Explorer, data: any, offer: DataModels.Offer) { constructor(container: Explorer, data: any, offer: DataModels.Offer) {
this.nodeKind = "Database"; this.nodeKind = "Database";
this.container = container; this.container = container;
this.self = data._self; this.self = data._self;

View File

@ -8,10 +8,11 @@ import DocumentsTab from "../Tabs/DocumentsTab";
import Q from "q"; import Q from "q";
import QueryTab from "../Tabs/QueryTab"; import QueryTab from "../Tabs/QueryTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer";
export default class ResourceTokenCollection implements ViewModels.CollectionBase { export default class ResourceTokenCollection implements ViewModels.CollectionBase {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public databaseId: string; public databaseId: string;
public self: string; public self: string;
public rid: string; public rid: string;
@ -24,7 +25,7 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>; public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
public isCollectionExpanded: ko.Observable<boolean>; public isCollectionExpanded: ko.Observable<boolean>;
constructor(container: ViewModels.Explorer, databaseId: string, data: DataModels.Collection) { constructor(container: Explorer, databaseId: string, data: DataModels.Collection) {
this.nodeKind = "Collection"; this.nodeKind = "Collection";
this.container = container; this.container = container;
this.databaseId = databaseId; this.databaseId = databaseId;

View File

@ -26,6 +26,7 @@ import * as GitHubUtils from "../../Utils/GitHubUtils";
import GalleryIcon from "../../../images/GalleryIcon.svg"; import GalleryIcon from "../../../images/GalleryIcon.svg";
import { Callout, Text, Link, DirectionalHint, Stack, ICalloutProps, ILinkProps } from "office-ui-fabric-react"; import { Callout, Text, Link, DirectionalHint, Stack, ICalloutProps, ILinkProps } from "office-ui-fabric-react";
import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility"; import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
import Explorer from "../Explorer";
export class ResourceTreeAdapter implements ReactAdapter { export class ResourceTreeAdapter implements ReactAdapter {
private static readonly DataTitle = "DATA"; private static readonly DataTitle = "DATA";
@ -42,7 +43,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
private koSubsCollectionIdMap: ArrayHashMap<ko.Subscription>; // collection id -> ko subs private koSubsCollectionIdMap: ArrayHashMap<ko.Subscription>; // collection id -> ko subs
private databaseCollectionIdMap: ArrayHashMap<string>; // database id -> collection ids private databaseCollectionIdMap: ArrayHashMap<string>; // database id -> collection ids
public constructor(private container: ViewModels.Explorer) { public constructor(private container: Explorer) {
this.parameters = ko.observable(Date.now()); this.parameters = ko.observable(Date.now());
this.container.selectedNode.subscribe((newValue: any) => this.triggerRender()); 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 * This is a rewrite of Collection.ts : showScriptsMenu, showStoredProcedures, showTriggers, showUserDefinedFunctions
* @param container * @param container
*/ */
private static showScriptNodes(container: ViewModels.Explorer): boolean { private static showScriptNodes(container: Explorer): boolean {
return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph(); return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph();
} }

View File

@ -7,9 +7,10 @@ import ResourceTokenCollection from "./ResourceTokenCollection";
import { ResourceTreeAdapterForResourceToken } from "./ResourceTreeAdapterForResourceToken"; import { ResourceTreeAdapterForResourceToken } from "./ResourceTreeAdapterForResourceToken";
import { shallow } from "enzyme"; import { shallow } from "enzyme";
import { TreeComponent, TreeNode, TreeComponentProps } from "../Controls/TreeComponent/TreeComponent"; import { TreeComponent, TreeNode, TreeComponentProps } from "../Controls/TreeComponent/TreeComponent";
import Explorer from "../Explorer";
const createMockContainer = (): ViewModels.Explorer => { const createMockContainer = (): Explorer => {
let mockContainer = {} as ViewModels.Explorer; let mockContainer = {} as Explorer;
mockContainer.resourceTokenCollection = createMockCollection(mockContainer); mockContainer.resourceTokenCollection = createMockCollection(mockContainer);
mockContainer.selectedNode = ko.observable<ViewModels.TreeNode>(); mockContainer.selectedNode = ko.observable<ViewModels.TreeNode>();
mockContainer.mostRecentActivity = new MostRecentActivity.MostRecentActivity(mockContainer); mockContainer.mostRecentActivity = new MostRecentActivity.MostRecentActivity(mockContainer);
@ -18,7 +19,7 @@ const createMockContainer = (): ViewModels.Explorer => {
return mockContainer; return mockContainer;
}; };
const createMockCollection = (container: ViewModels.Explorer): ko.Observable<ViewModels.CollectionBase> => { const createMockCollection = (container: Explorer): ko.Observable<ViewModels.CollectionBase> => {
let mockCollection = {} as DataModels.Collection; let mockCollection = {} as DataModels.Collection;
mockCollection._rid = "fakeRid"; mockCollection._rid = "fakeRid";
mockCollection._self = "fakeSelf"; mockCollection._self = "fakeSelf";
@ -33,7 +34,7 @@ const createMockCollection = (container: ViewModels.Explorer): ko.Observable<Vie
}; };
describe("Resource tree for resource token", () => { describe("Resource tree for resource token", () => {
const mockContainer: ViewModels.Explorer = createMockContainer(); const mockContainer: Explorer = createMockContainer();
const resourceTree = new ResourceTreeAdapterForResourceToken(mockContainer); const resourceTree = new ResourceTreeAdapterForResourceToken(mockContainer);
it("should render", () => { it("should render", () => {

View File

@ -7,12 +7,13 @@ import { NotebookContentItem } from "../Notebook/NotebookContentItem";
import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler";
import { TreeComponent, TreeNode } from "../Controls/TreeComponent/TreeComponent"; import { TreeComponent, TreeNode } from "../Controls/TreeComponent/TreeComponent";
import CollectionIcon from "../../../images/tree-collection.svg"; import CollectionIcon from "../../../images/tree-collection.svg";
import Explorer from "../Explorer";
export class ResourceTreeAdapterForResourceToken implements ReactAdapter { export class ResourceTreeAdapterForResourceToken implements ReactAdapter {
public parameters: ko.Observable<number>; public parameters: ko.Observable<number>;
public myNotebooksContentRoot: NotebookContentItem; public myNotebooksContentRoot: NotebookContentItem;
public constructor(private container: ViewModels.Explorer) { public constructor(private container: Explorer) {
this.parameters = ko.observable(Date.now()); this.parameters = ko.observable(Date.now());
this.container.resourceTokenCollection.subscribe((collection: ViewModels.CollectionBase) => this.triggerRender()); this.container.resourceTokenCollection.subscribe((collection: ViewModels.CollectionBase) => this.triggerRender());

View File

@ -6,6 +6,7 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
import StoredProcedureTab from "../Tabs/StoredProcedureTab"; import StoredProcedureTab from "../Tabs/StoredProcedureTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer";
const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE
function sample(prefix) { function sample(prefix) {
@ -36,7 +37,7 @@ function sample(prefix) {
export default class StoredProcedure implements ViewModels.StoredProcedure { export default class StoredProcedure implements ViewModels.StoredProcedure {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public collection: ViewModels.Collection; public collection: ViewModels.Collection;
public self: string; public self: string;
public rid: string; public rid: string;
@ -44,7 +45,7 @@ export default class StoredProcedure implements ViewModels.StoredProcedure {
public body: ko.Observable<string>; public body: ko.Observable<string>;
public isExecuteEnabled: boolean; 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.nodeKind = "StoredProcedure";
this.container = container; this.container = container;
this.collection = collection; this.collection = collection;

View File

@ -5,10 +5,11 @@ import * as DataModels from "../../Contracts/DataModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import TriggerTab from "../Tabs/TriggerTab"; import TriggerTab from "../Tabs/TriggerTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer";
export default class Trigger implements ViewModels.Trigger { export default class Trigger implements ViewModels.Trigger {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public collection: ViewModels.Collection; public collection: ViewModels.Collection;
public self: string; public self: string;
public rid: string; public rid: string;
@ -17,7 +18,7 @@ export default class Trigger implements ViewModels.Trigger {
public triggerType: ko.Observable<string>; public triggerType: ko.Observable<string>;
public triggerOperation: ko.Observable<string>; public triggerOperation: ko.Observable<string>;
constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: any) { constructor(container: Explorer, collection: ViewModels.Collection, data: any) {
this.nodeKind = "Trigger"; this.nodeKind = "Trigger";
this.container = container; this.container = container;
this.collection = collection; this.collection = collection;

View File

@ -5,17 +5,18 @@ import * as DataModels from "../../Contracts/DataModels";
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants"; import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab"; import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab";
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import Explorer from "../Explorer";
export default class UserDefinedFunction implements ViewModels.UserDefinedFunction { export default class UserDefinedFunction implements ViewModels.UserDefinedFunction {
public nodeKind: string; public nodeKind: string;
public container: ViewModels.Explorer; public container: Explorer;
public collection: ViewModels.Collection; public collection: ViewModels.Collection;
public self: string; public self: string;
public rid: string; public rid: string;
public id: ko.Observable<string>; public id: ko.Observable<string>;
public body: ko.Observable<string>; public body: ko.Observable<string>;
constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: DataModels.UserDefinedFunction) { constructor(container: Explorer, collection: ViewModels.Collection, data: DataModels.UserDefinedFunction) {
this.nodeKind = "UserDefinedFunction"; this.nodeKind = "UserDefinedFunction";
this.container = container; this.container = container;

View File

@ -6,6 +6,7 @@ import { GitHubConnector, IGitHubConnectorParams } from "./GitHubConnector";
import { GitHubOAuthService } from "./GitHubOAuthService"; import { GitHubOAuthService } from "./GitHubOAuthService";
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import NotebookManager from "../Explorer/Notebook/NotebookManager"; import NotebookManager from "../Explorer/Notebook/NotebookManager";
import Explorer from "../Explorer/Explorer";
const sampleDatabaseAccount: ViewModels.DatabaseAccount = { const sampleDatabaseAccount: ViewModels.DatabaseAccount = {
id: "id", id: "id",
@ -25,7 +26,7 @@ const sampleDatabaseAccount: ViewModels.DatabaseAccount = {
describe("GitHubOAuthService", () => { describe("GitHubOAuthService", () => {
let junoClient: JunoClient; let junoClient: JunoClient;
let gitHubOAuthService: GitHubOAuthService; let gitHubOAuthService: GitHubOAuthService;
let originalDataExplorer: ViewModels.Explorer; let originalDataExplorer: Explorer;
beforeEach(() => { beforeEach(() => {
junoClient = new JunoClient(ko.observable<ViewModels.DatabaseAccount>(sampleDatabaseAccount)); junoClient = new JunoClient(ko.observable<ViewModels.DatabaseAccount>(sampleDatabaseAccount));
@ -35,7 +36,7 @@ describe("GitHubOAuthService", () => {
...originalDataExplorer, ...originalDataExplorer,
logConsoleData: (data): void => logConsoleData: (data): void =>
data.type === ConsoleDataType.Error ? console.error(data.message) : console.log(data.message) 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 = new NotebookManager();
window.dataExplorer.notebookManager.junoClient = junoClient; window.dataExplorer.notebookManager.junoClient = junoClient;
window.dataExplorer.notebookManager.gitHubOAuthService = gitHubOAuthService; window.dataExplorer.notebookManager.gitHubOAuthService = gitHubOAuthService;

View File

@ -74,6 +74,7 @@ import { AuthType } from "./AuthType";
import { initializeIcons } from "office-ui-fabric-react/lib/Icons"; import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
import { applyExplorerBindings } from "./applyExplorerBindings"; import { applyExplorerBindings } from "./applyExplorerBindings";
import { initializeConfiguration, Platform } from "./Config"; import { initializeConfiguration, Platform } from "./Config";
import Explorer from "./Explorer/Explorer";
initializeIcons(/* optional base url */); initializeIcons(/* optional base url */);
@ -86,13 +87,13 @@ initializeConfiguration().then(config => {
// TODO Remove. All window variables should move to src/Config file // TODO Remove. All window variables should move to src/Config file
window.dataExplorerPlatform = PlatformType.Hosted; window.dataExplorerPlatform = PlatformType.Hosted;
Hosted.initializeExplorer().then( Hosted.initializeExplorer().then(
(explorer: ViewModels.Explorer) => { (explorer: Explorer) => {
applyExplorerBindings(explorer); applyExplorerBindings(explorer);
Hosted.configureTokenValidationDisplayPrompt(explorer); Hosted.configureTokenValidationDisplayPrompt(explorer);
}, },
(error: any) => { (error: any) => {
try { try {
const uninitializedExplorer: ViewModels.Explorer = Hosted.getUninitializedExplorerForGuestAccess(); const uninitializedExplorer: Explorer = Hosted.getUninitializedExplorerForGuestAccess();
window.dataExplorer = uninitializedExplorer; window.dataExplorer = uninitializedExplorer;
ko.applyBindings(uninitializedExplorer); ko.applyBindings(uninitializedExplorer);
BindingHandlersRegisterer.registerBindingHandlers(); BindingHandlersRegisterer.registerBindingHandlers();

View File

@ -1,4 +1,3 @@
import * as ViewModels from "../../Contracts/ViewModels";
import { AccountKind, TagNames, DefaultAccountExperience } from "../../Common/Constants"; import { AccountKind, TagNames, DefaultAccountExperience } from "../../Common/Constants";
import Explorer from "../../Explorer/Explorer"; import Explorer from "../../Explorer/Explorer";
@ -8,7 +7,7 @@ import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import { DataAccessUtility } from "./DataAccessUtility"; import { DataAccessUtility } from "./DataAccessUtility";
export default class EmulatorExplorerFactory { export default class EmulatorExplorerFactory {
public static createExplorer(): ViewModels.Explorer { public static createExplorer(): Explorer {
DocumentClientUtilityBase; DocumentClientUtilityBase;
const documentClientUtility: DocumentClientUtilityBase = new DocumentClientUtilityBase(new DataAccessUtility()); const documentClientUtility: DocumentClientUtilityBase = new DocumentClientUtilityBase(new DataAccessUtility());

View File

@ -1,7 +1,6 @@
import * as ViewModels from "../../Contracts/ViewModels";
import EmulatorExplorerFactory from "./ExplorerFactory"; import EmulatorExplorerFactory from "./ExplorerFactory";
import Explorer from "../../Explorer/Explorer";
export function initializeExplorer(): ViewModels.Explorer { export function initializeExplorer(): Explorer {
const explorer = EmulatorExplorerFactory.createExplorer(); return EmulatorExplorerFactory.createExplorer();
return explorer;
} }

View File

@ -90,7 +90,7 @@ export default class AuthHeadersUtil {
const url: string = `${ const url: string = `${
AuthHeadersUtil.extensionEndpoint AuthHeadersUtil.extensionEndpoint
}/api/tokens/generateToken${AuthHeadersUtil._generateResourceUrl()}`; }/api/tokens/generateToken${AuthHeadersUtil._generateResourceUrl()}`;
const explorer: ViewModels.Explorer = (<any>window).dataExplorer; const explorer = window.dataExplorer;
const headers: any = { authorization: CosmosClient.authorizationToken() }; const headers: any = { authorization: CosmosClient.authorizationToken() };
headers[Constants.HttpHeaders.getReadOnlyKey] = !explorer.hasWriteAccess(); headers[Constants.HttpHeaders.getReadOnlyKey] = !explorer.hasWriteAccess();

View File

@ -5,7 +5,7 @@ import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import { DataAccessUtility } from "./DataAccessUtility"; import { DataAccessUtility } from "./DataAccessUtility";
export default class HostedExplorerFactory { export default class HostedExplorerFactory {
public createExplorer(): ViewModels.Explorer { public createExplorer(): Explorer {
var documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility()); var documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility());
const explorer = new Explorer({ const explorer = new Explorer({
@ -17,7 +17,7 @@ export default class HostedExplorerFactory {
return explorer; return explorer;
} }
public static reInitializeDocumentClientUtilityForExplorer(explorer: ViewModels.Explorer): void { public static reInitializeDocumentClientUtilityForExplorer(explorer: Explorer): void {
if (!!explorer) { if (!!explorer) {
const documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility()); const documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility());
explorer.rebindDocumentClientUtility(documentClientUtility); explorer.rebindDocumentClientUtility(documentClientUtility);

View File

@ -23,6 +23,7 @@ import { MessageTypes } from "../../Contracts/ExplorerContracts";
import { SessionStorageUtility, StorageKey } from "../../Shared/StorageUtility"; import { SessionStorageUtility, StorageKey } from "../../Shared/StorageUtility";
import { SubscriptionUtilMappings } from "../../Shared/Constants"; import { SubscriptionUtilMappings } from "../../Shared/Constants";
import "../../Explorer/Tables/DataTable/DataTableBindingManager"; import "../../Explorer/Tables/DataTable/DataTableBindingManager";
import Explorer from "../../Explorer/Explorer";
export default class Main { export default class Main {
private static _databaseAccountId: string; private static _databaseAccountId: string;
@ -32,8 +33,8 @@ export default class Main {
private static _features: { [key: string]: string }; private static _features: { [key: string]: string };
// For AAD, Need to post message to hosted frame to do the auth // 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 // Use local deferred variable as work around until we find better solution
private static _getAadAccessDeferred: Q.Deferred<ViewModels.Explorer>; private static _getAadAccessDeferred: Q.Deferred<Explorer>;
private static _explorer: ViewModels.Explorer; private static _explorer: Explorer;
public static isUsingEncryptionToken(): boolean { public static isUsingEncryptionToken(): boolean {
const params = new URLSearchParams(window.parent.location.search); const params = new URLSearchParams(window.parent.location.search);
@ -43,11 +44,11 @@ export default class Main {
return false; return false;
} }
public static initializeExplorer(): Q.Promise<ViewModels.Explorer> { public static initializeExplorer(): Q.Promise<Explorer> {
window.addEventListener("message", this._handleMessage.bind(this), false); window.addEventListener("message", this._handleMessage.bind(this), false);
this._features = {}; this._features = {};
const params = new URLSearchParams(window.parent.location.search); const params = new URLSearchParams(window.parent.location.search);
const deferred: Q.Deferred<ViewModels.Explorer> = Q.defer<ViewModels.Explorer>(); const deferred: Q.Deferred<Explorer> = Q.defer<Explorer>();
let authType: string = null; let authType: string = null;
// Encrypted token flow // Encrypted token flow
@ -74,7 +75,7 @@ export default class Main {
return Q.reject("Sign in needed"); return Q.reject("Sign in needed");
} }
const explorer: ViewModels.Explorer = this._instantiateExplorer(); const explorer: Explorer = this._instantiateExplorer();
if (authType === AuthType.EncryptedToken) { if (authType === AuthType.EncryptedToken) {
MessageHandler.sendMessage({ MessageHandler.sendMessage({
type: MessageTypes.UpdateAccountSwitch, type: MessageTypes.UpdateAccountSwitch,
@ -109,7 +110,7 @@ export default class Main {
return Q(null); return Q(null);
} }
this._explorer = explorer; this._explorer = explorer;
this._getAadAccessDeferred = Q.defer<ViewModels.Explorer>(); this._getAadAccessDeferred = Q.defer<Explorer>();
return this._getAadAccessDeferred.promise.finally(() => { return this._getAadAccessDeferred.promise.finally(() => {
this._getAadAccessDeferred = null; this._getAadAccessDeferred = null;
}); });
@ -135,7 +136,7 @@ export default class Main {
return features; return features;
} }
public static configureTokenValidationDisplayPrompt(explorer: ViewModels.Explorer): void { public static configureTokenValidationDisplayPrompt(explorer: Explorer): void {
const authType: AuthType = (<any>window).authType; const authType: AuthType = (<any>window).authType;
if ( if (
!explorer || !explorer ||
@ -182,7 +183,7 @@ export default class Main {
}; };
} }
public static renewExplorerAccess = (explorer: ViewModels.Explorer, connectionString: string): Q.Promise<void> => { public static renewExplorerAccess = (explorer: Explorer, connectionString: string): Q.Promise<void> => {
if (!connectionString) { if (!connectionString) {
console.error("Missing or invalid connection string input"); console.error("Missing or invalid connection string input");
Q.reject("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); return deferred.promise.timeout(Constants.ClientDefaults.requestTimeoutMs);
}; };
public static getUninitializedExplorerForGuestAccess(): ViewModels.Explorer { public static getUninitializedExplorerForGuestAccess(): Explorer {
const explorer = Main._instantiateExplorer(); const explorer = Main._instantiateExplorer();
if (window.authType === AuthType.AAD) { if (window.authType === AuthType.AAD) {
this._explorer = explorer; this._explorer = explorer;
@ -260,7 +261,7 @@ export default class Main {
} }
private static _initDataExplorerFrameInputs( private static _initDataExplorerFrameInputs(
explorer: ViewModels.Explorer, explorer: Explorer,
masterKey?: string /* master key extracted from connection string if available */, masterKey?: string /* master key extracted from connection string if available */,
account?: DatabaseAccount, account?: DatabaseAccount,
authorizationToken?: string /* access key */ authorizationToken?: string /* access key */
@ -372,7 +373,7 @@ export default class Main {
return Q.reject(`Unsupported AuthType ${authType}`); return Q.reject(`Unsupported AuthType ${authType}`);
} }
private static _instantiateExplorer(): ViewModels.Explorer { private static _instantiateExplorer(): Explorer {
const hostedExplorerFactory = new HostedExplorerFactory(); const hostedExplorerFactory = new HostedExplorerFactory();
const explorer = hostedExplorerFactory.createExplorer(); const explorer = hostedExplorerFactory.createExplorer();
// workaround to resolve cyclic refs with view // workaround to resolve cyclic refs with view
@ -395,7 +396,7 @@ export default class Main {
return explorer; return explorer;
} }
private static _showGuestAccessTokenRenewalPromptInMs(explorer: ViewModels.Explorer, interval: number): void { private static _showGuestAccessTokenRenewalPromptInMs(explorer: Explorer, interval: number): void {
if (interval != null && !isNaN(interval)) { if (interval != null && !isNaN(interval)) {
setTimeout(() => { setTimeout(() => {
explorer.displayGuestAccessTokenRenewalPrompt(); explorer.displayGuestAccessTokenRenewalPrompt();
@ -454,7 +455,7 @@ export default class Main {
} }
private static _renewExplorerAccessWithResourceToken = ( private static _renewExplorerAccessWithResourceToken = (
explorer: ViewModels.Explorer, explorer: Explorer,
connectionString: string connectionString: string
): Q.Promise<void> => { ): Q.Promise<void> => {
window.authType = AuthType.ResourceToken; window.authType = AuthType.ResourceToken;
@ -506,7 +507,7 @@ export default class Main {
}; };
private static _setExplorerReady( private static _setExplorerReady(
explorer: ViewModels.Explorer, explorer: Explorer,
masterKey?: string, masterKey?: string,
account?: DatabaseAccount, account?: DatabaseAccount,
authorizationToken?: string authorizationToken?: string

View File

@ -70,7 +70,7 @@ export class DataAccessUtility extends DataAccessUtilityBase {
options: any options: any
): Q.Promise<void> { ): Q.Promise<void> {
const deferred: Q.Deferred<void> = Q.defer<void>(); const deferred: Q.Deferred<void> = Q.defer<void>();
const explorer: ViewModels.Explorer = (<any>window).dataExplorer; const explorer = window.dataExplorer;
const url: string = `${explorer.extensionEndpoint()}/api/offerthroughputrequest/updatebeyondspecifiedlimit`; const url: string = `${explorer.extensionEndpoint()}/api/offerthroughputrequest/updatebeyondspecifiedlimit`;
const authorizationHeader: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader(); const authorizationHeader: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader();
const requestOptions: any = _.extend({}, options, {}); const requestOptions: any = _.extend({}, options, {});

View File

@ -6,7 +6,7 @@ import DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import { DataAccessUtility } from "./DataAccessUtility"; import { DataAccessUtility } from "./DataAccessUtility";
export default class PortalExplorerFactory { export default class PortalExplorerFactory {
public createExplorer(): ViewModels.Explorer { public createExplorer(): Explorer {
var documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility()); var documentClientUtility = new DocumentClientUtilityBase(new DataAccessUtility());
var explorer = new Explorer({ var explorer = new Explorer({

View File

@ -1,8 +1,8 @@
import * as ViewModels from "../../Contracts/ViewModels";
import PortalExplorerFactory from "./ExplorerFactory"; import PortalExplorerFactory from "./ExplorerFactory";
import "../../Explorer/Tables/DataTable/DataTableBindingManager"; import "../../Explorer/Tables/DataTable/DataTableBindingManager";
import Explorer from "../../Explorer/Explorer";
export function initializeExplorer(): ViewModels.Explorer { export function initializeExplorer(): Explorer {
const portalExplorerFactory = new PortalExplorerFactory(); const portalExplorerFactory = new PortalExplorerFactory();
const explorer = portalExplorerFactory.createExplorer(); const explorer = portalExplorerFactory.createExplorer();

View File

@ -183,7 +183,6 @@ export class TabRouteHandler {
private _openQueryTabForResource(databaseId: string, collectionId: string): void { private _openQueryTabForResource(databaseId: string, collectionId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer;
const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource(
databaseId, databaseId,
collectionId collectionId
@ -203,7 +202,6 @@ export class TabRouteHandler {
private _openMongoQueryTabForResource(databaseId: string, collectionId: string): void { private _openMongoQueryTabForResource(databaseId: string, collectionId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer;
const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource(
databaseId, databaseId,
collectionId collectionId
@ -226,7 +224,6 @@ export class TabRouteHandler {
private _openMongoShellTabForResource(databaseId: string, collectionId: string): void { private _openMongoShellTabForResource(databaseId: string, collectionId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer;
const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource(
databaseId, databaseId,
collectionId collectionId
@ -249,7 +246,7 @@ export class TabRouteHandler {
private _openDatabaseSettingsTabForResource(databaseId: string): void { private _openDatabaseSettingsTabForResource(databaseId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer; const explorer = window.dataExplorer;
const database: ViewModels.Database = _.find( const database: ViewModels.Database = _.find(
explorer.databases(), explorer.databases(),
(database: ViewModels.Database) => database.id() === databaseId (database: ViewModels.Database) => database.id() === databaseId
@ -270,7 +267,6 @@ export class TabRouteHandler {
private _openNewSprocTabForResource(databaseId: string, collectionId: string): void { private _openNewSprocTabForResource(databaseId: string, collectionId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer;
const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource(
databaseId, databaseId,
collectionId collectionId
@ -303,7 +299,6 @@ export class TabRouteHandler {
private _openNewTriggerTabForResource(databaseId: string, collectionId: string): void { private _openNewTriggerTabForResource(databaseId: string, collectionId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer;
const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource(
databaseId, databaseId,
collectionId collectionId
@ -335,7 +330,6 @@ export class TabRouteHandler {
private _openNewUserDefinedFunctionTabForResource(databaseId: string, collectionId: string): void { private _openNewUserDefinedFunctionTabForResource(databaseId: string, collectionId: string): void {
this._executeActionHelper(() => { this._executeActionHelper(() => {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer;
const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource( const collection: ViewModels.Collection = this._findAndExpandMatchingCollectionForResource(
databaseId, databaseId,
collectionId collectionId
@ -389,7 +383,7 @@ export class TabRouteHandler {
tabKind: ViewModels.CollectionTabKind, tabKind: ViewModels.CollectionTabKind,
isNewScriptTab?: boolean isNewScriptTab?: boolean
): ViewModels.Tab { ): ViewModels.Tab {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer; const explorer = window.dataExplorer;
const matchingTabs: ViewModels.Tab[] = explorer.tabsManager.getTabs( const matchingTabs: ViewModels.Tab[] = explorer.tabsManager.getTabs(
tabKind, tabKind,
(tab: ViewModels.Tab) => (tab: ViewModels.Tab) =>
@ -402,7 +396,7 @@ export class TabRouteHandler {
} }
private _findMatchingCollectionForResource(databaseId: string, collectionId: string): ViewModels.Collection { private _findMatchingCollectionForResource(databaseId: string, collectionId: string): ViewModels.Collection {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer; const explorer = window.dataExplorer;
const matchedDatabase: ViewModels.Database = explorer.findDatabaseWithId(databaseId); const matchedDatabase: ViewModels.Database = explorer.findDatabaseWithId(databaseId);
const matchedCollection: ViewModels.Collection = const matchedCollection: ViewModels.Collection =
matchedDatabase && matchedDatabase.findCollectionWithId(collectionId); matchedDatabase && matchedDatabase.findCollectionWithId(collectionId);
@ -411,7 +405,7 @@ export class TabRouteHandler {
} }
private _executeActionHelper(action: () => void): void { private _executeActionHelper(action: () => void): void {
const explorer: ViewModels.Explorer = (<any>window).dataExplorer; const explorer = window.dataExplorer;
if (!!explorer && (explorer.isRefreshingExplorer() || !explorer.isAccountReady())) { if (!!explorer && (explorer.isRefreshingExplorer() || !explorer.isAccountReady())) {
const refreshSubscription = explorer.isRefreshingExplorer.subscribe((isRefreshing: boolean) => { const refreshSubscription = explorer.isRefreshingExplorer.subscribe((isRefreshing: boolean) => {
if (!isRefreshing) { if (!isRefreshing) {

View File

@ -11,6 +11,7 @@ import { MessageHandler } from "../Common/MessageHandler";
import { MessageTypes } from "../Contracts/ExplorerContracts"; import { MessageTypes } from "../Contracts/ExplorerContracts";
import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils"; import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils";
import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient"; import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient";
import Explorer from "../Explorer/Explorer";
export class CreateSqlCollectionUtilities { export class CreateSqlCollectionUtilities {
public static createSqlCollection( public static createSqlCollection(
@ -276,10 +277,7 @@ export class Utilities {
return defaults.throughput.unlimitedmin; return defaults.throughput.unlimitedmin;
} }
public static getMaxThroughput( public static getMaxThroughput(defaults: ViewModels.CollectionCreationDefaults, container: Explorer): number {
defaults: ViewModels.CollectionCreationDefaults,
container: ViewModels.Explorer
): number {
const throughput = defaults.throughput.unlimited; const throughput = defaults.throughput.unlimited;
if (typeof throughput === "number") { if (typeof throughput === "number") {
return throughput; 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()) || []; const databases = (container && container.databases && container.databases()) || [];
return _.any( return _.any(
databases, databases,

View File

@ -57,8 +57,8 @@ export function decryptJWTToken(token: string) {
} }
export function displayTokenRenewalPromptForStatus(httpStatusCode: number): void { export function displayTokenRenewalPromptForStatus(httpStatusCode: number): void {
const platformType: PlatformType = window.dataExplorerPlatform; const platformType = window.dataExplorerPlatform;
const explorer: ViewModels.Explorer = window.dataExplorer; const explorer = window.dataExplorer;
if ( if (
httpStatusCode == null || httpStatusCode == null ||

View File

@ -1,8 +1,8 @@
import * as GalleryUtils from "./GalleryUtils"; import * as GalleryUtils from "./GalleryUtils";
import { JunoClient, IGalleryItem } from "../Juno/JunoClient"; import { JunoClient, IGalleryItem } from "../Juno/JunoClient";
import { ExplorerStub } from "../Explorer/OpenActionsStubs";
import { HttpStatusCodes } from "../Common/Constants"; import { HttpStatusCodes } from "../Common/Constants";
import { GalleryTab, SortBy } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent"; import { GalleryTab, SortBy } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent";
import Explorer from "../Explorer/Explorer";
const galleryItem: IGalleryItem = { const galleryItem: IGalleryItem = {
id: "id", id: "id",
@ -25,7 +25,7 @@ describe("GalleryUtils", () => {
}); });
it("downloadItem shows dialog in data explorer", () => { it("downloadItem shows dialog in data explorer", () => {
const container = new ExplorerStub(); const container = {} as Explorer;
container.showOkCancelModalDialog = jest.fn().mockImplementation(); container.showOkCancelModalDialog = jest.fn().mockImplementation();
GalleryUtils.downloadItem(container, undefined, galleryItem, undefined); GalleryUtils.downloadItem(container, undefined, galleryItem, undefined);
@ -34,7 +34,7 @@ describe("GalleryUtils", () => {
}); });
it("favoriteItem favorites item", async () => { it("favoriteItem favorites item", async () => {
const container = new ExplorerStub(); const container = {} as Explorer;
const junoClient = new JunoClient(); const junoClient = new JunoClient();
junoClient.favoriteNotebook = jest junoClient.favoriteNotebook = jest
.fn() .fn()
@ -48,7 +48,7 @@ describe("GalleryUtils", () => {
}); });
it("unfavoriteItem unfavorites item", async () => { it("unfavoriteItem unfavorites item", async () => {
const container = new ExplorerStub(); const container = {} as Explorer;
const junoClient = new JunoClient(); const junoClient = new JunoClient();
junoClient.unfavoriteNotebook = jest junoClient.unfavoriteNotebook = jest
.fn() .fn()
@ -62,7 +62,7 @@ describe("GalleryUtils", () => {
}); });
it("deleteItem shows dialog in data explorer", () => { it("deleteItem shows dialog in data explorer", () => {
const container = new ExplorerStub(); const container = {} as Explorer;
container.showOkCancelModalDialog = jest.fn().mockImplementation(); container.showOkCancelModalDialog = jest.fn().mockImplementation();
GalleryUtils.deleteItem(container, undefined, galleryItem, undefined); GalleryUtils.deleteItem(container, undefined, galleryItem, undefined);

View File

@ -1,5 +1,4 @@
import { IGalleryItem, JunoClient } from "../Juno/JunoClient"; import { IGalleryItem, JunoClient } from "../Juno/JunoClient";
import * as ViewModels from "../Contracts/ViewModels";
import { NotificationConsoleUtils } from "./NotificationConsoleUtils"; import { NotificationConsoleUtils } from "./NotificationConsoleUtils";
import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import * as Logger from "../Common/Logger"; import * as Logger from "../Common/Logger";
@ -8,6 +7,7 @@ import {
SortBy, SortBy,
GalleryViewerComponent GalleryViewerComponent
} from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent"; } from "../Explorer/Controls/NotebookGallery/GalleryViewerComponent";
import Explorer from "../Explorer/Explorer";
export enum NotebookViewerParams { export enum NotebookViewerParams {
NotebookUrl = "notebookUrl", NotebookUrl = "notebookUrl",
@ -34,7 +34,7 @@ export interface GalleryViewerProps {
} }
export function downloadItem( export function downloadItem(
container: ViewModels.Explorer, container: Explorer,
junoClient: JunoClient, junoClient: JunoClient,
data: IGalleryItem, data: IGalleryItem,
onComplete: (item: IGalleryItem) => void onComplete: (item: IGalleryItem) => void
@ -80,7 +80,7 @@ export function downloadItem(
} }
export async function favoriteItem( export async function favoriteItem(
container: ViewModels.Explorer, container: Explorer,
junoClient: JunoClient, junoClient: JunoClient,
data: IGalleryItem, data: IGalleryItem,
onComplete: (item: IGalleryItem) => void onComplete: (item: IGalleryItem) => void
@ -102,7 +102,7 @@ export async function favoriteItem(
} }
export async function unfavoriteItem( export async function unfavoriteItem(
container: ViewModels.Explorer, container: Explorer,
junoClient: JunoClient, junoClient: JunoClient,
data: IGalleryItem, data: IGalleryItem,
onComplete: (item: IGalleryItem) => void onComplete: (item: IGalleryItem) => void
@ -124,7 +124,7 @@ export async function unfavoriteItem(
} }
export function deleteItem( export function deleteItem(
container: ViewModels.Explorer, container: Explorer,
junoClient: JunoClient, junoClient: JunoClient,
data: IGalleryItem, data: IGalleryItem,
onComplete: (item: IGalleryItem) => void onComplete: (item: IGalleryItem) => void

View File

@ -1,5 +1,5 @@
import * as DataModels from "../Contracts/DataModels"; import * as DataModels from "../Contracts/DataModels";
import { Explorer, KernelConnectionMetadata } from "../Contracts/ViewModels"; import { KernelConnectionMetadata } from "../Contracts/ViewModels";
import * as Logger from "../Common/Logger"; import * as Logger from "../Common/Logger";
export class NotebookConfigurationUtils { export class NotebookConfigurationUtils {
@ -27,7 +27,7 @@ export class NotebookConfigurationUtils {
return Promise.reject("Invalid or missing cluster connection info"); 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( const notebookEndpointInfo: DataModels.NotebookConfigurationEndpointInfo[] = clusterConnectionInfo.endpoints.map(
clusterEndpoint => ({ clusterEndpoint => ({
type: clusterEndpoint.kind.toLowerCase(), type: clusterEndpoint.kind.toLowerCase(),

View File

@ -1,7 +1,7 @@
import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer"; import { BindingHandlersRegisterer } from "./Bindings/BindingHandlersRegisterer";
import { MessageHandler } from "./Common/MessageHandler"; import { MessageHandler } from "./Common/MessageHandler";
import * as ko from "knockout"; import * as ko from "knockout";
import { Explorer } from "./Contracts/ViewModels"; import Explorer from "./Explorer/Explorer";
export const applyExplorerBindings = (explorer: Explorer) => { export const applyExplorerBindings = (explorer: Explorer) => {
if (!!explorer) { if (!!explorer) {

2
src/global.d.ts vendored
View File

@ -1,6 +1,6 @@
import { AuthType } from "./AuthType"; import { AuthType } from "./AuthType";
import { PlatformType } from "./PlatformType"; import { PlatformType } from "./PlatformType";
import { Explorer } from "./Contracts/ViewModels"; import Explorer from "./Explorer/Explorer";
declare global { declare global {
interface Window { interface Window {