diff --git a/jest.config.js b/jest.config.js index 2e361b190..efa93bc9b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -42,7 +42,7 @@ module.exports = { branches: 19.5, functions: 24, lines: 29.5, - statements: 28.5 + statements: 29.0 } }, diff --git a/src/Api/Apis.ts b/src/Api/Apis.ts deleted file mode 100644 index 4530d8b6a..000000000 --- a/src/Api/Apis.ts +++ /dev/null @@ -1,13 +0,0 @@ -import * as ViewModels from "../Contracts/ViewModels"; - -export class DefaultApi implements ViewModels.CosmosDbApi { - public isSystemDatabasePredicate = (database: ViewModels.Database): boolean => { - return false; - }; -} - -export class CassandraApi implements ViewModels.CosmosDbApi { - public isSystemDatabasePredicate = (database: ViewModels.Database): boolean => { - return database.id() === "system"; - }; -} diff --git a/src/Common/DataAccessUtilityBase.ts b/src/Common/DataAccessUtilityBase.ts index 71e17c70f..a8e92f0e7 100644 --- a/src/Common/DataAccessUtilityBase.ts +++ b/src/Common/DataAccessUtilityBase.ts @@ -27,6 +27,8 @@ import { RequestOptions } from "@azure/cosmos/dist-esm"; import StoredProcedure from "../Explorer/Tree/StoredProcedure"; import { Platform, config } from "../Config"; import { getAuthorizationHeader } from "../Utils/AuthorizationUtils"; +import DocumentId from "../Explorer/Tree/DocumentId"; +import ConflictId from "../Explorer/Tree/ConflictId"; export function getCommonQueryOptions(options: FeedOptions): any { const storedItemPerPageSetting: number = LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage); @@ -169,7 +171,7 @@ export function executeStoredProcedure( ); } -export function readDocument(collection: ViewModels.CollectionBase, documentId: ViewModels.DocumentId): Q.Promise { +export function readDocument(collection: ViewModels.CollectionBase, documentId: DocumentId): Q.Promise { const partitionKey = documentId.partitionKeyValue; return Q( @@ -182,7 +184,7 @@ export function readDocument(collection: ViewModels.CollectionBase, documentId: ); } -export function getPartitionKeyHeaderForConflict(conflictId: ViewModels.ConflictId): Object { +export function getPartitionKeyHeaderForConflict(conflictId: ConflictId): Object { const partitionKeyDefinition: DataModels.PartitionKey = conflictId.partitionKey; const partitionKeyValue: any = conflictId.partitionKeyValue; @@ -220,7 +222,7 @@ export function updateCollection( export function updateDocument( collection: ViewModels.CollectionBase, - documentId: ViewModels.DocumentId, + documentId: DocumentId, newDocument: any ): Q.Promise { const partitionKey = documentId.partitionKeyValue; @@ -347,10 +349,7 @@ export function createTrigger( ); } -export function deleteDocument( - collection: ViewModels.CollectionBase, - documentId: ViewModels.DocumentId -): Q.Promise { +export function deleteDocument(collection: ViewModels.CollectionBase, documentId: DocumentId): Q.Promise { const partitionKey = documentId.partitionKeyValue; return Q( @@ -364,7 +363,7 @@ export function deleteDocument( export function deleteConflict( collection: ViewModels.CollectionBase, - conflictId: ViewModels.ConflictId, + conflictId: ConflictId, options: any = {} ): Q.Promise { options.partitionKey = options.partitionKey || getPartitionKeyHeaderForConflict(conflictId); diff --git a/src/Common/DocumentClientUtilityBase.ts b/src/Common/DocumentClientUtilityBase.ts index eda4dbf36..5b0fd7397 100644 --- a/src/Common/DocumentClientUtilityBase.ts +++ b/src/Common/DocumentClientUtilityBase.ts @@ -13,6 +13,8 @@ import { MinimalQueryIterator, nextPage } from "./IteratorUtilities"; import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils"; import { RequestOptions } from "@azure/cosmos/dist-esm"; import StoredProcedure from "../Explorer/Tree/StoredProcedure"; +import ConflictId from "../Explorer/Tree/ConflictId"; +import DocumentId from "../Explorer/Tree/DocumentId"; // TODO: Log all promise resolutions and errors with verbosity levels export function queryDocuments( @@ -236,7 +238,7 @@ export function queryDocumentsPage( return deferred.promise; } -export function readDocument(collection: ViewModels.CollectionBase, documentId: ViewModels.DocumentId): Q.Promise { +export function readDocument(collection: ViewModels.CollectionBase, documentId: DocumentId): Q.Promise { var deferred = Q.defer(); const entityName = getEntityName(); const id = NotificationConsoleUtils.logConsoleMessage( @@ -303,7 +305,7 @@ export function updateCollection( export function updateDocument( collection: ViewModels.CollectionBase, - documentId: ViewModels.DocumentId, + documentId: DocumentId, newDocument: any ): Q.Promise { var deferred = Q.defer(); @@ -658,10 +660,7 @@ export function createTrigger( return deferred.promise; } -export function deleteDocument( - collection: ViewModels.CollectionBase, - documentId: ViewModels.DocumentId -): Q.Promise { +export function deleteDocument(collection: ViewModels.CollectionBase, documentId: DocumentId): Q.Promise { var deferred = Q.defer(); const entityName = getEntityName(); const id = NotificationConsoleUtils.logConsoleMessage( @@ -696,7 +695,7 @@ export function deleteDocument( export function deleteConflict( collection: ViewModels.CollectionBase, - conflictId: ViewModels.ConflictId, + conflictId: ConflictId, options?: any ): Q.Promise { var deferred = Q.defer(); diff --git a/src/Common/MongoProxyClient.test.ts b/src/Common/MongoProxyClient.test.ts index f5e15d1a0..2c05ce5f4 100644 --- a/src/Common/MongoProxyClient.test.ts +++ b/src/Common/MongoProxyClient.test.ts @@ -7,10 +7,12 @@ import { updateDocument } from "./MongoProxyClient"; import { AuthType } from "../AuthType"; -import { Collection, DatabaseAccount, DocumentId } from "../Contracts/ViewModels"; +import { Collection } from "../Contracts/ViewModels"; import { config } from "../Config"; import { CosmosClient } from "./CosmosClient"; import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient"; +import DocumentId from "../Explorer/Tree/DocumentId"; +import { DatabaseAccount } from "../Contracts/DataModels"; jest.mock("../ResourceProvider/ResourceProviderClient.ts"); const databaseId = "testDB"; diff --git a/src/Common/MongoProxyClient.ts b/src/Common/MongoProxyClient.ts index ca7f7fb51..172202b77 100644 --- a/src/Common/MongoProxyClient.ts +++ b/src/Common/MongoProxyClient.ts @@ -1,7 +1,6 @@ import * as Constants from "../Common/Constants"; import * as DataExplorerConstants from "../Common/Constants"; import * as DataModels from "../Contracts/DataModels"; -import * as ViewModels from "../Contracts/ViewModels"; import EnvironmentUtility from "./EnvironmentUtility"; import queryString from "querystring"; import { AddDbUtilities } from "../Shared/AddDatabaseUtility"; @@ -17,6 +16,7 @@ import { MessageTypes } from "../Contracts/ExplorerContracts"; import { NotificationConsoleUtils } from "../Utils/NotificationConsoleUtils"; import { ResourceProviderClient } from "../ResourceProvider/ResourceProviderClient"; import { MinimalQueryIterator } from "./IteratorUtilities"; +import DocumentId from "../Explorer/Tree/DocumentId"; const defaultHeaders = { [HttpHeaders.apiType]: ApiType.MongoDB.toString(), @@ -123,7 +123,7 @@ export function queryDocuments( export function readDocument( databaseId: string, collection: Collection, - documentId: ViewModels.DocumentId + documentId: DocumentId ): Promise { const databaseAccount = CosmosClient.databaseAccount(); const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; @@ -205,7 +205,7 @@ export function createDocument( export function updateDocument( databaseId: string, collection: Collection, - documentId: ViewModels.DocumentId, + documentId: DocumentId, documentContent: unknown ): Promise { const databaseAccount = CosmosClient.databaseAccount(); @@ -246,11 +246,7 @@ export function updateDocument( }); } -export function deleteDocument( - databaseId: string, - collection: Collection, - documentId: ViewModels.DocumentId -): Promise { +export function deleteDocument(databaseId: string, collection: Collection, documentId: DocumentId): Promise { const databaseAccount = CosmosClient.databaseAccount(); const resourceEndpoint = databaseAccount.properties.mongoEndpoint || databaseAccount.properties.documentEndpoint; const idComponents = documentId.self.split("/"); @@ -385,7 +381,7 @@ export function createMongoCollectionWithARM( return _createMongoCollectionWithARM(armEndpoint, params, additionalOptions); } -export function getEndpoint(databaseAccount: ViewModels.DatabaseAccount): string { +export function getEndpoint(databaseAccount: DataModels.DatabaseAccount): string { const serverId = window.dataExplorer.serverId(); const extensionEndpoint = window.dataExplorer.extensionEndpoint(); let url = config.MONGO_BACKEND_ENDPOINT diff --git a/src/Common/NotificationsClientBase.ts b/src/Common/NotificationsClientBase.ts index 32d83898a..89558276f 100644 --- a/src/Common/NotificationsClientBase.ts +++ b/src/Common/NotificationsClientBase.ts @@ -6,7 +6,7 @@ import * as ViewModels from "../Contracts/ViewModels"; import { getAuthorizationHeader } from "../Utils/AuthorizationUtils"; import { CosmosClient } from "./CosmosClient"; -export class NotificationsClientBase implements ViewModels.NotificationsClient { +export class NotificationsClientBase { private _extensionEndpoint: string; private _notificationsApiSuffix: string; @@ -16,7 +16,7 @@ export class NotificationsClientBase implements ViewModels.NotificationsClient { public fetchNotifications(): Q.Promise { const deferred: Q.Deferred = Q.defer(); - const databaseAccount: ViewModels.DatabaseAccount = CosmosClient.databaseAccount(); + const databaseAccount = CosmosClient.databaseAccount(); const subscriptionId: string = CosmosClient.subscriptionId(); const resourceGroup: string = CosmosClient.resourceGroup(); const url: string = `${this._extensionEndpoint}${this._notificationsApiSuffix}?accountName=${databaseAccount.name}&subscriptionId=${subscriptionId}&resourceGroup=${resourceGroup}`; diff --git a/src/Common/QueriesClient.ts b/src/Common/QueriesClient.ts index bbdf8aedf..73610e092 100644 --- a/src/Common/QueriesClient.ts +++ b/src/Common/QueriesClient.ts @@ -18,8 +18,9 @@ import { queryDocumentsPage, deleteDocument } from "./DocumentClientUtilityBase"; +import DocumentsTab from "../Explorer/Tabs/DocumentsTab"; -export class QueriesClient implements ViewModels.QueriesClient { +export class QueriesClient { private static readonly PartitionKey: DataModels.PartitionKey = { paths: [`/${SavedQueries.PartitionKeyProperty}`], kind: BackendDefaults.partitionKeyKind, @@ -216,11 +217,11 @@ export class QueriesClient implements ViewModels.QueriesClient { `Deleting query ${query.queryName}` ); query.id = query.queryName; - const documentId: ViewModels.DocumentId = new DocumentId( + const documentId = new DocumentId( { partitionKey: QueriesClient.PartitionKey, partitionKeyProperty: "id" - } as ViewModels.DocumentsTab, + } as DocumentsTab, query, query.queryName ); // TODO: Remove DocumentId's dependency on DocumentsTab @@ -248,7 +249,7 @@ export class QueriesClient implements ViewModels.QueriesClient { } public getResourceId(): string { - const databaseAccount: ViewModels.DatabaseAccount = CosmosClient.databaseAccount(); + const databaseAccount = CosmosClient.databaseAccount(); const databaseAccountName: string = (databaseAccount && databaseAccount.name) || ""; const subscriptionId: string = CosmosClient.subscriptionId() || ""; const resourceGroup: string = CosmosClient.resourceGroup() || ""; diff --git a/src/Contracts/ViewModels.ts b/src/Contracts/ViewModels.ts index 8954bbd60..464974d7d 100644 --- a/src/Contracts/ViewModels.ts +++ b/src/Contracts/ViewModels.ts @@ -1,39 +1,16 @@ import * as DataModels from "./DataModels"; -import * as monaco from "monaco-editor"; import Q from "q"; -import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList"; import { CassandraTableKey, CassandraTableKeys } from "../Explorer/Tables/TableDataClient"; import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent"; import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent"; -import { GitHubClient } from "../GitHub/GitHubClient"; -import { JunoClient, IGalleryItem } from "../Juno/JunoClient"; -import { NotebookContentItem } from "../Explorer/Notebook/NotebookContentItem"; import { QueryMetrics } from "@azure/cosmos"; import { UploadDetails } from "../workers/upload/definitions"; import Explorer from "../Explorer/Explorer"; import UserDefinedFunction from "../Explorer/Tree/UserDefinedFunction"; import StoredProcedure from "../Explorer/Tree/StoredProcedure"; -import ConflictsTab from "../Explorer/Tabs/ConflictsTab"; import Trigger from "../Explorer/Tree/Trigger"; - -export interface ExplorerOptions { - notificationsClient: NotificationsClient; - isEmulator: boolean; -} - -export interface Capability extends DataModels.Capability {} - -export interface ConfigurationOverrides extends DataModels.ConfigurationOverrides {} - -export interface NavbarButtonConfig extends CommandButtonComponentProps {} - -export interface DatabaseAccount extends DataModels.DatabaseAccount {} - -export interface KernelConnectionMetadata { - name: string; - configurationEndpoints: DataModels.NotebookConfigurationEndpoints; - notebookConnectionInfo: DataModels.NotebookWorkspaceConnectionInfo; -} +import DocumentId from "../Explorer/Tree/DocumentId"; +import ConflictId from "../Explorer/Tree/ConflictId"; export interface TokenProvider { getAuthHeader(): Promise; @@ -73,11 +50,6 @@ export interface WaitsForTemplate { isTemplateReady: ko.Observable; } -export interface AdHocAccessData { - readWriteUrl: string; - readUrl: string; -} - export interface TreeNode { nodeKind: string; rid: string; @@ -199,45 +171,6 @@ export interface Collection extends CollectionBase { getLabel(): string; } -export interface DocumentId { - container: DocumentsTab; - rid: string; - self: string; - ts: string; - partitionKeyValue: any; - partitionKeyProperty: string; - partitionKey: DataModels.PartitionKey; - stringPartitionKeyValue: string; - id: ko.Observable; - - isDirty: ko.Observable; - click(): void; - getPartitionKeyValueAsString(): string; - loadDocument(): Q.Promise; - partitionKeyHeader(): Object; -} - -export interface ConflictId { - container: ConflictsTab; - rid: string; - self: string; - ts: string; - partitionKeyValue: any; - partitionKeyProperty: string; - partitionKey: DataModels.PartitionKey; - stringPartitionKeyValue: string; - id: ko.Observable; - operationType: string; - resourceId: string; - resourceType: string; - - isDirty: ko.Observable; - click(): void; - buildDocumentIdFromConflict(partitionKeyValue: any): DocumentId; - getPartitionKeyValueAsString(): string; - loadConflict(): Q.Promise; -} - /** * Options used to initialize pane */ @@ -247,68 +180,6 @@ export interface PaneOptions { container?: Explorer; } -export interface ContextualPane { - formErrors: ko.Observable; - formErrorsDetails: ko.Observable; - id: string; - title: ko.Observable; - visible: ko.Observable; - firstFieldHasFocus: ko.Observable; - isExecuting: ko.Observable; - - submit: () => void; - cancel: () => void; - open: () => void; - close: () => void; - resetData: () => void; - showErrorDetails: () => void; - onCloseKeyPress(source: any, event: KeyboardEvent): void; - onPaneKeyDown(source: any, event: KeyboardEvent): boolean; -} - -export interface GitHubReposPaneOptions extends PaneOptions { - gitHubClient: GitHubClient; - junoClient: JunoClient; -} - -export interface PublishNotebookPaneOptions extends PaneOptions { - junoClient: JunoClient; -} - -export interface PublishNotebookPaneOpenOptions { - name: string; - author: string; - content: string; -} - -export interface AddCollectionPaneOptions extends PaneOptions { - isPreferredApiTable: ko.Computed; - databaseId?: string; - databaseSelfLink?: string; -} - -export interface UploadFilePaneOpenOptions { - paneTitle: string; - selectFileInputLabel: string; - errorMessage: string; // Could not upload notebook - inProgressMessage: string; // Uploading notebook - successMessage: string; // Successfully uploaded notebook - onSubmit: (file: File) => Promise; - extensions?: string; // input accept field. E.g: .ipynb - submitButtonLabel?: string; -} - -export interface StringInputPaneOpenOptions { - paneTitle: string; - inputLabel: string; - errorMessage: string; - inProgressMessage: string; - successMessage: string; - onSubmit: (input: string) => Promise; - submitButtonLabel: string; - defaultInput?: string; -} - /** * Graph configuration */ @@ -378,19 +249,6 @@ export interface DocumentRequestContainer { resourceName?: string; } -export interface NotificationsClient { - fetchNotifications(): Q.Promise; - setExtensionEndpoint(extensionEndpoint: string): void; -} - -export interface QueriesClient { - setupQueriesCollection(): Promise; - saveQuery(query: DataModels.Query): Promise; - getQueries(): Promise; - deleteQuery(query: DataModels.Query): Promise; - getResourceId(): string; -} - export interface DocumentClientOption { endpoint?: string; masterKey?: string; @@ -405,7 +263,7 @@ export interface TabOptions { selfLink: string; isActive: ko.Observable; hashLocation: string; - onUpdateTabsButtons: (buttons: NavbarButtonConfig[]) => void; + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]) => void; isTabsContentExpanded?: ko.Observable; onLoadStartKey?: number; @@ -418,47 +276,6 @@ export interface TabOptions { theme?: string; } -export interface SparkMasterTabOptions extends TabOptions { - clusterConnectionInfo: DataModels.SparkClusterConnectionInfo; - container: Explorer; -} - -export interface GraphTabOptions extends TabOptions { - account: DatabaseAccount; - masterKey: string; - collectionId: string; - databaseId: string; - collectionPartitionKeyProperty: string; -} - -export interface NotebookTabOptions extends TabOptions { - account: DatabaseAccount; - masterKey: string; - container: Explorer; - notebookContentItem: NotebookContentItem; -} - -export interface TerminalTabOptions extends TabOptions { - account: DatabaseAccount; - container: Explorer; - kind: TerminalKind; -} - -export interface GalleryTabOptions extends TabOptions { - account: DatabaseAccount; - container: Explorer; - junoClient: JunoClient; - notebookUrl?: string; - galleryItem?: IGalleryItem; - isFavorite?: boolean; -} - -export interface NotebookViewerTabOptions extends TabOptions { - account: DatabaseAccount; - container: Explorer; - notebookUrl: string; -} - export interface DocumentsTabOptions extends TabOptions { partitionKey: DataModels.PartitionKey; documentIds: ko.ObservableArray; @@ -486,155 +303,15 @@ export interface ScriptTabOption extends TabOptions { partitionKey?: DataModels.PartitionKey; } -// Tabs -export interface Tab { - node: TreeNode; // Can be null - collection: CollectionBase; - rid: string; - tabKind: CollectionTabKind; - tabId: string; - isActive: ko.Observable; - isMouseOver: ko.Observable; - tabPath: ko.Observable; - tabTitle: ko.Observable; - hashLocation: ko.Observable; - closeTabButton: Button; - onCloseTabButtonClick(): void; - onTabClick(): Q.Promise; - onKeyPressActivate(source: any, event: KeyboardEvent): void; - onKeyPressClose(source: any, event: KeyboardEvent): void; - onActivate(): Q.Promise; - refresh(): void; - closeButtonTabIndex: ko.Computed; - isExecutionError: ko.Observable; - isExecuting: ko.Observable; -} - -export interface DocumentsTab extends Tab { - /* Documents Grid */ - selectDocument(documentId: DocumentId): Q.Promise; - selectedDocumentId: ko.Observable; - selectedDocumentContent: Editable; - onDocumentIdClick(documentId: DocumentId): Q.Promise; - dataContentsGridScrollHeight: ko.Observable; - accessibleDocumentList: AccessibleVerticalList; - documentContentsGridId: string; - - partitionKey: DataModels.PartitionKey; - idHeader: string; - partitionKeyPropertyHeader: string; - partitionKeyProperty: string; - documentIds: ko.ObservableArray; - - /* Documents Filter */ - filterContent: ko.Observable; - appliedFilter: ko.Observable; - lastFilterContents: ko.ObservableArray; - isFilterExpanded: ko.Observable; - applyFilterButton: Button; - onShowFilterClick(): Q.Promise; - onHideFilterClick(): Q.Promise; - onApplyFilterClick(): Q.Promise; - - /* Document Editor */ - isEditorDirty: ko.Computed; - editorState: ko.Observable; - onValidDocumentEdit(content: any): Q.Promise; - onInvalidDocumentEdit(content: any): Q.Promise; - - onNewDocumentClick(): Q.Promise; - onSaveNewDocumentClick(): Q.Promise; - onRevertNewDocumentClick(): Q.Promise; - onSaveExisitingDocumentClick(): Q.Promise; - onRevertExisitingDocumentClick(): Q.Promise; - onDeleteExisitingDocumentClick(): Q.Promise; - - /* Errors */ - displayedError: ko.Observable; - - initDocumentEditor(documentId: DocumentId, content: any): Q.Promise; - loadNextPage(): Q.Promise; -} - export interface WaitsForTemplate { isTemplateReady: ko.Observable; } -export interface QueryTab extends Tab { - queryEditorId: string; - isQueryMetricsEnabled: ko.Computed; - activityId: ko.Observable; - - /* Command Bar */ - executeQueryButton: Button; - fetchNextPageButton: Button; - saveQueryButton: Button; - onExecuteQueryClick(): Q.Promise; - onFetchNextPageClick(): Q.Promise; - - /*Query Editor*/ - initialEditorContent: ko.Observable; - sqlQueryEditorContent: ko.Observable; - sqlStatementToExecute: ko.Observable; - - /* Results */ - allResultsMetadata: ko.ObservableArray; - - /* Errors */ - errors: ko.ObservableArray; - - /* Status */ - statusMessge: ko.Observable; - statusIcon: ko.Observable; -} - -export interface ScriptTab extends Tab { - id: Editable; - editorId: string; - - saveButton: Button; - updateButton: Button; - discardButton: Button; - deleteButton: Button; - - editorState: ko.Observable; - editorContent: ko.Observable; - editor: ko.Observable; - - errors: ko.ObservableArray; - statusMessge: ko.Observable; - statusIcon: ko.Observable; - - formFields: ko.ObservableArray>; - formIsValid: ko.Computed; - formIsDirty: ko.Computed; - - isNew: ko.Observable; - resource: ko.Observable; - - setBaselines(): void; -} - -export interface StoredProcedureTab extends ScriptTab { - onExecuteSprocsResult(result: any, logsData: any): void; - onExecuteSprocsError(error: string): void; -} - -export interface UserDefinedFunctionTab extends ScriptTab {} - -export interface TriggerTab extends ScriptTab { - triggerType: Editable; - triggerOperation: Editable; -} - -export interface GraphTab extends Tab {} export interface EditorPosition { line: number; column: number; } -export interface MongoShellTab extends Tab {} - export enum DocumentExplorerState { noDocumentSelected, newDocumentValid, @@ -752,40 +429,8 @@ export interface AuthorizationTokenHeaderMetadata { token: string; } -export interface TelemetryActions { - sendEvent(name: string, telemetryProperties?: { [propertyName: string]: string }): Q.Promise; - sendError(errorInfo: DataModels.ITelemetryError): Q.Promise; - sendMetric( - name: string, - metricNumber: number, - telemetryProperties?: { [propertyName: string]: string } - ): Q.Promise; -} - -export interface ConfigurationOverrides { - EnableBsonSchema: string; -} - -export interface CosmosDbApi { - isSystemDatabasePredicate: (database: Database) => boolean; -} - export interface DropdownOption { text: string; value: T; disable?: boolean; } - -export interface INotebookContainerClient { - resetWorkspace: () => Promise; -} - -export interface INotebookContentClient { - updateItemChildren: (item: NotebookContentItem) => Promise; - createNewNotebookFile: (parent: NotebookContentItem) => Promise; - deleteContentItem: (item: NotebookContentItem) => Promise; - uploadFileAsync: (name: string, content: string, parent: NotebookContentItem) => Promise; - renameNotebook: (item: NotebookContentItem, targetName: string) => Promise; - createDirectory: (parent: NotebookContentItem, newDirectoryName: string) => Promise; - readFileContent: (filePath: string) => Promise; -} diff --git a/src/Explorer/ComponentRegisterer.ts b/src/Explorer/ComponentRegisterer.ts index 2325237b3..7f8355916 100644 --- a/src/Explorer/ComponentRegisterer.ts +++ b/src/Explorer/ComponentRegisterer.ts @@ -13,9 +13,7 @@ import { NewVertexComponent } from "./Graph/NewVertexComponent/NewVertexComponen import { TabsManagerKOComponent } from "./Tabs/TabsManager"; import { ThroughputInputComponent } from "./Controls/ThroughputInput/ThroughputInputComponent"; import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3"; -import { ToolbarComponent } from "./Controls/Toolbar/Toolbar"; -ko.components.register("toolbar", new ToolbarComponent()); ko.components.register("input-typeahead", new InputTypeaheadComponent()); ko.components.register("new-vertex-form", NewVertexComponent); ko.components.register("error-display", new ErrorDisplayComponent()); diff --git a/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx b/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx index ae1d548d1..e255d64ac 100644 --- a/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx +++ b/src/Explorer/Controls/QueriesGridReactComponent/QueriesGridComponent.tsx @@ -27,9 +27,10 @@ import { TextField, ITextFieldProps, ITextField } from "office-ui-fabric-react/l import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor"; import SaveQueryBannerIcon from "../../../../images/save_query_banner.png"; +import { QueriesClient } from "../../../Common/QueriesClient"; export interface QueriesGridComponentProps { - queriesClient: ViewModels.QueriesClient; + queriesClient: QueriesClient; onQuerySelect: (query: DataModels.Query) => void; containerVisible: boolean; saveQueryEnabled: boolean; diff --git a/src/Explorer/Controls/Toolbar/IToolbarAction.ts b/src/Explorer/Controls/Toolbar/IToolbarAction.ts deleted file mode 100644 index 94d638390..000000000 --- a/src/Explorer/Controls/Toolbar/IToolbarAction.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import IToolbarDisplayable from "./IToolbarDisplayable"; - -interface IToolbarAction extends IToolbarDisplayable { - type: "action"; - action: () => void; -} - -export default IToolbarAction; diff --git a/src/Explorer/Controls/Toolbar/IToolbarDisplayable.ts b/src/Explorer/Controls/Toolbar/IToolbarDisplayable.ts deleted file mode 100644 index ffc9c598c..000000000 --- a/src/Explorer/Controls/Toolbar/IToolbarDisplayable.ts +++ /dev/null @@ -1,18 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -interface IToolbarDisplayable { - id: string; - title: ko.Subscribable; - displayName: ko.Subscribable; - enabled: ko.Subscribable; - visible: ko.Observable; - focused: ko.Observable; - icon: string; - mouseDown: (data: any, event: MouseEvent) => any; - keyUp: (data: any, event: KeyboardEvent) => any; - keyDown: (data: any, event: KeyboardEvent) => any; -} - -export default IToolbarDisplayable; diff --git a/src/Explorer/Controls/Toolbar/IToolbarDropDown.ts b/src/Explorer/Controls/Toolbar/IToolbarDropDown.ts deleted file mode 100644 index e87e9d721..000000000 --- a/src/Explorer/Controls/Toolbar/IToolbarDropDown.ts +++ /dev/null @@ -1,56 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import IToolbarDisplayable from "./IToolbarDisplayable"; - -interface IToolbarDropDown extends IToolbarDisplayable { - type: "dropdown"; - subgroup: IActionConfigItem[]; - expanded: ko.Observable; - open: () => void; -} - -export interface IDropdown { - type: "dropdown"; - title: string; - displayName: string; - id: string; - enabled: ko.Observable; - visible?: ko.Observable; - icon?: string; - subgroup?: IActionConfigItem[]; -} - -export interface ISeperator { - type: "separator"; - visible?: ko.Observable; -} - -export interface IToggle { - type: "toggle"; - title: string; - displayName: string; - checkedTitle: string; - checkedDisplayName: string; - id: string; - checked: ko.Observable; - enabled: ko.Observable; - visible?: ko.Observable; - icon?: string; -} - -export interface IAction { - type: "action"; - title: string; - displayName: string; - id: string; - action: () => any; - enabled: ko.Subscribable; - visible?: ko.Observable; - icon?: string; -} - -export type IActionConfigItem = ISeperator | IAction | IToggle | IDropdown; - -export default IToolbarDropDown; diff --git a/src/Explorer/Controls/Toolbar/IToolbarItem.ts b/src/Explorer/Controls/Toolbar/IToolbarItem.ts deleted file mode 100644 index 97221c112..000000000 --- a/src/Explorer/Controls/Toolbar/IToolbarItem.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import IToolbarAction from "./IToolbarAction"; -import IToolbarToggle from "./IToolbarToggle"; -import IToolbarSeperator from "./IToolbarSeperator"; -import IToolbarDropDown from "./IToolbarDropDown"; - -type IToolbarItem = IToolbarAction | IToolbarToggle | IToolbarSeperator | IToolbarDropDown; - -export default IToolbarItem; diff --git a/src/Explorer/Controls/Toolbar/IToolbarSeperator.ts b/src/Explorer/Controls/Toolbar/IToolbarSeperator.ts deleted file mode 100644 index 16bfcfa18..000000000 --- a/src/Explorer/Controls/Toolbar/IToolbarSeperator.ts +++ /dev/null @@ -1,10 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -interface IToolbarSeperator { - type: "separator"; - visible: ko.Observable; -} - -export default IToolbarSeperator; diff --git a/src/Explorer/Controls/Toolbar/IToolbarToggle.ts b/src/Explorer/Controls/Toolbar/IToolbarToggle.ts deleted file mode 100644 index 70643eb76..000000000 --- a/src/Explorer/Controls/Toolbar/IToolbarToggle.ts +++ /dev/null @@ -1,12 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import IToolbarDisplayable from "./IToolbarDisplayable"; - -interface IToolbarToggle extends IToolbarDisplayable { - type: "toggle"; - checked: ko.Observable; - toggle: () => void; -} -export default IToolbarToggle; diff --git a/src/Explorer/Controls/Toolbar/KeyCodes.ts b/src/Explorer/Controls/Toolbar/KeyCodes.ts deleted file mode 100644 index 1cbeee700..000000000 --- a/src/Explorer/Controls/Toolbar/KeyCodes.ts +++ /dev/null @@ -1,58 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -var keyCodes = { - RightClick: 3, - Enter: 13, - Esc: 27, - Tab: 9, - LeftArrow: 37, - UpArrow: 38, - RightArrow: 39, - DownArrow: 40, - Delete: 46, - A: 65, - B: 66, - C: 67, - D: 68, - E: 69, - F: 70, - G: 71, - H: 72, - I: 73, - J: 74, - K: 75, - L: 76, - M: 77, - N: 78, - O: 79, - P: 80, - Q: 81, - R: 82, - S: 83, - T: 84, - U: 85, - V: 86, - W: 87, - X: 88, - Y: 89, - Z: 90, - Period: 190, - DecimalPoint: 110, - F1: 112, - F2: 113, - F3: 114, - F4: 115, - F5: 116, - F6: 117, - F7: 118, - F8: 119, - F9: 120, - F10: 121, - F11: 122, - F12: 123, - Dash: 189 -}; - -export default keyCodes; diff --git a/src/Explorer/Controls/Toolbar/Toolbar.ts b/src/Explorer/Controls/Toolbar/Toolbar.ts deleted file mode 100644 index 57eed701c..000000000 --- a/src/Explorer/Controls/Toolbar/Toolbar.ts +++ /dev/null @@ -1,145 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ -import { IDropdown } from "./IToolbarDropDown"; -import { IActionConfigItem } from "./IToolbarDropDown"; -import IToolbarItem from "./IToolbarItem"; - -import * as ko from "knockout"; -import ToolbarDropDown from "./ToolbarDropDown"; -import ToolbarAction from "./ToolbarAction"; -import ToolbarToggle from "./ToolbarToggle"; -import template from "./toolbar.html"; - -export default class Toolbar { - private _toolbarWidth = ko.observable(); - private _actionConfigs: IActionConfigItem[]; - private _afterExecute: (id: string) => void; - - private _hasFocus: boolean = false; - private _focusedSubscription: ko.Subscription; - - constructor(actionItems: IActionConfigItem[], afterExecute?: (id: string) => void) { - this._actionConfigs = actionItems; - this._afterExecute = afterExecute; - this.toolbarItems.subscribe(this._focusFirstEnabledItem); - - $(window).resize(() => { - this._toolbarWidth($(".toolbar").width()); - }); - setTimeout(() => { - this._toolbarWidth($(".toolbar").width()); - }, 500); - } - - public toolbarItems: ko.PureComputed = ko.pureComputed(() => { - var remainingToolbarSpace = this._toolbarWidth(); - var toolbarItems: IToolbarItem[] = []; - - var moreItem: IDropdown = { - type: "dropdown", - title: "More", - displayName: "More", - id: "more-actions-toggle", - enabled: ko.observable(true), - visible: ko.observable(true), - icon: "images/ASX_More.svg", - subgroup: [] - }; - - var showHasMoreItem = false; - var addSeparator = false; - this._actionConfigs.forEach(actionConfig => { - if (actionConfig.type === "separator") { - addSeparator = true; - } else if (remainingToolbarSpace / 60 > 2) { - if (addSeparator) { - addSeparator = false; - toolbarItems.push(Toolbar._createToolbarItemFromConfig({ type: "separator" })); - remainingToolbarSpace -= 10; - } - - toolbarItems.push(Toolbar._createToolbarItemFromConfig(actionConfig)); - remainingToolbarSpace -= 60; - } else { - showHasMoreItem = true; - if (addSeparator) { - addSeparator = false; - moreItem.subgroup.push({ - type: "separator" - }); - } - - if (!!actionConfig) { - moreItem.subgroup.push(actionConfig); - } - } - }); - - if (showHasMoreItem) { - toolbarItems.push( - Toolbar._createToolbarItemFromConfig({ type: "separator" }), - Toolbar._createToolbarItemFromConfig(moreItem) - ); - } - - return toolbarItems; - }); - - public focus() { - this._hasFocus = true; - this._focusFirstEnabledItem(this.toolbarItems()); - } - - private _focusFirstEnabledItem = (items: IToolbarItem[]) => { - if (!!this._focusedSubscription) { - // no memory leaks! :D - this._focusedSubscription.dispose(); - } - if (this._hasFocus) { - for (var i = 0; i < items.length; i++) { - if (items[i].type !== "separator" && (items[i]).enabled()) { - (items[i]).focused(true); - this._focusedSubscription = (items[i]).focused.subscribe((newValue: any) => { - if (!newValue) { - this._hasFocus = false; - this._focusedSubscription.dispose(); - } - }); - break; - } - } - } - }; - - private static _createToolbarItemFromConfig( - configItem: IActionConfigItem, - afterExecute?: (id: string) => void - ): IToolbarItem { - switch (configItem.type) { - case "dropdown": - return new ToolbarDropDown(configItem, afterExecute); - case "action": - return new ToolbarAction(configItem, afterExecute); - case "toggle": - return new ToolbarToggle(configItem, afterExecute); - case "separator": - return { - type: "separator", - visible: ko.observable(true) - }; - } - } -} - -/** - * Helper class for ko component registration - */ -export class ToolbarComponent { - constructor() { - return { - viewModel: Toolbar, - template - }; - } -} diff --git a/src/Explorer/Controls/Toolbar/ToolbarAction.ts b/src/Explorer/Controls/Toolbar/ToolbarAction.ts deleted file mode 100644 index f8d3fc591..000000000 --- a/src/Explorer/Controls/Toolbar/ToolbarAction.ts +++ /dev/null @@ -1,86 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import * as ko from "knockout"; -import { IAction } from "./IToolbarDropDown"; -import IToolbarAction from "./IToolbarAction"; -import KeyCodes from "./KeyCodes"; -import Utilities from "./Utilities"; - -export default class ToolbarAction implements IToolbarAction { - public type: "action" = "action"; - public id: string; - public icon: string; - public title: ko.Observable; - public displayName: ko.Observable; - public enabled: ko.Subscribable; - public visible: ko.Observable; - public focused: ko.Observable; - public action: () => void; - private _afterExecute: (id: string) => void; - - constructor(actionItem: IAction, afterExecute?: (id: string) => void) { - this.action = actionItem.action; - this.title = ko.observable(actionItem.title); - this.displayName = ko.observable(actionItem.displayName); - this.id = actionItem.id; - this.enabled = actionItem.enabled; - this.visible = actionItem.visible ? actionItem.visible : ko.observable(true); - this.focused = ko.observable(false); - this.icon = actionItem.icon; - this._afterExecute = afterExecute; - } - - private _executeAction = () => { - this.action(); - if (!!this._afterExecute) { - this._afterExecute(this.id); - } - }; - - public mouseDown = (data: any, event: MouseEvent): boolean => { - this._executeAction(); - return false; - }; - - public keyUp = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = false; - - handled = Utilities.onEnter(event, ($sourceElement: JQuery) => { - this._executeAction(); - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - return true; - }); - - return !handled; - }; - - public keyDown = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = false; - - handled = Utilities.onEnter(event, ($sourceElement: JQuery) => { - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - return true; - }); - - if (!handled) { - // Reset color if [shift-] tabbing, 'up/down arrowing', or 'esc'-aping away from button while holding down 'enter' - Utilities.onKeys( - event, - [KeyCodes.Tab, KeyCodes.UpArrow, KeyCodes.DownArrow, KeyCodes.Esc], - ($sourceElement: JQuery) => { - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - } - ); - } - - return !handled; - }; -} diff --git a/src/Explorer/Controls/Toolbar/ToolbarDropDown.ts b/src/Explorer/Controls/Toolbar/ToolbarDropDown.ts deleted file mode 100644 index e6d654b3f..000000000 --- a/src/Explorer/Controls/Toolbar/ToolbarDropDown.ts +++ /dev/null @@ -1,167 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import * as ko from "knockout"; -import { IDropdown } from "./IToolbarDropDown"; -import { IActionConfigItem } from "./IToolbarDropDown"; -import IToolbarDropDown from "./IToolbarDropDown"; -import KeyCodes from "./KeyCodes"; -import Utilities from "./Utilities"; - -interface IMenuItem { - id?: string; - type: "normal" | "separator" | "submenu"; - label?: string; - enabled?: boolean; - visible?: boolean; - submenu?: IMenuItem[]; -} - -export default class ToolbarDropDown implements IToolbarDropDown { - public type: "dropdown" = "dropdown"; - public title: ko.Observable; - public displayName: ko.Observable; - public id: string; - public enabled: ko.Observable; - public visible: ko.Observable; - public focused: ko.Observable; - public icon: string; - public subgroup: IActionConfigItem[] = []; - public expanded: ko.Observable = ko.observable(false); - private _afterExecute: (id: string) => void; - - constructor(dropdown: IDropdown, afterExecute?: (id: string) => void) { - this.subgroup = dropdown.subgroup; - this.title = ko.observable(dropdown.title); - this.displayName = ko.observable(dropdown.displayName); - this.id = dropdown.id; - this.enabled = dropdown.enabled; - this.visible = dropdown.visible ? dropdown.visible : ko.observable(true); - this.focused = ko.observable(false); - this.icon = dropdown.icon; - this._afterExecute = afterExecute; - } - - private static _convertToMenuItem = ( - actionConfigs: IActionConfigItem[], - actionMap: { [id: string]: () => void } = {} - ): { menuItems: IMenuItem[]; actionMap: { [id: string]: () => void } } => { - var returnValue = { - menuItems: actionConfigs.map((actionConfig: IActionConfigItem, index, array) => { - var menuItem: IMenuItem; - switch (actionConfig.type) { - case "action": - menuItem = { - id: actionConfig.id, - type: "normal", - label: actionConfig.displayName, - enabled: actionConfig.enabled(), - visible: actionConfig.visible ? actionConfig.visible() : true - }; - actionMap[actionConfig.id] = actionConfig.action; - break; - case "dropdown": - menuItem = { - id: actionConfig.id, - type: "submenu", - label: actionConfig.displayName, - enabled: actionConfig.enabled(), - visible: actionConfig.visible ? actionConfig.visible() : true, - submenu: ToolbarDropDown._convertToMenuItem(actionConfig.subgroup, actionMap).menuItems - }; - break; - case "toggle": - menuItem = { - id: actionConfig.id, - type: "normal", - label: actionConfig.checked() ? actionConfig.checkedDisplayName : actionConfig.displayName, - enabled: actionConfig.enabled(), - visible: actionConfig.visible ? actionConfig.visible() : true - }; - actionMap[actionConfig.id] = () => { - actionConfig.checked(!actionConfig.checked()); - }; - break; - case "separator": - menuItem = { - type: "separator", - visible: true - }; - break; - } - return menuItem; - }), - actionMap: actionMap - }; - - return returnValue; - }; - - public open = () => { - if (!!(window).host) { - var convertedMenuItem = ToolbarDropDown._convertToMenuItem(this.subgroup); - - (window).host - .executeProviderOperation("MenuManager.showMenu", { - iFrameStack: [`#${window.frameElement.id}`], - anchor: `#${this.id}`, - menuItems: convertedMenuItem.menuItems - }) - .then((id?: string) => { - if (!!id && !!convertedMenuItem.actionMap[id]) { - convertedMenuItem.actionMap[id](); - } - }); - - if (!!this._afterExecute) { - this._afterExecute(this.id); - } - } - }; - - public mouseDown = (data: any, event: MouseEvent): boolean => { - this.open(); - return false; - }; - - public keyUp = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = false; - - handled = Utilities.onEnter(event, ($sourceElement: JQuery) => { - this.open(); - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - return true; - }); - - return !handled; - }; - - public keyDown = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = false; - - handled = Utilities.onEnter(event, ($sourceElement: JQuery) => { - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - return true; - }); - - if (!handled) { - // Reset color if [shift-] tabbing, 'up/down arrowing', or 'esc'-aping away from button while holding down 'enter' - Utilities.onKeys( - event, - [KeyCodes.Tab, KeyCodes.UpArrow, KeyCodes.DownArrow, KeyCodes.Esc], - ($sourceElement: JQuery) => { - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - } - ); - } - - return !handled; - }; -} diff --git a/src/Explorer/Controls/Toolbar/ToolbarToggle.ts b/src/Explorer/Controls/Toolbar/ToolbarToggle.ts deleted file mode 100644 index 419a1c9ce..000000000 --- a/src/Explorer/Controls/Toolbar/ToolbarToggle.ts +++ /dev/null @@ -1,109 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import * as ko from "knockout"; -import { IToggle } from "./IToolbarDropDown"; -import IToolbarToggle from "./IToolbarToggle"; -import KeyCodes from "./KeyCodes"; -import Utilities from "./Utilities"; - -export default class ToolbarToggle implements IToolbarToggle { - public type: "toggle" = "toggle"; - public checked: ko.Observable; - public id: string; - public enabled: ko.Observable; - public visible: ko.Observable; - public focused: ko.Observable; - public icon: string; - - private _title: string; - private _displayName: string; - private _checkedTitle: string; - private _checkedDisplayName: string; - - private _afterExecute: (id: string) => void; - - constructor(toggleItem: IToggle, afterExecute?: (id: string) => void) { - this._title = toggleItem.title; - this._displayName = toggleItem.displayName; - this.id = toggleItem.id; - this.enabled = toggleItem.enabled; - this.visible = toggleItem.visible ? toggleItem.visible : ko.observable(true); - this.focused = ko.observable(false); - this.icon = toggleItem.icon; - this.checked = toggleItem.checked; - this._checkedTitle = toggleItem.checkedTitle; - this._checkedDisplayName = toggleItem.checkedDisplayName; - this._afterExecute = afterExecute; - } - - public title = ko.pureComputed(() => { - if (this.checked()) { - return this._checkedTitle; - } else { - return this._title; - } - }); - - public displayName = ko.pureComputed(() => { - if (this.checked()) { - return this._checkedDisplayName; - } else { - return this._displayName; - } - }); - - public toggle = () => { - this.checked(!this.checked()); - - if (this.checked() && !!this._afterExecute) { - this._afterExecute(this.id); - } - }; - - public mouseDown = (data: any, event: MouseEvent): boolean => { - this.toggle(); - return false; - }; - - public keyUp = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = false; - - handled = Utilities.onEnter(event, ($sourceElement: JQuery) => { - this.toggle(); - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - return true; - }); - - return !handled; - }; - - public keyDown = (data: any, event: KeyboardEvent): boolean => { - var handled: boolean = false; - - handled = Utilities.onEnter(event, ($sourceElement: JQuery) => { - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - return true; - }); - - if (!handled) { - // Reset color if [shift-] tabbing, 'up/down arrowing', or 'esc'-aping away from button while holding down 'enter' - Utilities.onKeys( - event, - [KeyCodes.Tab, KeyCodes.UpArrow, KeyCodes.DownArrow, KeyCodes.Esc], - ($sourceElement: JQuery) => { - if ($sourceElement.hasClass("active")) { - $sourceElement.removeClass("active"); - } - } - ); - } - - return !handled; - }; -} diff --git a/src/Explorer/Controls/Toolbar/Utilities.ts b/src/Explorer/Controls/Toolbar/Utilities.ts deleted file mode 100644 index cf00c96e0..000000000 --- a/src/Explorer/Controls/Toolbar/Utilities.ts +++ /dev/null @@ -1,166 +0,0 @@ -/*!--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *----------------------------------------------------------*/ - -import KeyCodes from "./KeyCodes"; - -export default class Utilities { - /** - * Executes an action on a keyboard event. - * Modifiers: ctrlKey - control/command key, shiftKey - shift key, altKey - alt/option key; - * pass on 'null' to ignore the modifier (default). - */ - public static onKey( - event: any, - eventKeyCode: number, - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - var source: any = event.target || event.srcElement, - keyCode: number = event.keyCode, - $sourceElement = $(source), - handled: boolean = false; - - if ( - $sourceElement.length && - keyCode === eventKeyCode && - $.isFunction(action) && - (metaKey === null || metaKey === event.metaKey) && - (shiftKey === null || shiftKey === event.shiftKey) && - (altKey === null || altKey === event.altKey) - ) { - action($sourceElement); - handled = true; - } - - return handled; - } - - /** - * Executes an action on the first matched keyboard event. - */ - public static onKeys( - event: any, - eventKeyCodes: number[], - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - var handled: boolean = false, - keyCount: number, - i: number; - - if ($.isArray(eventKeyCodes)) { - keyCount = eventKeyCodes.length; - - for (i = 0; i < keyCount; ++i) { - handled = Utilities.onKey(event, eventKeyCodes[i], action, metaKey, shiftKey, altKey); - - if (handled) { - break; - } - } - } - - return handled; - } - - /** - * Executes an action on an 'enter' keyboard event. - */ - public static onEnter( - event: any, - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - return Utilities.onKey(event, KeyCodes.Enter, action, metaKey, shiftKey, altKey); - } - - /** - * Executes an action on a 'tab' keyboard event. - */ - public static onTab( - event: any, - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - return Utilities.onKey(event, KeyCodes.Tab, action, metaKey, shiftKey, altKey); - } - - /** - * Executes an action on an 'Esc' keyboard event. - */ - public static onEsc( - event: any, - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - return Utilities.onKey(event, KeyCodes.Esc, action, metaKey, shiftKey, altKey); - } - - /** - * Executes an action on an 'UpArrow' keyboard event. - */ - public static onUpArrow( - event: any, - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - return Utilities.onKey(event, KeyCodes.UpArrow, action, metaKey, shiftKey, altKey); - } - - /** - * Executes an action on a 'DownArrow' keyboard event. - */ - public static onDownArrow( - event: any, - action: ($sourceElement: JQuery) => void, - metaKey: boolean = null, - shiftKey: boolean = null, - altKey: boolean = null - ): boolean { - return Utilities.onKey(event, KeyCodes.DownArrow, action, metaKey, shiftKey, altKey); - } - - /** - * Executes an action on a mouse event. - */ - public static onButton(event: any, eventButtonCode: number, action: ($sourceElement: JQuery) => void): boolean { - var source: any = event.currentTarget; - var buttonCode: number = event.button; - var $sourceElement = $(source); - var handled: boolean = false; - - if ($sourceElement.length && buttonCode === eventButtonCode && $.isFunction(action)) { - action($sourceElement); - handled = true; - } - - return handled; - } - - /** - * Executes an action on a 'left' mouse event. - */ - public static onLeftButton(event: any, action: ($sourceElement: JQuery) => void): boolean { - return Utilities.onButton(event, buttonCodes.Left, action); - } -} - -var buttonCodes = { - None: -1, - Left: 0, - Middle: 1, - Right: 2 -}; diff --git a/src/Explorer/Controls/Toolbar/toolbar.html b/src/Explorer/Controls/Toolbar/toolbar.html deleted file mode 100644 index d4ac6c03c..000000000 --- a/src/Explorer/Controls/Toolbar/toolbar.html +++ /dev/null @@ -1,44 +0,0 @@ -
- - -
- - diff --git a/src/Explorer/Explorer.ts b/src/Explorer/Explorer.ts index e2570c473..92a7aaf8b 100644 --- a/src/Explorer/Explorer.ts +++ b/src/Explorer/Explorer.ts @@ -21,7 +21,7 @@ import EnvironmentUtility from "../Common/EnvironmentUtility"; import GraphStylingPane from "./Panes/GraphStylingPane"; import hasher from "hasher"; import NewVertexPane from "./Panes/NewVertexPane"; -import NotebookV2Tab from "./Tabs/NotebookV2Tab"; +import NotebookV2Tab, { NotebookTabOptions } from "./Tabs/NotebookV2Tab"; import Q from "q"; import ResourceTokenCollection from "./Tree/ResourceTokenCollection"; import TelemetryProcessor from "../Shared/Telemetry/TelemetryProcessor"; @@ -33,7 +33,6 @@ import { ArcadiaWorkspaceItem } from "./Controls/Arcadia/ArcadiaMenuPicker"; import { AuthType } from "../AuthType"; import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer"; import { BrowseQueriesPane } from "./Panes/BrowseQueriesPane"; -import { CassandraApi } from "../Api/Apis"; import { CassandraAPIDataClient, TableDataClient, TablesAPIDataClient } from "./Tables/TableDataClient"; import { CommandBarComponentAdapter } from "./Menus/CommandBar/CommandBarComponentAdapter"; import { config } from "../Config"; @@ -82,6 +81,10 @@ import { toRawContentUri, fromContentUri } from "../Utils/GitHubUtils"; import UserDefinedFunction from "./Tree/UserDefinedFunction"; import StoredProcedure from "./Tree/StoredProcedure"; import Trigger from "./Tree/Trigger"; +import { NotificationsClientBase } from "../Common/NotificationsClientBase"; +import { ContextualPaneBase } from "./Panes/ContextualPaneBase"; +import TabsBase from "./Tabs/TabsBase"; +import { CommandButtonComponentProps } from "./Controls/CommandButton/CommandButtonComponent"; BindingHandlersRegisterer.registerBindingHandlers(); // Hold a reference to ComponentRegisterer to prevent transpiler to ignore import @@ -92,6 +95,15 @@ enum ShareAccessToggleState { Read } +interface ExplorerOptions { + notificationsClient: NotificationsClientBase; + isEmulator: boolean; +} +interface AdHocAccessData { + readWriteUrl: string; + readUrl: string; +} + export default class Explorer { public flight: ko.Observable = ko.observable( SharedConstants.CollectionCreation.DefaultAddCollectionDefaultFlight @@ -107,7 +119,7 @@ export default class Explorer { public hasWriteAccess: ko.Observable; public collapsedResourceTreeWidth: number = ExplorerMetrics.CollapsedResourceTreeWidth; - public databaseAccount: ko.Observable; + public databaseAccount: ko.Observable; public collectionCreationDefaults: ViewModels.CollectionCreationDefaults = SharedConstants.CollectionCreationDefaults; public subscriptionType: ko.Observable; public quotaId: ko.Observable; @@ -127,8 +139,8 @@ export default class Explorer { public extensionEndpoint: ko.Observable; public armEndpoint: ko.Observable; public isTryCosmosDBSubscription: ko.Observable; - public notificationsClient: ViewModels.NotificationsClient; - public queriesClient: ViewModels.QueriesClient; + public notificationsClient: NotificationsClientBase; + public queriesClient: QueriesClient; public tableDataClient: TableDataClient; public splitter: Splitter; public parentFrameDataExplorerVersion: ko.Observable = ko.observable(""); @@ -139,7 +151,7 @@ export default class Explorer { public isNotificationConsoleExpanded: ko.Observable; // Panes - public contextPanes: ViewModels.ContextualPane[]; + public contextPanes: ContextualPaneBase[]; // Resource Tree public databases: ko.ObservableArray; @@ -184,12 +196,12 @@ export default class Explorer { public uploadItemsPane: UploadItemsPane; public uploadItemsPaneAdapter: UploadItemsPaneAdapter; public loadQueryPane: LoadQueryPane; - public saveQueryPane: ViewModels.ContextualPane; + public saveQueryPane: ContextualPaneBase; public browseQueriesPane: BrowseQueriesPane; public uploadFilePane: UploadFilePane; public stringInputPane: StringInputPane; public setupNotebooksPane: SetupNotebooksPane; - public gitHubReposPane: ViewModels.ContextualPane; + public gitHubReposPane: ContextualPaneBase; public publishNotebookPaneAdapter: ReactAdapter; // features @@ -202,7 +214,7 @@ export default class Explorer { public hasAutoPilotV2FeatureFlag: ko.Computed; public shouldShowShareDialogContents: ko.Observable; - public shareAccessData: ko.Observable; + public shareAccessData: ko.Observable; public renewExplorerShareAccess: (explorer: Explorer, token: string) => Q.Promise; public renewTokenError: ko.Observable; public tokenForRenewal: ko.Observable; @@ -228,7 +240,7 @@ export default class Explorer { public memoryUsageInfo: ko.Observable; public notebookManager?: any; // This is dynamically loaded - private _panes: ViewModels.ContextualPane[] = []; + private _panes: ContextualPaneBase[] = []; private _importExplorerConfigComplete: boolean = false; private _isSystemDatabasePredicate: (database: ViewModels.Database) => boolean = database => false; private _isInitializingNotebooks: boolean; @@ -251,7 +263,7 @@ export default class Explorer { private static readonly MaxNbDatabasesToAutoExpand = 5; - constructor(options: ViewModels.ExplorerOptions) { + constructor(options: ExplorerOptions) { const startKey: number = TelemetryProcessor.traceStart(Action.InitializeDataExplorer, { dataExplorerArea: Constants.Areas.ResourceTree }); @@ -264,7 +276,7 @@ export default class Explorer { this.deleteDatabaseText = ko.observable("Delete Database"); this.refreshTreeTitle = ko.observable("Refresh collections"); - this.databaseAccount = ko.observable(); + this.databaseAccount = ko.observable(); this.subscriptionType = ko.observable( SharedConstants.CollectionCreation.DefaultSubscriptionType ); @@ -373,7 +385,7 @@ export default class Explorer { this.resourceTokenPartitionKey = ko.observable(); this.isAuthWithResourceToken = ko.observable(false); - this.shareAccessData = ko.observable({ + this.shareAccessData = ko.observable({ readWriteUrl: undefined, readUrl: undefined }); @@ -458,7 +470,7 @@ export default class Explorer { }); this.notificationConsoleData = ko.observableArray([]); this.defaultExperience = ko.observable(); - this.databaseAccount.subscribe((databaseAccount: ViewModels.DatabaseAccount) => { + this.databaseAccount.subscribe(databaseAccount => { this.defaultExperience(DefaultExperienceUtility.getDefaultExperienceFromDatabaseAccount(databaseAccount)); }); @@ -551,8 +563,9 @@ export default class Explorer { defaultExperience && defaultExperience.toLowerCase() === Constants.DefaultAccountExperience.Cassandra.toLowerCase() ) { - const api = new CassandraApi(); - this._isSystemDatabasePredicate = api.isSystemDatabasePredicate; + this._isSystemDatabasePredicate = (database: ViewModels.Database): boolean => { + return database.id() === "system"; + }; } }); @@ -1003,7 +1016,7 @@ export default class Explorer { ); try { - const databaseAccount: ViewModels.DatabaseAccount = await resourceProviderClient.patchAsync( + const databaseAccount: DataModels.DatabaseAccount = await resourceProviderClient.patchAsync( this.databaseAccount().id, "2019-12-12", { @@ -1951,7 +1964,7 @@ export default class Explorer { return _.find(selectedCollection.storedProcedures(), (storedProcedure: StoredProcedure) => { const openedSprocTab = this.tabsManager.getTabs( ViewModels.CollectionTabKind.StoredProcedures, - (tab: ViewModels.Tab) => tab.node && tab.node.rid === storedProcedure.rid + tab => tab.node && tab.node.rid === storedProcedure.rid ); return ( storedProcedure.rid === this.selectedNode().rid || @@ -1965,7 +1978,7 @@ export default class Explorer { return _.find(selectedCollection.userDefinedFunctions(), (userDefinedFunction: UserDefinedFunction) => { const openedUdfTab = this.tabsManager.getTabs( ViewModels.CollectionTabKind.UserDefinedFunctions, - (tab: ViewModels.Tab) => tab.node && tab.node.rid === userDefinedFunction.rid + tab => tab.node && tab.node.rid === userDefinedFunction.rid ); return ( userDefinedFunction.rid === this.selectedNode().rid || @@ -1979,7 +1992,7 @@ export default class Explorer { return _.find(selectedCollection.triggers(), (trigger: Trigger) => { const openedTriggerTab = this.tabsManager.getTabs( ViewModels.CollectionTabKind.Triggers, - (tab: ViewModels.Tab) => tab.node && tab.node.rid === trigger.rid + tab => tab.node && tab.node.rid === trigger.rid ); return ( trigger.rid === this.selectedNode().rid || @@ -1989,7 +2002,7 @@ export default class Explorer { } public closeAllPanes(): void { - this._panes.forEach((pane: ViewModels.ContextualPane) => pane.close()); + this._panes.forEach((pane: ContextualPaneBase) => pane.close()); } public getPlatformType(): PlatformType { @@ -2004,7 +2017,7 @@ export default class Explorer { ); } - public onUpdateTabsButtons(buttons: ViewModels.NavbarButtonConfig[]): void { + public onUpdateTabsButtons(buttons: CommandButtonComponentProps[]): void { this.commandBarComponentAdapter.onUpdateTabsButtons(buttons); } @@ -2064,9 +2077,7 @@ export default class Explorer { if (isNewDatabase) { database.expandDatabase(); } - this.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.getDatabase().rid === database.rid - ); + this.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.getDatabase().rid === database.rid); }) ); }); @@ -2169,7 +2180,7 @@ export default class Explorer { } const urlPrefixWithKeyParam: string = `${config.hostedExplorerURL}?key=`; - const currentActiveTab: ViewModels.Tab = this.tabsManager.activeTab(); + const currentActiveTab = this.tabsManager.activeTab(); return `${urlPrefixWithKeyParam}${token}#/${(currentActiveTab && currentActiveTab.hashLocation()) || ""}`; } @@ -2432,18 +2443,18 @@ export default class Explorer { throw new Error(`Invalid notebookContentItem: ${notebookContentItem}`); } - const notebookTabs: NotebookV2Tab[] = this.tabsManager.getTabs( + const notebookTabs = this.tabsManager.getTabs( ViewModels.CollectionTabKind.NotebookV2, - (tab: ViewModels.Tab) => + tab => (tab as NotebookV2Tab).notebookPath && FileSystemUtil.isPathEqual((tab as NotebookV2Tab).notebookPath(), notebookContentItem.path) ) as NotebookV2Tab[]; - let notebookTab: NotebookV2Tab = notebookTabs && notebookTabs[0]; + let notebookTab = notebookTabs && notebookTabs[0]; if (notebookTab) { this.tabsManager.activateTab(notebookTab); } else { - const options: ViewModels.NotebookTabOptions = { + const options: NotebookTabOptions = { account: CosmosClient.databaseAccount(), tabKind: ViewModels.CollectionTabKind.NotebookV2, node: null, @@ -2507,7 +2518,7 @@ export default class Explorer { onSubmit: (input: string) => this.notebookManager?.notebookContentClient.renameNotebook(notebookFile, input) }) .then(newNotebookFile => { - const notebookTabs: ViewModels.Tab[] = this.tabsManager.getTabs( + const notebookTabs = this.tabsManager.getTabs( ViewModels.CollectionTabKind.NotebookV2, (tab: NotebookV2Tab) => tab.notebookPath && FileSystemUtil.isPathEqual(tab.notebookPath(), originalPath) ); @@ -2877,7 +2888,7 @@ export default class Explorer { const terminalTabs: TerminalTab[] = this.tabsManager.getTabs( ViewModels.CollectionTabKind.Terminal, - (tab: ViewModels.Tab) => tab.hashLocation() == hashLocation + tab => tab.hashLocation() == hashLocation ) as TerminalTab[]; let terminalTab: TerminalTab = terminalTabs && terminalTabs[0]; @@ -2911,7 +2922,7 @@ export default class Explorer { const galleryTabs = this.tabsManager.getTabs( ViewModels.CollectionTabKind.Gallery, - (tab: ViewModels.Tab) => tab.hashLocation() == hashLocation + tab => tab.hashLocation() == hashLocation ); let galleryTab = galleryTabs && galleryTabs[0]; @@ -2957,17 +2968,14 @@ export default class Explorer { const notebookViewerTabModule = this.notebookViewerTab; - let isNotebookViewerOpen = (tab: ViewModels.Tab) => { + let isNotebookViewerOpen = (tab: TabsBase) => { const notebookViewerTab = tab as typeof notebookViewerTabModule.default; return notebookViewerTab.notebookUrl === notebookUrl; }; - const notebookViewerTabs = this.tabsManager.getTabs( - ViewModels.CollectionTabKind.NotebookV2, - (tab: ViewModels.Tab) => { - return tab.hashLocation() == hashLocation && isNotebookViewerOpen(tab); - } - ); + const notebookViewerTabs = this.tabsManager.getTabs(ViewModels.CollectionTabKind.NotebookV2, tab => { + return tab.hashLocation() == hashLocation && isNotebookViewerOpen(tab); + }); let notebookViewerTab = notebookViewerTabs && notebookViewerTabs[0]; if (notebookViewerTab) { diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx index f0e009ad0..463de1281 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentAdapter.tsx @@ -12,11 +12,12 @@ import { CommandBar, ICommandBarItemProps } from "office-ui-fabric-react/lib/Com import { StyleConstants } from "../../../Common/Constants"; import { CommandBarUtil } from "./CommandBarUtil"; import Explorer from "../../Explorer"; +import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; export class CommandBarComponentAdapter implements ReactAdapter { public parameters: ko.Observable; public container: Explorer; - private tabsButtons: ViewModels.NavbarButtonConfig[]; + private tabsButtons: CommandButtonComponentProps[]; private isNotebookTabActive: ko.Computed; constructor(container: Explorer) { @@ -51,7 +52,7 @@ export class CommandBarComponentAdapter implements ReactAdapter { this.parameters = ko.observable(Date.now()); } - public onUpdateTabsButtons(buttons: ViewModels.NavbarButtonConfig[]): void { + public onUpdateTabsButtons(buttons: CommandButtonComponentProps[]): void { this.tabsButtons = buttons; this.triggerRender(); } diff --git a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts index c672cc51a..67daef835 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts +++ b/src/Explorer/Menus/CommandBar/CommandBarComponentButtonFactory.ts @@ -26,17 +26,18 @@ import GitHubIcon from "../../../../images/github.svg"; import SynapseIcon from "../../../../images/synapse-link.svg"; import { config, Platform } from "../../../Config"; import Explorer from "../../Explorer"; +import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; export class CommandBarComponentButtonFactory { private static counter: number = 0; - public static createStaticCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { + public static createStaticCommandBarButtons(container: Explorer): CommandButtonComponentProps[] { if (container.isAuthWithResourceToken()) { return CommandBarComponentButtonFactory.createStaticCommandBarButtonsForResourceToken(container); } const newCollectionBtn = CommandBarComponentButtonFactory.createNewCollectionGroup(container); - const buttons: ViewModels.NavbarButtonConfig[] = [newCollectionBtn]; + const buttons: CommandButtonComponentProps[] = [newCollectionBtn]; const addSynapseLink = CommandBarComponentButtonFactory.createOpenSynapseLinkDialogButton(container); if (addSynapseLink) { @@ -112,7 +113,7 @@ export class CommandBarComponentButtonFactory { if (CommandBarComponentButtonFactory.areScriptsSupported(container)) { const label = "New Stored Procedure"; - const newStoredProcedureBtn: ViewModels.NavbarButtonConfig = { + const newStoredProcedureBtn: CommandButtonComponentProps = { iconSrc: AddStoredProcedureIcon, iconAlt: label, onCommandClick: () => { @@ -133,12 +134,12 @@ export class CommandBarComponentButtonFactory { return buttons; } - public static createContextCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + public static createContextCommandBarButtons(container: Explorer): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; if (!container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()) { const label = "New Shell"; - const newMongoShellBtn: ViewModels.NavbarButtonConfig = { + const newMongoShellBtn: CommandButtonComponentProps = { iconSrc: HostedTerminalIcon, iconAlt: label, onCommandClick: () => { @@ -156,15 +157,15 @@ export class CommandBarComponentButtonFactory { return buttons; } - public static createControlCommandBarButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + public static createControlCommandBarButtons(container: Explorer): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; if (window.dataExplorerPlatform === PlatformType.Hosted) { return buttons; } if (!container.isPreferredApiCassandra()) { const label = "Settings"; - const settingsPaneButton: ViewModels.NavbarButtonConfig = { + const settingsPaneButton: CommandButtonComponentProps = { iconSrc: SettingsIcon, iconAlt: label, onCommandClick: () => container.settingsPane.open(), @@ -179,7 +180,7 @@ export class CommandBarComponentButtonFactory { if (container.isHostedDataExplorerEnabled()) { const label = "Open Full Screen"; - const fullScreenButton: ViewModels.NavbarButtonConfig = { + const fullScreenButton: CommandButtonComponentProps = { iconSrc: OpenInTabIcon, iconAlt: label, onCommandClick: () => container.generateSharedAccessData(), @@ -195,7 +196,7 @@ export class CommandBarComponentButtonFactory { if (!container.hasOwnProperty("isEmulator") || !container.isEmulator) { const label = "Feedback"; - const feedbackButtonOptions: ViewModels.NavbarButtonConfig = { + const feedbackButtonOptions: CommandButtonComponentProps = { iconSrc: FeedbackIcon, iconAlt: label, onCommandClick: () => container.provideFeedbackEmail(), @@ -211,7 +212,7 @@ export class CommandBarComponentButtonFactory { return buttons; } - public static createDivider(): ViewModels.NavbarButtonConfig { + public static createDivider(): CommandButtonComponentProps { const label = `divider${CommandBarComponentButtonFactory.counter++}`; return { isDivider: true, @@ -228,7 +229,7 @@ export class CommandBarComponentButtonFactory { return container.isPreferredApiDocumentDB() || container.isPreferredApiGraph(); } - private static createNewCollectionGroup(container: Explorer): ViewModels.NavbarButtonConfig { + private static createNewCollectionGroup(container: Explorer): CommandButtonComponentProps { const label = container.addCollectionText(); return { iconSrc: AddCollectionIcon, @@ -241,7 +242,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenSynapseLinkDialogButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createOpenSynapseLinkDialogButton(container: Explorer): CommandButtonComponentProps { if (config.platform === Platform.Emulator) { return null; } @@ -276,7 +277,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNewDatabase(container: Explorer): ViewModels.NavbarButtonConfig { + private static createNewDatabase(container: Explorer): CommandButtonComponentProps { const label = container.addDatabaseText(); return { iconSrc: AddDatabaseIcon, @@ -291,7 +292,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNewSQLQueryButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createNewSQLQueryButton(container: Explorer): CommandButtonComponentProps { if (container.isPreferredApiDocumentDB() || container.isPreferredApiGraph()) { const label = "New SQL Query"; return { @@ -325,15 +326,15 @@ export class CommandBarComponentButtonFactory { return null; } - public static createScriptCommandButtons(container: Explorer): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + public static createScriptCommandButtons(container: Explorer): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; const shouldEnableScriptsCommands: boolean = !container.isDatabaseNodeOrNoneSelected() && CommandBarComponentButtonFactory.areScriptsSupported(container); if (shouldEnableScriptsCommands) { const label = "New Stored Procedure"; - const newStoredProcedureBtn: ViewModels.NavbarButtonConfig = { + const newStoredProcedureBtn: CommandButtonComponentProps = { iconSrc: AddStoredProcedureIcon, iconAlt: label, onCommandClick: () => { @@ -350,7 +351,7 @@ export class CommandBarComponentButtonFactory { if (shouldEnableScriptsCommands) { const label = "New UDF"; - const newUserDefinedFunctionBtn: ViewModels.NavbarButtonConfig = { + const newUserDefinedFunctionBtn: CommandButtonComponentProps = { iconSrc: AddUdfIcon, iconAlt: label, onCommandClick: () => { @@ -367,7 +368,7 @@ export class CommandBarComponentButtonFactory { if (shouldEnableScriptsCommands) { const label = "New Trigger"; - const newTriggerBtn: ViewModels.NavbarButtonConfig = { + const newTriggerBtn: CommandButtonComponentProps = { iconSrc: AddTriggerIcon, iconAlt: label, onCommandClick: () => { @@ -385,7 +386,7 @@ export class CommandBarComponentButtonFactory { return buttons; } - private static createScaleAndSettingsButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createScaleAndSettingsButton(container: Explorer): CommandButtonComponentProps { let isShared = false; if (container.isDatabaseNodeSelected()) { isShared = container.findSelectedDatabase().isDatabaseShared(); @@ -410,7 +411,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNewNotebookButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createNewNotebookButton(container: Explorer): CommandButtonComponentProps { const label = "New Notebook"; return { iconSrc: NewNotebookIcon, @@ -423,7 +424,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createuploadNotebookButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createuploadNotebookButton(container: Explorer): CommandButtonComponentProps { const label = "Upload to Notebook Server"; return { iconSrc: NewNotebookIcon, @@ -436,7 +437,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenQueryButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createOpenQueryButton(container: Explorer): CommandButtonComponentProps { const label = "Open Query"; return { iconSrc: BrowseQueriesIcon, @@ -449,7 +450,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenQueryFromDiskButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createOpenQueryFromDiskButton(container: Explorer): CommandButtonComponentProps { const label = "Open Query From Disk"; return { iconSrc: OpenQueryFromDiskIcon, @@ -462,7 +463,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createEnableNotebooksButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createEnableNotebooksButton(container: Explorer): CommandButtonComponentProps { if (config.platform === Platform.Emulator) { return null; } @@ -483,7 +484,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createOpenTerminalButton(container: Explorer): CommandButtonComponentProps { const label = "Open Terminal"; return { iconSrc: CosmosTerminalIcon, @@ -496,7 +497,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenMongoTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createOpenMongoTerminalButton(container: Explorer): CommandButtonComponentProps { 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."; @@ -522,7 +523,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createOpenCassandraTerminalButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createOpenCassandraTerminalButton(container: Explorer): CommandButtonComponentProps { 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."; @@ -548,7 +549,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createNotebookWorkspaceResetButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createNotebookWorkspaceResetButton(container: Explorer): CommandButtonComponentProps { const label = "Reset Workspace"; return { iconSrc: ResetWorkspaceIcon, @@ -561,7 +562,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createManageGitHubAccountButton(container: Explorer): ViewModels.NavbarButtonConfig { + private static createManageGitHubAccountButton(container: Explorer): CommandButtonComponentProps { let connectedToGitHub: boolean = container.notebookManager?.gitHubOAuthService.isLoggedIn(); const label = connectedToGitHub ? "Manage GitHub settings" : "Connect to GitHub"; return { @@ -584,7 +585,7 @@ export class CommandBarComponentButtonFactory { }; } - private static createStaticCommandBarButtonsForResourceToken(container: Explorer): ViewModels.NavbarButtonConfig[] { + private static createStaticCommandBarButtonsForResourceToken(container: Explorer): CommandButtonComponentProps[] { const newSqlQueryBtn = CommandBarComponentButtonFactory.createNewSQLQueryButton(container); const openQueryBtn = CommandBarComponentButtonFactory.createOpenQueryButton(container); diff --git a/src/Explorer/Menus/CommandBar/CommandBarUtil.test.tsx b/src/Explorer/Menus/CommandBar/CommandBarUtil.test.tsx index d4df3d774..0c6b899c6 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarUtil.test.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarUtil.test.tsx @@ -1,9 +1,10 @@ import { CommandBarUtil } from "./CommandBarUtil"; import * as ViewModels from "../../../Contracts/ViewModels"; import { ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar"; +import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; describe("CommandBarUtil tests", () => { - const createButton = (): ViewModels.NavbarButtonConfig => { + const createButton = (): CommandButtonComponentProps => { return { iconSrc: "icon", iconAlt: "label", @@ -54,7 +55,7 @@ describe("CommandBarUtil tests", () => { }); it("should create buttons with unique keys", () => { - const btns: ViewModels.NavbarButtonConfig[] = []; + const btns: CommandButtonComponentProps[] = []; for (let i = 0; i < 5; i++) { btns.push(createButton()); } diff --git a/src/Explorer/Menus/CommandBar/CommandBarUtil.tsx b/src/Explorer/Menus/CommandBar/CommandBarUtil.tsx index 964f636f3..ca9ac1723 100644 --- a/src/Explorer/Menus/CommandBar/CommandBarUtil.tsx +++ b/src/Explorer/Menus/CommandBar/CommandBarUtil.tsx @@ -1,12 +1,11 @@ import _ from "underscore"; import * as React from "react"; -import * as ViewModels from "../../../Contracts/ViewModels"; import { Observable } from "knockout"; import { IconType } from "office-ui-fabric-react/lib/Icon"; import { IComponentAsProps } from "office-ui-fabric-react/lib/Utilities"; -import { KeyCodes, StyleConstants } from "../../../Common/Constants"; +import { StyleConstants } from "../../../Common/Constants"; import { ICommandBarItemProps } from "office-ui-fabric-react/lib/CommandBar"; -import { Dropdown, DropdownMenuItemType, IDropdownStyles, IDropdownOption } from "office-ui-fabric-react/lib/Dropdown"; +import { Dropdown, IDropdownStyles, IDropdownOption } from "office-ui-fabric-react/lib/Dropdown"; import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; import ChevronDownIcon from "../../../../images/Chevron_down.svg"; import { ArcadiaMenuPicker } from "../../Controls/Arcadia/ArcadiaMenuPicker"; @@ -21,13 +20,13 @@ export class CommandBarUtil { * Convert our NavbarButtonConfig to UI Fabric buttons * @param btns */ - public static convertButton(btns: ViewModels.NavbarButtonConfig[], backgroundColor: string): ICommandBarItemProps[] { + public static convertButton(btns: CommandButtonComponentProps[], backgroundColor: string): ICommandBarItemProps[] { const buttonHeightPx = StyleConstants.CommandBarButtonHeight; return btns .filter(btn => btn) .map( - (btn: ViewModels.NavbarButtonConfig, index: number): ICommandBarItemProps => { + (btn: CommandButtonComponentProps, index: number): ICommandBarItemProps => { if (btn.isDivider) { return CommandBarUtil.createDivider(btn.commandButtonLabel); } diff --git a/src/Explorer/Menus/NavBar/ControlBarComponent.tsx b/src/Explorer/Menus/NavBar/ControlBarComponent.tsx index e9d564842..1b274c5ab 100644 --- a/src/Explorer/Menus/NavBar/ControlBarComponent.tsx +++ b/src/Explorer/Menus/NavBar/ControlBarComponent.tsx @@ -3,17 +3,19 @@ */ import * as React from "react"; -import * as ViewModels from "../../../Contracts/ViewModels"; -import { CommandButtonComponent } from "../../Controls/CommandButton/CommandButtonComponent"; +import { + CommandButtonComponent, + CommandButtonComponentProps +} from "../../Controls/CommandButton/CommandButtonComponent"; export interface ControlBarComponentProps { - buttons: ViewModels.NavbarButtonConfig[]; + buttons: CommandButtonComponentProps[]; } export class ControlBarComponent extends React.Component { - private static renderButtons(commandButtonOptions: ViewModels.NavbarButtonConfig[]): JSX.Element[] { + private static renderButtons(commandButtonOptions: CommandButtonComponentProps[]): JSX.Element[] { return commandButtonOptions.map( - (btn: ViewModels.NavbarButtonConfig, index: number): JSX.Element => { + (btn: CommandButtonComponentProps, index: number): JSX.Element => { // Remove label btn.commandButtonLabel = null; return CommandButtonComponent.renderButton(btn, `${index}`); diff --git a/src/Explorer/Menus/NavBar/ControlBarComponentAdapter.tsx b/src/Explorer/Menus/NavBar/ControlBarComponentAdapter.tsx index 85e1f1a39..b6af77dbe 100644 --- a/src/Explorer/Menus/NavBar/ControlBarComponentAdapter.tsx +++ b/src/Explorer/Menus/NavBar/ControlBarComponentAdapter.tsx @@ -8,12 +8,12 @@ import * as ko from "knockout"; import * as React from "react"; import { ReactAdapter } from "../../../Bindings/ReactBindingHandler"; import { ControlBarComponent } from "./ControlBarComponent"; -import * as ViewModels from "../../../Contracts/ViewModels"; +import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent"; export class ControlBarComponentAdapter implements ReactAdapter { public parameters: ko.Observable; - constructor(private buttons: ko.ObservableArray) { + constructor(private buttons: ko.ObservableArray) { this.buttons.subscribe(() => this.forceRender()); this.parameters = ko.observable(Date.now()); } diff --git a/src/Explorer/Notebook/NotebookContainerClient.ts b/src/Explorer/Notebook/NotebookContainerClient.ts index 017ace6b5..e0ede4109 100644 --- a/src/Explorer/Notebook/NotebookContainerClient.ts +++ b/src/Explorer/Notebook/NotebookContainerClient.ts @@ -2,13 +2,12 @@ * Notebook container related stuff */ import * as DataModels from "../../Contracts/DataModels"; -import * as ViewModels from "../../Contracts/ViewModels"; import * as Constants from "../../Common/Constants"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import * as Logger from "../../Common/Logger"; -export class NotebookContainerClient implements ViewModels.INotebookContainerClient { +export class NotebookContainerClient { private reconnectingNotificationId: string; private isResettingWorkspace: boolean; diff --git a/src/Explorer/Notebook/NotebookContentClient.ts b/src/Explorer/Notebook/NotebookContentClient.ts index 89bbd3a27..4fe92b435 100644 --- a/src/Explorer/Notebook/NotebookContentClient.ts +++ b/src/Explorer/Notebook/NotebookContentClient.ts @@ -1,5 +1,4 @@ import * as DataModels from "../../Contracts/DataModels"; -import * as ViewModels from "../../Contracts/ViewModels"; import { NotebookContentItem, NotebookContentItemType } from "./NotebookContentItem"; import { StringUtils } from "../../Utils/StringUtils"; import { FileSystemUtil } from "./FileSystemUtil"; @@ -9,7 +8,7 @@ import { ServerConfig, IContent, IContentProvider, FileType, IEmptyContent } fro import { AjaxResponse } from "rxjs/ajax"; import { stringifyNotebook } from "@nteract/commutable"; -export class NotebookContentClient implements ViewModels.INotebookContentClient { +export class NotebookContentClient { constructor( private notebookServerInfo: ko.Observable, private notebookBasePath: ko.Observable, diff --git a/src/Explorer/Notebook/NotebookManager.ts b/src/Explorer/Notebook/NotebookManager.ts index fdb5dc545..eeafd2cbf 100644 --- a/src/Explorer/Notebook/NotebookManager.ts +++ b/src/Explorer/Notebook/NotebookManager.ts @@ -3,7 +3,6 @@ */ import { JunoClient } from "../../Juno/JunoClient"; -import * as ViewModels from "../../Contracts/ViewModels"; import { GitHubOAuthService } from "../../GitHub/GitHubOAuthService"; import { GitHubClient } from "../../GitHub/GitHubClient"; import * as Logger from "../../Common/Logger"; @@ -25,6 +24,7 @@ import { PublishNotebookPaneAdapter } from "../Panes/PublishNotebookPaneAdapter" import { getFullName } from "../../Utils/UserUtils"; import { ImmutableNotebook } from "@nteract/commutable"; import Explorer from "../Explorer"; +import { ContextualPaneBase } from "../Panes/ContextualPaneBase"; export interface NotebookManagerOptions { container: Explorer; @@ -40,14 +40,14 @@ export default class NotebookManager { public junoClient: JunoClient; public notebookContentProvider: IContentProvider; - public notebookClient: ViewModels.INotebookContainerClient; - public notebookContentClient: ViewModels.INotebookContentClient; + public notebookClient: NotebookContainerClient; + public notebookContentClient: NotebookContentClient; private gitHubContentProvider: GitHubContentProvider; public gitHubOAuthService: GitHubOAuthService; private gitHubClient: GitHubClient; - public gitHubReposPane: ViewModels.ContextualPane; + public gitHubReposPane: ContextualPaneBase; public publishNotebookPaneAdapter: PublishNotebookPaneAdapter; public initialize(params: NotebookManagerOptions): void { diff --git a/src/Explorer/Panes/AddCollectionPane.test.ts b/src/Explorer/Panes/AddCollectionPane.test.ts index c7243f58c..f156540d2 100644 --- a/src/Explorer/Panes/AddCollectionPane.test.ts +++ b/src/Explorer/Panes/AddCollectionPane.test.ts @@ -1,14 +1,13 @@ import * as Constants from "../../Common/Constants"; -import * as ViewModels from "../../Contracts/ViewModels"; import AddCollectionPane from "./AddCollectionPane"; import Explorer from "../Explorer"; import ko from "knockout"; -import { AutopilotTier } from "../../Contracts/DataModels"; +import { AutopilotTier, DatabaseAccount } from "../../Contracts/DataModels"; describe("Add Collection Pane", () => { describe("isValid()", () => { let explorer: Explorer; - const mockDatabaseAccount: ViewModels.DatabaseAccount = { + const mockDatabaseAccount: DatabaseAccount = { id: "mock", kind: "DocumentDB", location: "", @@ -24,7 +23,7 @@ describe("Add Collection Pane", () => { tags: [] }; - const mockFreeTierDatabaseAccount: ViewModels.DatabaseAccount = { + const mockFreeTierDatabaseAccount: DatabaseAccount = { id: "mock", kind: "DocumentDB", location: "", diff --git a/src/Explorer/Panes/AddCollectionPane.ts b/src/Explorer/Panes/AddCollectionPane.ts index 7886822b4..d05f21732 100644 --- a/src/Explorer/Panes/AddCollectionPane.ts +++ b/src/Explorer/Panes/AddCollectionPane.ts @@ -22,6 +22,12 @@ import { HashMap } from "../../Common/HashMap"; import { PlatformType } from "../../PlatformType"; import { refreshCachedResources, getOrCreateDatabaseAndCollection } from "../../Common/DocumentClientUtilityBase"; +export interface AddCollectionPaneOptions extends ViewModels.PaneOptions { + isPreferredApiTable: ko.Computed; + databaseId?: string; + databaseSelfLink?: string; +} + export default class AddCollectionPane extends ContextualPaneBase { public defaultExperience: ko.Computed; public databaseIds: ko.ObservableArray; @@ -100,7 +106,7 @@ export default class AddCollectionPane extends ContextualPaneBase { private _databaseOffers: HashMap; private _isSynapseLinkEnabled: ko.Computed; - constructor(options: ViewModels.AddCollectionPaneOptions) { + constructor(options: AddCollectionPaneOptions) { super(options); this._databaseOffers = new HashMap(); this.hasAutoPilotV2FeatureFlag = ko.pureComputed(() => this.container.hasAutoPilotV2FeatureFlag()); @@ -619,7 +625,7 @@ export default class AddCollectionPane extends ContextualPaneBase { this._isSynapseLinkEnabled = ko.computed(() => { const databaseAccount = (this.container && this.container.databaseAccount && this.container.databaseAccount()) || - ({} as ViewModels.DatabaseAccount); + ({} as DataModels.DatabaseAccount); const properties = databaseAccount.properties || ({} as DataModels.DatabaseAccountExtendedProperties); // TODO: remove check for capability once all accounts have been migrated @@ -1266,10 +1272,7 @@ export default class AddCollectionPane extends ContextualPaneBase { : SharedConstants.CollectionCreation.NumberOfPartitionsInUnlimitedCollection; } - private _convertShardKeyToPartitionKey( - shardKey: string, - configurationOverrides: ViewModels.ConfigurationOverrides - ): string { + private _convertShardKeyToPartitionKey(shardKey: string): string { if (!shardKey) { return shardKey; } @@ -1331,10 +1334,7 @@ export default class AddCollectionPane extends ContextualPaneBase { }; if (this.container.isPreferredApiMongoDB()) { transform = (value: string) => { - return this._convertShardKeyToPartitionKey( - value, - this.container.databaseAccount().properties.configurationOverrides - ); + return this._convertShardKeyToPartitionKey(value); }; } diff --git a/src/Explorer/Panes/AddDatabasePane.test.ts b/src/Explorer/Panes/AddDatabasePane.test.ts index ecf27a8e7..58f123b5a 100644 --- a/src/Explorer/Panes/AddDatabasePane.test.ts +++ b/src/Explorer/Panes/AddDatabasePane.test.ts @@ -2,11 +2,12 @@ import * as Constants from "../../Common/Constants"; import * as ViewModels from "../../Contracts/ViewModels"; import Explorer from "../Explorer"; import AddDatabasePane from "./AddDatabasePane"; +import { DatabaseAccount } from "../../Contracts/DataModels"; describe("Add Database Pane", () => { describe("getSharedThroughputDefault()", () => { let explorer: Explorer; - const mockDatabaseAccount: ViewModels.DatabaseAccount = { + const mockDatabaseAccount: DatabaseAccount = { id: "mock", kind: "DocumentDB", location: "", @@ -22,7 +23,7 @@ describe("Add Database Pane", () => { tags: [] }; - const mockFreeTierDatabaseAccount: ViewModels.DatabaseAccount = { + const mockFreeTierDatabaseAccount: DatabaseAccount = { id: "mock", kind: "DocumentDB", location: "", diff --git a/src/Explorer/Panes/BrowseQueriesPane.ts b/src/Explorer/Panes/BrowseQueriesPane.ts index 9d3f3c276..7e4db0dbd 100644 --- a/src/Explorer/Panes/BrowseQueriesPane.ts +++ b/src/Explorer/Panes/BrowseQueriesPane.ts @@ -6,6 +6,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase"; import * as Logger from "../../Common/Logger"; import { QueriesGridComponentAdapter } from "../Controls/QueriesGridReactComponent/QueriesGridComponentAdapter"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import QueryTab from "../Tabs/QueryTab"; export class BrowseQueriesPane extends ContextualPaneBase { public queriesGridComponentAdapter: QueriesGridComponentAdapter; @@ -87,7 +88,7 @@ export class BrowseQueriesPane extends ContextualPaneBase { } else { selectedCollection.onNewQueryClick(selectedCollection, null); } - const queryTab: ViewModels.QueryTab = this.container.tabsManager.activeTab() as ViewModels.QueryTab; + const queryTab = this.container.tabsManager.activeTab() as QueryTab; queryTab.tabTitle(savedQuery.queryName); queryTab.tabPath(`${selectedCollection.databaseId}>${selectedCollection.id()}>${savedQuery.queryName}`); queryTab.initialEditorContent(savedQuery.query); diff --git a/src/Explorer/Panes/ContextualPaneBase.ts b/src/Explorer/Panes/ContextualPaneBase.ts index 2c5312f3f..d63a46492 100644 --- a/src/Explorer/Panes/ContextualPaneBase.ts +++ b/src/Explorer/Panes/ContextualPaneBase.ts @@ -8,7 +8,7 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import Explorer from "../Explorer"; // TODO: Use specific actions for logging telemetry data -export abstract class ContextualPaneBase extends WaitsForTemplateViewModel implements ViewModels.ContextualPane { +export abstract class ContextualPaneBase extends WaitsForTemplateViewModel { public id: string; public container: Explorer; public firstFieldHasFocus: ko.Observable; diff --git a/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts b/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts index e7a77e05c..305c96655 100644 --- a/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts +++ b/src/Explorer/Panes/DeleteCollectionConfirmationPane.test.ts @@ -106,10 +106,10 @@ describe("Delete Collection Confirmation Pane", () => { fakeExplorer.isSelectedDatabaseShared = () => false; const SubscriptionId = "testId"; const AccountName = "testAccount"; - fakeExplorer.databaseAccount = ko.observable({ + fakeExplorer.databaseAccount = ko.observable({ id: SubscriptionId, name: AccountName - } as ViewModels.DatabaseAccount); + } as DataModels.DatabaseAccount); fakeExplorer.defaultExperience = ko.observable("DocumentDB"); fakeExplorer.isPreferredApiCassandra = ko.computed(() => { diff --git a/src/Explorer/Panes/DeleteCollectionConfirmationPane.ts b/src/Explorer/Panes/DeleteCollectionConfirmationPane.ts index bd6fd13f1..c02b675b0 100644 --- a/src/Explorer/Panes/DeleteCollectionConfirmationPane.ts +++ b/src/Explorer/Panes/DeleteCollectionConfirmationPane.ts @@ -66,9 +66,7 @@ export default class DeleteCollectionConfirmationPane extends ContextualPaneBase this.isExecuting(false); this.close(); this.container.selectedNode(selectedCollection.database); - this.container.tabsManager?.closeTabsByComparator( - (tab: ViewModels.Tab) => tab.node && tab.node.rid === selectedCollection.rid - ); + this.container.tabsManager?.closeTabsByComparator(tab => tab.node && tab.node.rid === selectedCollection.rid); this.container.refreshAllDatabases(); this.resetData(); TelemetryProcessor.traceSuccess( diff --git a/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts b/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts index 57d8e487e..3819017cb 100644 --- a/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts +++ b/src/Explorer/Panes/DeleteDatabaseConfirmationPane.test.ts @@ -97,10 +97,10 @@ describe("Delete Database Confirmation Pane", () => { fakeExplorer.isSelectedDatabaseShared = () => false; const SubscriptionId = "testId"; const AccountName = "testAccount"; - fakeExplorer.databaseAccount = ko.observable({ + fakeExplorer.databaseAccount = ko.observable({ id: SubscriptionId, name: AccountName - } as ViewModels.DatabaseAccount); + } as DataModels.DatabaseAccount); fakeExplorer.defaultExperience = ko.observable("DocumentDB"); fakeExplorer.isPreferredApiCassandra = ko.computed(() => { return false; diff --git a/src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts b/src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts index 8644b7c59..5f055fd40 100644 --- a/src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts +++ b/src/Explorer/Panes/DeleteDatabaseConfirmationPane.ts @@ -67,16 +67,12 @@ export default class DeleteDatabaseConfirmationPane extends ContextualPaneBase { this.isExecuting(false); this.close(); this.container.refreshAllDatabases(); - this.container.tabsManager.closeTabsByComparator( - (tab: ViewModels.Tab) => tab.node && tab.node.rid === selectedDatabase.rid - ); + this.container.tabsManager.closeTabsByComparator(tab => tab.node && tab.node.rid === selectedDatabase.rid); this.container.selectedNode(null); selectedDatabase .collections() .forEach((collection: ViewModels.Collection) => - this.container.tabsManager.closeTabsByComparator( - (tab: ViewModels.Tab) => tab.node && tab.node.rid === collection.rid - ) + this.container.tabsManager.closeTabsByComparator(tab => tab.node && tab.node.rid === collection.rid) ); this.resetData(); TelemetryProcessor.traceSuccess( diff --git a/src/Explorer/Panes/GitHubReposPane.ts b/src/Explorer/Panes/GitHubReposPane.ts index 19920296a..8f6fbe3a7 100644 --- a/src/Explorer/Panes/GitHubReposPane.ts +++ b/src/Explorer/Panes/GitHubReposPane.ts @@ -16,6 +16,11 @@ import { BranchesProps, PinnedReposProps, UnpinnedReposProps } from "../Controls import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { ContextualPaneBase } from "./ContextualPaneBase"; +interface GitHubReposPaneOptions extends ViewModels.PaneOptions { + gitHubClient: GitHubClient; + junoClient: JunoClient; +} + export class GitHubReposPane extends ContextualPaneBase { private static readonly PageSize = 30; @@ -33,7 +38,7 @@ export class GitHubReposPane extends ContextualPaneBase { private allGitHubReposLastPageInfo?: IGitHubPageInfo; private pinnedReposUpdated: boolean; - constructor(options: ViewModels.GitHubReposPaneOptions) { + constructor(options: GitHubReposPaneOptions) { super(options); this.gitHubClient = options.gitHubClient; diff --git a/src/Explorer/Panes/LoadQueryPane.ts b/src/Explorer/Panes/LoadQueryPane.ts index 15ab8d99c..c5e21e632 100644 --- a/src/Explorer/Panes/LoadQueryPane.ts +++ b/src/Explorer/Panes/LoadQueryPane.ts @@ -6,6 +6,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import * as Logger from "../../Common/Logger"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; +import QueryTab from "../Tabs/QueryTab"; export class LoadQueryPane extends ContextualPaneBase { public selectedFilesTitle: ko.Observable; @@ -111,7 +112,7 @@ export class LoadQueryPane extends ContextualPaneBase { const reader = new FileReader(); reader.onload = (evt: any): void => { const fileData: string = evt.target.result; - const queryTab: ViewModels.QueryTab = this.container.tabsManager.activeTab() as ViewModels.QueryTab; + const queryTab = this.container.tabsManager.activeTab() as QueryTab; queryTab.initialEditorContent(fileData); queryTab.sqlQueryEditorContent(fileData); deferred.resolve(); diff --git a/src/Explorer/Panes/SaveQueryPane.ts b/src/Explorer/Panes/SaveQueryPane.ts index 548a39769..a64070ef8 100644 --- a/src/Explorer/Panes/SaveQueryPane.ts +++ b/src/Explorer/Panes/SaveQueryPane.ts @@ -7,6 +7,7 @@ import { ContextualPaneBase } from "./ContextualPaneBase"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; +import QueryTab from "../Tabs/QueryTab"; export class SaveQueryPane extends ContextualPaneBase { public queryName: ko.Observable; @@ -34,8 +35,7 @@ export class SaveQueryPane extends ContextualPaneBase { } const queryName: string = this.queryName(); - const queryTab: ViewModels.QueryTab = - this.container && (this.container.tabsManager.activeTab() as ViewModels.QueryTab); + const queryTab = this.container && (this.container.tabsManager.activeTab() as QueryTab); const query: string = queryTab && queryTab.sqlQueryEditorContent(); if (!queryName || queryName.length === 0) { this.formErrors("No query name specified"); diff --git a/src/Explorer/Panes/StringInputPane.ts b/src/Explorer/Panes/StringInputPane.ts index 3e060f2f7..56b6c0463 100644 --- a/src/Explorer/Panes/StringInputPane.ts +++ b/src/Explorer/Panes/StringInputPane.ts @@ -5,11 +5,22 @@ import { ContextualPaneBase } from "./ContextualPaneBase"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; +export interface StringInputPaneOpenOptions { + paneTitle: string; + inputLabel: string; + errorMessage: string; + inProgressMessage: string; + successMessage: string; + onSubmit: (input: string) => Promise; + submitButtonLabel: string; + defaultInput?: string; +} + /** * Generic pane to get a single string input from user */ export class StringInputPane extends ContextualPaneBase { - private openOptions: ViewModels.StringInputPaneOpenOptions; + private openOptions: StringInputPaneOpenOptions; private submitButtonLabel: ko.Observable; private inputLabel: ko.Observable; private stringInput: ko.Observable; @@ -78,7 +89,7 @@ export class StringInputPane extends ContextualPaneBase { this.resetFileInput(); } - public openWithOptions(options: ViewModels.StringInputPaneOpenOptions): Q.Promise { + public openWithOptions(options: StringInputPaneOpenOptions): Q.Promise { this.openOptions = options; this.title(this.openOptions.paneTitle); if (this.openOptions.submitButtonLabel) { diff --git a/src/Explorer/Panes/UploadFilePane.ts b/src/Explorer/Panes/UploadFilePane.ts index 5a1472e92..60dfeb796 100644 --- a/src/Explorer/Panes/UploadFilePane.ts +++ b/src/Explorer/Panes/UploadFilePane.ts @@ -5,10 +5,21 @@ import { ContextualPaneBase } from "./ContextualPaneBase"; import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent"; import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; +export interface UploadFilePaneOpenOptions { + paneTitle: string; + selectFileInputLabel: string; + errorMessage: string; // Could not upload notebook + inProgressMessage: string; // Uploading notebook + successMessage: string; // Successfully uploaded notebook + onSubmit: (file: File) => Promise; + extensions?: string; // input accept field. E.g: .ipynb + submitButtonLabel?: string; +} + export class UploadFilePane extends ContextualPaneBase { public selectedFilesTitle: ko.Observable; public files: ko.Observable; - private openOptions: ViewModels.UploadFilePaneOpenOptions; + private openOptions: UploadFilePaneOpenOptions; private submitButtonLabel: ko.Observable; private selectFileInputLabel: ko.Observable; private extensions: ko.Observable; @@ -79,7 +90,7 @@ export class UploadFilePane extends ContextualPaneBase { this.resetFileInput(); } - public openWithOptions(options: ViewModels.UploadFilePaneOpenOptions): void { + public openWithOptions(options: UploadFilePaneOpenOptions): void { this.openOptions = options; this.title(this.openOptions.paneTitle); if (this.openOptions.submitButtonLabel) { diff --git a/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx b/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx index bd2f381b8..01577934e 100644 --- a/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx +++ b/src/Explorer/SplashScreen/SplashScreenComponentApdapter.tsx @@ -32,7 +32,7 @@ export class SplashScreenComponentAdapter implements ReactAdapter { constructor(private container: Explorer) { this.parameters = ko.observable(Date.now()); - this.container.tabsManager.openedTabs.subscribe((tabs: ViewModels.Tab[]) => { + this.container.tabsManager.openedTabs.subscribe(tabs => { if (tabs.length === 0) { this.forceRender(); } diff --git a/src/Explorer/Tabs/ConflictsTab.ts b/src/Explorer/Tabs/ConflictsTab.ts index a59258bf4..9e6b3c556 100644 --- a/src/Explorer/Tabs/ConflictsTab.ts +++ b/src/Explorer/Tabs/ConflictsTab.ts @@ -14,7 +14,6 @@ import TabsBase from "./TabsBase"; import { DocumentsGridMetrics } from "../../Common/Constants"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; -import Toolbar from "../Controls/Toolbar/Toolbar"; import SaveIcon from "../../../images/save-cosmos.svg"; import DiscardIcon from "../../../images/discard.svg"; import DeleteIcon from "../../../images/delete.svg"; @@ -28,16 +27,16 @@ import { createDocument, updateDocument } from "../../Common/DocumentClientUtilityBase"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; export default class ConflictsTab extends TabsBase { - public selectedConflictId: ko.Observable; + public selectedConflictId: ko.Observable; public selectedConflictContent: ViewModels.Editable; public selectedConflictCurrent: ViewModels.Editable; public documentContentsGridId: string; public documentContentsContainerId: string; public isEditorDirty: ko.Computed; public editorState: ko.Observable; - public toolbarViewModel = ko.observable(); public acceptChangesButton: ViewModels.Button; public discardButton: ViewModels.Button; public deleteButton: ViewModels.Button; @@ -54,7 +53,7 @@ export default class ConflictsTab extends TabsBase { public partitionKeyPropertyHeader: string; public partitionKeyProperty: string; public conflictOperation: ko.Observable = ko.observable(); - public conflictIds: ko.ObservableArray; + public conflictIds: ko.ObservableArray; private _documentsIterator: MinimalQueryIterator; private _container: Explorer; @@ -70,7 +69,7 @@ export default class ConflictsTab extends TabsBase { this.editorState = ko.observable( ViewModels.DocumentExplorerState.noDocumentSelected ); - this.selectedConflictId = ko.observable(); + this.selectedConflictId = ko.observable(); this.selectedConflictContent = editable.observable(""); this.selectedConflictCurrent = editable.observable(""); this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey); @@ -106,14 +105,14 @@ export default class ConflictsTab extends TabsBase { this.accessibleDocumentList = new AccessibleVerticalList(this.conflictIds()); this.accessibleDocumentList.setOnSelect( - (selectedDocument: ViewModels.ConflictId) => selectedDocument && selectedDocument.click() + (selectedDocument: ConflictId) => selectedDocument && selectedDocument.click() ); - this.selectedConflictId.subscribe((newSelectedDocumentId: ViewModels.ConflictId) => { + this.selectedConflictId.subscribe((newSelectedDocumentId: ConflictId) => { this.accessibleDocumentList.updateCurrentItem(newSelectedDocumentId); this.conflictOperation(newSelectedDocumentId && newSelectedDocumentId.operationType); }); - this.conflictIds.subscribe((newDocuments: ViewModels.ConflictId[]) => { + this.conflictIds.subscribe((newDocuments: ConflictId[]) => { this.accessibleDocumentList.updateItemList(newDocuments); this.dataContentsGridScrollHeight( newDocuments.length * DocumentsGridMetrics.IndividualRowHeight + DocumentsGridMetrics.BufferHeight + "px" @@ -259,7 +258,7 @@ export default class ConflictsTab extends TabsBase { return true; }; - public onConflictIdClick(clickedDocumentId: ViewModels.ConflictId): Q.Promise { + public onConflictIdClick(clickedDocumentId: ConflictId): Q.Promise { if (this.editorState() !== ViewModels.DocumentExplorerState.noDocumentSelected) { return Q(); } @@ -319,7 +318,7 @@ export default class ConflictsTab extends TabsBase { .then( () => { return deleteConflict(this.collection, selectedConflict).then(() => { - this.conflictIds.remove((conflictId: ViewModels.ConflictId) => conflictId.rid === selectedConflict.rid); + this.conflictIds.remove((conflictId: ConflictId) => conflictId.rid === selectedConflict.rid); this.selectedConflictContent(""); this.selectedConflictCurrent(""); this.selectedConflictId(null); @@ -380,7 +379,7 @@ export default class ConflictsTab extends TabsBase { return deleteConflict(this.collection, selectedConflict) .then( () => { - this.conflictIds.remove((conflictId: ViewModels.ConflictId) => conflictId.rid === selectedConflict.rid); + this.conflictIds.remove((conflictId: ConflictId) => conflictId.rid === selectedConflict.rid); this.selectedConflictContent(""); this.selectedConflictCurrent(""); this.selectedConflictId(null); @@ -515,7 +514,7 @@ export default class ConflictsTab extends TabsBase { }) // map raw response to view model .map((rawDocument: any) => { - return new ConflictId(this, rawDocument); + return new ConflictId(this, rawDocument); }); const merged = currentConflicts.concat(nextConflictIds); @@ -580,7 +579,7 @@ export default class ConflictsTab extends TabsBase { } } - public initDocumentEditorForCreate(documentId: ViewModels.ConflictId, documentToInsert: any): Q.Promise { + public initDocumentEditorForCreate(documentId: ConflictId, documentToInsert: any): Q.Promise { if (documentId) { let parsedConflictContent: any = JSON.parse(documentToInsert); const renderedConflictContent: string = this.renderObjectForEditor(parsedConflictContent, null, 4); @@ -592,7 +591,7 @@ export default class ConflictsTab extends TabsBase { } public initDocumentEditorForReplace( - documentId: ViewModels.ConflictId, + documentId: ConflictId, conflictContent: any, currentContent: any ): Q.Promise { @@ -612,7 +611,7 @@ export default class ConflictsTab extends TabsBase { return Q(); } - public initDocumentEditorForDelete(documentId: ViewModels.ConflictId, documentToDelete: any): Q.Promise { + public initDocumentEditorForDelete(documentId: ConflictId, documentToDelete: any): Q.Promise { if (documentId) { let parsedDocumentToDelete: any = JSON.parse(documentToDelete); parsedDocumentToDelete = ConflictsTab.removeSystemProperties(parsedDocumentToDelete); @@ -624,15 +623,15 @@ export default class ConflictsTab extends TabsBase { return Q(); } - public initDocumentEditorForNoOp(documentId: ViewModels.ConflictId): Q.Promise { + public initDocumentEditorForNoOp(documentId: ConflictId): Q.Promise { this.selectedConflictContent(null); this.selectedConflictCurrent(null); this.editorState(ViewModels.DocumentExplorerState.noDocumentSelected); return Q(); } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; const label = this._acceptButtonLabel(); if (this.acceptChangesButton.visible()) { buttons.push({ diff --git a/src/Explorer/Tabs/DatabaseSettingsTab.ts b/src/Explorer/Tabs/DatabaseSettingsTab.ts index 54ccff808..0abcb19c6 100644 --- a/src/Explorer/Tabs/DatabaseSettingsTab.ts +++ b/src/Explorer/Tabs/DatabaseSettingsTab.ts @@ -19,6 +19,7 @@ import { PlatformType } from "../../PlatformType"; import { RequestOptions } from "@azure/cosmos/dist-esm"; import Explorer from "../Explorer"; import { updateOfferThroughputBeyondLimit, updateOffer } from "../../Common/DocumentClientUtilityBase"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; const updateThroughputBeyondLimitWarningMessage: string = ` You are about to request an increase in throughput beyond the pre-allocated capacity. @@ -667,8 +668,8 @@ export default class DatabaseSettingsTab extends TabsBase implements ViewModels. } } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; const label = "Save"; if (this.saveSettingsButton.visible()) { buttons.push({ diff --git a/src/Explorer/Tabs/DocumentsTab.test.ts b/src/Explorer/Tabs/DocumentsTab.test.ts index f5c6a022b..51753969f 100644 --- a/src/Explorer/Tabs/DocumentsTab.test.ts +++ b/src/Explorer/Tabs/DocumentsTab.test.ts @@ -3,13 +3,15 @@ import * as ViewModels from "../../Contracts/ViewModels"; import * as Constants from "../../Common/Constants"; import DocumentsTab from "./DocumentsTab"; import Explorer from "../Explorer"; +import DocumentId from "../Tree/DocumentId"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; describe("Documents tab", () => { describe("buildQuery", () => { it("should generate the right select query for SQL API", () => { const documentsTab = new DocumentsTab({ partitionKey: null, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, title: "", tabPath: "", @@ -17,7 +19,7 @@ describe("Documents tab", () => { hashLocation: "", isActive: ko.observable(false), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(documentsTab.buildQuery("")).toContain("select"); @@ -89,7 +91,7 @@ describe("Documents tab", () => { it("should be false for null or undefined collection", () => { const documentsTab = new DocumentsTab({ partitionKey: null, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, title: "", tabPath: "", @@ -97,7 +99,7 @@ describe("Documents tab", () => { hashLocation: "", isActive: ko.observable(false), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(documentsTab.showPartitionKey).toBe(false); @@ -107,7 +109,7 @@ describe("Documents tab", () => { const documentsTab = new DocumentsTab({ collection: collectionWithoutPartitionKey, partitionKey: null, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, title: "", tabPath: "", @@ -115,7 +117,7 @@ describe("Documents tab", () => { hashLocation: "", isActive: ko.observable(false), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(documentsTab.showPartitionKey).toBe(false); @@ -125,7 +127,7 @@ describe("Documents tab", () => { const documentsTab = new DocumentsTab({ collection: collectionWithSystemPartitionKey, partitionKey: null, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, title: "", tabPath: "", @@ -133,7 +135,7 @@ describe("Documents tab", () => { hashLocation: "", isActive: ko.observable(false), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(documentsTab.showPartitionKey).toBe(true); @@ -143,7 +145,7 @@ describe("Documents tab", () => { const documentsTab = new DocumentsTab({ collection: mongoCollectionWithSystemPartitionKey, partitionKey: null, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, title: "", tabPath: "", @@ -151,7 +153,7 @@ describe("Documents tab", () => { hashLocation: "", isActive: ko.observable(false), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(documentsTab.showPartitionKey).toBe(false); @@ -161,7 +163,7 @@ describe("Documents tab", () => { const documentsTab = new DocumentsTab({ collection: collectionWithNonSystemPartitionKey, partitionKey: null, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, title: "", tabPath: "", @@ -169,7 +171,7 @@ describe("Documents tab", () => { hashLocation: "", isActive: ko.observable(false), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(documentsTab.showPartitionKey).toBe(true); diff --git a/src/Explorer/Tabs/DocumentsTab.ts b/src/Explorer/Tabs/DocumentsTab.ts index a2d59974f..b055a24a0 100644 --- a/src/Explorer/Tabs/DocumentsTab.ts +++ b/src/Explorer/Tabs/DocumentsTab.ts @@ -15,13 +15,11 @@ import { DocumentsGridMetrics } from "../../Common/Constants"; import { QueryUtils } from "../../Utils/QueryUtils"; import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; -import Toolbar from "../Controls/Toolbar/Toolbar"; import NewDocumentIcon from "../../../images/NewDocument.svg"; import SaveIcon from "../../../images/save-cosmos.svg"; import DiscardIcon from "../../../images/discard.svg"; import DeleteDocumentIcon from "../../../images/DeleteDocument.svg"; import UploadIcon from "../../../images/Upload_16x16.svg"; -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"; @@ -33,9 +31,10 @@ import { updateDocument, createDocument } from "../../Common/DocumentClientUtilityBase"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; -export default class DocumentsTab extends TabsBase implements ViewModels.DocumentsTab { - public selectedDocumentId: ko.Observable; +export default class DocumentsTab extends TabsBase { + public selectedDocumentId: ko.Observable; public selectedDocumentContent: ViewModels.Editable; public initialDocumentContent: ko.Observable; public documentContentsGridId: string; @@ -48,7 +47,6 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen public applyFilterButton: ViewModels.Button; public isEditorDirty: ko.Computed; public editorState: ko.Observable; - public toolbarViewModel = ko.observable(); public newDocumentButton: ViewModels.Button; public saveNewDocumentButton: ViewModels.Button; public saveExisitingDocumentButton: ViewModels.Button; @@ -68,7 +66,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen public partitionKey: DataModels.PartitionKey; public partitionKeyPropertyHeader: string; public partitionKeyProperty: string; - public documentIds: ko.ObservableArray; + public documentIds: ko.ObservableArray; private _documentsIterator: QueryIterator; private _resourceTokenPartitionKey: string; @@ -87,7 +85,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen this.editorState = ko.observable( ViewModels.DocumentExplorerState.noDocumentSelected ); - this.selectedDocumentId = ko.observable(); + this.selectedDocumentId = ko.observable(); this.selectedDocumentContent = editable.observable(""); this.initialDocumentContent = ko.observable(""); this.partitionKey = options.partitionKey || (this.collection && this.collection.partitionKey); @@ -415,7 +413,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen return true; }; - public onDocumentIdClick(clickedDocumentId: ViewModels.DocumentId): Q.Promise { + public onDocumentIdClick(clickedDocumentId: DocumentId): Q.Promise { if (this.editorState() !== ViewModels.DocumentExplorerState.noDocumentSelected) { return Q(); } @@ -528,7 +526,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen const value: string = this.renderObjectForEditor(updatedDocument || {}, null, 4); this.selectedDocumentContent.setBaseline(value); this.initialDocumentContent(value); - this.documentIds().forEach((documentId: ViewModels.DocumentId) => { + this.documentIds().forEach((documentId: DocumentId) => { if (documentId.rid === updatedDocument._rid) { documentId.id(updatedDocument.id); } @@ -669,11 +667,11 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen return window.confirm(msg); }; - protected __deleteDocument(documentId: ViewModels.DocumentId): Q.Promise { + protected __deleteDocument(documentId: DocumentId): Q.Promise { return deleteDocument(this.collection, documentId); } - private _deleteDocument(selectedDocumentId: ViewModels.DocumentId): Q.Promise { + private _deleteDocument(selectedDocumentId: DocumentId): Q.Promise { this.isExecutionError(false); const startKey: number = TelemetryProcessor.traceStart(Action.DeleteDocument, { databaseAccountName: this.collection && this.collection.container.databaseAccount().name, @@ -685,7 +683,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen return this.__deleteDocument(selectedDocumentId) .then( (result: any) => { - this.documentIds.remove((documentId: ViewModels.DocumentId) => documentId.rid === selectedDocumentId.rid); + this.documentIds.remove((documentId: DocumentId) => documentId.rid === selectedDocumentId.rid); this.selectedDocumentContent(""); this.selectedDocumentId(null); this.editorState(ViewModels.DocumentExplorerState.noDocumentSelected); @@ -732,7 +730,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen return queryDocuments(this.collection.databaseId, this.collection.id(), query, options); } - public selectDocument(documentId: ViewModels.DocumentId): Q.Promise { + public selectDocument(documentId: DocumentId): Q.Promise { this.selectedDocumentId(documentId); return readDocument(this.collection, documentId).then((content: any) => { this.initDocumentEditor(documentId, content); @@ -755,7 +753,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen // map raw response to view model .map((rawDocument: any) => { const partitionKeyValue = rawDocument._partitionKeyValue; - return new DocumentId(this, rawDocument, partitionKeyValue); + return new DocumentId(this, rawDocument, partitionKeyValue); }); const merged = currentDocuments.concat(nextDocumentIds); @@ -826,7 +824,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen } } - public initDocumentEditor(documentId: ViewModels.DocumentId, documentContent: any): Q.Promise { + public initDocumentEditor(documentId: DocumentId, documentContent: any): Q.Promise { if (documentId) { const content: string = this.renderObjectForEditor(documentContent, null, 4); this.selectedDocumentContent.setBaseline(content); @@ -844,8 +842,8 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen return QueryUtils.buildDocumentsQuery(filter, this.partitionKeyProperty, this.partitionKey); } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; const label = !this.isPreferredApiMongoDB ? "New Item" : "New Document"; if (this.newDocumentButton.visible()) { buttons.push({ @@ -963,7 +961,7 @@ export default class DocumentsTab extends TabsBase implements ViewModels.Documen ); } - public static _createUploadButton(container: Explorer): ViewModels.NavbarButtonConfig { + public static _createUploadButton(container: Explorer): CommandButtonComponentProps { const label = "Upload Item"; return { iconSrc: UploadIcon, diff --git a/src/Explorer/Tabs/GalleryTab.tsx b/src/Explorer/Tabs/GalleryTab.tsx index 0820adbea..2d9768021 100644 --- a/src/Explorer/Tabs/GalleryTab.tsx +++ b/src/Explorer/Tabs/GalleryTab.tsx @@ -4,15 +4,26 @@ import { GalleryAndNotebookViewerComponentAdapter } from "../Controls/NotebookGa import { GalleryTab as GalleryViewerTab, SortBy } from "../Controls/NotebookGallery/GalleryViewerComponent"; import TabsBase from "./TabsBase"; import Explorer from "../Explorer"; +import { DatabaseAccount } from "../../Contracts/DataModels"; +import { JunoClient, IGalleryItem } from "../../Juno/JunoClient"; + +interface GalleryTabOptions extends ViewModels.TabOptions { + account: DatabaseAccount; + container: Explorer; + junoClient: JunoClient; + notebookUrl?: string; + galleryItem?: IGalleryItem; + isFavorite?: boolean; +} /** * Notebook gallery tab */ -export default class GalleryTab extends TabsBase implements ViewModels.Tab { +export default class GalleryTab extends TabsBase { private container: Explorer; public galleryAndNotebookViewerComponentAdapter: GalleryAndNotebookViewerComponentAdapter; - constructor(options: ViewModels.GalleryTabOptions) { + constructor(options: GalleryTabOptions) { super(options); this.container = options.container; diff --git a/src/Explorer/Tabs/GraphTab.ts b/src/Explorer/Tabs/GraphTab.ts index bca170500..4cd08f000 100644 --- a/src/Explorer/Tabs/GraphTab.ts +++ b/src/Explorer/Tabs/GraphTab.ts @@ -2,13 +2,14 @@ import * as ko from "knockout"; import * as Q from "q"; import * as ViewModels from "../../Contracts/ViewModels"; import TabsBase from "./TabsBase"; -import Toolbar from "../Controls/Toolbar/Toolbar"; import { GraphExplorerAdapter } from "../Graph/GraphExplorerComponent/GraphExplorerAdapter"; import { GraphAccessor, GraphExplorerError } from "../Graph/GraphExplorerComponent/GraphExplorer"; import NewVertexIcon from "../../../images/NewVertex.svg"; import StyleIcon from "../../../images/Style.svg"; import GraphStylingPane from "../Panes/GraphStylingPane"; import NewVertexPane from "../Panes/NewVertexPane"; +import { DatabaseAccount } from "../../Contracts/DataModels"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; export interface GraphIconMap { [key: string]: { data: string; format: string }; @@ -26,7 +27,15 @@ export interface GraphConfig { iconsMap: ko.Observable; } -export default class GraphTab extends TabsBase implements ViewModels.Tab { +interface GraphTabOptions extends ViewModels.TabOptions { + account: DatabaseAccount; + masterKey: string; + collectionId: string; + databaseId: string; + collectionPartitionKeyProperty: string; +} + +export default class GraphTab extends TabsBase { // Graph default configuration public static readonly DEFAULT_NODE_CAPTION = "id"; private static readonly LINK_COLOR = "#aaa"; @@ -38,7 +47,6 @@ export default class GraphTab extends TabsBase implements ViewModels.Tab { private isPropertyEditing: ko.Observable; private isGraphDisplayed: ko.Observable; private graphAccessor: GraphAccessor; - public toolbarViewModel: ko.Observable; private graphConfig: GraphConfig; private graphConfigUiData: ViewModels.GraphConfigUiData; private isFilterQueryLoading: ko.Observable; @@ -47,7 +55,7 @@ export default class GraphTab extends TabsBase implements ViewModels.Tab { private graphStylingPane: GraphStylingPane; private collectionPartitionKeyProperty: string; - constructor(options: ViewModels.GraphTabOptions) { + constructor(options: GraphTabOptions) { super(options); this.newVertexPane = options.collection && options.collection.container.newVertexPane; @@ -100,10 +108,9 @@ export default class GraphTab extends TabsBase implements ViewModels.Tab { this.isFilterQueryLoading = ko.observable(false); this.isValidQuery = ko.observable(true); - this.toolbarViewModel = ko.observable(); } - public static getGremlinEndpoint(account: ViewModels.DatabaseAccount): string { + public static getGremlinEndpoint(account: DatabaseAccount): string { return account.properties.gremlinEndpoint ? GraphTab.sanitizeHost(account.properties.gremlinEndpoint) : `${account.name}.graphs.azure.com:443/`; @@ -202,9 +209,9 @@ export default class GraphTab extends TabsBase implements ViewModels.Tab { this.graphConfigUiData.nodeIconChoice(this.graphConfigUiData.nodePropertiesWithNone()[0]); } } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { + protected getTabsButtons(): CommandButtonComponentProps[] { const label = "New Vertex"; - const buttons: ViewModels.NavbarButtonConfig[] = [ + const buttons: CommandButtonComponentProps[] = [ { iconSrc: NewVertexIcon, iconAlt: label, diff --git a/src/Explorer/Tabs/MongoDocumentsTab.ts b/src/Explorer/Tabs/MongoDocumentsTab.ts index 393166176..4ca9e6cb3 100644 --- a/src/Explorer/Tabs/MongoDocumentsTab.ts +++ b/src/Explorer/Tabs/MongoDocumentsTab.ts @@ -21,7 +21,7 @@ import { extractPartitionKey } from "@azure/cosmos"; import * as Logger from "../../Common/Logger"; import { PartitionKeyDefinition } from "@azure/cosmos"; -export default class MongoDocumentsTab extends DocumentsTab implements ViewModels.DocumentsTab { +export default class MongoDocumentsTab extends DocumentsTab { public collection: ViewModels.Collection; private continuationToken: string; @@ -151,7 +151,7 @@ export default class MongoDocumentsTab extends DocumentsTab implements ViewModel let value: string = this.renderObjectForEditor(updatedDocument || {}, null, 4); this.selectedDocumentContent.setBaseline(value); - this.documentIds().forEach((documentId: ViewModels.DocumentId) => { + this.documentIds().forEach((documentId: DocumentId) => { if (documentId.rid === updatedDocument._rid) { const partitionKeyArray = extractPartitionKey( updatedDocument, @@ -199,7 +199,7 @@ export default class MongoDocumentsTab extends DocumentsTab implements ViewModel return filter || "{}"; } - public selectDocument(documentId: ViewModels.DocumentId): Q.Promise { + public selectDocument(documentId: DocumentId): Q.Promise { this.selectedDocumentId(documentId); return Q( readDocument(this.collection.databaseId, this.collection, documentId).then((content: any) => { @@ -226,7 +226,7 @@ export default class MongoDocumentsTab extends DocumentsTab implements ViewModel }) .map((rawDocument: any) => { const partitionKeyValue = rawDocument._partitionKeyValue; - return new DocumentId(this, rawDocument, partitionKeyValue); + return new DocumentId(this, rawDocument, partitionKeyValue); }); const merged = currentDocuments.concat(nextDocumentIds); @@ -324,7 +324,7 @@ export default class MongoDocumentsTab extends DocumentsTab implements ViewModel return partitionKey; } - protected __deleteDocument(documentId: ViewModels.DocumentId): Q.Promise { + protected __deleteDocument(documentId: DocumentId): Q.Promise { return Q(deleteDocument(this.collection.databaseId, this.collection, documentId)); } } diff --git a/src/Explorer/Tabs/MongoQueryTab.ts b/src/Explorer/Tabs/MongoQueryTab.ts index 455ca290d..53ba3271e 100644 --- a/src/Explorer/Tabs/MongoQueryTab.ts +++ b/src/Explorer/Tabs/MongoQueryTab.ts @@ -6,7 +6,7 @@ import * as HeadersUtility from "../../Common/HeadersUtility"; import { queryIterator } from "../../Common/MongoProxyClient"; import { MinimalQueryIterator } from "../../Common/IteratorUtilities"; -export default class MongoQueryTab extends QueryTab implements ViewModels.QueryTab { +export default class MongoQueryTab extends QueryTab { public collection: ViewModels.Collection; constructor(options: ViewModels.QueryTabOptions) { diff --git a/src/Explorer/Tabs/MongoShellTab.ts b/src/Explorer/Tabs/MongoShellTab.ts index dbeda93cc..058eebd64 100644 --- a/src/Explorer/Tabs/MongoShellTab.ts +++ b/src/Explorer/Tabs/MongoShellTab.ts @@ -15,7 +15,7 @@ import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils"; import { PlatformType } from "../../PlatformType"; import Explorer from "../Explorer"; -export default class MongoShellTab extends TabsBase implements ViewModels.MongoShellTab { +export default class MongoShellTab extends TabsBase { public url: ko.Computed; private _container: Explorer; private _runtimeEndpoint: string; @@ -26,7 +26,7 @@ export default class MongoShellTab extends TabsBase implements ViewModels.MongoS this._logTraces = new HashMap(); this._container = options.collection.container; this.url = ko.computed(() => { - const account: ViewModels.DatabaseAccount = CosmosClient.databaseAccount(); + const account = CosmosClient.databaseAccount(); const resourceId: string = account && account.id; const accountName = account && account.name; const mongoEndpoint = account && (account.properties.mongoEndpoint || account.properties.documentEndpoint); diff --git a/src/Explorer/Tabs/NotebookV2Tab.ts b/src/Explorer/Tabs/NotebookV2Tab.ts index 75e775da0..cbcf4ddf4 100644 --- a/src/Explorer/Tabs/NotebookV2Tab.ts +++ b/src/Explorer/Tabs/NotebookV2Tab.ts @@ -28,15 +28,24 @@ import { NotebookConfigurationUtils } from "../../Utils/NotebookConfigurationUti import { KernelSpecsDisplay, NotebookClientV2 } from "../Notebook/NotebookClientV2"; import { config } from "../../Config"; import Explorer from "../Explorer"; +import { NotebookContentItem } from "../Notebook/NotebookContentItem"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; -export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { +export interface NotebookTabOptions extends ViewModels.TabOptions { + account: DataModels.DatabaseAccount; + masterKey: string; + container: Explorer; + notebookContentItem: NotebookContentItem; +} + +export default class NotebookTabV2 extends TabsBase { private static clientManager: NotebookClientV2; private container: Explorer; public notebookPath: ko.Observable; private selectedSparkPool: ko.Observable; private notebookComponentAdapter: NotebookComponentAdapter; - constructor(options: ViewModels.NotebookTabOptions) { + constructor(options: NotebookTabOptions) { super(options); this.container = options.container; @@ -109,7 +118,7 @@ export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { return this.container; } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { + protected getTabsButtons(): CommandButtonComponentProps[] { const availableKernels = NotebookTabV2.clientManager.getAvailableKernelSpecs(); const saveLabel = "Save"; @@ -136,7 +145,7 @@ export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { const cellCodeType = "code"; const cellMarkdownType = "markdown"; const cellRawType = "raw"; - let buttons: ViewModels.NavbarButtonConfig[] = [ + let buttons: CommandButtonComponentProps[] = [ { iconSrc: SaveIcon, iconAlt: saveLabel, @@ -188,7 +197,7 @@ export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { hasPopup: false, disabled: false, ariaLabel: kernel.displayName - } as ViewModels.NavbarButtonConfig) + } as CommandButtonComponentProps) ), ariaLabel: kernelLabel }, @@ -363,7 +372,7 @@ export default class NotebookTabV2 extends TabsBase implements ViewModels.Tab { ]; if (this.container.hasStorageAnalyticsAfecFeature()) { - const arcadiaWorkspaceDropdown: ViewModels.NavbarButtonConfig = { + const arcadiaWorkspaceDropdown: CommandButtonComponentProps = { iconSrc: null, iconAlt: workspaceLabel, ariaLabel: workspaceLabel, diff --git a/src/Explorer/Tabs/NotebookViewerTab.tsx b/src/Explorer/Tabs/NotebookViewerTab.tsx index f9b573e42..8cbce11e8 100644 --- a/src/Explorer/Tabs/NotebookViewerTab.tsx +++ b/src/Explorer/Tabs/NotebookViewerTab.tsx @@ -8,6 +8,14 @@ import { } from "../Controls/NotebookViewer/NotebookViewerComponent"; import TabsBase from "./TabsBase"; import Explorer from "../Explorer"; +import { DatabaseAccount } from "../../Contracts/DataModels"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; + +interface NotebookViewerTabOptions extends ViewModels.TabOptions { + account: DatabaseAccount; + container: Explorer; + notebookUrl: string; +} /** * Notebook Viewer tab @@ -29,13 +37,13 @@ class NotebookViewerComponentAdapter implements ReactAdapter { } } -export default class NotebookViewerTab extends TabsBase implements ViewModels.Tab { +export default class NotebookViewerTab extends TabsBase { private container: Explorer; public notebookUrl: string; public notebookViewerComponentAdapter: NotebookViewerComponentAdapter; - constructor(options: ViewModels.NotebookViewerTabOptions) { + constructor(options: NotebookViewerTabOptions) { super(options); this.container = options.container; this.notebookUrl = options.notebookUrl; @@ -54,7 +62,7 @@ export default class NotebookViewerTab extends TabsBase implements ViewModels.Ta return this.container; } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { + protected getTabsButtons(): CommandButtonComponentProps[] { return []; } diff --git a/src/Explorer/Tabs/QueryTab.test.ts b/src/Explorer/Tabs/QueryTab.test.ts index 9917b99af..d63eb25c2 100644 --- a/src/Explorer/Tabs/QueryTab.test.ts +++ b/src/Explorer/Tabs/QueryTab.test.ts @@ -3,11 +3,10 @@ import * as Constants from "../../Common/Constants"; import * as ViewModels from "../../Contracts/ViewModels"; import Explorer from "../Explorer"; import QueryTab from "./QueryTab"; -import { View } from "@nteract/data-explorer/lib/utilities/types"; -import { PartitionKey } from "../../Contracts/DataModels"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; describe("Query Tab", () => { - function getNewQueryTabForContainer(container: Explorer): ViewModels.QueryTab { + function getNewQueryTabForContainer(container: Explorer): QueryTab { const database = { container: container, id: ko.observable("test"), @@ -28,7 +27,7 @@ describe("Query Tab", () => { selfLink: "", isActive: ko.observable(false), hashLocation: "", - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); } @@ -55,13 +54,13 @@ describe("Query Tab", () => { it("should be true for accounts using SQL API", () => { explorer.defaultExperience(Constants.DefaultAccountExperience.DocumentDB.toLowerCase()); - const queryTab: ViewModels.QueryTab = getNewQueryTabForContainer(explorer); + const queryTab = getNewQueryTabForContainer(explorer); expect(queryTab.isQueryMetricsEnabled()).toBe(true); }); it("should be false for accounts using other APIs", () => { explorer.defaultExperience(Constants.DefaultAccountExperience.Graph.toLowerCase()); - const queryTab: ViewModels.QueryTab = getNewQueryTabForContainer(explorer); + const queryTab = getNewQueryTabForContainer(explorer); expect(queryTab.isQueryMetricsEnabled()).toBe(false); }); }); @@ -75,13 +74,13 @@ describe("Query Tab", () => { it("should be visible when using a supported API", () => { explorer.defaultExperience(Constants.DefaultAccountExperience.DocumentDB); - const queryTab: ViewModels.QueryTab = getNewQueryTabForContainer(explorer); + const queryTab = getNewQueryTabForContainer(explorer); expect(queryTab.saveQueryButton.visible()).toBe(true); }); it("should not be visible when using an unsupported API", () => { explorer.defaultExperience(Constants.DefaultAccountExperience.MongoDB); - const queryTab: ViewModels.QueryTab = getNewQueryTabForContainer(explorer); + const queryTab = getNewQueryTabForContainer(explorer); expect(queryTab.saveQueryButton.visible()).toBe(false); }); }); diff --git a/src/Explorer/Tabs/QueryTab.ts b/src/Explorer/Tabs/QueryTab.ts index 855849bc7..6b076b45f 100644 --- a/src/Explorer/Tabs/QueryTab.ts +++ b/src/Explorer/Tabs/QueryTab.ts @@ -17,13 +17,14 @@ import SaveQueryIcon from "../../../images/save-cosmos.svg"; import { MinimalQueryIterator } from "../../Common/IteratorUtilities"; import { queryDocuments, queryDocumentsPage } from "../../Common/DocumentClientUtilityBase"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; enum ToggleState { Result, QueryMetrics } -export default class QueryTab extends TabsBase implements ViewModels.QueryTab, ViewModels.WaitsForTemplate { +export default class QueryTab extends TabsBase implements ViewModels.WaitsForTemplate { public queryEditorId: string; public executeQueryButton: ViewModels.Button; public fetchNextPageButton: ViewModels.Button; @@ -586,8 +587,8 @@ export default class QueryTab extends TabsBase implements ViewModels.QueryTab, V return csvData; } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; if (this.executeQueryButton.visible()) { const label = this._executeQueryButtonTitle(); buttons.push({ diff --git a/src/Explorer/Tabs/QueryTablesTab.ts b/src/Explorer/Tabs/QueryTablesTab.ts index 626e641c5..6d4b50040 100644 --- a/src/Explorer/Tabs/QueryTablesTab.ts +++ b/src/Explorer/Tabs/QueryTablesTab.ts @@ -14,6 +14,7 @@ import AddEntityIcon from "../../../images/AddEntity.svg"; import EditEntityIcon from "../../../images/Edit-entity.svg"; import DeleteEntitiesIcon from "../../../images/DeleteEntities.svg"; import Explorer from "../Explorer"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; // Will act as table explorer class export default class QueryTablesTab extends TabsBase { @@ -173,8 +174,8 @@ export default class QueryTablesTab extends TabsBase { }); } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; if (this.queryBuilderButton.visible()) { const label = this.container.isPreferredApiCassandra() ? "CQL Query Builder" : "Query Builder"; buttons.push({ diff --git a/src/Explorer/Tabs/ScriptTabBase.ts b/src/Explorer/Tabs/ScriptTabBase.ts index ee5be1c18..ab2d46250 100644 --- a/src/Explorer/Tabs/ScriptTabBase.ts +++ b/src/Explorer/Tabs/ScriptTabBase.ts @@ -9,9 +9,9 @@ import editable from "../../Common/EditableUtility"; import * as monaco from "monaco-editor"; import SaveIcon from "../../../images/save-cosmos.svg"; import DiscardIcon from "../../../images/discard.svg"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; -export default abstract class ScriptTabBase extends TabsBase - implements ViewModels.ScriptTab, ViewModels.WaitsForTemplate { +export default abstract class ScriptTabBase extends TabsBase implements ViewModels.WaitsForTemplate { public ariaLabel: ko.Observable; public editorState: ko.Observable; public id: ViewModels.Editable; @@ -216,8 +216,8 @@ export default abstract class ScriptTabBase extends TabsBase return Q(); } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; const label = "Save"; if (this.saveButton.visible()) { buttons.push({ diff --git a/src/Explorer/Tabs/SettingsTab.test.ts b/src/Explorer/Tabs/SettingsTab.test.ts index d45c3776a..67242446c 100644 --- a/src/Explorer/Tabs/SettingsTab.test.ts +++ b/src/Explorer/Tabs/SettingsTab.test.ts @@ -6,6 +6,7 @@ import Collection from "../Tree/Collection"; import Database from "../Tree/Database"; import Explorer from "../Explorer"; import SettingsTab from "../Tabs/SettingsTab"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; describe("Settings tab", () => { const baseCollection: DataModels.Collection = { @@ -189,7 +190,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(settingsTab.shouldUpdateCollection()).toBe(false); @@ -212,7 +213,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(settingsTab.shouldUpdateCollection()).toBe(false); @@ -230,7 +231,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(settingsTab.shouldUpdateCollection()).toBe(false); @@ -268,7 +269,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(settingsTab.getUpdatedConflictResolutionPolicy()).toBe(null); @@ -284,7 +285,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(settingsTab.getUpdatedConflictResolutionPolicy()).toBe(null); @@ -309,7 +310,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: new Collection(explorer, "mydb", baseCollection, quotaInfo, null), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); expect(settingsTab.getUpdatedConflictResolutionPolicy()).toBe(null); @@ -388,7 +389,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: getCollection(defaultApi, partitionKeyOption), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); } @@ -532,7 +533,7 @@ describe("Settings tab", () => { hashLocation: "", isActive: ko.observable(false), collection: getCollection(autoPilotTier), - onUpdateTabsButtons: (buttons: ViewModels.NavbarButtonConfig[]): void => {} + onUpdateTabsButtons: (buttons: CommandButtonComponentProps[]): void => {} }); } describe("Visible", () => { diff --git a/src/Explorer/Tabs/SettingsTab.ts b/src/Explorer/Tabs/SettingsTab.ts index 01f0d0de6..38127aea4 100644 --- a/src/Explorer/Tabs/SettingsTab.ts +++ b/src/Explorer/Tabs/SettingsTab.ts @@ -23,6 +23,7 @@ import { updateOffer, updateCollection } from "../../Common/DocumentClientUtilityBase"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; 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. @@ -412,14 +413,14 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor }); this.isAutoScaleEnabled = ko.pureComputed(() => { - const accountCapabilities: ViewModels.Capability[] = + const accountCapabilities: DataModels.Capability[] = this.container && this.container.databaseAccount() && this.container.databaseAccount().properties && this.container.databaseAccount().properties.capabilities; - const enableAutoScaleCapability: ViewModels.Capability = + const enableAutoScaleCapability = accountCapabilities && - _.find(accountCapabilities, (capability: ViewModels.Capability) => { + _.find(accountCapabilities, capability => { return ( capability && capability.name && @@ -1692,8 +1693,8 @@ export default class SettingsTab extends TabsBase implements ViewModels.WaitsFor return document.getElementById(this.indexingPolicyEditorId); } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; if (this.saveSettingsButton.visible()) { const label = "Save"; buttons.push({ diff --git a/src/Explorer/Tabs/SparkMasterTab.ts b/src/Explorer/Tabs/SparkMasterTab.ts index 3469f7240..9ef5d3a51 100644 --- a/src/Explorer/Tabs/SparkMasterTab.ts +++ b/src/Explorer/Tabs/SparkMasterTab.ts @@ -4,13 +4,18 @@ import * as ViewModels from "../../Contracts/ViewModels"; import TabsBase from "./TabsBase"; import Explorer from "../Explorer"; +interface SparkMasterTabOptions extends ViewModels.TabOptions { + clusterConnectionInfo: DataModels.SparkClusterConnectionInfo; + container: Explorer; +} + export default class SparkMasterTab extends TabsBase { public sparkMasterSrc: ko.Observable; private _clusterConnectionInfo: DataModels.SparkClusterConnectionInfo; private _container: Explorer; - constructor(options: ViewModels.SparkMasterTabOptions) { + constructor(options: SparkMasterTabOptions) { super(options); super.onActivate.bind(this); this._container = options.container; diff --git a/src/Explorer/Tabs/StoredProcedureTab.ts b/src/Explorer/Tabs/StoredProcedureTab.ts index e8bed992e..46487ca63 100644 --- a/src/Explorer/Tabs/StoredProcedureTab.ts +++ b/src/Explorer/Tabs/StoredProcedureTab.ts @@ -11,13 +11,14 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import ExecuteQueryIcon from "../../../images/ExecuteQuery.svg"; import StoredProcedure from "../Tree/StoredProcedure"; import { createStoredProcedure, updateStoredProcedure } from "../../Common/DocumentClientUtilityBase"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; enum ToggleState { Result = "result", Logs = "logs" } -export default class StoredProcedureTab extends ScriptTabBase implements ViewModels.StoredProcedureTab { +export default class StoredProcedureTab extends ScriptTabBase { public collection: ViewModels.Collection; public node: StoredProcedure; public executeResultsEditorId: string; @@ -204,7 +205,7 @@ export default class StoredProcedureTab extends ScriptTabBase implements ViewMod super.buildCommandBarOptions(); } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { + protected getTabsButtons(): CommandButtonComponentProps[] { const label = "Execute"; return super.getTabsButtons().concat({ iconSrc: ExecuteQueryIcon, diff --git a/src/Explorer/Tabs/TabsBase.ts b/src/Explorer/Tabs/TabsBase.ts index 164533ddf..f2544883b 100644 --- a/src/Explorer/Tabs/TabsBase.ts +++ b/src/Explorer/Tabs/TabsBase.ts @@ -8,9 +8,10 @@ import { WaitsForTemplateViewModel } from "../WaitsForTemplateViewModel"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import ThemeUtility from "../../Common/ThemeUtility"; import Explorer from "../Explorer"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; // TODO: Use specific actions for logging telemetry data -export default class TabsBase extends WaitsForTemplateViewModel implements ViewModels.Tab { +export default class TabsBase extends WaitsForTemplateViewModel { public closeTabButton: ViewModels.Button; public node: ViewModels.TreeNode; public collection: ViewModels.CollectionBase; @@ -187,7 +188,7 @@ export default class TabsBase extends WaitsForTemplateViewModel implements ViewM /** * @return buttons that are displayed in the navbar */ - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { + protected getTabsButtons(): CommandButtonComponentProps[] { return []; } diff --git a/src/Explorer/Tabs/TabsManager.test.ts b/src/Explorer/Tabs/TabsManager.test.ts index 8e8cb8825..1b7747da6 100644 --- a/src/Explorer/Tabs/TabsManager.test.ts +++ b/src/Explorer/Tabs/TabsManager.test.ts @@ -1,9 +1,11 @@ import * as ko from "knockout"; import * as ViewModels from "../../Contracts/ViewModels"; +import * as DataModels from "../../Contracts/DataModels"; import { TabsManager } from "./TabsManager"; import DocumentsTab from "./DocumentsTab"; import Explorer from "../Explorer"; import QueryTab from "./QueryTab"; +import DocumentId from "../Tree/DocumentId"; describe("Tabs manager tests", () => { let tabsManager: TabsManager; @@ -15,7 +17,7 @@ describe("Tabs manager tests", () => { beforeAll(() => { explorer = new Explorer({ notificationsClient: undefined, isEmulator: false }); - explorer.databaseAccount = ko.observable({ + explorer.databaseAccount = ko.observable({ id: "test", name: "test", location: "", @@ -56,7 +58,7 @@ describe("Tabs manager tests", () => { documentsTab = new DocumentsTab({ partitionKey: undefined, - documentIds: ko.observableArray(), + documentIds: ko.observableArray(), tabKind: ViewModels.CollectionTabKind.Documents, collection, title: "", @@ -102,13 +104,13 @@ describe("Tabs manager tests", () => { tabsManager.activateNewTab(queryTab); tabsManager.activateNewTab(documentsTab); - const queryTabs: ViewModels.Tab[] = tabsManager.getTabs(ViewModels.CollectionTabKind.Query); + const queryTabs = tabsManager.getTabs(ViewModels.CollectionTabKind.Query); expect(queryTabs.length).toBe(1); expect(queryTabs[0]).toEqual(queryTab); - const documentsTabs: ViewModels.Tab[] = tabsManager.getTabs( + const documentsTabs = tabsManager.getTabs( ViewModels.CollectionTabKind.Documents, - (tab: ViewModels.Tab) => tab.tabId === documentsTab.tabId + tab => tab.tabId === documentsTab.tabId ); expect(documentsTabs.length).toBe(1); expect(documentsTabs[0]).toEqual(documentsTab); @@ -125,7 +127,7 @@ describe("Tabs manager tests", () => { expect(queryTab.isActive()).toBe(true); expect(documentsTab.isActive()).toBe(false); - tabsManager.closeTabsByComparator((tab: ViewModels.Tab) => tab.tabId === queryTab.tabId); + tabsManager.closeTabsByComparator(tab => tab.tabId === queryTab.tabId); expect(tabsManager.openedTabs().length).toBe(0); expect(tabsManager.activeTab()).toEqual(undefined); expect(queryTab.isActive()).toBe(false); diff --git a/src/Explorer/Tabs/TabsManager.ts b/src/Explorer/Tabs/TabsManager.ts index 2d8746c2f..86bf6556e 100644 --- a/src/Explorer/Tabs/TabsManager.ts +++ b/src/Explorer/Tabs/TabsManager.ts @@ -2,39 +2,37 @@ import * as ko from "knockout"; import * as ViewModels from "../../Contracts/ViewModels"; import TabsManagerTemplate from "./TabsManager.html"; import Explorer from "../Explorer"; +import TabsBase from "./TabsBase"; export class TabsManager { - public openedTabs: ko.ObservableArray; - public activeTab: ko.Observable; + public openedTabs: ko.ObservableArray; + public activeTab: ko.Observable; constructor() { - this.openedTabs = ko.observableArray([]); - this.activeTab = ko.observable(); + this.openedTabs = ko.observableArray([]); + this.activeTab = ko.observable(); } - public activateNewTab(tab: ViewModels.Tab): void { + public activateNewTab(tab: TabsBase): void { this.openedTabs.push(tab); this.activateTab(tab); } - public activateTab(tab: ViewModels.Tab): void { + public activateTab(tab: TabsBase): void { this.activeTab() && this.activeTab().isActive(false); tab.isActive(true); this.activeTab(tab); } - public getTabs( - tabKind: ViewModels.CollectionTabKind, - comparator?: (tab: ViewModels.Tab) => boolean - ): ViewModels.Tab[] { - return this.openedTabs().filter((openedTab: ViewModels.Tab) => { + public getTabs(tabKind: ViewModels.CollectionTabKind, comparator?: (tab: TabsBase) => boolean): TabsBase[] { + return this.openedTabs().filter((openedTab: TabsBase) => { return openedTab.tabKind === tabKind && (!comparator || comparator(openedTab)); }); } - public refreshActiveTab(comparator: (tab: ViewModels.Tab) => boolean): void { + public refreshActiveTab(comparator: (tab: TabsBase) => boolean): void { // ensures that the tab selects/highlights the right node based on resource tree expand/collapse state - this.openedTabs().forEach((tab: ViewModels.Tab) => { + this.openedTabs().forEach((tab: TabsBase) => { if (comparator(tab) && tab.isActive()) { tab.onActivate(); } @@ -42,17 +40,17 @@ export class TabsManager { } public removeTabById(tabId: string): void { - this.openedTabs.remove((tab: ViewModels.Tab) => tab.tabId === tabId); + this.openedTabs.remove((tab: TabsBase) => tab.tabId === tabId); } - public removeTabByComparator(comparator: (tab: ViewModels.Tab) => boolean): void { - this.openedTabs.remove((tab: ViewModels.Tab) => comparator(tab)); + public removeTabByComparator(comparator: (tab: TabsBase) => boolean): void { + this.openedTabs.remove((tab: TabsBase) => comparator(tab)); } - public closeTabsByComparator(comparator: (tab: ViewModels.Tab) => boolean): void { + public closeTabsByComparator(comparator: (tab: TabsBase) => boolean): void { this.activeTab() && this.activeTab().isActive(false); this.activeTab(undefined); - this.openedTabs().forEach((tab: ViewModels.Tab) => { + this.openedTabs().forEach((tab: TabsBase) => { if (comparator(tab)) { tab.onCloseTabButtonClick(); } @@ -64,9 +62,9 @@ export class TabsManager { } public closeTab(tabId: string, explorer: Explorer): void { - const tabIndex: number = this.openedTabs().findIndex((tab: ViewModels.Tab) => tab.tabId === tabId); + const tabIndex: number = this.openedTabs().findIndex((tab: TabsBase) => tab.tabId === tabId); if (tabIndex !== -1) { - const tabToActive: ViewModels.Tab = this.openedTabs()[tabIndex + 1] || this.openedTabs()[tabIndex - 1]; + const tabToActive: TabsBase = this.openedTabs()[tabIndex + 1] || this.openedTabs()[tabIndex - 1]; this.openedTabs()[tabIndex].isActive(false); this.removeTabById(tabId); if (tabToActive) { diff --git a/src/Explorer/Tabs/TerminalTab.tsx b/src/Explorer/Tabs/TerminalTab.tsx index a2c8bac2c..8ee5658d3 100644 --- a/src/Explorer/Tabs/TerminalTab.tsx +++ b/src/Explorer/Tabs/TerminalTab.tsx @@ -6,6 +6,13 @@ import * as React from "react"; import { ReactAdapter } from "../../Bindings/ReactBindingHandler"; import { NotebookTerminalComponent } from "../Controls/Notebook/NotebookTerminalComponent"; import Explorer from "../Explorer"; +import { CommandButtonComponentProps } from "../Controls/CommandButton/CommandButtonComponent"; + +export interface TerminalTabOptions extends ViewModels.TabOptions { + account: DataModels.DatabaseAccount; + container: Explorer; + kind: ViewModels.TerminalKind; +} /** * Notebook terminal tab @@ -30,11 +37,11 @@ class NotebookTerminalComponentAdapter implements ReactAdapter { } } -export default class TerminalTab extends TabsBase implements ViewModels.Tab { +export default class TerminalTab extends TabsBase { private container: Explorer; private notebookTerminalComponentAdapter: NotebookTerminalComponentAdapter; - constructor(options: ViewModels.TerminalTabOptions) { + constructor(options: TerminalTabOptions) { super(options); this.container = options.container; this.notebookTerminalComponentAdapter = new NotebookTerminalComponentAdapter( @@ -53,15 +60,15 @@ export default class TerminalTab extends TabsBase implements ViewModels.Tab { return this.container; } - protected getTabsButtons(): ViewModels.NavbarButtonConfig[] { - const buttons: ViewModels.NavbarButtonConfig[] = []; + protected getTabsButtons(): CommandButtonComponentProps[] { + const buttons: CommandButtonComponentProps[] = []; return buttons; } protected buildCommandBarOptions(): void { this.updateNavbarWithTabsButtons(); } - private getNotebookServerInfo(options: ViewModels.TerminalTabOptions): DataModels.NotebookWorkspaceConnectionInfo { + private getNotebookServerInfo(options: TerminalTabOptions): DataModels.NotebookWorkspaceConnectionInfo { let endpointSuffix: string; switch (options.kind) { diff --git a/src/Explorer/Tabs/TriggerTab.ts b/src/Explorer/Tabs/TriggerTab.ts index b2c4daf3e..94ec2f821 100644 --- a/src/Explorer/Tabs/TriggerTab.ts +++ b/src/Explorer/Tabs/TriggerTab.ts @@ -9,7 +9,7 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import Trigger from "../Tree/Trigger"; import { createTrigger, updateTrigger } from "../../Common/DocumentClientUtilityBase"; -export default class TriggerTab extends ScriptTabBase implements ViewModels.TriggerTab { +export default class TriggerTab extends ScriptTabBase { public collection: ViewModels.Collection; public node: Trigger; public triggerType: ViewModels.Editable; diff --git a/src/Explorer/Tabs/UserDefinedFunctionTab.ts b/src/Explorer/Tabs/UserDefinedFunctionTab.ts index 93a765cfc..ac8f3dd69 100644 --- a/src/Explorer/Tabs/UserDefinedFunctionTab.ts +++ b/src/Explorer/Tabs/UserDefinedFunctionTab.ts @@ -8,7 +8,7 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import UserDefinedFunction from "../Tree/UserDefinedFunction"; import { createUserDefinedFunction, updateUserDefinedFunction } from "../../Common/DocumentClientUtilityBase"; -export default class UserDefinedFunctionTab extends ScriptTabBase implements ViewModels.UserDefinedFunctionTab { +export default class UserDefinedFunctionTab extends ScriptTabBase { public collection: ViewModels.Collection; public node: UserDefinedFunction; constructor(options: ViewModels.ScriptTabOption) { diff --git a/src/Explorer/Tree/Collection.ts b/src/Explorer/Tree/Collection.ts index 8032ba504..54a2db164 100644 --- a/src/Explorer/Tree/Collection.ts +++ b/src/Explorer/Tree/Collection.ts @@ -240,9 +240,7 @@ export default class Collection implements ViewModels.Collection { this.expandCollection(); } this.container.onUpdateTabsButtons([]); - this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid - ); + this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); } public collapseCollection() { @@ -293,7 +291,7 @@ export default class Collection implements ViewModels.Collection { const documentsTabs: DocumentsTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.Documents, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + tab => tab.collection && tab.collection.rid === this.rid ) as DocumentsTab[]; let documentsTab: DocumentsTab = documentsTabs && documentsTabs[0]; @@ -344,7 +342,7 @@ export default class Collection implements ViewModels.Collection { const conflictsTabs: ConflictsTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.Conflicts, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + tab => tab.collection && tab.collection.rid === this.rid ) as ConflictsTab[]; let conflictsTab: ConflictsTab = conflictsTabs && conflictsTabs[0]; @@ -401,7 +399,7 @@ export default class Collection implements ViewModels.Collection { const queryTablesTabs: QueryTablesTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.QueryTables, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + tab => tab.collection && tab.collection.rid === this.rid ) as QueryTablesTab[]; let queryTablesTab: QueryTablesTab = queryTablesTabs && queryTablesTabs[0]; @@ -455,7 +453,7 @@ export default class Collection implements ViewModels.Collection { const graphTabs: GraphTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.Graph, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + tab => tab.collection && tab.collection.rid === this.rid ) as GraphTab[]; let graphTab: GraphTab = graphTabs && graphTabs[0]; @@ -511,7 +509,7 @@ export default class Collection implements ViewModels.Collection { const mongoDocumentsTabs: MongoDocumentsTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.Documents, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + tab => tab.collection && tab.collection.rid === this.rid ) as MongoDocumentsTab[]; let mongoDocumentsTab: MongoDocumentsTab = mongoDocumentsTabs && mongoDocumentsTabs[0]; @@ -562,12 +560,9 @@ export default class Collection implements ViewModels.Collection { const tabTitle = !this.offer() ? "Settings" : "Scale & Settings"; const pendingNotificationsPromise: Q.Promise = this._getPendingThroughputSplitNotification(); - const matchingTabs: ViewModels.Tab[] = this.container.tabsManager.getTabs( - ViewModels.CollectionTabKind.Settings, - (tab: ViewModels.Tab) => { - return tab.collection && tab.collection.rid === this.rid; - } - ); + const matchingTabs = this.container.tabsManager.getTabs(ViewModels.CollectionTabKind.Settings, tab => { + return tab.collection && tab.collection.rid === this.rid; + }); let settingsTab: SettingsTab = matchingTabs && (matchingTabs[0] as SettingsTab); if (!settingsTab) { @@ -902,9 +897,7 @@ export default class Collection implements ViewModels.Collection { } else { this.expandStoredProcedures(); } - this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid - ); + this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); } public expandStoredProcedures() { @@ -961,9 +954,7 @@ export default class Collection implements ViewModels.Collection { } else { this.expandUserDefinedFunctions(); } - this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid - ); + this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); } public expandUserDefinedFunctions() { @@ -1020,9 +1011,7 @@ export default class Collection implements ViewModels.Collection { } else { this.expandTriggers(); } - this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid - ); + this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === this.rid); } public expandTriggers() { diff --git a/src/Explorer/Tree/ConflictId.ts b/src/Explorer/Tree/ConflictId.ts index fc7ba9a2f..885f113fe 100644 --- a/src/Explorer/Tree/ConflictId.ts +++ b/src/Explorer/Tree/ConflictId.ts @@ -8,7 +8,7 @@ import { extractPartitionKey } from "@azure/cosmos"; import ConflictsTab from "../Tabs/ConflictsTab"; import { readDocument } from "../../Common/DocumentClientUtilityBase"; -export default class ConflictId implements ViewModels.ConflictId { +export default class ConflictId { public container: ConflictsTab; public rid: string; public self: string; @@ -115,7 +115,7 @@ export default class ConflictId implements ViewModels.ConflictId { return JSON.stringify(partitionKeyValue); } - public buildDocumentIdFromConflict(partitionKeyValue: any): ViewModels.DocumentId { + public buildDocumentIdFromConflict(partitionKeyValue: any): DocumentId { const conflictDocumentRid = Constants.HashRoutePrefixes.docsWithIds( this.container.collection.getDatabase().rid, this.container.collection.rid, diff --git a/src/Explorer/Tree/Database.ts b/src/Explorer/Tree/Database.ts index 7e243ebf6..6b1ae0120 100644 --- a/src/Explorer/Tree/Database.ts +++ b/src/Explorer/Tree/Database.ts @@ -52,9 +52,9 @@ export default class Database implements ViewModels.Database { }); const pendingNotificationsPromise: Q.Promise = this._getPendingThroughputSplitNotification(); - const matchingTabs: ViewModels.Tab[] = this.container.tabsManager.getTabs( + const matchingTabs = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.DatabaseSettings, - (tab: ViewModels.Tab) => tab.rid === this.rid + tab => tab.rid === this.rid ); let settingsTab: DatabaseSettingsTab = matchingTabs && (matchingTabs[0] as DatabaseSettingsTab); if (!settingsTab) { @@ -223,9 +223,7 @@ export default class Database implements ViewModels.Database { this.expandDatabase(); } this.container.onUpdateTabsButtons([]); - this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.getDatabase().rid === this.rid - ); + this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.getDatabase().rid === this.rid); } public expandDatabase() { diff --git a/src/Explorer/Tree/DocumentId.ts b/src/Explorer/Tree/DocumentId.ts index 57f0971c7..2e9a53bd3 100644 --- a/src/Explorer/Tree/DocumentId.ts +++ b/src/Explorer/Tree/DocumentId.ts @@ -1,9 +1,9 @@ import * as ko from "knockout"; import * as DataModels from "../../Contracts/DataModels"; -import * as ViewModels from "../../Contracts/ViewModels"; +import DocumentsTab from "../Tabs/DocumentsTab"; -export default class DocumentId implements ViewModels.DocumentId { - public container: ViewModels.DocumentsTab; +export default class DocumentId { + public container: DocumentsTab; public rid: string; public self: string; public ts: string; @@ -14,7 +14,7 @@ export default class DocumentId implements ViewModels.DocumentId { public stringPartitionKeyValue: string; public isDirty: ko.Observable; - constructor(container: ViewModels.DocumentsTab, data: any, partitionKeyValue: any) { + constructor(container: DocumentsTab, data: any, partitionKeyValue: any) { this.container = container; this.self = data._self; this.rid = data._rid; diff --git a/src/Explorer/Tree/ObjectId.ts b/src/Explorer/Tree/ObjectId.ts index 06f97338b..04be68be9 100644 --- a/src/Explorer/Tree/ObjectId.ts +++ b/src/Explorer/Tree/ObjectId.ts @@ -1,9 +1,9 @@ import * as ko from "knockout"; -import * as ViewModels from "../../Contracts/ViewModels"; import DocumentId from "./DocumentId"; +import DocumentsTab from "../Tabs/DocumentsTab"; -export default class ObjectId extends DocumentId implements ViewModels.DocumentId { - constructor(container: ViewModels.DocumentsTab, data: any, partitionKeyValue: any) { +export default class ObjectId extends DocumentId { + constructor(container: DocumentsTab, data: any, partitionKeyValue: any) { super(container, data, partitionKeyValue); if (typeof data._id === "object") { this.id = ko.observable(data._id[Object.keys(data._id)[0]]); diff --git a/src/Explorer/Tree/ResourceTokenCollection.ts b/src/Explorer/Tree/ResourceTokenCollection.ts index b38bebb7f..7bad94a6b 100644 --- a/src/Explorer/Tree/ResourceTokenCollection.ts +++ b/src/Explorer/Tree/ResourceTokenCollection.ts @@ -9,6 +9,7 @@ import Q from "q"; import QueryTab from "../Tabs/QueryTab"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import Explorer from "../Explorer"; +import TabsBase from "../Tabs/TabsBase"; export default class ResourceTokenCollection implements ViewModels.CollectionBase { public nodeKind: string; @@ -120,7 +121,7 @@ export default class ResourceTokenCollection implements ViewModels.CollectionBas const documentsTabs: DocumentsTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.Documents, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + (tab: TabsBase) => tab.collection && tab.collection.rid === this.rid ) as DocumentsTab[]; let documentsTab: DocumentsTab = documentsTabs && documentsTabs[0]; diff --git a/src/Explorer/Tree/ResourceTreeAdapter.tsx b/src/Explorer/Tree/ResourceTreeAdapter.tsx index 2b00a37d9..89c5c7106 100644 --- a/src/Explorer/Tree/ResourceTreeAdapter.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapter.tsx @@ -30,6 +30,7 @@ import Explorer from "../Explorer"; import UserDefinedFunction from "./UserDefinedFunction"; import StoredProcedure from "./StoredProcedure"; import Trigger from "./Trigger"; +import TabsBase from "../Tabs/TabsBase"; export class ResourceTreeAdapter implements ReactAdapter { private static readonly DataTitle = "DATA"; @@ -50,7 +51,7 @@ export class ResourceTreeAdapter implements ReactAdapter { this.parameters = ko.observable(Date.now()); this.container.selectedNode.subscribe((newValue: any) => this.triggerRender()); - this.container.tabsManager.activeTab.subscribe((newValue: ViewModels.Tab) => this.triggerRender()); + this.container.tabsManager.activeTab.subscribe((newValue: TabsBase) => this.triggerRender()); this.container.isNotebookEnabled.subscribe(newValue => this.triggerRender()); this.koSubsDatabaseIdMap = new ArrayHashMap(); @@ -176,7 +177,7 @@ export class ResourceTreeAdapter implements ReactAdapter { database.selectDatabase(); this.container.onUpdateTabsButtons([]); this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.getDatabase().rid === database.rid + (tab: TabsBase) => tab.collection && tab.collection.getDatabase().rid === database.rid ); }, onContextMenuOpen: () => this.container.selectedNode(database) @@ -275,7 +276,7 @@ export class ResourceTreeAdapter implements ReactAdapter { this.container.selectedNode(collection); this.container.onUpdateTabsButtons([]); this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === collection.rid + (tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid ); }, onExpanded: () => { @@ -303,7 +304,7 @@ export class ResourceTreeAdapter implements ReactAdapter { onClick: () => { collection.selectedSubnodeKind(ViewModels.CollectionTabKind.StoredProcedures); this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === collection.rid + (tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid ); } }; @@ -322,7 +323,7 @@ export class ResourceTreeAdapter implements ReactAdapter { onClick: () => { collection.selectedSubnodeKind(ViewModels.CollectionTabKind.UserDefinedFunctions); this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === collection.rid + (tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid ); } }; @@ -340,7 +341,7 @@ export class ResourceTreeAdapter implements ReactAdapter { onClick: () => { collection.selectedSubnodeKind(ViewModels.CollectionTabKind.Triggers); this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === collection.rid + (tab: TabsBase) => tab.collection && tab.collection.rid === collection.rid ); } }; diff --git a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx index 625d83968..f24022501 100644 --- a/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx +++ b/src/Explorer/Tree/ResourceTreeAdapterForResourceToken.tsx @@ -16,10 +16,9 @@ export class ResourceTreeAdapterForResourceToken implements ReactAdapter { public constructor(private container: Explorer) { this.parameters = ko.observable(Date.now()); - this.container.resourceTokenCollection.subscribe((collection: ViewModels.CollectionBase) => this.triggerRender()); + this.container.resourceTokenCollection.subscribe(() => this.triggerRender()); this.container.selectedNode.subscribe((newValue: any) => this.triggerRender()); - this.container.tabsManager && - this.container.tabsManager.activeTab.subscribe((newValue: ViewModels.Tab) => this.triggerRender()); + this.container.tabsManager && this.container.tabsManager.activeTab.subscribe(() => this.triggerRender()); this.triggerRender(); } @@ -65,9 +64,7 @@ export class ResourceTreeAdapterForResourceToken implements ReactAdapter { // Rewritten version of expandCollapseCollection this.container.selectedNode(collection); this.container.onUpdateTabsButtons([]); - this.container.tabsManager.refreshActiveTab( - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === collection.rid - ); + this.container.tabsManager.refreshActiveTab(tab => tab.collection && tab.collection.rid === collection.rid); }, isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", undefined) }; diff --git a/src/Explorer/Tree/StoredProcedure.ts b/src/Explorer/Tree/StoredProcedure.ts index fa325473c..e50711c8c 100644 --- a/src/Explorer/Tree/StoredProcedure.ts +++ b/src/Explorer/Tree/StoredProcedure.ts @@ -8,6 +8,7 @@ import StoredProcedureTab from "../Tabs/StoredProcedureTab"; import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor"; import Explorer from "../Explorer"; import { deleteStoredProcedure, executeStoredProcedure } from "../../Common/DocumentClientUtilityBase"; +import TabsBase from "../Tabs/TabsBase"; const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE function sample(prefix) { @@ -96,7 +97,7 @@ export default class StoredProcedure { const storedProcedureTabs: StoredProcedureTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.StoredProcedures, - (tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid + (tab: TabsBase) => tab.node && tab.node.rid === this.rid ) as StoredProcedureTab[]; let storedProcedureTab: StoredProcedureTab = storedProcedureTabs && storedProcedureTabs[0]; @@ -145,9 +146,7 @@ export default class StoredProcedure { deleteStoredProcedure(this.collection, storedProcedureData).then( () => { - this.container.tabsManager.removeTabByComparator( - (tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid - ); + this.container.tabsManager.removeTabByComparator((tab: TabsBase) => tab.node && tab.node.rid === this.rid); this.collection.children.remove(this); }, reason => {} @@ -155,11 +154,11 @@ export default class StoredProcedure { } public execute(params: string[], partitionKeyValue?: string): void { - const sprocTabs: ViewModels.StoredProcedureTab[] = this.container.tabsManager.getTabs( + const sprocTabs = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.StoredProcedures, - (tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid - ) as ViewModels.StoredProcedureTab[]; - const sprocTab: ViewModels.StoredProcedureTab = sprocTabs && sprocTabs.length > 0 && sprocTabs[0]; + (tab: TabsBase) => tab.node && tab.node.rid === this.rid + ) as StoredProcedureTab[]; + const sprocTab = sprocTabs && sprocTabs.length > 0 && sprocTabs[0]; sprocTab.isExecuting(true); this.container && executeStoredProcedure(this.collection, this, partitionKeyValue, params) diff --git a/src/Explorer/Tree/Trigger.ts b/src/Explorer/Tree/Trigger.ts index 3a19c066a..2c9a83004 100644 --- a/src/Explorer/Tree/Trigger.ts +++ b/src/Explorer/Tree/Trigger.ts @@ -72,7 +72,7 @@ export default class Trigger { const triggerTabs: TriggerTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.Triggers, - (tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid + tab => tab.node && tab.node.rid === this.rid ) as TriggerTab[]; let triggerTab: TriggerTab = triggerTabs && triggerTabs[0]; @@ -125,9 +125,7 @@ export default class Trigger { deleteTrigger(this.collection, triggerData).then( () => { - this.container.tabsManager.removeTabByComparator( - (tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid - ); + this.container.tabsManager.removeTabByComparator(tab => tab.node && tab.node.rid === this.rid); this.collection.children.remove(this); }, reason => {} diff --git a/src/Explorer/Tree/UserDefinedFunction.ts b/src/Explorer/Tree/UserDefinedFunction.ts index d8ab66f90..9f34bbc62 100644 --- a/src/Explorer/Tree/UserDefinedFunction.ts +++ b/src/Explorer/Tree/UserDefinedFunction.ts @@ -57,7 +57,7 @@ export default class UserDefinedFunction { const userDefinedFunctionTabs: UserDefinedFunctionTab[] = this.container.tabsManager.getTabs( ViewModels.CollectionTabKind.UserDefinedFunctions, - (tab: ViewModels.Tab) => tab.collection && tab.collection.rid === this.rid + tab => tab.collection && tab.collection.rid === this.rid ) as UserDefinedFunctionTab[]; let userDefinedFunctionTab: UserDefinedFunctionTab = userDefinedFunctionTabs && userDefinedFunctionTabs[0]; @@ -115,9 +115,7 @@ export default class UserDefinedFunction { }; deleteUserDefinedFunction(this.collection, userDefinedFunctionData).then( () => { - this.container.tabsManager.removeTabByComparator( - (tab: ViewModels.Tab) => tab.node && tab.node.rid === this.rid - ); + this.container.tabsManager.removeTabByComparator(tab => tab.node && tab.node.rid === this.rid); this.collection.children.remove(this); }, reason => {} diff --git a/src/GitHub/GitHubOAuthService.test.ts b/src/GitHub/GitHubOAuthService.test.ts index 2e914867b..6c41891c5 100644 --- a/src/GitHub/GitHubOAuthService.test.ts +++ b/src/GitHub/GitHubOAuthService.test.ts @@ -1,6 +1,6 @@ import ko from "knockout"; import { HttpStatusCodes } from "../Common/Constants"; -import * as ViewModels from "../Contracts/ViewModels"; +import * as DataModels from "../Contracts/DataModels"; import { JunoClient } from "../Juno/JunoClient"; import { GitHubConnector, IGitHubConnectorParams } from "./GitHubConnector"; import { GitHubOAuthService } from "./GitHubOAuthService"; @@ -8,7 +8,7 @@ import { ConsoleDataType } from "../Explorer/Menus/NotificationConsole/Notificat import NotebookManager from "../Explorer/Notebook/NotebookManager"; import Explorer from "../Explorer/Explorer"; -const sampleDatabaseAccount: ViewModels.DatabaseAccount = { +const sampleDatabaseAccount: DataModels.DatabaseAccount = { id: "id", name: "name", location: "location", @@ -29,7 +29,7 @@ describe("GitHubOAuthService", () => { let originalDataExplorer: Explorer; beforeEach(() => { - junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); + junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); gitHubOAuthService = new GitHubOAuthService(junoClient); originalDataExplorer = window.dataExplorer; window.dataExplorer = { diff --git a/src/HostedExplorer.ts b/src/HostedExplorer.ts index 4ba4aeda3..76bbe691e 100644 --- a/src/HostedExplorer.ts +++ b/src/HostedExplorer.ts @@ -27,7 +27,6 @@ import * as Logger from "./Common/Logger"; import { MeControlComponentProps } from "./Explorer/Menus/NavBar/MeControlComponent"; import { MeControlComponentAdapter } from "./Explorer/Menus/NavBar/MeControlComponentAdapter"; import { MessageTypes } from "./Contracts/ExplorerContracts"; -import { NavbarButtonConfig } from "./Contracts/ViewModels"; import * as ReactBindingHandler from "./Bindings/ReactBindingHandler"; import { SwitchDirectoryPane, SwitchDirectoryPaneComponent } from "./Explorer/Panes/SwitchDirectoryPane"; import TelemetryProcessor from "./Shared/Telemetry/TelemetryProcessor"; @@ -38,6 +37,7 @@ import ConnectIcon from "../images/HostedConnectwhite.svg"; import SettingsIcon from "../images/HostedSettings.svg"; import FeedbackIcon from "../images/Feedback.svg"; import SwitchDirectoryIcon from "../images/DirectorySwitch.svg"; +import { CommandButtonComponentProps } from "./Explorer/Controls/CommandButton/CommandButtonComponent"; ReactBindingHandler.Registerer.register(); ko.components.register("switch-directory-pane", new SwitchDirectoryPaneComponent()); @@ -56,7 +56,7 @@ class HostedExplorer { private _dialogProps: ko.Observable; private _meControlProps: ko.Observable; private _accountSwitchProps: ko.Observable; - private _controlbarCommands: ko.ObservableArray; + private _controlbarCommands: ko.ObservableArray; private _directoryDropdownProps: ko.Observable; private _directoryListProps: ko.Observable; @@ -1086,7 +1086,7 @@ class HostedExplorer { } private _setAadControlBar() { - const switchDirectoryCommand: NavbarButtonConfig = { + const switchDirectoryCommand: CommandButtonComponentProps = { iconSrc: SwitchDirectoryIcon, iconAlt: "switch directory button", onCommandClick: () => this.openDirectoryPane(), diff --git a/src/Juno/JunoClient.test.ts b/src/Juno/JunoClient.test.ts index 5031a9feb..b7c00e3a2 100644 --- a/src/Juno/JunoClient.test.ts +++ b/src/Juno/JunoClient.test.ts @@ -4,8 +4,9 @@ import * as ViewModels from "../Contracts/ViewModels"; import { IPinnedRepo, JunoClient, IGalleryItem } from "./JunoClient"; import { config } from "../Config"; import { getAuthorizationHeader } from "../Utils/AuthorizationUtils"; +import { DatabaseAccount } from "../Contracts/DataModels"; -const sampleDatabaseAccount: ViewModels.DatabaseAccount = { +const sampleDatabaseAccount: DatabaseAccount = { id: "id", name: "name", location: "location", @@ -51,7 +52,7 @@ const sampleGalleryItems: IGalleryItem[] = [ ]; describe("Pinned repos", () => { - const junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); + const junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); beforeEach(() => { window.fetch = jest.fn().mockImplementation(() => { @@ -88,7 +89,7 @@ describe("Pinned repos", () => { }); describe("GitHub", () => { - const junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); + const junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); afterEach(() => { jest.resetAllMocks(); @@ -147,7 +148,7 @@ describe("GitHub", () => { }); describe("Gallery", () => { - const junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); + const junoClient = new JunoClient(ko.observable(sampleDatabaseAccount)); afterEach(() => { jest.resetAllMocks(); diff --git a/src/Juno/JunoClient.ts b/src/Juno/JunoClient.ts index ca60af888..05fac182f 100644 --- a/src/Juno/JunoClient.ts +++ b/src/Juno/JunoClient.ts @@ -1,7 +1,7 @@ import ko from "knockout"; import { HttpStatusCodes } from "../Common/Constants"; import { config } from "../Config"; -import * as ViewModels from "../Contracts/ViewModels"; +import * as DataModels from "../Contracts/DataModels"; import { AuthorizeAccessComponent } from "../Explorer/Controls/GitHub/AuthorizeAccessComponent"; import { IGitHubResponse } from "../GitHub/GitHubClient"; import { IGitHubOAuthToken } from "../GitHub/GitHubOAuthService"; @@ -55,7 +55,7 @@ interface IPublishNotebookRequest { export class JunoClient { private cachedPinnedRepos: ko.Observable; - constructor(private databaseAccount?: ko.Observable) { + constructor(private databaseAccount?: ko.Observable) { this.cachedPinnedRepos = ko.observable([]); } diff --git a/src/Platform/Hosted/Authorization.ts b/src/Platform/Hosted/Authorization.ts index 215f1cf20..01c6cd566 100644 --- a/src/Platform/Hosted/Authorization.ts +++ b/src/Platform/Hosted/Authorization.ts @@ -272,7 +272,7 @@ export default class AuthHeadersUtil { } private static _generateResourceUrl(): string { - const databaseAccount: ViewModels.DatabaseAccount = CosmosClient.databaseAccount(); + const databaseAccount = CosmosClient.databaseAccount(); const subscriptionId: string = CosmosClient.subscriptionId(); const resourceGroup: string = CosmosClient.resourceGroup(); const defaultExperience: string = DefaultExperienceUtility.getDefaultExperienceFromDatabaseAccount(databaseAccount); diff --git a/src/RouteHandlers/TabRouteHandler.ts b/src/RouteHandlers/TabRouteHandler.ts index 6303f924e..251bc7c75 100644 --- a/src/RouteHandlers/TabRouteHandler.ts +++ b/src/RouteHandlers/TabRouteHandler.ts @@ -4,6 +4,8 @@ import * as ViewModels from "../Contracts/ViewModels"; import crossroads from "crossroads"; import hasher from "hasher"; +import ScriptTabBase from "../Explorer/Tabs/ScriptTabBase"; +import TabsBase from "../Explorer/Tabs/TabsBase"; export class TabRouteHandler { private _tabRouter: any; @@ -187,7 +189,7 @@ export class TabRouteHandler { databaseId, collectionId ); - const matchingTab: ViewModels.Tab = this._findMatchingTabByTabKind( + const matchingTab: TabsBase = this._findMatchingTabByTabKind( databaseId, collectionId, ViewModels.CollectionTabKind.Query @@ -206,7 +208,7 @@ export class TabRouteHandler { databaseId, collectionId ); - const matchingTab: ViewModels.Tab = this._findMatchingTabByTabKind( + const matchingTab: TabsBase = this._findMatchingTabByTabKind( databaseId, collectionId, ViewModels.CollectionTabKind.Query @@ -228,7 +230,7 @@ export class TabRouteHandler { databaseId, collectionId ); - const matchingTab: ViewModels.Tab = this._findMatchingTabByTabKind( + const matchingTab: TabsBase = this._findMatchingTabByTabKind( databaseId, collectionId, ViewModels.CollectionTabKind.MongoShell @@ -271,7 +273,7 @@ export class TabRouteHandler { databaseId, collectionId ); - const matchingTab: ViewModels.Tab = this._findMatchingTabByTabKind( + const matchingTab: TabsBase = this._findMatchingTabByTabKind( databaseId, collectionId, ViewModels.CollectionTabKind.StoredProcedures, @@ -302,7 +304,7 @@ export class TabRouteHandler { databaseId, collectionId ); - const matchingTab: ViewModels.Tab = this._findMatchingTabByTabKind( + const matchingTab: TabsBase = this._findMatchingTabByTabKind( databaseId, collectionId, ViewModels.CollectionTabKind.Triggers, @@ -333,7 +335,7 @@ export class TabRouteHandler { databaseId, collectionId ); - const matchingTab: ViewModels.Tab = this._findMatchingTabByTabKind( + const matchingTab: TabsBase = this._findMatchingTabByTabKind( databaseId, collectionId, ViewModels.CollectionTabKind.UserDefinedFunctions, @@ -380,15 +382,15 @@ export class TabRouteHandler { collectionId: string, tabKind: ViewModels.CollectionTabKind, isNewScriptTab?: boolean - ): ViewModels.Tab { + ): TabsBase { const explorer = window.dataExplorer; - const matchingTabs: ViewModels.Tab[] = explorer.tabsManager.getTabs( + const matchingTabs: TabsBase[] = explorer.tabsManager.getTabs( tabKind, - (tab: ViewModels.Tab) => + (tab: TabsBase) => tab.collection && tab.collection.databaseId === databaseId && tab.collection.id() === collectionId && - (!isNewScriptTab || (tab as ViewModels.ScriptTab).isNew()) + (!isNewScriptTab || (tab as ScriptTabBase).isNew()) ); return matchingTabs && matchingTabs[0]; } diff --git a/src/Shared/DefaultExperienceUtility.test.ts b/src/Shared/DefaultExperienceUtility.test.ts index 16383cccd..372f54c02 100644 --- a/src/Shared/DefaultExperienceUtility.test.ts +++ b/src/Shared/DefaultExperienceUtility.test.ts @@ -71,12 +71,12 @@ describe("Default Experience Utility", () => { }); describe("getDefaultExperienceFromDatabaseAccount()", () => { - function runScenario(databaseAccount: ViewModels.DatabaseAccount, expectedDefaultExperience: string): void { + function runScenario(databaseAccount: DataModels.DatabaseAccount, expectedDefaultExperience: string): void { const resolvedExperience = DefaultExperienceUtility.getDefaultExperienceFromDatabaseAccount(databaseAccount); expect(resolvedExperience).toEqual(expectedDefaultExperience); } - const databaseAccountWithWrongTagsAndCapabilities: ViewModels.DatabaseAccount = { + const databaseAccountWithWrongTagsAndCapabilities: DataModels.DatabaseAccount = { id: "test", kind: "GlobalDocumentDB", name: "test", @@ -99,7 +99,7 @@ describe("Default Experience Utility", () => { } }; - const databaseAccountWithApiKind: ViewModels.DatabaseAccount = { + const databaseAccountWithApiKind: DataModels.DatabaseAccount = { id: "test", kind: Constants.AccountKind.MongoDB, name: "test", diff --git a/src/Shared/DefaultExperienceUtility.ts b/src/Shared/DefaultExperienceUtility.ts index c1724825a..f3837a7d8 100644 --- a/src/Shared/DefaultExperienceUtility.ts +++ b/src/Shared/DefaultExperienceUtility.ts @@ -1,18 +1,16 @@ import * as _ from "underscore"; import * as Constants from "../Common/Constants"; import * as DataModels from "../Contracts/DataModels"; -import * as ViewModels from "../Contracts/ViewModels"; export class DefaultExperienceUtility { - public static getDefaultExperienceFromDatabaseAccount(databaseAccount: ViewModels.DatabaseAccount): string { + public static getDefaultExperienceFromDatabaseAccount(databaseAccount: DataModels.DatabaseAccount): string { if (!databaseAccount) { return null; } const kind: string = databaseAccount && databaseAccount.kind && databaseAccount.kind && databaseAccount.kind.toLowerCase(); - const capabilities: ViewModels.Capability[] = - (databaseAccount.properties && databaseAccount.properties.capabilities) || []; + const capabilities = (databaseAccount.properties && databaseAccount.properties.capabilities) || []; return DefaultExperienceUtility._getDefaultExperience(kind, capabilities); } @@ -61,7 +59,7 @@ export class DefaultExperienceUtility { } } - private static _getDefaultExperience(kind: string, capabilities: ViewModels.Capability[]): string { + private static _getDefaultExperience(kind: string, capabilities: DataModels.Capability[]): string { const defaultDefaultExperience: string = Constants.DefaultAccountExperience.DocumentDB; const defaultExperienceFromKind: string = DefaultExperienceUtility._getDefaultExperienceFromAccountKind(kind); const defaultExperienceFromCapabilities: string = DefaultExperienceUtility._getDefaultExperienceFromAccountCapabilities( @@ -95,7 +93,7 @@ export class DefaultExperienceUtility { return null; } - private static _getDefaultExperienceFromAccountCapabilities(capabilities: ViewModels.Capability[]): string { + private static _getDefaultExperienceFromAccountCapabilities(capabilities: DataModels.Capability[]): string { if (!capabilities) { return null; } @@ -104,15 +102,12 @@ export class DefaultExperienceUtility { return null; } - const enableTable: ViewModels.Capability = DefaultExperienceUtility._findCapability( - capabilities, - Constants.CapabilityNames.EnableTable - ); + const enableTable = DefaultExperienceUtility._findCapability(capabilities, Constants.CapabilityNames.EnableTable); if (enableTable) { return Constants.DefaultAccountExperience.Table; } - const enableGremlin: ViewModels.Capability = DefaultExperienceUtility._findCapability( + const enableGremlin = DefaultExperienceUtility._findCapability( capabilities, Constants.CapabilityNames.EnableGremlin ); @@ -120,7 +115,7 @@ export class DefaultExperienceUtility { return Constants.DefaultAccountExperience.Graph; } - const enableCassandra: ViewModels.Capability = DefaultExperienceUtility._findCapability( + const enableCassandra = DefaultExperienceUtility._findCapability( capabilities, Constants.CapabilityNames.EnableCassandra ); @@ -131,8 +126,8 @@ export class DefaultExperienceUtility { return null; } - private static _findCapability(capabilities: ViewModels.Capability[], capabilityName: string): ViewModels.Capability { - return _.find(capabilities, (capability: ViewModels.Capability) => { + private static _findCapability(capabilities: DataModels.Capability[], capabilityName: string): DataModels.Capability { + return _.find(capabilities, capability => { return capability && capability.name && capability.name.toLowerCase() === capabilityName.toLowerCase(); }); } diff --git a/src/Utils/DatabaseAccountUtils.test.ts b/src/Utils/DatabaseAccountUtils.test.ts deleted file mode 100644 index 84026ed00..000000000 --- a/src/Utils/DatabaseAccountUtils.test.ts +++ /dev/null @@ -1,154 +0,0 @@ -import * as DataModels from "../Contracts/DataModels"; -import * as ViewModels from "../Contracts/ViewModels"; -import { DatabaseAccountUtils } from "./DatabaseAccountUtils"; - -describe("DatabaseAccountUtils Tests", () => { - describe("mergeDatabaseAccountWithGateway", () => { - const databaseAccountWithProperties: ViewModels.DatabaseAccount = { - id: "test", - kind: "GlobalDocumentDB", - name: "test", - location: "somewhere", - type: "DocumentDB", - tags: [], - properties: { - documentEndpoint: "", - cassandraEndpoint: "", - gremlinEndpoint: "", - tableEndpoint: "" - } - }; - - const databaseAccountWithLocations: ViewModels.DatabaseAccount = { - id: "test", - kind: "GlobalDocumentDB", - name: "test", - location: "somewhere", - type: "DocumentDB", - tags: [], - properties: { - documentEndpoint: "", - cassandraEndpoint: "", - gremlinEndpoint: "", - tableEndpoint: "", - enableMultipleWriteLocations: false, - readLocations: [ - { - documentEndpoint: "https://centralus", - failoverPriority: 0, - id: "", - locationId: "", - locationName: "Central US", - provisioningState: "Succeeded" - } - ], - writeLocations: [ - { - documentEndpoint: "https://centralus", - failoverPriority: 0, - id: "", - locationId: "", - locationName: "Central US", - provisioningState: "Succeeded" - } - ] - } - }; - - const databaseAccountWithoutProperties: ViewModels.DatabaseAccount = { - id: "test", - kind: "GlobalDocumentDB", - name: "test", - location: "somewhere", - type: "DocumentDB", - tags: [], - properties: null - }; - - const gatewayDatabaseAccount: DataModels.GatewayDatabaseAccount = { - EnableMultipleWriteLocations: true, - CurrentMediaStorageUsageInMB: 0, - DatabasesLink: "", - MaxMediaStorageUsageInMB: 0, - MediaLink: "", - ReadableLocations: [ - { - name: "Central US", - documentAccountEndpoint: "https://centralus" - }, - { - name: "North Central US", - documentAccountEndpoint: "https://northcentralus" - } - ], - WritableLocations: [ - { - name: "Central US", - documentAccountEndpoint: "https://centralus" - } - ] - }; - - it("should return databaseAccount when gatewayDatabaseAccount is not defined", () => { - expect(DatabaseAccountUtils.mergeDatabaseAccountWithGateway(databaseAccountWithoutProperties, null)).toBe( - databaseAccountWithoutProperties - ); - }); - - it("should return null when databaseAccount is not defined", () => { - expect(DatabaseAccountUtils.mergeDatabaseAccountWithGateway(null, null)).toBeNull(); - }); - - it("should return merged with no properties when databaseAccount has no properties", () => { - const merged = DatabaseAccountUtils.mergeDatabaseAccountWithGateway( - databaseAccountWithoutProperties, - gatewayDatabaseAccount - ); - expect(merged).toBeDefined(); - expect(merged.properties).toBeNull(); - }); - - it("should return merged writableLocations", () => { - const merged = DatabaseAccountUtils.mergeDatabaseAccountWithGateway( - databaseAccountWithProperties, - gatewayDatabaseAccount - ); - expect(merged.properties).toBeDefined(); - expect(merged.properties.writeLocations).toBeDefined(); - expect(merged.properties.writeLocations.length).toBe(gatewayDatabaseAccount.WritableLocations.length); - }); - - it("should return merged readableLocations", () => { - const merged = DatabaseAccountUtils.mergeDatabaseAccountWithGateway( - databaseAccountWithProperties, - gatewayDatabaseAccount - ); - expect(merged.properties).toBeDefined(); - expect(merged.properties.readLocations).toBeDefined(); - expect(merged.properties.readLocations.length).toBe(gatewayDatabaseAccount.ReadableLocations.length); - }); - - it("should return merged enableMultipleWriteLocations", () => { - const merged = DatabaseAccountUtils.mergeDatabaseAccountWithGateway( - databaseAccountWithProperties, - gatewayDatabaseAccount - ); - expect(merged.properties).toBeDefined(); - expect(merged.properties.enableMultipleWriteLocations).toBe(gatewayDatabaseAccount.EnableMultipleWriteLocations); - }); - - it("should not overwrite existing values", () => { - const merged = DatabaseAccountUtils.mergeDatabaseAccountWithGateway( - databaseAccountWithLocations, - gatewayDatabaseAccount - ); - expect(merged.properties.enableMultipleWriteLocations).toBe( - databaseAccountWithLocations.properties.enableMultipleWriteLocations - ); - expect(merged.properties.readLocations.length).toBe(databaseAccountWithLocations.properties.readLocations.length); - expect(merged.properties.writeLocations.length).toBe( - databaseAccountWithLocations.properties.writeLocations.length - ); - }); - }); -}); diff --git a/src/Utils/DatabaseAccountUtils.ts b/src/Utils/DatabaseAccountUtils.ts deleted file mode 100644 index fe8a9a400..000000000 --- a/src/Utils/DatabaseAccountUtils.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as DataModels from "../Contracts/DataModels"; -import * as ViewModels from "../Contracts/ViewModels"; -import { StringUtils } from "./StringUtils"; - -export class DatabaseAccountUtils { - public static mergeDatabaseAccountWithGateway( - databaseAccount: ViewModels.DatabaseAccount, - gatewayDatabaseAccount: DataModels.GatewayDatabaseAccount - ): ViewModels.DatabaseAccount { - if (!databaseAccount || !gatewayDatabaseAccount) { - return databaseAccount; - } - - if (databaseAccount.properties && gatewayDatabaseAccount.EnableMultipleWriteLocations) { - databaseAccount.properties.enableMultipleWriteLocations = gatewayDatabaseAccount.EnableMultipleWriteLocations; - } - - if (databaseAccount.properties && !databaseAccount.properties.readLocations) { - databaseAccount.properties.readLocations = DatabaseAccountUtils._convertToDatabaseAccountResponseLocation( - gatewayDatabaseAccount.ReadableLocations - ); - } - - if (databaseAccount.properties && !databaseAccount.properties.writeLocations) { - databaseAccount.properties.writeLocations = DatabaseAccountUtils._convertToDatabaseAccountResponseLocation( - gatewayDatabaseAccount.WritableLocations - ); - } - - return databaseAccount; - } - - private static _convertToDatabaseAccountResponseLocation( - gatewayLocations: DataModels.RegionEndpoint[] - ): DataModels.DatabaseAccountResponseLocation[] { - if (!gatewayLocations) { - return undefined; - } - - return gatewayLocations.map((gatewayLocation: DataModels.RegionEndpoint, index: number) => { - const responseLocation: DataModels.DatabaseAccountResponseLocation = { - documentEndpoint: gatewayLocation.documentAccountEndpoint, - locationName: gatewayLocation.name, - failoverPriority: index, - locationId: StringUtils.stripSpacesFromString(gatewayLocation.name).toLowerCase(), - provisioningState: "Succeeded", - id: gatewayLocation.name - }; - - return responseLocation; - }); - } -} diff --git a/src/Utils/NotebookConfigurationUtils.ts b/src/Utils/NotebookConfigurationUtils.ts index cfaae70ba..815fa435e 100644 --- a/src/Utils/NotebookConfigurationUtils.ts +++ b/src/Utils/NotebookConfigurationUtils.ts @@ -1,7 +1,12 @@ import * as DataModels from "../Contracts/DataModels"; -import { KernelConnectionMetadata } from "../Contracts/ViewModels"; import * as Logger from "../Common/Logger"; +interface KernelConnectionMetadata { + name: string; + configurationEndpoints: DataModels.NotebookConfigurationEndpoints; + notebookConnectionInfo: DataModels.NotebookWorkspaceConnectionInfo; +} + export class NotebookConfigurationUtils { private constructor() {} diff --git a/tsconfig.strict.json b/tsconfig.strict.json index 2ac148266..a7efd2996 100644 --- a/tsconfig.strict.json +++ b/tsconfig.strict.json @@ -38,13 +38,6 @@ "./src/Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.ts", "./src/Explorer/Controls/GitHub/GitHubStyleConstants.ts", "./src/Explorer/Controls/SmartUi/InputUtils.ts", - "./src/Explorer/Controls/Toolbar/IToolbarAction.ts", - "./src/Explorer/Controls/Toolbar/IToolbarDisplayable.ts", - "./src/Explorer/Controls/Toolbar/IToolbarDropDown.ts", - "./src/Explorer/Controls/Toolbar/IToolbarItem.ts", - "./src/Explorer/Controls/Toolbar/IToolbarSeperator.ts", - "./src/Explorer/Controls/Toolbar/IToolbarToggle.ts", - "./src/Explorer/Controls/Toolbar/KeyCodes.ts", "./src/Explorer/Notebook/FileSystemUtil.ts", "./src/Explorer/Notebook/NTeractUtil.ts", "./src/Explorer/Notebook/NotebookComponent/actions.ts",