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
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:

View File

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

View File

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

View File

@ -6,27 +6,17 @@ import Q from "q";
import QueryViewModel from "../Explorer/Tables/QueryBuilder/QueryViewModel";
import TableEntityListViewModel from "../Explorer/Tables/DataTable/TableEntityListViewModel";
import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList";
import { ArcadiaWorkspaceItem } from "../Explorer/Controls/Arcadia/ArcadiaMenuPicker";
import { CassandraTableKey, CassandraTableKeys, TableDataClient } from "../Explorer/Tables/TableDataClient";
import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient";
import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent";
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import { ExecuteSprocParam } from "../Explorer/Panes/ExecuteSprocParamsPane";
import { GitHubClient } from "../GitHub/GitHubClient";
import { IColumnSetting } from "../Explorer/Panes/Tables/TableColumnOptionsPane";
import { JunoClient, IGalleryItem } from "../Juno/JunoClient";
import { Library } from "./DataModels";
import { MostRecentActivity } from "../Explorer/MostRecentActivity/MostRecentActivity";
import { NotebookContentItem } from "../Explorer/Notebook/NotebookContentItem";
import { PlatformType } from "../PlatformType";
import { QueryMetrics } from "@azure/cosmos";
import { SetupNotebooksPane } from "../Explorer/Panes/SetupNotebooksPane";
import { Splitter } from "../Common/Splitter";
import { StringInputPane } from "../Explorer/Panes/StringInputPane";
import { TabsManager } from "../Explorer/Tabs/TabsManager";
import { TextFieldProps } from "../Explorer/Controls/DialogReactComponent/DialogComponent";
import { UploadDetails } from "../workers/upload/definitions";
import { UploadItemsPaneAdapter } from "../Explorer/Panes/UploadItemsPaneAdapter";
import { ReactAdapter } from "../Bindings/ReactBindingHandler";
import Explorer from "../Explorer/Explorer";
export interface ExplorerOptions {
documentClientUtility: DocumentClientUtilityBase;
@ -42,213 +32,6 @@ export interface NavbarButtonConfig extends CommandButtonComponentProps {}
export interface DatabaseAccount extends DataModels.DatabaseAccount {}
export interface Explorer {
flight: ko.Observable<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 {
getNotebookWorkspacesAsync(cosmosAccountResourceId: string): Promise<DataModels.NotebookWorkspace[]>;
getNotebookWorkspaceAsync(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -8,11 +8,12 @@ import * as React from "react";
import * as ViewModels from "../../../Contracts/ViewModels";
import { QueriesGridComponent, QueriesGridComponentProps } from "./QueriesGridComponent";
import { ReactAdapter } from "../../../Bindings/ReactBindingHandler";
import Explorer from "../../Explorer";
export class QueriesGridComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>;
constructor(private container: ViewModels.Explorer) {
constructor(private container: Explorer) {
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 DocumentClientUtilityBase from "../../Common/DocumentClientUtilityBase";
import Q from "q";
import { CollectionStub, DatabaseStub, ExplorerStub } from "../OpenActionsStubs";
import { CollectionStub, DatabaseStub } from "../OpenActionsStubs";
import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
import { CosmosClient } from "../../Common/CosmosClient";
import { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
import Explorer from "../Explorer";
describe("ContainerSampleGenerator", () => {
const createExplorerStub = (database: ViewModels.Database): ExplorerStub => {
const explorerStub = new ExplorerStub();
const createExplorerStub = (database: ViewModels.Database): Explorer => {
const explorerStub = {} as Explorer;
explorerStub.nonSystemDatabases = ko.computed(() => [database]);
explorerStub.isPreferredApiGraph = ko.computed<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 { GremlinClient } from "../Graph/GraphExplorerComponent/GremlinClient";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import Explorer from "../Explorer";
interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
data: any[];
@ -14,12 +15,12 @@ interface SampleDataFile extends DataModels.CreateDatabaseAndCollectionRequest {
export class ContainerSampleGenerator {
private sampleDataFile: SampleDataFile;
private constructor(private container: ViewModels.Explorer) {}
private constructor(private container: Explorer) {}
/**
* Factory function to load the json data file
*/
public static async createSampleGeneratorAsync(container: ViewModels.Explorer): Promise<ContainerSampleGenerator> {
public static async createSampleGeneratorAsync(container: Explorer): Promise<ContainerSampleGenerator> {
const generator = new ContainerSampleGenerator(container);
let dataFileContent: any;
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 * as sinon from "sinon";
import { ContainerSampleGenerator } from "./ContainerSampleGenerator";
import * as ko from "knockout";
import Explorer from "../Explorer";
describe("DataSampleUtils", () => {
const sampleCollectionId = "sampleCollectionId";
@ -14,7 +15,7 @@ describe("DataSampleUtils", () => {
id: ko.observable(sampleDatabaseId),
collections: ko.observableArray([collection])
});
const explorer = new ExplorerStub();
const explorer = {} as Explorer;
explorer.nonSystemDatabases = ko.computed(() => [database]);
explorer.showOkModalDialog = () => {};
const dataSamplesUtil = new DataSamplesUtil(explorer);

View File

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

View File

@ -89,7 +89,7 @@ enum ShareAccessToggleState {
Read
}
export default class Explorer implements ViewModels.Explorer {
export default class Explorer {
public flight: ko.Observable<string> = ko.observable<string>(
SharedConstants.CollectionCreation.DefaultAddCollectionDefaultFlight
);
@ -200,7 +200,7 @@ export default class Explorer implements ViewModels.Explorer {
public shouldShowShareDialogContents: ko.Observable<boolean>;
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 tokenForRenewal: ko.Observable<string>;
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 { StyleConstants } from "../../../Common/Constants";
import { CommandBarUtil } from "./CommandBarUtil";
import Explorer from "../../Explorer";
export class CommandBarComponentAdapter implements ReactAdapter {
public parameters: ko.Observable<number>;
public container: ViewModels.Explorer;
public container: Explorer;
private tabsButtons: ViewModels.NavbarButtonConfig[];
private isNotebookTabActive: ko.Computed<boolean>;
constructor(container: ViewModels.Explorer) {
constructor(container: Explorer) {
this.container = container;
this.tabsButtons = [];
this.isNotebookTabActive = ko.computed(() =>

View File

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

View File

@ -25,11 +25,12 @@ import ResetWorkspaceIcon from "../../../../images/notebook/Notebook-reset-works
import GitHubIcon from "../../../../images/github.svg";
import SynapseIcon from "../../../../images/synapse-link.svg";
import { config, Platform } from "../../../Config";
import Explorer from "../../Explorer";
export class CommandBarComponentButtonFactory {
private static counter: number = 0;
public static createStaticCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] {
public static createStaticCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
if (container.isAuthWithResourceToken()) {
return CommandBarComponentButtonFactory.createStaticCommandBarButtonsForResourceToken(container);
}
@ -132,7 +133,7 @@ export class CommandBarComponentButtonFactory {
return buttons;
}
public static createContextCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] {
public static createContextCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
const buttons: ViewModels.NavbarButtonConfig[] = [];
if (!container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()) {
@ -155,7 +156,7 @@ export class CommandBarComponentButtonFactory {
return buttons;
}
public static createControlCommandBarButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] {
public static createControlCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
const buttons: ViewModels.NavbarButtonConfig[] = [];
if (window.dataExplorerPlatform === PlatformType.Hosted) {
return buttons;
@ -223,11 +224,11 @@ export class CommandBarComponentButtonFactory {
};
}
private static areScriptsSupported(container: ViewModels.Explorer): boolean {
private static areScriptsSupported(container: Explorer): boolean {
return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph();
}
private static createNewCollectionGroup(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createNewCollectionGroup(container: Explorer): ViewModels.NavbarButtonConfig {
const label = container.addCollectionText();
return {
iconSrc: AddCollectionIcon,
@ -240,7 +241,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createOpenSynapseLinkDialogButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createOpenSynapseLinkDialogButton(container: Explorer): ViewModels.NavbarButtonConfig {
if (config.platform === Platform.Emulator) {
return null;
}
@ -275,7 +276,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createNewDatabase(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createNewDatabase(container: Explorer): ViewModels.NavbarButtonConfig {
const label = container.addDatabaseText();
return {
iconSrc: AddDatabaseIcon,
@ -290,7 +291,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createNewSQLQueryButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createNewSQLQueryButton(container: Explorer): ViewModels.NavbarButtonConfig {
if (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph()) {
const label = "New SQL Query";
return {
@ -324,7 +325,7 @@ export class CommandBarComponentButtonFactory {
return null;
}
public static createScriptCommandButtons(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig[] {
public static createScriptCommandButtons(container: Explorer): ViewModels.NavbarButtonConfig[] {
const buttons: ViewModels.NavbarButtonConfig[] = [];
const shouldEnableScriptsCommands: boolean =
@ -384,7 +385,7 @@ export class CommandBarComponentButtonFactory {
return buttons;
}
private static createScaleAndSettingsButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createScaleAndSettingsButton(container: Explorer): ViewModels.NavbarButtonConfig {
let isShared = false;
if (container.isDatabaseNodeSelected()) {
isShared = container.findSelectedDatabase().isDatabaseShared();
@ -409,7 +410,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createNewNotebookButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createNewNotebookButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "New Notebook";
return {
iconSrc: NewNotebookIcon,
@ -422,7 +423,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createuploadNotebookButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createuploadNotebookButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Upload to Notebook Server";
return {
iconSrc: NewNotebookIcon,
@ -435,7 +436,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createOpenQueryButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createOpenQueryButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Open Query";
return {
iconSrc: BrowseQueriesIcon,
@ -448,7 +449,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createOpenQueryFromDiskButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createOpenQueryFromDiskButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Open Query From Disk";
return {
iconSrc: OpenQueryFromDiskIcon,
@ -461,7 +462,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createEnableNotebooksButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createEnableNotebooksButton(container: Explorer): ViewModels.NavbarButtonConfig {
if (config.platform === Platform.Emulator) {
return null;
}
@ -482,7 +483,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createOpenTerminalButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createOpenTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Open Terminal";
return {
iconSrc: CosmosTerminalIcon,
@ -495,7 +496,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createOpenMongoTerminalButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createOpenMongoTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Open Mongo Shell";
const tooltip =
"This feature is not yet available in your account's region. View supported regions here: https://aka.ms/cosmos-enable-notebooks.";
@ -521,7 +522,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createOpenCassandraTerminalButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createOpenCassandraTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Open Cassandra Shell";
const tooltip =
"This feature is not yet available in your account's region. View supported regions here: https://aka.ms/cosmos-enable-notebooks.";
@ -547,7 +548,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createNotebookWorkspaceResetButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createNotebookWorkspaceResetButton(container: Explorer): ViewModels.NavbarButtonConfig {
const label = "Reset Workspace";
return {
iconSrc: ResetWorkspaceIcon,
@ -560,7 +561,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createManageGitHubAccountButton(container: ViewModels.Explorer): ViewModels.NavbarButtonConfig {
private static createManageGitHubAccountButton(container: Explorer): ViewModels.NavbarButtonConfig {
let connectedToGitHub: boolean = container.notebookManager?.gitHubOAuthService.isLoggedIn();
const label = connectedToGitHub ? "Manage GitHub settings" : "Connect to GitHub";
return {
@ -583,9 +584,7 @@ export class CommandBarComponentButtonFactory {
};
}
private static createStaticCommandBarButtonsForResourceToken(
container: ViewModels.Explorer
): ViewModels.NavbarButtonConfig[] {
private static createStaticCommandBarButtonsForResourceToken(container: Explorer): ViewModels.NavbarButtonConfig[] {
const newSqlQueryBtn = CommandBarComponentButtonFactory.createNewSQLQueryButton(container);
const openQueryBtn = CommandBarComponentButtonFactory.createOpenQueryButton(container);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,425 +3,13 @@ import * as ko from "knockout";
import * as ViewModels from "../../src/Contracts/ViewModels";
import DocumentClientUtilityBase from "../Common/DocumentClientUtilityBase";
import Q from "q";
import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker";
import { CassandraTableKey, CassandraTableKeys, TableDataClient } from "../../src/Explorer/Tables/TableDataClient";
import { ConsoleData } from "../../src/Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
import { MostRecentActivity } from "./MostRecentActivity/MostRecentActivity";
import { NotebookContentItem } from "./Notebook/NotebookContentItem";
import { PlatformType } from "../../src/PlatformType";
import { QuerySelectPane } from "../../src/Explorer/Panes/Tables/QuerySelectPane";
import { SetupNotebooksPane } from "./Panes/SetupNotebooksPane";
import { Splitter } from "../../src/Common/Splitter";
import { StringInputPane } from "./Panes/StringInputPane";
import { TableColumnOptionsPane } from "../../src/Explorer/Panes/Tables/TableColumnOptionsPane";
import { TextFieldProps } from "./Controls/DialogReactComponent/DialogComponent";
import { CassandraTableKey, CassandraTableKeys } from "../../src/Explorer/Tables/TableDataClient";
import { UploadDetails } from "../workers/upload/definitions";
import { UploadFilePane } from "./Panes/UploadFilePane";
import { UploadItemsPaneAdapter } from "./Panes/UploadItemsPaneAdapter";
import { Versions } from "../../src/Contracts/ExplorerContracts";
import { CollectionCreationDefaults } from "../Shared/Constants";
import { IGalleryItem } from "../Juno/JunoClient";
import { ReactAdapter } from "../Bindings/ReactBindingHandler";
import { TabsManager } from "./Tabs/TabsManager";
export class ExplorerStub implements ViewModels.Explorer {
public flight: ko.Observable<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");
}
}
import Explorer from "./Explorer";
export class DatabaseStub implements ViewModels.Database {
public nodeKind: string;
public container: ViewModels.Explorer;
public container: Explorer;
public self: string;
public rid: string;
public id: ko.Observable<string>;
@ -498,7 +86,7 @@ export class DatabaseStub implements ViewModels.Database {
export class CollectionStub implements ViewModels.Collection {
public nodeKind: string;
public container: ViewModels.Explorer;
public container: Explorer;
public rawDataModel: DataModels.Collection;
public self: string;
public rid: string;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -17,6 +17,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { CosmosClient } from "../../Common/CosmosClient";
import { PlatformType } from "../../PlatformType";
import { RequestOptions } from "@azure/cosmos/dist-esm";
import Explorer from "../Explorer";
const updateThroughputBeyondLimitWarningMessage: string = `
You are about to request an increase in throughput beyond the pre-allocated capacity.
@ -94,7 +95,7 @@ export default class DatabaseSettingsTab extends TabsBase
private _hasProvisioningTypeChanged: ko.Computed<boolean>;
private _wasAutopilotOriginallySet: ko.Observable<boolean>;
private _offerReplacePending: ko.Computed<boolean>;
private container: ViewModels.Explorer;
private container: Explorer;
constructor(options: ViewModels.TabOptions) {
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 { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
import Explorer from "../Explorer";
export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab {
public selectedDocumentId: ko.Observable<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";
return {
iconSrc: UploadIcon,

View File

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

View File

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

View File

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

View File

@ -7,6 +7,7 @@ import {
NotebookViewerComponentProps
} from "../Controls/NotebookViewer/NotebookViewerComponent";
import TabsBase from "./TabsBase";
import Explorer from "../Explorer";
/**
* Notebook Viewer tab
@ -29,7 +30,7 @@ class NotebookViewerComponentAdapter implements ReactAdapter {
}
export default class NotebookViewerTab extends TabsBase implements ViewModels.Tab {
private container: ViewModels.Explorer;
private container: Explorer;
public notebookUrl: string;
public notebookViewerComponentAdapter: NotebookViewerComponentAdapter;
@ -49,7 +50,7 @@ export default class NotebookViewerTab extends TabsBase implements ViewModels.Ta
});
}
protected getContainer(): ViewModels.Explorer {
protected getContainer(): Explorer {
return this.container;
}

View File

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

View File

@ -115,7 +115,7 @@ export default class QueryTab extends TabsBase implements ViewModels.QueryTab, V
};
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;
});

View File

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

View File

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

View File

@ -17,6 +17,7 @@ import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import { CosmosClient } from "../../Common/CosmosClient";
import { PlatformType } from "../../PlatformType";
import { RequestOptions } from "@azure/cosmos/dist-esm";
import Explorer from "../Explorer";
const ttlWarning: string = `
The system will automatically delete items based on the TTL value (in seconds) you provide, without needing a delete operation explicitly issued by a client application.
@ -218,7 +219,7 @@ export default class SettingsTab extends TabsBase implements ViewModels.Settings
public throughputModeRadioName: string;
private _offerReplacePending: ko.PureComputed<boolean>;
private container: ViewModels.Explorer;
private container: Explorer;
private _wasAutopilotOriginallySet: ko.Observable<boolean>;
private _isAutoPilotDirty: 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 ViewModels from "../../Contracts/ViewModels";
import TabsBase from "./TabsBase";
import Explorer from "../Explorer";
export default class SparkMasterTab extends TabsBase {
public sparkMasterSrc: ko.Observable<string>;
private _clusterConnectionInfo: DataModels.SparkClusterConnectionInfo;
private _container: ViewModels.Explorer;
private _container: Explorer;
constructor(options: ViewModels.SparkMasterTabOptions) {
super(options);

View File

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

View File

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

View File

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

View File

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

View File

@ -2,11 +2,12 @@ import * as DataModels from "../../Contracts/DataModels";
import * as ko from "knockout";
import * as ViewModels from "../../Contracts/ViewModels";
import Collection from "./Collection";
import Explorer from "../Explorer";
jest.mock("monaco-editor");
describe("Collection", () => {
function generateCollection(
container: ViewModels.Explorer,
container: Explorer,
databaseId: string,
data: DataModels.Collection,
quotaInfo: DataModels.CollectionQuotaInfo,
@ -31,7 +32,7 @@ describe("Collection", () => {
}
function generateMockCollectionWithDataModel(data: DataModels.Collection): Collection {
const mockContainer = {} as ViewModels.Explorer;
const mockContainer = {} as Explorer;
mockContainer.isPreferredApiMongoDB = ko.computed(() => {
return false;
});
@ -47,9 +48,7 @@ describe("Collection", () => {
mockContainer.isPreferredApiGraph = ko.computed(() => {
return false;
});
mockContainer.deleteCollectionText = ko.computed(() => {
return "delete collection";
});
mockContainer.deleteCollectionText = ko.observable<string>("delete collection");
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 UserDefinedFunction from "./UserDefinedFunction";
import { config } from "../../Config";
import Explorer from "../Explorer";
export default class Collection implements ViewModels.Collection {
public nodeKind: string;
public container: ViewModels.Explorer;
public container: Explorer;
public self: string;
public rid: string;
public databaseId: string;
@ -86,7 +87,7 @@ export default class Collection implements ViewModels.Collection {
public triggersFocused: ko.Observable<boolean>;
constructor(
container: ViewModels.Explorer,
container: Explorer,
databaseId: string,
data: DataModels.Collection,
quotaInfo: DataModels.CollectionQuotaInfo,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -70,7 +70,7 @@ export class DataAccessUtility extends DataAccessUtilityBase {
options: any
): Q.Promise<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 authorizationHeader: ViewModels.AuthorizationTokenHeaderMetadata = getAuthorizationHeader();
const requestOptions: any = _.extend({}, options, {});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

2
src/global.d.ts vendored
View File

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