mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2024-11-24 14:36:54 +00:00
Remove old resource tree and cleanup (#28)
* Remove old resource tree and its various components * Fix stored procedure, udf, trigger not always deleting when context menu option chosen * Reformat and fix eslint warnings * Remove CommandButtonOptions
This commit is contained in:
parent
d70e30c4fc
commit
73f2c612ed
@ -117,7 +117,6 @@ export class Features {
|
||||
public static readonly notebookServerUrl = "notebookserverurl";
|
||||
public static readonly notebookServerToken = "notebookservertoken";
|
||||
public static readonly notebookBasePath = "notebookbasepath";
|
||||
public static readonly enableLegacyResourceTree = "enablelegacyresourcetree";
|
||||
public static readonly canExceedMaximumValue = "canexceedmaximumvalue";
|
||||
public static readonly enableFixedCollectionWithSharedThroughput = "enablefixedcollectionwithsharedthroughput";
|
||||
public static readonly enableAutoPilotV2 = "enableautopilotv2";
|
||||
|
@ -5,6 +5,7 @@ import { SeverityLevel } from "@microsoft/applicationinsights-web";
|
||||
|
||||
// TODO: Move to a separate Diagnostics folder
|
||||
export class Logger {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
public static logInfo(message: string | Record<string, any>, area: string, code?: number): void {
|
||||
let logMessage: string;
|
||||
if (typeof message === "string") {
|
||||
|
@ -9,7 +9,6 @@ import { AccessibleVerticalList } from "../Explorer/Tree/AccessibleVerticalList"
|
||||
import { ArcadiaWorkspaceItem } from "../Explorer/Controls/Arcadia/ArcadiaMenuPicker";
|
||||
import { CassandraTableKey, CassandraTableKeys, TableDataClient } from "../Explorer/Tables/TableDataClient";
|
||||
import { CommandButtonComponentProps } from "../Explorer/Controls/CommandButton/CommandButtonComponent";
|
||||
import { CommandButtonOptions } from "../Explorer/Controls/CommandButton/CommandButton";
|
||||
import { ConsoleData } from "../Explorer/Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { ExecuteSprocParam } from "../Explorer/Panes/ExecuteSprocParamsPane";
|
||||
import { GitHubClient } from "../GitHub/GitHubClient";
|
||||
@ -339,17 +338,6 @@ export interface Button {
|
||||
isSelected?: ko.Computed<boolean>;
|
||||
}
|
||||
|
||||
export interface CommandButton {
|
||||
disabled: ko.Subscribable<boolean>;
|
||||
visible: ko.Subscribable<boolean>;
|
||||
iconSrc: string;
|
||||
commandButtonLabel: string | ko.Observable<string>;
|
||||
tooltipText: string | ko.Observable<string>;
|
||||
children: ko.ObservableArray<CommandButtonOptions>;
|
||||
|
||||
commandClickCallback: () => void;
|
||||
}
|
||||
|
||||
export interface NotificationConsole {
|
||||
filteredConsoleData: ko.ObservableArray<ConsoleData>;
|
||||
isConsoleExpanded: ko.Observable<boolean>;
|
||||
@ -373,7 +361,6 @@ export interface TreeNode {
|
||||
id: ko.Observable<string>;
|
||||
database?: Database;
|
||||
collection?: Collection;
|
||||
contextMenu?: ContextMenu;
|
||||
|
||||
onNewQueryClick?(source: any, event: MouseEvent): void;
|
||||
onNewStoredProcedureClick?(source: Collection, event: MouseEvent): void;
|
||||
@ -538,7 +525,7 @@ export interface StoredProcedure extends TreeNode {
|
||||
id: ko.Observable<string>;
|
||||
body: ko.Observable<string>;
|
||||
|
||||
delete(source: TreeNode, event: MouseEvent | KeyboardEvent): void;
|
||||
delete(): void;
|
||||
open: () => void;
|
||||
select(): void;
|
||||
execute(params: string[], partitionKeyValue?: string): void;
|
||||
@ -552,7 +539,7 @@ export interface UserDefinedFunction extends TreeNode {
|
||||
id: ko.Observable<string>;
|
||||
body: ko.Observable<string>;
|
||||
|
||||
delete(source: TreeNode, event: MouseEvent | KeyboardEvent): void;
|
||||
delete(): void;
|
||||
open: () => void;
|
||||
select(): void;
|
||||
}
|
||||
@ -567,7 +554,7 @@ export interface Trigger extends TreeNode {
|
||||
triggerType: ko.Observable<string>;
|
||||
triggerOperation: ko.Observable<string>;
|
||||
|
||||
delete(source: TreeNode, event: MouseEvent | KeyboardEvent): void;
|
||||
delete(): void;
|
||||
open: () => void;
|
||||
select(): void;
|
||||
}
|
||||
@ -1233,17 +1220,6 @@ export enum TerminalKind {
|
||||
Cassandra = 2
|
||||
}
|
||||
|
||||
export interface ContextMenu {
|
||||
container: Explorer;
|
||||
visible: ko.Observable<boolean>;
|
||||
elementId: string;
|
||||
options: ko.ObservableArray<CommandButtonOptions>;
|
||||
tabIndex: ko.Observable<number>;
|
||||
|
||||
show(source: any, event: MouseEvent | KeyboardEvent): void;
|
||||
hide(source: any, event: MouseEvent | KeyboardEvent): void;
|
||||
}
|
||||
|
||||
export interface DataExplorerInputsFrame {
|
||||
databaseAccount: any;
|
||||
subscriptionId: string;
|
||||
|
@ -4,10 +4,6 @@ import * as ko from "knockout";
|
||||
import "./ComponentRegisterer";
|
||||
|
||||
describe("Component Registerer", () => {
|
||||
it("should register command-button component", () => {
|
||||
expect(ko.components.isRegistered("command-button")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register input-typeahead component", () => {
|
||||
expect(ko.components.isRegistered("input-typeahead")).toBe(true);
|
||||
});
|
||||
@ -80,30 +76,6 @@ describe("Component Registerer", () => {
|
||||
expect(ko.components.isRegistered("mongo-shell-tab")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register resource-tree component", () => {
|
||||
expect(ko.components.isRegistered("resource-tree")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register database-node component", () => {
|
||||
expect(ko.components.isRegistered("database-node")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register collection-node component", () => {
|
||||
expect(ko.components.isRegistered("collection-node")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register stored-procedure-node component", () => {
|
||||
expect(ko.components.isRegistered("stored-procedure-node")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register trigger-node component", () => {
|
||||
expect(ko.components.isRegistered("trigger-node")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register user-defined-function-node component", () => {
|
||||
expect(ko.components.isRegistered("user-defined-function-node")).toBe(true);
|
||||
});
|
||||
|
||||
it("should registeradd-collection-pane component", () => {
|
||||
expect(ko.components.isRegistered("add-collection-pane")).toBe(true);
|
||||
});
|
||||
@ -152,10 +124,6 @@ describe("Component Registerer", () => {
|
||||
expect(ko.components.isRegistered("manage-spark-cluster-pane")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register collection-node-context-menu component", () => {
|
||||
expect(ko.components.isRegistered("collection-node-context-menu")).toBe(true);
|
||||
});
|
||||
|
||||
it("should register dynamic-list component", () => {
|
||||
expect(ko.components.isRegistered("dynamic-list")).toBe(true);
|
||||
});
|
||||
|
@ -1,9 +1,7 @@
|
||||
import * as ko from "knockout";
|
||||
import * as PaneComponents from "./Panes/PaneComponents";
|
||||
import * as TabComponents from "./Tabs/TabComponents";
|
||||
import * as TreeComponents from "./Tree/TreeComponents";
|
||||
import { CollapsiblePanelComponent } from "./Controls/CollapsiblePanel/CollapsiblePanelComponent";
|
||||
import { CommandButtonComponent } from "./Controls/CommandButton/CommandButton";
|
||||
import { DiffEditorComponent } from "./Controls/DiffEditor/DiffEditorComponent";
|
||||
import { DynamicListComponent } from "./Controls/DynamicList/DynamicListComponent";
|
||||
import { EditorComponent } from "./Controls/Editor/EditorComponent";
|
||||
@ -16,7 +14,6 @@ import { ThroughputInputComponent } from "./Controls/ThroughputInput/ThroughputI
|
||||
import { ThroughputInputComponentAutoPilotV3 } from "./Controls/ThroughputInput/ThroughputInputComponentAutoPilotV3";
|
||||
import { ToolbarComponent } from "./Controls/Toolbar/Toolbar";
|
||||
|
||||
ko.components.register("command-button", CommandButtonComponent);
|
||||
ko.components.register("toolbar", new ToolbarComponent());
|
||||
ko.components.register("input-typeahead", new InputTypeaheadComponent());
|
||||
ko.components.register("new-vertex-form", NewVertexComponent);
|
||||
@ -51,14 +48,6 @@ ko.components.register("notebook-viewer-tab", new TabComponents.NotebookViewerTa
|
||||
// Database Tabs
|
||||
ko.components.register("database-settings-tab", new TabComponents.DatabaseSettingsTab());
|
||||
|
||||
// Resource Tree nodes
|
||||
ko.components.register("resource-tree", new TreeComponents.ResourceTree());
|
||||
ko.components.register("database-node", new TreeComponents.DatabaseTreeNode());
|
||||
ko.components.register("collection-node", new TreeComponents.CollectionTreeNode());
|
||||
ko.components.register("stored-procedure-node", new TreeComponents.StoredProcedureTreeNode());
|
||||
ko.components.register("trigger-node", new TreeComponents.TriggerTreeNode());
|
||||
ko.components.register("user-defined-function-node", new TreeComponents.UserDefinedFunctionTreeNode());
|
||||
|
||||
// Panes
|
||||
ko.components.register("add-database-pane", new PaneComponents.AddDatabasePaneComponent());
|
||||
ko.components.register("add-collection-pane", new PaneComponents.AddCollectionPaneComponent());
|
||||
@ -92,6 +81,3 @@ ko.components.register("manage-spark-cluster-pane", new PaneComponents.ManageSpa
|
||||
ko.components.register("library-manage-pane", new PaneComponents.LibraryManagePaneComponent());
|
||||
ko.components.register("cluster-library-pane", new PaneComponents.ClusterLibraryPaneComponent());
|
||||
ko.components.register("github-repos-pane", new PaneComponents.GitHubReposPaneComponent());
|
||||
|
||||
// Menus
|
||||
ko.components.register("collection-node-context-menu", new TreeComponents.CollectionTreeNodeContextMenu());
|
||||
|
@ -1,6 +1,5 @@
|
||||
import * as ko from "knockout";
|
||||
import * as ViewModels from "../Contracts/ViewModels";
|
||||
import { CommandButtonOptions } from "./Controls/CommandButton/CommandButton";
|
||||
import { TreeNodeMenuItem } from "./Controls/TreeComponent/TreeComponent";
|
||||
import AddCollectionIcon from "../../images/AddCollection.svg";
|
||||
import AddSqlQueryIcon from "../../images/AddSqlQuery_16x16.svg";
|
||||
@ -115,7 +114,10 @@ export class ResourceTreeContextMenuButtonFactory {
|
||||
return items;
|
||||
}
|
||||
|
||||
public static createStoreProcedureContextMenuItems(container: ViewModels.Explorer): TreeNodeMenuItem[] {
|
||||
public static createStoreProcedureContextMenuItems(
|
||||
container: ViewModels.Explorer,
|
||||
storedProcedure: ViewModels.StoredProcedure
|
||||
): TreeNodeMenuItem[] {
|
||||
if (container.isPreferredApiCassandra()) {
|
||||
return [];
|
||||
}
|
||||
@ -123,16 +125,16 @@ export class ResourceTreeContextMenuButtonFactory {
|
||||
return [
|
||||
{
|
||||
iconSrc: DeleteSprocIcon,
|
||||
onClick: () => {
|
||||
const selectedStoreProcedure: ViewModels.StoredProcedure = container.findSelectedStoredProcedure();
|
||||
selectedStoreProcedure && selectedStoreProcedure.delete(selectedStoreProcedure, null);
|
||||
},
|
||||
onClick: () => storedProcedure.delete(),
|
||||
label: "Delete Store Procedure"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
public static createTriggerContextMenuItems(container: ViewModels.Explorer): TreeNodeMenuItem[] {
|
||||
public static createTriggerContextMenuItems(
|
||||
container: ViewModels.Explorer,
|
||||
trigger: ViewModels.Trigger
|
||||
): TreeNodeMenuItem[] {
|
||||
if (container.isPreferredApiCassandra()) {
|
||||
return [];
|
||||
}
|
||||
@ -140,16 +142,16 @@ export class ResourceTreeContextMenuButtonFactory {
|
||||
return [
|
||||
{
|
||||
iconSrc: DeleteTriggerIcon,
|
||||
onClick: () => {
|
||||
const selectedTrigger: ViewModels.Trigger = container.findSelectedTrigger();
|
||||
selectedTrigger && selectedTrigger.delete(selectedTrigger, null);
|
||||
},
|
||||
onClick: () => trigger.delete(),
|
||||
label: "Delete Trigger"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
public static createUserDefinedFunctionContextMenuItems(container: ViewModels.Explorer): TreeNodeMenuItem[] {
|
||||
public static createUserDefinedFunctionContextMenuItems(
|
||||
container: ViewModels.Explorer,
|
||||
userDefinedFunction: ViewModels.UserDefinedFunction
|
||||
): TreeNodeMenuItem[] {
|
||||
if (container.isPreferredApiCassandra()) {
|
||||
return [];
|
||||
}
|
||||
@ -157,266 +159,9 @@ export class ResourceTreeContextMenuButtonFactory {
|
||||
return [
|
||||
{
|
||||
iconSrc: DeleteUDFIcon,
|
||||
onClick: () => {
|
||||
const selectedUDF: ViewModels.UserDefinedFunction = container.findSelectedUDF();
|
||||
selectedUDF && selectedUDF.delete(selectedUDF, null);
|
||||
},
|
||||
onClick: () => userDefinedFunction.delete(),
|
||||
label: "Delete User Defined Function"
|
||||
}
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Current resource tree (in KO)
|
||||
* TODO: Remove when switching to new resource tree
|
||||
*/
|
||||
export class ContextMenuButtonFactory {
|
||||
public static createDatabaseContextMenuButton(
|
||||
container: ViewModels.Explorer,
|
||||
btnParams: DatabaseContextMenuButtonParams
|
||||
): CommandButtonOptions[] {
|
||||
const addCollectionId = `${btnParams.databaseId}-${container.addCollectionText()}`;
|
||||
const deleteDatabaseId = `${btnParams.databaseId}-${container.deleteDatabaseText()}`;
|
||||
const newCollectionButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: AddCollectionIcon,
|
||||
id: addCollectionId,
|
||||
onCommandClick: () => {
|
||||
if (container.isPreferredApiCassandra()) {
|
||||
container.cassandraAddCollectionPane.open();
|
||||
} else {
|
||||
container.addCollectionPane.open(container.selectedDatabaseId());
|
||||
}
|
||||
|
||||
const selectedDatabase: ViewModels.Database = container.findSelectedDatabase();
|
||||
selectedDatabase && selectedDatabase.contextMenu.hide(selectedDatabase, null);
|
||||
},
|
||||
commandButtonLabel: container.addCollectionText(),
|
||||
hasPopup: true
|
||||
};
|
||||
|
||||
const deleteDatabaseButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: DeleteDatabaseIcon,
|
||||
id: deleteDatabaseId,
|
||||
onCommandClick: () => {
|
||||
const database: ViewModels.Database = container.findSelectedDatabase();
|
||||
database.onDeleteDatabaseContextMenuClick(database, null);
|
||||
},
|
||||
commandButtonLabel: container.deleteDatabaseText(),
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(() => container.isNoneSelected()),
|
||||
visible: ko.computed<boolean>(() => !container.isNoneSelected())
|
||||
};
|
||||
|
||||
return [newCollectionButtonOptions, deleteDatabaseButtonOptions];
|
||||
}
|
||||
|
||||
public static createCollectionContextMenuButton(
|
||||
container: ViewModels.Explorer,
|
||||
btnParams: CollectionContextMenuButtonParams
|
||||
): CommandButtonOptions[] {
|
||||
const newSqlQueryId = `${btnParams.databaseId}-${btnParams.collectionId}-newSqlQuery`;
|
||||
const newSqlQueryForGraphId = `${btnParams.databaseId}-${btnParams.collectionId}-newSqlQueryForGraph`;
|
||||
const newQueryForMongoId = `${btnParams.databaseId}-${btnParams.collectionId}-newQuery`;
|
||||
const newShellForMongoId = `${btnParams.databaseId}-${btnParams.collectionId}-newShell`;
|
||||
const newStoredProcedureId = `${btnParams.databaseId}-${btnParams.collectionId}-newStoredProcedure`;
|
||||
const udfId = `${btnParams.databaseId}-${btnParams.collectionId}-udf`;
|
||||
const newTriggerId = `${btnParams.databaseId}-${btnParams.collectionId}-newTrigger`;
|
||||
const deleteCollectionId = `${btnParams.databaseId}-${btnParams.collectionId}-${container.deleteCollectionText()}`;
|
||||
|
||||
const newSQLQueryButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: AddSqlQueryIcon,
|
||||
id: newSqlQueryId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: "New SQL Query",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(
|
||||
() => container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiDocumentDB()
|
||||
),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiDocumentDB()
|
||||
)
|
||||
//TODO: Merge with add query logic below, same goes for CommandBarButtonFactory
|
||||
};
|
||||
|
||||
const newSQLQueryButtonOptionsForGraph: CommandButtonOptions = {
|
||||
iconSrc: AddSqlQueryIcon,
|
||||
id: newSqlQueryForGraphId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewQueryClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: "New SQL Query",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiGraph()),
|
||||
visible: ko.computed<boolean>(() => !container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiGraph())
|
||||
};
|
||||
|
||||
const newMongoQueryButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: AddSqlQueryIcon,
|
||||
id: newQueryForMongoId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: "New Query",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(
|
||||
() => container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()
|
||||
),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()
|
||||
)
|
||||
};
|
||||
|
||||
const newMongoShellButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: HostedTerminalIcon,
|
||||
id: newShellForMongoId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewMongoShellClick();
|
||||
},
|
||||
commandButtonLabel: "New Shell",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(
|
||||
() => container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()
|
||||
),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && container.isPreferredApiMongoDB()
|
||||
)
|
||||
};
|
||||
|
||||
const newStoredProcedureButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: AddStoredProcedureIcon,
|
||||
id: newStoredProcedureId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewStoredProcedureClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: "New Stored Procedure",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && !container.isPreferredApiCassandra()
|
||||
)
|
||||
};
|
||||
|
||||
const newUserDefinedFunctionButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: AddUdfIcon,
|
||||
id: udfId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewUserDefinedFunctionClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: "New UDF",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && !container.isPreferredApiCassandra()
|
||||
)
|
||||
};
|
||||
|
||||
const newTriggerButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: AddTriggerIcon,
|
||||
id: newTriggerId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onNewTriggerClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: "New Trigger",
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && !container.isPreferredApiCassandra()
|
||||
)
|
||||
};
|
||||
|
||||
const deleteCollectionButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: DeleteCollectionIcon,
|
||||
id: deleteCollectionId,
|
||||
onCommandClick: () => {
|
||||
const selectedCollection: ViewModels.Collection = container.findSelectedCollection();
|
||||
selectedCollection && selectedCollection.onDeleteCollectionContextMenuClick(selectedCollection, null);
|
||||
},
|
||||
commandButtonLabel: container.deleteCollectionText(),
|
||||
hasPopup: true,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(() => !container.isDatabaseNodeOrNoneSelected())
|
||||
//TODO: Change to isCollectionNodeorNoneSelected and same in CommandBarButtonFactory
|
||||
};
|
||||
|
||||
return [
|
||||
newSQLQueryButtonOptions,
|
||||
newSQLQueryButtonOptionsForGraph,
|
||||
newMongoQueryButtonOptions,
|
||||
newMongoShellButtonOptions,
|
||||
newStoredProcedureButtonOptions,
|
||||
newUserDefinedFunctionButtonOptions,
|
||||
newTriggerButtonOptions,
|
||||
deleteCollectionButtonOptions
|
||||
];
|
||||
}
|
||||
|
||||
public static createStoreProcedureContextMenuButton(container: ViewModels.Explorer): CommandButtonOptions[] {
|
||||
const deleteStoredProcedureId = "Context Menu - Delete Stored Procedure";
|
||||
const deleteStoreProcedureButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: DeleteSprocIcon,
|
||||
id: deleteStoredProcedureId,
|
||||
onCommandClick: () => {
|
||||
const selectedStoreProcedure: ViewModels.StoredProcedure = container.findSelectedStoredProcedure();
|
||||
selectedStoreProcedure && selectedStoreProcedure.delete(selectedStoreProcedure, null);
|
||||
},
|
||||
commandButtonLabel: "Delete Stored Procedure",
|
||||
hasPopup: false,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && !container.isPreferredApiCassandra()
|
||||
)
|
||||
};
|
||||
|
||||
return [deleteStoreProcedureButtonOptions];
|
||||
}
|
||||
|
||||
public static createTriggerContextMenuButton(container: ViewModels.Explorer): CommandButtonOptions[] {
|
||||
const deleteTriggerId = "Context Menu - Delete Trigger";
|
||||
const deleteTriggerButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: DeleteTriggerIcon,
|
||||
id: deleteTriggerId,
|
||||
onCommandClick: () => {
|
||||
const selectedTrigger: ViewModels.Trigger = container.findSelectedTrigger();
|
||||
selectedTrigger && selectedTrigger.delete(selectedTrigger, null);
|
||||
},
|
||||
commandButtonLabel: "Delete Trigger",
|
||||
hasPopup: false,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && !container.isPreferredApiCassandra()
|
||||
)
|
||||
};
|
||||
|
||||
return [deleteTriggerButtonOptions];
|
||||
}
|
||||
|
||||
public static createUserDefinedFunctionContextMenuButton(container: ViewModels.Explorer): CommandButtonOptions[] {
|
||||
const deleteUserDefinedFunctionId = "Context Menu - Delete User Defined Function";
|
||||
const deleteUserDefinedFunctionButtonOptions: CommandButtonOptions = {
|
||||
iconSrc: DeleteUDFIcon,
|
||||
id: deleteUserDefinedFunctionId,
|
||||
onCommandClick: () => {
|
||||
const selectedUDF: ViewModels.UserDefinedFunction = container.findSelectedUDF();
|
||||
selectedUDF && selectedUDF.delete(selectedUDF, null);
|
||||
},
|
||||
commandButtonLabel: "Delete User Defined Function",
|
||||
hasPopup: false,
|
||||
disabled: ko.computed<boolean>(() => container.isDatabaseNodeOrNoneSelected()),
|
||||
visible: ko.computed<boolean>(
|
||||
() => !container.isDatabaseNodeOrNoneSelected() && !container.isPreferredApiCassandra()
|
||||
)
|
||||
};
|
||||
|
||||
return [deleteUserDefinedFunctionButtonOptions];
|
||||
}
|
||||
}
|
||||
|
@ -1,200 +0,0 @@
|
||||
@import "../../../../less/Common/Constants";
|
||||
|
||||
@ButtonIconSize: 18px;
|
||||
|
||||
.commandBar {
|
||||
padding-left: @DefaultSpace;
|
||||
border-bottom: @ButtonBorderWidth solid @BaseMedium;
|
||||
display: flex;
|
||||
overflow: hidden;
|
||||
height: @topcommandbarheight;
|
||||
|
||||
.staticCommands {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.overflowCommands {
|
||||
display:flex;
|
||||
flex: 1 0 auto;
|
||||
|
||||
.visibleCommands {
|
||||
display: inline-flex;
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.partialSplitterContainer {
|
||||
padding: @SmallSpace @DefaultSpace @SmallSpace @SmallSpace;
|
||||
.flex-display();
|
||||
}
|
||||
}
|
||||
|
||||
.commandExpand {
|
||||
border: none;
|
||||
padding: 0px;
|
||||
direction: rtl;
|
||||
|
||||
&:hover {
|
||||
.hover();
|
||||
cursor: pointer;
|
||||
& > .commandDropdownContainer {
|
||||
display: block !important; // TODO: Remove after reusing KO mouseover and mouseout event handlers
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
.focus();
|
||||
}
|
||||
|
||||
.commandDropdownLauncher {
|
||||
direction: ltr;
|
||||
padding-top: @SmallSpace;
|
||||
|
||||
.commandIcon {
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.commandBarEllipses {
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hiddenCommandsContainer > .commandDropdownLauncher {
|
||||
padding: 0px @DefaultSpace;
|
||||
}
|
||||
|
||||
.commandDropdownContainer {
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
direction: ltr;
|
||||
position: absolute;
|
||||
width: fit-content;
|
||||
padding: 0px;
|
||||
background-color: @BaseLight;
|
||||
box-shadow: 1px 2px 6px @BaseMediumHigh, -2px 2px 6px @BaseMediumHigh;
|
||||
|
||||
.commandDropdown {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.feedbackButton {
|
||||
margin-right: @LargeSpace;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
command-button,
|
||||
.commandButtonReact {
|
||||
display: inline-flex;
|
||||
.commandButtonComponent {
|
||||
width: 100%;
|
||||
color: @BaseHigh;
|
||||
background-color: transparent;
|
||||
text-decoration: none;
|
||||
border: @ButtonBorderWidth solid transparent;
|
||||
.flex-display();
|
||||
|
||||
&:hover:not(.commandDisabled) {
|
||||
cursor: pointer;
|
||||
.hover();
|
||||
}
|
||||
|
||||
&:active:not(.commandDisabled) {
|
||||
border: @ButtonBorderWidth dashed @AccentMedium;
|
||||
.active();
|
||||
}
|
||||
|
||||
&:focus:not(.commandDisabled) {
|
||||
border: @ButtonBorderWidth dashed @AccentMedium;
|
||||
}
|
||||
|
||||
.commandContent {
|
||||
padding: @DefaultSpace @DefaultSpace @DefaultSpace;
|
||||
flex: 0 0 auto;
|
||||
|
||||
.commandIcon {
|
||||
margin: 0 @SmallSpace 0 0;
|
||||
vertical-align: text-top;
|
||||
width: @ButtonIconSize;
|
||||
height: @ButtonIconSize;
|
||||
}
|
||||
|
||||
.commandLabel {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.commandContent .hasHiddenItems {
|
||||
padding-right: @SmallSpace;
|
||||
}
|
||||
}
|
||||
|
||||
.commandButtonComponent.commandDisabled {
|
||||
color: @BaseMediumHigh;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.commandExpand {
|
||||
padding-top: @SmallSpace;
|
||||
padding-bottom: @SmallSpace;
|
||||
&:hover {
|
||||
.hover();
|
||||
& > .commandDropdownContainer {
|
||||
display: block !important; // TODO: Remove after reusing KO mouseover and mouseout event handlers
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
.focus();
|
||||
}
|
||||
|
||||
.commandDropdownLauncher {
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
|
||||
.commandButtonComponent {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.expandDropdown {
|
||||
padding: @SmallSpace;
|
||||
|
||||
img {
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
.partialSplitter {
|
||||
margin: @SmallSpace 0px 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.commandButtonComponent[tabindex]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.selectedButton {
|
||||
background-color: @AccentLow;
|
||||
outline: none
|
||||
}
|
||||
}
|
||||
|
||||
.partialSplitter {
|
||||
border-left: @ButtonBorderWidth solid @BaseMediumHigh;
|
||||
}
|
||||
|
||||
.commandDropdown .commandButtonComponent {
|
||||
padding-left: 0px;
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
import * as ko from "knockout";
|
||||
import { CommandButtonComponent, CommandButtonOptions } from "./CommandButton";
|
||||
|
||||
const mockLabel = "Some Label";
|
||||
const id = "Some id";
|
||||
|
||||
function buildComponent(buttonOptions: any) {
|
||||
document.body.innerHTML = CommandButtonComponent.template as any;
|
||||
const vm = new CommandButtonComponent.viewModel(buttonOptions);
|
||||
ko.applyBindings(vm);
|
||||
}
|
||||
|
||||
describe("Command Button Component", () => {
|
||||
function buildButtonOptions(
|
||||
onClick: () => void,
|
||||
id?: string,
|
||||
label?: string,
|
||||
disabled?: ko.Observable<boolean>,
|
||||
visible?: ko.Observable<boolean>,
|
||||
tooltipText?: string
|
||||
): { buttonProps: CommandButtonOptions } {
|
||||
return {
|
||||
buttonProps: {
|
||||
iconSrc: "images/AddCollection.svg",
|
||||
id: id,
|
||||
commandButtonLabel: label || mockLabel,
|
||||
disabled: disabled,
|
||||
visible: visible,
|
||||
tooltipText: tooltipText,
|
||||
hasPopup: false,
|
||||
onCommandClick: onClick
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function buildSplitterButtonOptions(
|
||||
onClick: () => void,
|
||||
id?: string,
|
||||
label?: string,
|
||||
disabled?: ko.Observable<boolean>,
|
||||
visible?: ko.Observable<boolean>,
|
||||
tooltipText?: string
|
||||
): { buttonProps: CommandButtonOptions } {
|
||||
const child: CommandButtonOptions = {
|
||||
iconSrc: "images/settings_15x15.svg",
|
||||
id: id,
|
||||
commandButtonLabel: label || mockLabel,
|
||||
disabled: disabled,
|
||||
visible: visible,
|
||||
tooltipText: tooltipText,
|
||||
hasPopup: false,
|
||||
onCommandClick: onClick
|
||||
};
|
||||
|
||||
return {
|
||||
buttonProps: {
|
||||
iconSrc: "images/AddCollection.svg",
|
||||
id: id,
|
||||
commandButtonLabel: label || mockLabel,
|
||||
disabled: disabled,
|
||||
visible: visible,
|
||||
tooltipText: tooltipText,
|
||||
hasPopup: false,
|
||||
onCommandClick: onClick,
|
||||
children: [child]
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
ko.cleanNode(document);
|
||||
document.body.innerHTML = "";
|
||||
});
|
||||
|
||||
describe("Rendering", () => {
|
||||
it("should display button label", () => {
|
||||
const buttonOptions = buildButtonOptions(() => {
|
||||
/** do nothing **/
|
||||
}, mockLabel);
|
||||
buildComponent(buttonOptions);
|
||||
expect(document.getElementsByClassName("commandButtonComponent").item(0).textContent).toContain(mockLabel);
|
||||
});
|
||||
|
||||
it("should display button icon", () => {
|
||||
const buttonOptions = buildButtonOptions(() => {
|
||||
/** do nothing **/
|
||||
});
|
||||
buildComponent(buttonOptions);
|
||||
expect(
|
||||
document
|
||||
.getElementsByTagName("img")
|
||||
.item(0)
|
||||
.getAttribute("src")
|
||||
).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Behavior", () => {
|
||||
let clickSpy: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
clickSpy = jasmine.createSpy("Command button click spy");
|
||||
});
|
||||
|
||||
it("should trigger the click handler when the command button is clicked", () => {
|
||||
const buttonOptions = buildButtonOptions(() => clickSpy());
|
||||
buildComponent(buttonOptions);
|
||||
document
|
||||
.getElementsByClassName("commandButtonComponent")
|
||||
.item(0)
|
||||
.dispatchEvent(new Event("click"));
|
||||
expect(clickSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not trigger the click handler when command button is disabled", () => {
|
||||
const buttonOptions = buildButtonOptions(() => clickSpy(), id, mockLabel, ko.observable(true));
|
||||
buildComponent(buttonOptions);
|
||||
document
|
||||
.getElementsByClassName("commandButtonComponent")
|
||||
.item(0)
|
||||
.dispatchEvent(new Event("click"));
|
||||
expect(clickSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should not have a dropdown if it has no child", () => {
|
||||
const buttonOptions = buildButtonOptions(() => clickSpy(), id, mockLabel, ko.observable(true));
|
||||
buildComponent(buttonOptions);
|
||||
const dropdownSize = document.getElementsByClassName("commandExpand").length;
|
||||
expect(dropdownSize).toBe(0);
|
||||
});
|
||||
|
||||
it("should have a dropdown if it has a child", () => {
|
||||
const buttonOptions = buildSplitterButtonOptions(() => clickSpy(), id, mockLabel, ko.observable(true));
|
||||
buildComponent(buttonOptions);
|
||||
const dropdownSize = document.getElementsByClassName("commandExpand").length;
|
||||
expect(dropdownSize).toBe(1);
|
||||
});
|
||||
});
|
||||
});
|
@ -1,191 +0,0 @@
|
||||
/**
|
||||
* How to use this component:
|
||||
*
|
||||
* In your html markup, use:
|
||||
* <command-button params="{
|
||||
* iconSrc: '/icon/example/src/',
|
||||
* onCommandClick: () => { doSomething },
|
||||
* commandButtonLabel: 'Some Label'
|
||||
* disabled: true/false
|
||||
* }">
|
||||
* </command-button>
|
||||
*
|
||||
*/
|
||||
|
||||
import * as ko from "knockout";
|
||||
import * as ViewModels from "../../../Contracts/ViewModels";
|
||||
import { Action, ActionModifiers } from "../../../Shared/Telemetry/TelemetryConstants";
|
||||
import { WaitsForTemplateViewModel } from "../../WaitsForTemplateViewModel";
|
||||
import { KeyCodes } from "../../../Common/Constants";
|
||||
|
||||
import TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
|
||||
import template from "./command-button.html";
|
||||
|
||||
/**
|
||||
* Options for this component
|
||||
*/
|
||||
export interface CommandButtonOptions {
|
||||
/**
|
||||
* image source for the button icon
|
||||
*/
|
||||
iconSrc: string;
|
||||
|
||||
/**
|
||||
* Id for the button icon
|
||||
*/
|
||||
id: string;
|
||||
|
||||
/**
|
||||
* Click handler for command button click
|
||||
*/
|
||||
onCommandClick: () => void;
|
||||
|
||||
/**
|
||||
* Label for the button
|
||||
*/
|
||||
commandButtonLabel: string | ko.Observable<string>;
|
||||
|
||||
/**
|
||||
* True if this button opens a tab or pane, false otherwise.
|
||||
*/
|
||||
hasPopup: boolean;
|
||||
|
||||
/**
|
||||
* Enabled/disabled state of command button
|
||||
*/
|
||||
disabled?: ko.Subscribable<boolean>;
|
||||
|
||||
/**
|
||||
* Visibility/Invisibility of the button
|
||||
*/
|
||||
visible?: ko.Subscribable<boolean>;
|
||||
|
||||
/**
|
||||
* Whether or not the button should have the 'selectedButton' styling
|
||||
*/
|
||||
isSelected?: ko.Observable<boolean>;
|
||||
|
||||
/**
|
||||
* Text to displayed in the tooltip on hover
|
||||
*/
|
||||
tooltipText?: string | ko.Observable<string>;
|
||||
|
||||
/**
|
||||
* Callback triggered when the template is bound to the component
|
||||
*/
|
||||
onTemplateReady?: () => void;
|
||||
|
||||
/**
|
||||
* tabindex for the command button
|
||||
*/
|
||||
tabIndex?: ko.Observable<number>;
|
||||
|
||||
/**
|
||||
* Childrens command buttons to hide in the dropdown
|
||||
*/
|
||||
children?: CommandButtonOptions[];
|
||||
}
|
||||
|
||||
export class CommandButtonViewModel extends WaitsForTemplateViewModel implements ViewModels.CommandButton {
|
||||
public commandClickCallback: () => void;
|
||||
public commandButtonId: string;
|
||||
public disabled: ko.Subscribable<boolean>;
|
||||
public visible: ko.Subscribable<boolean>;
|
||||
public isSelected: ko.Observable<boolean>;
|
||||
public iconSrc: string;
|
||||
public commandButtonLabel: ko.Observable<string>;
|
||||
public tooltipText: ko.Observable<string>;
|
||||
public tabIndex: ko.Observable<number>;
|
||||
public isTemplateReady: ko.Observable<boolean>;
|
||||
public hasPopup: boolean;
|
||||
public children: ko.ObservableArray<CommandButtonOptions>;
|
||||
|
||||
public constructor(options: { buttonProps: CommandButtonOptions }) {
|
||||
super();
|
||||
const props = options.buttonProps;
|
||||
const commandButtonLabel = props.commandButtonLabel;
|
||||
const tooltipText = props.tooltipText;
|
||||
this.commandButtonLabel =
|
||||
typeof commandButtonLabel === "string" ? ko.observable<string>(commandButtonLabel) : commandButtonLabel;
|
||||
this.commandButtonId = props.id;
|
||||
this.disabled = props.disabled || ko.observable(false);
|
||||
this.visible = props.visible || ko.observable(true);
|
||||
this.isSelected = props.isSelected || ko.observable(false);
|
||||
this.iconSrc = props.iconSrc;
|
||||
this.tabIndex = props.tabIndex || ko.observable(0);
|
||||
this.hasPopup = props.hasPopup;
|
||||
this.children = ko.observableArray(props.children);
|
||||
|
||||
super.onTemplateReady((isTemplateReady: boolean) => {
|
||||
if (isTemplateReady && props.onTemplateReady) {
|
||||
props.onTemplateReady();
|
||||
}
|
||||
});
|
||||
|
||||
if (tooltipText && typeof tooltipText === "string") {
|
||||
this.tooltipText = ko.observable<string>(tooltipText);
|
||||
} else if (tooltipText && typeof tooltipText === "function") {
|
||||
this.tooltipText = tooltipText;
|
||||
} else {
|
||||
this.tooltipText = this.commandButtonLabel;
|
||||
}
|
||||
|
||||
this.commandClickCallback = () => {
|
||||
if (this.disabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const el = document.querySelector(".commandDropdownContainer") as HTMLElement;
|
||||
if (el) {
|
||||
el.style.display = "none";
|
||||
}
|
||||
props.onCommandClick();
|
||||
TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, {
|
||||
commandButtonClicked: this.commandButtonLabel
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
public onKeyPress(source: any, event: KeyboardEvent): boolean {
|
||||
if (event.keyCode === KeyCodes.Space || event.keyCode === KeyCodes.Enter) {
|
||||
this.commandClickCallback && this.commandClickCallback();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public onLauncherKeyDown(source: any, event: KeyboardEvent): boolean {
|
||||
// TODO: Convert JQuery code into Knockout
|
||||
if (event.keyCode === KeyCodes.DownArrow) {
|
||||
$(event.target)
|
||||
.parent()
|
||||
.siblings()
|
||||
.children(".commandExpand")
|
||||
.children(".commandDropdownContainer")
|
||||
.hide();
|
||||
$(event.target)
|
||||
.children(".commandDropdownContainer")
|
||||
.show()
|
||||
.focus();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
if (event.keyCode === KeyCodes.UpArrow) {
|
||||
$(event.target)
|
||||
.children(".commandDropdownContainer")
|
||||
.hide();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for ko component registration
|
||||
*/
|
||||
export const CommandButtonComponent = {
|
||||
viewModel: CommandButtonViewModel,
|
||||
template
|
||||
};
|
@ -1,40 +0,0 @@
|
||||
<span
|
||||
class="commandButtonComponent"
|
||||
role="menuitem"
|
||||
tabindex="0"
|
||||
data-bind="setTemplateReady: true,
|
||||
css: {
|
||||
commandDisabled: disabled,
|
||||
selectedButton: isSelected
|
||||
},
|
||||
event: {
|
||||
keypress: onKeyPress
|
||||
},
|
||||
attr: {
|
||||
title: tooltipText,
|
||||
id: commandButtonId,
|
||||
tabindex: tabIndex ,
|
||||
'aria-disabled': disabled,
|
||||
'aria-haspopup': hasPopup
|
||||
},
|
||||
click: commandClickCallback,
|
||||
visible: visible"
|
||||
>
|
||||
<div class="commandContent" data-bind="css: { hasHiddenItems: children().length > 0 }">
|
||||
<img class="commandIcon" data-bind="attr: {src: iconSrc, alt: commandButtonLabel}" />
|
||||
<span class="commandLabel" data-bind="text: commandButtonLabel"></span>
|
||||
</div>
|
||||
</span>
|
||||
<!-- ko if: children().length > 0 -->
|
||||
<div class="commandExpand" tabindex="0" data-bind="visible: visible, event: { keydown: onLauncherKeyDown }">
|
||||
<div class="commandDropdownLauncher">
|
||||
<span class="partialSplitter"></span>
|
||||
<span class="expandDropdown"> <img src="/QueryBuilder/CollapseChevronDown_16x.png" /> </span>
|
||||
</div>
|
||||
<div class="commandDropdownContainer">
|
||||
<div class="commandDropdown" data-bind="foreach: children">
|
||||
<command-button params="{buttonProps: $data}"></command-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /ko -->
|
@ -10,7 +10,6 @@ import {
|
||||
GalleryViewerComponent,
|
||||
GalleryViewerComponentProps
|
||||
} from "./GalleryViewerComponent";
|
||||
import * as DataModels from "../../../Contracts/DataModels";
|
||||
|
||||
describe("GalleryCardsComponent", () => {
|
||||
it("renders", () => {
|
||||
@ -18,14 +17,8 @@ describe("GalleryCardsComponent", () => {
|
||||
const props: GalleryCardsComponentProps = {
|
||||
data: [],
|
||||
userMetadata: undefined,
|
||||
onNotebookMetadataChange: (officialSamplesIndex: number, notebookMetadata: DataModels.NotebookMetadata) =>
|
||||
Promise.resolve(),
|
||||
onClick: (
|
||||
url: string,
|
||||
notebookMetadata: DataModels.NotebookMetadata,
|
||||
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||
isLikedNotebook: boolean
|
||||
) => Promise.resolve()
|
||||
onNotebookMetadataChange: () => Promise.resolve(),
|
||||
onClick: () => Promise.resolve()
|
||||
};
|
||||
|
||||
const wrapper = shallow(<GalleryCardsComponent {...props} />);
|
||||
@ -39,12 +32,7 @@ describe("FullWidthTabs", () => {
|
||||
officialSamplesContent: [],
|
||||
likedNotebooksContent: [],
|
||||
userMetadata: undefined,
|
||||
onClick: (
|
||||
url: string,
|
||||
notebookMetadata: DataModels.NotebookMetadata,
|
||||
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||
isLikedNotebook: boolean
|
||||
) => Promise.resolve()
|
||||
onClick: () => Promise.resolve()
|
||||
};
|
||||
|
||||
const wrapper = shallow(<FullWidthTabs {...props} />);
|
||||
|
@ -39,7 +39,7 @@ export class GalleryCardsComponent extends React.Component<GalleryCardsComponent
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<Stack horizontal wrap tokens={this.sectionStackTokens}>
|
||||
{this.props.data.map((githubInfo: DataModels.GitHubInfoJunoResponse, index: any) => {
|
||||
{this.props.data.map((githubInfo: DataModels.GitHubInfoJunoResponse) => {
|
||||
const name = githubInfo.name;
|
||||
const url = githubInfo.downloadUrl;
|
||||
const notebookMetadata = githubInfo.metadata || {
|
||||
@ -56,7 +56,7 @@ export class GalleryCardsComponent extends React.Component<GalleryCardsComponent
|
||||
const officialSamplesIndex = githubInfo.officialSamplesIndex;
|
||||
const isLikedNotebook = githubInfo.isLikedNotebook;
|
||||
const updateTabsStatePerNotebook = this.props.onNotebookMetadataChange
|
||||
? (notebookMetadata: DataModels.NotebookMetadata) =>
|
||||
? (notebookMetadata: DataModels.NotebookMetadata): Promise<void> =>
|
||||
this.props.onNotebookMetadataChange(officialSamplesIndex, notebookMetadata)
|
||||
: undefined;
|
||||
|
||||
@ -68,7 +68,9 @@ export class GalleryCardsComponent extends React.Component<GalleryCardsComponent
|
||||
name={name}
|
||||
url={url}
|
||||
notebookMetadata={notebookMetadata}
|
||||
onClick={() => this.props.onClick(url, notebookMetadata, updateTabsStatePerNotebook, isLikedNotebook)}
|
||||
onClick={(): Promise<void> =>
|
||||
this.props.onClick(url, notebookMetadata, updateTabsStatePerNotebook, isLikedNotebook)
|
||||
}
|
||||
/>
|
||||
)
|
||||
);
|
||||
@ -115,7 +117,7 @@ export class FullWidthTabs extends React.Component<FullWidthTabsProps, FullWidth
|
||||
title: "Official Samples",
|
||||
content: {
|
||||
className: "",
|
||||
render: () => (
|
||||
render: (): JSX.Element => (
|
||||
<GalleryCardsComponent
|
||||
data={this.state.officialSamplesContent}
|
||||
onClick={this.props.onClick}
|
||||
@ -124,13 +126,13 @@ export class FullWidthTabs extends React.Component<FullWidthTabsProps, FullWidth
|
||||
/>
|
||||
)
|
||||
},
|
||||
isVisible: () => true
|
||||
isVisible: (): boolean => true
|
||||
},
|
||||
{
|
||||
title: "Liked Notebooks",
|
||||
content: {
|
||||
className: "",
|
||||
render: () => (
|
||||
render: (): JSX.Element => (
|
||||
<GalleryCardsComponent
|
||||
data={this.state.likedNotebooksContent}
|
||||
onClick={this.props.onClick}
|
||||
@ -139,12 +141,15 @@ export class FullWidthTabs extends React.Component<FullWidthTabsProps, FullWidth
|
||||
/>
|
||||
)
|
||||
},
|
||||
isVisible: () => true
|
||||
isVisible: (): boolean => true
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
public updateTabsState = async (officialSamplesIndex: number, notebookMetadata: DataModels.NotebookMetadata) => {
|
||||
public updateTabsState = async (
|
||||
officialSamplesIndex: number,
|
||||
notebookMetadata: DataModels.NotebookMetadata
|
||||
): Promise<void> => {
|
||||
let currentLikedNotebooksContent = [...this.state.likedNotebooksContent];
|
||||
let currentUserMetadata = { ...this.state.userMetadata };
|
||||
let currentLikedNotebooks = [...currentUserMetadata.likedNotebooks];
|
||||
@ -187,7 +192,7 @@ export class FullWidthTabs extends React.Component<FullWidthTabsProps, FullWidth
|
||||
});
|
||||
|
||||
JunoUtils.updateNotebookMetadata(this.authorizationToken, notebookMetadata).then(
|
||||
async returnedNotebookMetadata => {
|
||||
async () => {
|
||||
if (metadataLikesUpdates !== 0) {
|
||||
JunoUtils.updateUserMetadata(this.authorizationToken, currentUserMetadata);
|
||||
// TODO: update state here?
|
||||
@ -203,9 +208,9 @@ export class FullWidthTabs extends React.Component<FullWidthTabsProps, FullWidth
|
||||
);
|
||||
};
|
||||
|
||||
private onTabIndexChange = (activeTabIndex: number) => this.setState({ activeTabIndex });
|
||||
private onTabIndexChange = (activeTabIndex: number): void => this.setState({ activeTabIndex });
|
||||
|
||||
public render() {
|
||||
public render(): JSX.Element {
|
||||
return (
|
||||
<TabComponent.TabComponent
|
||||
tabs={this.appTabs}
|
||||
@ -238,7 +243,7 @@ export class GalleryViewerContainerComponent extends React.Component<
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
componentDidMount(): void {
|
||||
const authToken = CosmosClient.authorizationToken();
|
||||
JunoUtils.getOfficialSampleNotebooks(authToken).then(
|
||||
(data1: DataModels.GitHubInfoJunoResponse[]) => {
|
||||
@ -341,7 +346,7 @@ export class GalleryViewerComponent extends React.Component<GalleryViewerCompone
|
||||
notebookMetadata: DataModels.NotebookMetadata,
|
||||
onNotebookMetadataChange: (newNotebookMetadata: DataModels.NotebookMetadata) => Promise<void>,
|
||||
isLikedNotebook: boolean
|
||||
) => {
|
||||
): Promise<void> => {
|
||||
if (!this.props.container) {
|
||||
SessionStorageUtility.setEntryString(
|
||||
StorageKey.NotebookMetadata,
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React from "react";
|
||||
import { shallow } from "enzyme";
|
||||
import { NotebookMetadataComponentProps, NotebookMetadataComponent } from "./NotebookMetadataComponent";
|
||||
import { NotebookMetadata } from "../../../Contracts/DataModels";
|
||||
|
||||
describe("NotebookMetadataComponent", () => {
|
||||
it("renders un-liked notebook", () => {
|
||||
@ -10,7 +9,7 @@ describe("NotebookMetadataComponent", () => {
|
||||
container: undefined,
|
||||
notebookMetadata: undefined,
|
||||
notebookContent: {},
|
||||
onNotebookMetadataChange: (newNotebookMetadata: NotebookMetadata) => Promise.resolve(),
|
||||
onNotebookMetadataChange: () => Promise.resolve(),
|
||||
isLikedNotebook: false
|
||||
};
|
||||
|
||||
@ -24,7 +23,7 @@ describe("NotebookMetadataComponent", () => {
|
||||
container: undefined,
|
||||
notebookMetadata: undefined,
|
||||
notebookContent: {},
|
||||
onNotebookMetadataChange: (newNotebookMetadata: NotebookMetadata) => Promise.resolve(),
|
||||
onNotebookMetadataChange: () => Promise.resolve(),
|
||||
isLikedNotebook: true
|
||||
};
|
||||
|
||||
|
@ -154,7 +154,6 @@ export default class Explorer implements ViewModels.Explorer {
|
||||
public selectedNode: ko.Observable<ViewModels.TreeNode>;
|
||||
public isRefreshingExplorer: ko.Observable<boolean>;
|
||||
private resourceTree: ResourceTreeAdapter;
|
||||
private enableLegacyResourceTree: ko.Observable<boolean>;
|
||||
|
||||
// Resource Token
|
||||
public resourceTokenDatabaseId: ko.Observable<string>;
|
||||
@ -382,7 +381,6 @@ export default class Explorer implements ViewModels.Explorer {
|
||||
this.armEndpoint = ko.observable<string>(undefined);
|
||||
this.queriesClient = new QueriesClient(this);
|
||||
this.isTryCosmosDBSubscription = ko.observable<boolean>(false);
|
||||
this.enableLegacyResourceTree = ko.observable<boolean>(false);
|
||||
|
||||
this.resourceTokenDatabaseId = ko.observable<string>();
|
||||
this.resourceTokenCollectionId = ko.observable<string>();
|
||||
@ -1103,8 +1101,6 @@ export default class Explorer implements ViewModels.Explorer {
|
||||
this.sparkClusterConnectionInfo.valueHasMutated();
|
||||
}
|
||||
|
||||
this.enableLegacyResourceTree(this.isFeatureEnabled(Constants.Features.enableLegacyResourceTree));
|
||||
|
||||
featureSubcription.dispose();
|
||||
});
|
||||
|
||||
|
@ -1,43 +0,0 @@
|
||||
import * as ko from "knockout";
|
||||
import * as ViewModels from "../../Contracts/ViewModels";
|
||||
import { CommandButtonOptions } from "./../Controls/CommandButton/CommandButton";
|
||||
|
||||
export default class ContextMenu implements ViewModels.ContextMenu {
|
||||
public container: ViewModels.Explorer;
|
||||
public visible: ko.Observable<boolean>;
|
||||
public elementId: string;
|
||||
public options: ko.ObservableArray<CommandButtonOptions>;
|
||||
public tabIndex: ko.Observable<number>;
|
||||
|
||||
constructor(container: ViewModels.Explorer, rid: string) {
|
||||
this.container = container;
|
||||
this.visible = ko.observable<boolean>(false);
|
||||
this.elementId = `contextMenu${rid}`;
|
||||
this.options = ko.observableArray<CommandButtonOptions>([]);
|
||||
this.tabIndex = ko.observable<number>(0);
|
||||
}
|
||||
|
||||
public show(source: ViewModels.TreeNode, event: MouseEvent) {
|
||||
if (source && source.contextMenu && source.contextMenu.visible && source.contextMenu.visible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.container.selectedNode(source);
|
||||
const elementId = source.contextMenu.elementId;
|
||||
const htmlElement = document.getElementById(elementId);
|
||||
htmlElement.style.left = `${event.clientX}px`;
|
||||
htmlElement.style.top = `${event.clientY}px`;
|
||||
|
||||
!!source.contextMenu && source.contextMenu.visible(true);
|
||||
source.contextMenu.tabIndex(0);
|
||||
htmlElement.focus();
|
||||
}
|
||||
|
||||
public hide(source: ViewModels.TreeNode, event: MouseEvent) {
|
||||
if (!source || !source.contextMenu || !source.contextMenu.visible || !source.contextMenu.visible()) {
|
||||
return;
|
||||
}
|
||||
source.contextMenu.tabIndex(-1);
|
||||
source.contextMenu.visible(false);
|
||||
}
|
||||
}
|
@ -449,7 +449,6 @@ export class DatabaseStub implements ViewModels.Database {
|
||||
public collections: ko.ObservableArray<ViewModels.Collection>;
|
||||
public isDatabaseExpanded: ko.Observable<boolean>;
|
||||
public isDatabaseShared: ko.Computed<boolean>;
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
|
||||
public offer: ko.Observable<DataModels.Offer>;
|
||||
|
||||
@ -461,7 +460,6 @@ export class DatabaseStub implements ViewModels.Database {
|
||||
this.id = options.id;
|
||||
this.collections = options.collections;
|
||||
this.isDatabaseExpanded = options.isDatabaseExpanded;
|
||||
this.contextMenu = options.contextMenu;
|
||||
this.offer = options.offer;
|
||||
this.selectedSubnodeKind = options.selectedSubnodeKind;
|
||||
}
|
||||
@ -564,8 +562,6 @@ export class CollectionStub implements ViewModels.Collection {
|
||||
public storedProceduresFocused: ko.Observable<boolean>;
|
||||
public userDefinedFunctionsFocused: ko.Observable<boolean>;
|
||||
public triggersFocused: ko.Observable<boolean>;
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
public documentsContextMenu: ViewModels.ContextMenu;
|
||||
public conflictResolutionPolicy: ko.Observable<DataModels.ConflictResolutionPolicy>;
|
||||
public changeFeedPolicy: ko.Observable<DataModels.ChangeFeedPolicy>;
|
||||
public geospatialConfig: ko.Observable<DataModels.GeospatialConfig>;
|
||||
@ -610,69 +606,8 @@ export class CollectionStub implements ViewModels.Collection {
|
||||
this.storedProceduresFocused = options.storedProceduresFocused;
|
||||
this.userDefinedFunctionsFocused = options.userDefinedFunctionsFocused;
|
||||
this.triggersFocused = options.triggersFocused;
|
||||
this.contextMenu = options.contextMenu;
|
||||
this.documentsContextMenu = options.documentsContextMenu;
|
||||
}
|
||||
|
||||
public onKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onMenuKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onDocumentDBDocumentsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onDocumentDBDocumentsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onMongoDBDocumentsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onMongoDBDocumentsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onSettingsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onSettingsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onStoredProceduresKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onStoredProceduresKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onUserDefinedFunctionsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onUserDefinedFunctionsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onTriggersKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
|
||||
public onTriggersKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
throw new Error("Not implemented");
|
||||
};
|
||||
public expandCollapseCollection() {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
|
@ -14,8 +14,6 @@ import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { OfferUtils } from "../../Utils/OfferUtils";
|
||||
import { StartUploadMessageParams, UploadDetails, UploadDetailsRecord } from "../../workers/upload/definitions";
|
||||
import { ContextMenuButtonFactory } from "../ContextMenuButtonFactory";
|
||||
import ContextMenu from "../Menus/ContextMenu";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { CassandraAPIDataClient, CassandraTableKey, CassandraTableKeys } from "../Tables/TableDataClient";
|
||||
import { ConflictsTab } from "../Tabs/ConflictsTab";
|
||||
@ -86,9 +84,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
public userDefinedFunctionsFocused: ko.Observable<boolean>;
|
||||
public triggersFocused: ko.Observable<boolean>;
|
||||
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
public documentsContextMenu: ViewModels.ContextMenu;
|
||||
|
||||
constructor(
|
||||
container: ViewModels.Explorer,
|
||||
databaseId: string,
|
||||
@ -216,217 +211,8 @@ export default class Collection implements ViewModels.Collection {
|
||||
this.isStoredProceduresExpanded = ko.observable<boolean>(false);
|
||||
this.isUserDefinedFunctionsExpanded = ko.observable<boolean>(false);
|
||||
this.isTriggersExpanded = ko.observable<boolean>(false);
|
||||
this.contextMenu = new ContextMenu(this.container, this.rid);
|
||||
this.contextMenu.options(
|
||||
ContextMenuButtonFactory.createCollectionContextMenuButton(container, {
|
||||
databaseId: this.databaseId,
|
||||
collectionId: this.id()
|
||||
})
|
||||
);
|
||||
this.documentsContextMenu = new ContextMenu(this.container, `${this.rid}/documents`);
|
||||
}
|
||||
|
||||
public onKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.expandCollapseCollection();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Delete") {
|
||||
this.onDeleteCollectionContextMenuClick(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowRight" && !this.isCollectionExpanded()) {
|
||||
this.expandCollection();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowDown" && !this.isCollectionExpanded()) {
|
||||
this.expandCollection();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowLeft" && this.isCollectionExpanded()) {
|
||||
this.collapseCollection();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMenuKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Escape") {
|
||||
this.contextMenu.hide(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onTableEntitiesKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
public onTableEntitiesKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.onTableEntitiesClick();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onGraphDocumentsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
public onGraphDocumentsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.onGraphDocumentsClick();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onDocumentDBDocumentsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
public onDocumentDBDocumentsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.onDocumentDBDocumentsClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onConflictsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.onConflictsClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMongoDBDocumentsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMongoDBDocumentsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.onMongoDBDocumentsClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onSettingsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
public onSettingsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.onSettingsClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onStoredProceduresKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "ArrowRight" && !this.isStoredProceduresExpanded()) {
|
||||
this.expandStoredProcedures();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowDown" && !this.isStoredProceduresExpanded()) {
|
||||
this.expandStoredProcedures();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowLeft" && this.isStoredProceduresExpanded()) {
|
||||
this.collapseStoredProcedures();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onStoredProceduresKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.expandCollapseStoredProcedures();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onUserDefinedFunctionsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "ArrowRight" && !this.isUserDefinedFunctionsExpanded()) {
|
||||
this.expandUserDefinedFunctions();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowDown" && !this.isUserDefinedFunctionsExpanded()) {
|
||||
this.expandUserDefinedFunctions();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowLeft" && this.isUserDefinedFunctionsExpanded()) {
|
||||
this.collapseUserDefinedFunctions();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onUserDefinedFunctionsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.expandCollapseUserDefinedFunctions();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onTriggersKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "ArrowRight" && !this.isTriggersExpanded()) {
|
||||
this.expandTriggers();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowDown" && !this.isTriggersExpanded()) {
|
||||
this.expandTriggers();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowLeft" && this.isTriggersExpanded()) {
|
||||
this.collapseTriggers();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onTriggersKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.keyCode === Constants.KeyCodes.Space || event.keyCode === Constants.KeyCodes.Enter) {
|
||||
this.expandCollapseTriggers();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
public expandCollapseCollection() {
|
||||
this.container.selectedNode(this);
|
||||
TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, {
|
||||
@ -985,9 +771,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
|
||||
// Activate
|
||||
queryTab.onTabClick();
|
||||
|
||||
// Hide Context Menu (if necessary)
|
||||
collection.contextMenu.hide(this, null);
|
||||
}
|
||||
|
||||
public onNewMongoQueryClick(source: any, event: MouseEvent, queryText?: string) {
|
||||
@ -1025,9 +808,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
|
||||
// Activate
|
||||
queryTab.onTabClick();
|
||||
|
||||
// Hide Context Menu (if necessary)
|
||||
collection.contextMenu.hide(this, null);
|
||||
}
|
||||
|
||||
public onNewGraphClick() {
|
||||
@ -1036,8 +816,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
this.container.openedTabs.push(graphTab);
|
||||
// Activate
|
||||
graphTab.onTabClick();
|
||||
// Hide Context Menu (if necessary)
|
||||
this.contextMenu.hide(this, null);
|
||||
}
|
||||
|
||||
public onNewMongoShellClick() {
|
||||
@ -1060,9 +838,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
|
||||
// Activate
|
||||
mongoShellTab.onTabClick();
|
||||
|
||||
// Hide Context Menu (if necessary)
|
||||
this.contextMenu.hide(this, null);
|
||||
}
|
||||
|
||||
public onNewStoredProcedureClick(source: ViewModels.Collection, event: MouseEvent) {
|
||||
@ -1357,7 +1132,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
}
|
||||
|
||||
public onDeleteCollectionContextMenuClick(source: ViewModels.Collection, event: MouseEvent | KeyboardEvent) {
|
||||
this._onContextMenuClick(source, event);
|
||||
this.container.deleteCollectionConfirmationPane.open();
|
||||
}
|
||||
|
||||
@ -1605,11 +1379,6 @@ export default class Collection implements ViewModels.Collection {
|
||||
});
|
||||
}
|
||||
|
||||
private _onContextMenuClick(source: ViewModels.Collection, event: MouseEvent | KeyboardEvent) {
|
||||
this.container.selectedNode(this);
|
||||
this.contextMenu.hide(source, event);
|
||||
}
|
||||
|
||||
protected _getOfferForCollection(offers: DataModels.Offer[], collection: DataModels.Collection): DataModels.Offer {
|
||||
return _.find(offers, (offer: DataModels.Offer) => offer.resource.indexOf(collection._rid) >= 0);
|
||||
}
|
||||
|
@ -1,425 +0,0 @@
|
||||
<div class="pointerCursor">
|
||||
<div
|
||||
role="treeitem"
|
||||
data-test="collectionList"
|
||||
tabindex="0"
|
||||
class="collectionMenu treeHovermargin highlight"
|
||||
data-bind="
|
||||
click: $data.expandCollapseCollection,
|
||||
clickBubble: false,
|
||||
contextmenuBubble: false,
|
||||
css:{
|
||||
collectionNodeSelected: isCollectionNodeSelected(),
|
||||
contextmenushowing: $data.contextMenu.visible
|
||||
},
|
||||
event: {
|
||||
keydown: onKeyDown,
|
||||
keypress: onKeyPress,
|
||||
contextmenu: $data.contextMenu.show,
|
||||
drop: $data.onDrop,
|
||||
dragover: $data.onDragOver
|
||||
},
|
||||
attr:{
|
||||
'aria-expanded': $data.isCollectionExpanded,
|
||||
'aria-selected': isCollectionNodeSelected()
|
||||
}"
|
||||
>
|
||||
<span
|
||||
class="collectionList databaseCollChildTextOverflow"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-right.svg"
|
||||
alt="Show collection properties"
|
||||
data-bind="visible: !$data.isCollectionExpanded()"
|
||||
/>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-down.svg"
|
||||
alt="Hide collection properties"
|
||||
data-bind="visible: $data.isCollectionExpanded()"
|
||||
/>
|
||||
<img
|
||||
src="/tree-collection.svg"
|
||||
data-bind="
|
||||
attr: {
|
||||
alt: container.addCollectionText
|
||||
}"
|
||||
/>
|
||||
<!--ko text: $data.id-->
|
||||
<!--/ko-->
|
||||
</span>
|
||||
<span
|
||||
class="menuEllipsis"
|
||||
data-test="collectionEllipsisMenu"
|
||||
name="context menu"
|
||||
role="button"
|
||||
data-bind="click: $data.contextMenu.show, clickBubble: false"
|
||||
>…</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Collection node children - Start -->
|
||||
<div
|
||||
class="collectionChildList"
|
||||
role="group"
|
||||
data-bind="
|
||||
visible: $data.isCollectionExpanded,
|
||||
clickBubble: false"
|
||||
>
|
||||
<!-- Documents Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="documentsMenu"
|
||||
data-bind="
|
||||
visible: $root.isPreferredApiDocumentDB(),
|
||||
click: $data.onDocumentDBDocumentsClick,
|
||||
event: {
|
||||
keydown: onDocumentDBDocumentsKeyDown,
|
||||
keypress: onDocumentDBDocumentsKeyPress
|
||||
},
|
||||
clickBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: isSubNodeSelected(0)
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': isSubNodeSelected(0)
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments">Items</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Documents Node - End -->
|
||||
|
||||
<!-- Entitites Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="documentsMenu"
|
||||
data-bind="
|
||||
visible: $root.isPreferredApiTable(),
|
||||
click: $data.onTableEntitiesClick,
|
||||
event: {
|
||||
keydown: onTableEntitiesKeyDown,
|
||||
keypress: onTableEntitiesKeyPress
|
||||
},
|
||||
clickBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 9
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 9
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments">Entities</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Entitites Node - End -->
|
||||
|
||||
<!-- Rows Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="documentsMenu"
|
||||
data-bind="
|
||||
visible: $root.isPreferredApiCassandra(),
|
||||
click: $data.onTableEntitiesClick,
|
||||
event: {
|
||||
keydown: onTableEntitiesKeyDown,
|
||||
keypress: onTableEntitiesKeyPress
|
||||
},
|
||||
clickBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 9
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 9
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments">Rows</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Rows Node - End -->
|
||||
|
||||
<!-- Graph Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="documentsMenu"
|
||||
data-bind="
|
||||
visible: $root.isPreferredApiGraph,
|
||||
click: $data.onGraphDocumentsClick,
|
||||
event: {
|
||||
keydown: onGraphDocumentsKeyDown,
|
||||
keypress: onGraphDocumentsKeyPress
|
||||
},
|
||||
clickBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 6
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 6
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments">Graph</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Graph Node - End -->
|
||||
|
||||
<!-- MongoDB Documents Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="documentsMenu"
|
||||
data-bind="
|
||||
visible: $root.isPreferredApiMongoDB,
|
||||
click: $data.onMongoDBDocumentsClick,
|
||||
event: {
|
||||
keydown: onMongoDBDocumentsKeyDown,
|
||||
keypress: onMongoDBDocumentsKeyPress
|
||||
},
|
||||
clickBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 0
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 0
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments">Documents</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- MongoDB Documents Node - End -->
|
||||
|
||||
<!-- Scale & Setings Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
data-bind="
|
||||
click: $data.onSettingsClick,
|
||||
event: {
|
||||
keydown: onSettingsKeyDown,
|
||||
keypress: onSettingsKeyPress
|
||||
},
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 1
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 1
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments">
|
||||
<!-- ko if: !$data.database.isDatabaseShared() -->
|
||||
Scale & Settings
|
||||
<!-- /ko -->
|
||||
<!-- ko if: $data.database.isDatabaseShared() -->
|
||||
Settings
|
||||
<!-- /ko -->
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Scale & Setings Node - End -->
|
||||
|
||||
<!-- Stored Procedures Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="storedProcedureMenu highlight"
|
||||
data-bind="
|
||||
click: $data.expandCollapseStoredProcedures,
|
||||
event: {
|
||||
keydown: onStoredProceduresKeyDown,
|
||||
keypress: onStoredProceduresKeyPress
|
||||
},
|
||||
css: {
|
||||
collectionNodeSelected: !isStoredProceduresExpanded() && isSubNodeSelected(2)
|
||||
},
|
||||
attr:{
|
||||
'aria-expanded': $data.isStoredProceduresExpanded(),
|
||||
'aria-selected': !isStoredProceduresExpanded() && isSubNodeSelected(2)
|
||||
},
|
||||
visible: showStoredProcedures"
|
||||
>
|
||||
<span
|
||||
class="collectionMenuChildren"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-right.svg"
|
||||
alt="Show storedprocedures properties"
|
||||
data-bind="visible: !$data.isStoredProceduresExpanded()"
|
||||
/>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-down.svg"
|
||||
alt="Hide storedprocedures properties"
|
||||
data-bind="visible: $data.isStoredProceduresExpanded()"
|
||||
/>
|
||||
Stored Procedures
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="storedUdfTriggerMenu"
|
||||
data-bind=" visible: $data.isStoredProceduresExpanded(), foreach: $data.storedProcedures"
|
||||
>
|
||||
<stored-procedure-node params="{data: $data}"></stored-procedure-node>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stored Procedures Node - End -->
|
||||
|
||||
<!-- User Defined Functions Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="userDefinedMenu highlight"
|
||||
data-bind="
|
||||
click: $data.expandCollapseUserDefinedFunctions,
|
||||
event: {
|
||||
keydown: onUserDefinedFunctionsKeyDown,
|
||||
keypress: onUserDefinedFunctionsKeyPress
|
||||
},
|
||||
css: {
|
||||
collectionNodeSelected: !isUserDefinedFunctionsExpanded() && isSubNodeSelected(3)
|
||||
},
|
||||
attr:{
|
||||
'aria-expanded': $data.isUserDefinedFunctionsExpanded(),
|
||||
'aria-selected': !isUserDefinedFunctionsExpanded() && isSubNodeSelected(3)
|
||||
},
|
||||
visible: showUserDefinedFunctions"
|
||||
>
|
||||
<div>
|
||||
<span
|
||||
class="collectionMenuChildren"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-right.svg"
|
||||
alt="Show userdefinedfunctions properties"
|
||||
data-bind="visible: !$data.isUserDefinedFunctionsExpanded()"
|
||||
/>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-down.svg"
|
||||
alt="Hide userdefinedfunctions properties"
|
||||
data-bind="visible: $data.isUserDefinedFunctionsExpanded()"
|
||||
/>
|
||||
User Defined Functions
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="storedUdfTriggerMenu"
|
||||
data-bind="visible: $data.isUserDefinedFunctionsExpanded(), foreach: $data.userDefinedFunctions"
|
||||
>
|
||||
<user-defined-function-node params="{data: $data}"></user-defined-function-node>
|
||||
</div>
|
||||
</div>
|
||||
<!-- User Defined Functions Node - End -->
|
||||
|
||||
<!-- Triggers Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="triggersMenu highlight"
|
||||
data-bind="
|
||||
click: $data.expandCollapseTriggers,
|
||||
event: {
|
||||
keydown: onTriggersKeyDown,
|
||||
keypress: onTriggersKeyPress
|
||||
},
|
||||
css: {
|
||||
collectionNodeSelected: !isTriggersExpanded() && isSubNodeSelected(4)
|
||||
},
|
||||
attr:{
|
||||
'aria-expanded': $data.isTriggersExpanded(),
|
||||
'aria-selected': !isTriggersExpanded() && isSubNodeSelected(4)
|
||||
},
|
||||
visible: showTriggers"
|
||||
>
|
||||
<div>
|
||||
<span
|
||||
class="collectionMenuChildren"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-right.svg"
|
||||
alt="Show Triggers properties"
|
||||
data-bind="visible: !$data.isTriggersExpanded()"
|
||||
/>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-down.svg"
|
||||
alt="Hide Triggers properties"
|
||||
data-bind="visible: $data.isTriggersExpanded()"
|
||||
/>
|
||||
Triggers
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="storedUdfTriggerMenu" data-bind="visible: $data.isTriggersExpanded(), foreach: $data.triggers">
|
||||
<trigger-node params="{data: $data}"></trigger-node>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Triggers Node - End -->
|
||||
|
||||
<!-- Conflicts Node - Start -->
|
||||
<div>
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
data-bind="
|
||||
click: $data.onConflictsClick,
|
||||
event: {
|
||||
keypress: onConflictsKeyPress
|
||||
},
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: isSubNodeSelected(12)
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': isSubNodeSelected(12)
|
||||
},
|
||||
visible: showConflicts"
|
||||
>
|
||||
<span class=" databaseDocuments"> Conflicts </span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Conflicts Node - End -->
|
||||
</div>
|
||||
<!-- Collection node children - End -->
|
||||
</div>
|
@ -1,16 +0,0 @@
|
||||
<div data-bind="event: { keydown: onMenuKeyDown }">
|
||||
<div
|
||||
class="context-menu-background"
|
||||
data-bind="
|
||||
visible: $data.contextMenu.visible,
|
||||
click: $data.contextMenu.hide"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="context-menu"
|
||||
data-test="collectionContextMenu"
|
||||
data-bind="attr:{ tabindex: $data.contextMenu.tabIndex, id: $data.contextMenu.elementId }, visible: $data.contextMenu.visible, foreach: $data.contextMenu.options"
|
||||
>
|
||||
<command-button class="context-menu-option" params="{buttonProps: $data}"></command-button>
|
||||
</div>
|
||||
</div>
|
@ -7,11 +7,9 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import DatabaseSettingsTab from "../Tabs/DatabaseSettingsTab";
|
||||
import Collection from "./Collection";
|
||||
import ContextMenu from "../Menus/ContextMenu";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { NotificationConsoleUtils } from "../../Utils/NotificationConsoleUtils";
|
||||
import { ConsoleDataType } from "../Menus/NotificationConsole/NotificationConsoleComponent";
|
||||
import { ContextMenuButtonFactory } from "../ContextMenuButtonFactory";
|
||||
import { Logger } from "../../Common/Logger";
|
||||
|
||||
export default class Database implements ViewModels.Database {
|
||||
@ -25,7 +23,6 @@ export default class Database implements ViewModels.Database {
|
||||
public isDatabaseExpanded: ko.Observable<boolean>;
|
||||
public isDatabaseShared: ko.Computed<boolean>;
|
||||
public selectedSubnodeKind: ko.Observable<ViewModels.CollectionTabKind>;
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
|
||||
constructor(container: ViewModels.Explorer, data: any, offer: DataModels.Offer) {
|
||||
this.nodeKind = "Database";
|
||||
@ -36,71 +33,12 @@ export default class Database implements ViewModels.Database {
|
||||
this.offer = ko.observable(offer);
|
||||
this.collections = ko.observableArray<Collection>();
|
||||
this.isDatabaseExpanded = ko.observable<boolean>(false);
|
||||
this.contextMenu = new ContextMenu(this.container, this.rid);
|
||||
this.contextMenu.options(
|
||||
ContextMenuButtonFactory.createDatabaseContextMenuButton(container, { databaseId: this.id() })
|
||||
);
|
||||
this.selectedSubnodeKind = ko.observable<ViewModels.CollectionTabKind>();
|
||||
this.isDatabaseShared = ko.pureComputed(() => {
|
||||
return this.offer && !!this.offer();
|
||||
});
|
||||
}
|
||||
|
||||
public onKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === " " || event.key === "Enter") {
|
||||
this.expandCollapseDatabase();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Delete") {
|
||||
this.onDeleteDatabaseContextMenuClick(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowRight") {
|
||||
this.expandDatabase();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "ArrowLeft") {
|
||||
this.collapseDatabase();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.key === "Enter") {
|
||||
this.expandCollapseDatabase();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMenuKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Escape") {
|
||||
this.contextMenu.hide(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onSettingsKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
return true;
|
||||
};
|
||||
|
||||
public onSettingsKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === " " || event.key === "Enter") {
|
||||
this.onSettingsClick();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onSettingsClick = () => {
|
||||
this.container.selectedNode(this);
|
||||
this.selectedSubnodeKind(ViewModels.CollectionTabKind.DatabaseSettings);
|
||||
@ -262,8 +200,6 @@ export default class Database implements ViewModels.Database {
|
||||
}
|
||||
|
||||
public onDeleteDatabaseContextMenuClick(source: ViewModels.Database, event: MouseEvent | KeyboardEvent) {
|
||||
source.container.selectedNode(source);
|
||||
source.contextMenu.hide(source, event);
|
||||
this.container.deleteDatabaseConfirmationPane.open();
|
||||
}
|
||||
|
||||
@ -346,7 +282,6 @@ export default class Database implements ViewModels.Database {
|
||||
}
|
||||
|
||||
public openAddCollection(database: Database, event: MouseEvent) {
|
||||
database.contextMenu.hide(database, event);
|
||||
database.container.addCollectionPane.databaseId(database.id());
|
||||
database.container.addCollectionPane.open();
|
||||
}
|
||||
|
@ -1,110 +0,0 @@
|
||||
<div class="pointerCursor">
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
data-test="databaseMenu"
|
||||
class="databaseMenu treeHovermargin highlight"
|
||||
data-bind="
|
||||
click: $data.expandCollapseDatabase,
|
||||
event: {
|
||||
keydown: onKeyDown,
|
||||
keypress: onKeyPress,
|
||||
contextmenu: $data.contextMenu.show
|
||||
},
|
||||
clickBubble: false,
|
||||
contextmenuBubble: false,
|
||||
css:{
|
||||
contextmenushowing: $data.contextMenu.visible,
|
||||
highlight: true,
|
||||
databaseNodeSelected: isDatabaseNodeSelected()
|
||||
},
|
||||
attr:{
|
||||
'aria-expanded': $data.isDatabaseExpanded,
|
||||
'aria-selected': isDatabaseNodeSelected()
|
||||
}"
|
||||
>
|
||||
<span
|
||||
class="databaseId databaseCollChildTextOverflow"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-right.svg"
|
||||
alt="Show database properties"
|
||||
data-bind="visible: !$data.isDatabaseExpanded()"
|
||||
/>
|
||||
<img
|
||||
class="imgiconwidth collectionsTreeCollapseExpand"
|
||||
src="/Triangle-down.svg"
|
||||
alt="Hide database properties"
|
||||
data-bind="visible: $data.isDatabaseExpanded()"
|
||||
/>
|
||||
<img src="/Azure-Cosmos-DB.svg" alt="Database" />
|
||||
<!--ko text: $data.id--><!--/ko-->
|
||||
</span>
|
||||
<span
|
||||
class="menuEllipsis"
|
||||
data-test="databaseEllipsisMenu"
|
||||
name="context menu"
|
||||
role="button"
|
||||
data-bind="
|
||||
click: $data.contextMenu.show,
|
||||
clickBubble: false
|
||||
"
|
||||
>…</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="databaseList" data-test="databaseList" data-bind="visible: $data.isDatabaseExpanded">
|
||||
<!-- Scale & Setings Node - Start -->
|
||||
<div data-bind="visible: $data.isDatabaseShared">
|
||||
<div
|
||||
role="treeitem"
|
||||
class="databaseCollChildTextOverflow treeHovermargin highlight"
|
||||
tabindex="0"
|
||||
data-bind="
|
||||
click: $data.onSettingsClick,
|
||||
event: {
|
||||
keydown: onSettingsKeyDown,
|
||||
keypress: onSettingsKeyPress
|
||||
},
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 11
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid && $data.selectedSubnodeKind() === 11
|
||||
}"
|
||||
>
|
||||
<span class="databaseDocuments"> Scale </span>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Scale & Setings Node - End -->
|
||||
<div data-bind="foreach: $data.collections">
|
||||
<collection-node params="{data: $data}"></collection-node>
|
||||
<collection-node-context-menu params="{data: $data}"></collection-node-context-menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Database Context Menu - Start -->
|
||||
<div data-bind="event: { keydown: onMenuKeyDown }">
|
||||
<div
|
||||
class="context-menu-background"
|
||||
data-bind="
|
||||
visible: $data.contextMenu.visible,
|
||||
click: $data.contextMenu.hide"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="context-menu"
|
||||
data-test="databaseContextMenu"
|
||||
data-bind="attr:{ tabindex: $data.contextMenu.tabIndex, id: $data.contextMenu.elementId }, visible: $data.contextMenu.visible, foreach: $data.contextMenu.options"
|
||||
>
|
||||
<command-button class="context-menu-option" params="{buttonProps: $data}"></command-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Database Context Menu - End -->
|
||||
</div>
|
@ -1,11 +0,0 @@
|
||||
<div
|
||||
class="collectionstree"
|
||||
data-test="resoureTree-collectionsTree"
|
||||
tabindex="0"
|
||||
role="tree"
|
||||
data-bind="attr: { 'aria-label': collectionTitle }"
|
||||
>
|
||||
<div class="databaseList" data-bind="foreach: nonSystemDatabases">
|
||||
<database-node params="{data: $data}"></database-node>
|
||||
</div>
|
||||
</div>
|
@ -301,7 +301,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
onClick: sp.open.bind(sp),
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.StoredProcedures),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container)
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createStoreProcedureContextMenuItems(this.container, sp)
|
||||
})),
|
||||
onClick: () => {
|
||||
collection.selectedSubnodeKind(ViewModels.CollectionTabKind.StoredProcedures);
|
||||
@ -318,7 +318,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
onClick: udf.open.bind(udf),
|
||||
isSelected: () =>
|
||||
this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.UserDefinedFunctions),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container)
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createUserDefinedFunctionContextMenuItems(this.container, udf)
|
||||
})),
|
||||
onClick: () => {
|
||||
collection.selectedSubnodeKind(ViewModels.CollectionTabKind.UserDefinedFunctions);
|
||||
@ -334,7 +334,7 @@ export class ResourceTreeAdapter implements ReactAdapter {
|
||||
label: trigger.id(),
|
||||
onClick: trigger.open.bind(trigger),
|
||||
isSelected: () => this.isDataNodeSelected(collection.rid, "Collection", ViewModels.CollectionTabKind.Triggers),
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container)
|
||||
contextMenu: ResourceTreeContextMenuButtonFactory.createTriggerContextMenuItems(this.container, trigger)
|
||||
})),
|
||||
onClick: () => {
|
||||
collection.selectedSubnodeKind(ViewModels.CollectionTabKind.Triggers);
|
||||
|
@ -5,9 +5,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
|
||||
import StoredProcedureTab from "../Tabs/StoredProcedureTab";
|
||||
import ContextMenu from "../Menus/ContextMenu";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { ContextMenuButtonFactory } from "../ContextMenuButtonFactory";
|
||||
|
||||
const sampleStoredProcedureBody: string = `// SAMPLE STORED PROCEDURE
|
||||
function sample(prefix) {
|
||||
@ -44,7 +42,6 @@ export default class StoredProcedure implements ViewModels.StoredProcedure {
|
||||
public rid: string;
|
||||
public id: ko.Observable<string>;
|
||||
public body: ko.Observable<string>;
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
public isExecuteEnabled: boolean;
|
||||
|
||||
constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: DataModels.StoredProcedure) {
|
||||
@ -56,9 +53,6 @@ export default class StoredProcedure implements ViewModels.StoredProcedure {
|
||||
this.id = ko.observable(data.id);
|
||||
this.body = ko.observable(data.body);
|
||||
this.isExecuteEnabled = this.container.isFeatureEnabled(Constants.Features.executeSproc);
|
||||
|
||||
this.contextMenu = new ContextMenu(this.container, this.rid);
|
||||
this.contextMenu.options(ContextMenuButtonFactory.createStoreProcedureContextMenuButton(container));
|
||||
}
|
||||
|
||||
public static create(source: ViewModels.Collection, event: MouseEvent) {
|
||||
@ -89,9 +83,6 @@ export default class StoredProcedure implements ViewModels.StoredProcedure {
|
||||
|
||||
// Activate
|
||||
storedProcedureTab.onTabClick();
|
||||
|
||||
// Hide Context Menu (if necessary)
|
||||
source.contextMenu.hide(source, event);
|
||||
}
|
||||
|
||||
public select() {
|
||||
@ -148,10 +139,7 @@ export default class StoredProcedure implements ViewModels.StoredProcedure {
|
||||
storedProcedureTab.onTabClick();
|
||||
};
|
||||
|
||||
public delete(source: ViewModels.Collection, event: MouseEvent | KeyboardEvent) {
|
||||
// Hide Context Menu (if necessary)
|
||||
this.contextMenu.hide(source, event);
|
||||
|
||||
public delete() {
|
||||
if (!window.confirm("Are you sure you want to delete the stored procedure?")) {
|
||||
return;
|
||||
}
|
||||
@ -192,33 +180,6 @@ export default class StoredProcedure implements ViewModels.StoredProcedure {
|
||||
});
|
||||
}
|
||||
|
||||
public onKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Delete") {
|
||||
this.delete(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMenuKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Escape") {
|
||||
this.contextMenu.hide(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === " " || event.key === "Enter") {
|
||||
this.open();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onFocusAfterExecute(): void {
|
||||
const focusElement = document.getElementById("execute-storedproc-toggles");
|
||||
focusElement && focusElement.focus();
|
||||
|
@ -1,63 +0,0 @@
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="pointerCursor"
|
||||
data-bind="
|
||||
click: $data.open,
|
||||
event: {
|
||||
keydown: onKeyDown,
|
||||
keypress: onKeyPress,
|
||||
contextmenu: $data.contextMenu.show
|
||||
},
|
||||
clickBubble: false,
|
||||
contextmenuBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid,
|
||||
contextmenushowing: $data.contextMenu.visible
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid
|
||||
}"
|
||||
>
|
||||
<div class="storedChildMenu treeChildMenu">
|
||||
<div
|
||||
class="childMenu"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<!--ko text: $data.id-->
|
||||
<!--/ko-->
|
||||
</div>
|
||||
|
||||
<span
|
||||
class="menuEllipsis"
|
||||
name="context menu"
|
||||
role="button"
|
||||
data-bind="
|
||||
click: $data.contextMenu.show,
|
||||
clickBubble: false
|
||||
"
|
||||
>…</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stored Procedure Node Context Menu - Start -->
|
||||
<div data-bind="event: { keydown: onMenuKeyDown }">
|
||||
<div
|
||||
class="context-menu-background"
|
||||
data-bind="
|
||||
visible: $data.contextMenu.visible,
|
||||
click: $data.contextMenu.hide"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="context-menu"
|
||||
data-bind="attr:{ tabindex: $data.contextMenu.tabIndex, id: $data.contextMenu.elementId }, visible: $data.contextMenu.visible, foreach: $data.contextMenu.options"
|
||||
>
|
||||
<command-button class="context-menu-option" params="{buttonProps: $data}"></command-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Stored Procedure Node Context Menu - End -->
|
@ -1,76 +0,0 @@
|
||||
import resourceTreeTemplate from "./ResourceTree.html";
|
||||
import databaseTreeNoteTemplate from "./DatabaseTreeNode.html";
|
||||
import collectionTreeNodeTemplate from "./CollectionTreeNode.html";
|
||||
import storedProcedureTreeNodeTemplate from "./StoredProcedureTreeNode.html";
|
||||
import userDefinedFunctionTreeNodeTemplate from "./UserDefinedFunctionTreeNode.html";
|
||||
import triggerTreeNodeTemplate from "./TriggerTreeNode.html";
|
||||
import collectionTreeNodeContextMenuTemplate from "./CollectionTreeNodeContextMenu.html";
|
||||
|
||||
export class TreeNodeComponent {
|
||||
constructor(data: any) {
|
||||
return data.data;
|
||||
}
|
||||
}
|
||||
|
||||
export class ResourceTree {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: resourceTreeTemplate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class DatabaseTreeNode {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: databaseTreeNoteTemplate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CollectionTreeNode {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: collectionTreeNodeTemplate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class StoredProcedureTreeNode {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: storedProcedureTreeNodeTemplate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class UserDefinedFunctionTreeNode {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: userDefinedFunctionTreeNodeTemplate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class TriggerTreeNode {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: triggerTreeNodeTemplate
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class CollectionTreeNodeContextMenu {
|
||||
constructor() {
|
||||
return {
|
||||
viewModel: TreeNodeComponent,
|
||||
template: collectionTreeNodeContextMenuTemplate
|
||||
};
|
||||
}
|
||||
}
|
@ -5,9 +5,7 @@ import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import Collection from "./Collection";
|
||||
import TriggerTab from "../Tabs/TriggerTab";
|
||||
import ContextMenu from "../Menus/ContextMenu";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { ContextMenuButtonFactory } from "../ContextMenuButtonFactory";
|
||||
|
||||
export default class Trigger implements ViewModels.Trigger {
|
||||
public nodeKind: string;
|
||||
@ -19,7 +17,6 @@ export default class Trigger implements ViewModels.Trigger {
|
||||
public body: ko.Observable<string>;
|
||||
public triggerType: ko.Observable<string>;
|
||||
public triggerOperation: ko.Observable<string>;
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
|
||||
constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: any) {
|
||||
this.nodeKind = "Trigger";
|
||||
@ -31,9 +28,6 @@ export default class Trigger implements ViewModels.Trigger {
|
||||
this.body = ko.observable(data.body);
|
||||
this.triggerOperation = ko.observable(data.triggerOperation);
|
||||
this.triggerType = ko.observable(data.triggerType);
|
||||
|
||||
this.contextMenu = new ContextMenu(this.container, this.rid);
|
||||
this.contextMenu.options(ContextMenuButtonFactory.createTriggerContextMenuButton(container));
|
||||
}
|
||||
|
||||
public select() {
|
||||
@ -78,9 +72,6 @@ export default class Trigger implements ViewModels.Trigger {
|
||||
|
||||
// Activate
|
||||
triggerTab.onTabClick();
|
||||
|
||||
// Hide Context Menu (if necessary)
|
||||
source.contextMenu.hide(source, event);
|
||||
}
|
||||
|
||||
public open = () => {
|
||||
@ -125,10 +116,7 @@ export default class Trigger implements ViewModels.Trigger {
|
||||
triggerTab.onTabClick();
|
||||
};
|
||||
|
||||
public delete(source: Collection, event: MouseEvent | KeyboardEvent) {
|
||||
// Hide Context Menu (if necessary)
|
||||
this.contextMenu.hide(source, event);
|
||||
|
||||
public delete() {
|
||||
if (!window.confirm("Are you sure you want to delete the trigger?")) {
|
||||
return;
|
||||
}
|
||||
@ -150,31 +138,4 @@ export default class Trigger implements ViewModels.Trigger {
|
||||
reason => {}
|
||||
);
|
||||
}
|
||||
|
||||
public onKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Delete") {
|
||||
this.delete(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMenuKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Escape") {
|
||||
this.contextMenu.hide(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === " " || event.key === "Enter") {
|
||||
this.open();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="pointerCursor"
|
||||
data-bind="
|
||||
click: $data.open,
|
||||
event: {
|
||||
keydown: onKeyDown,
|
||||
keypress: onKeyPress,
|
||||
contextmenu: $data.contextMenu.show
|
||||
},
|
||||
clickBubble: false,
|
||||
contextmenuBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid,
|
||||
contextmenushowing: $data.contextMenu.visible
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid
|
||||
}"
|
||||
>
|
||||
<div class="triggersChildMenu treeChildMenu">
|
||||
<div
|
||||
class="childMenu"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<!--ko text: $data.id-->
|
||||
<!--/ko-->
|
||||
</div>
|
||||
<span
|
||||
class="menuEllipsis"
|
||||
name="context menu"
|
||||
role="button"
|
||||
data-bind="
|
||||
click: $data.contextMenu.show,
|
||||
clickBubble: false
|
||||
"
|
||||
>…</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trigger Node Context Menu - Start -->
|
||||
<div data-bind="event: { keydown: onMenuKeyDown }">
|
||||
<div
|
||||
class="context-menu-background"
|
||||
data-bind="
|
||||
visible: $data.contextMenu.visible,
|
||||
click: $data.contextMenu.hide"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="context-menu"
|
||||
data-bind="attr:{ tabindex: $data.contextMenu.tabIndex, id: $data.contextMenu.elementId }, visible: $data.contextMenu.visible, foreach: $data.contextMenu.options"
|
||||
>
|
||||
<command-button class="context-menu-option" params="{buttonProps: $data}"></command-button>
|
||||
</div>
|
||||
</div>
|
@ -4,9 +4,7 @@ import * as Constants from "../../Common/Constants";
|
||||
import * as DataModels from "../../Contracts/DataModels";
|
||||
import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstants";
|
||||
import UserDefinedFunctionTab from "../Tabs/UserDefinedFunctionTab";
|
||||
import ContextMenu from "../Menus/ContextMenu";
|
||||
import TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
import { ContextMenuButtonFactory } from "../ContextMenuButtonFactory";
|
||||
import Collection from "./Collection";
|
||||
|
||||
export default class UserDefinedFunction implements ViewModels.UserDefinedFunction {
|
||||
@ -17,7 +15,6 @@ export default class UserDefinedFunction implements ViewModels.UserDefinedFuncti
|
||||
public rid: string;
|
||||
public id: ko.Observable<string>;
|
||||
public body: ko.Observable<string>;
|
||||
public contextMenu: ViewModels.ContextMenu;
|
||||
|
||||
constructor(container: ViewModels.Explorer, collection: ViewModels.Collection, data: DataModels.UserDefinedFunction) {
|
||||
this.nodeKind = "UserDefinedFunction";
|
||||
@ -28,9 +25,6 @@ export default class UserDefinedFunction implements ViewModels.UserDefinedFuncti
|
||||
this.rid = data._rid;
|
||||
this.id = ko.observable(data.id);
|
||||
this.body = ko.observable(data.body);
|
||||
|
||||
this.contextMenu = new ContextMenu(this.container, this.rid);
|
||||
this.contextMenu.options(ContextMenuButtonFactory.createUserDefinedFunctionContextMenuButton(container));
|
||||
}
|
||||
|
||||
public static create(source: ViewModels.Collection, event: MouseEvent) {
|
||||
@ -61,9 +55,6 @@ export default class UserDefinedFunction implements ViewModels.UserDefinedFuncti
|
||||
|
||||
// Activate
|
||||
userDefinedFunctionTab.onTabClick();
|
||||
|
||||
// Hide Context Menu (if necessary)
|
||||
source.contextMenu.hide(source, event);
|
||||
}
|
||||
|
||||
public open = () => {
|
||||
@ -115,10 +106,7 @@ export default class UserDefinedFunction implements ViewModels.UserDefinedFuncti
|
||||
});
|
||||
}
|
||||
|
||||
public delete(source: Collection, event: MouseEvent | KeyboardEvent) {
|
||||
// Hide Context Menu (if necessary)
|
||||
this.contextMenu.hide(source, event);
|
||||
|
||||
public delete() {
|
||||
if (!window.confirm("Are you sure you want to delete the user defined function?")) {
|
||||
return;
|
||||
}
|
||||
@ -137,31 +125,4 @@ export default class UserDefinedFunction implements ViewModels.UserDefinedFuncti
|
||||
reason => {}
|
||||
);
|
||||
}
|
||||
|
||||
public onKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Delete") {
|
||||
this.delete(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onMenuKeyDown = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === "Escape") {
|
||||
this.contextMenu.hide(source, event);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
public onKeyPress = (source: any, event: KeyboardEvent): boolean => {
|
||||
if (event.key === " " || event.key === "Enter") {
|
||||
this.open();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
@ -1,62 +0,0 @@
|
||||
<div
|
||||
role="treeitem"
|
||||
tabindex="0"
|
||||
class="pointerCursor"
|
||||
data-bind="
|
||||
click: $data.open,
|
||||
event: {
|
||||
keydown: onKeyDown,
|
||||
keypress: onKeyPress,
|
||||
contextmenu: $data.contextMenu.show
|
||||
},
|
||||
clickBubble: false,
|
||||
contextmenuBubble: false,
|
||||
css: {
|
||||
highlight: true,
|
||||
collectionNodeSelected: $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid,
|
||||
contextmenushowing: $data.contextMenu.visible
|
||||
},
|
||||
attr:{
|
||||
'aria-selected': $root.selectedNode && $root.selectedNode() && $root.selectedNode().rid === $data.rid
|
||||
}"
|
||||
>
|
||||
<div class="userDefinedchildMenu treeChildMenu">
|
||||
<div
|
||||
class="childMenu"
|
||||
data-bind="
|
||||
attr: {
|
||||
title: $data.id()
|
||||
}"
|
||||
>
|
||||
<!--ko text: $data.id-->
|
||||
<!--/ko-->
|
||||
</div>
|
||||
<span
|
||||
class="menuEllipsis"
|
||||
name="context menu"
|
||||
role="button"
|
||||
data-bind="
|
||||
click: $data.contextMenu.show,
|
||||
clickBubble: false
|
||||
"
|
||||
>…</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- User Defined Function Node Context Menu - Start -->
|
||||
<div data-bind="event: { keydown: onMenuKeyDown }">
|
||||
<div
|
||||
class="context-menu-background"
|
||||
data-bind="
|
||||
visible: $data.contextMenu.visible,
|
||||
click: $data.contextMenu.hide"
|
||||
></div>
|
||||
|
||||
<div
|
||||
class="context-menu"
|
||||
data-bind="attr:{ tabindex: $data.contextMenu.tabIndex, id: $data.contextMenu.elementId }, visible: $data.contextMenu.visible, foreach: $data.contextMenu.options"
|
||||
>
|
||||
<command-button class="context-menu-option" params="{buttonProps: $data}"></command-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- User Defined Function Node Context Menu - End -->
|
@ -7,7 +7,6 @@ import "../less/menus.less";
|
||||
import "../less/infobox.less";
|
||||
import "../less/messagebox.less";
|
||||
import "./Explorer/Controls/InputTypeahead/InputTypeahead.less";
|
||||
import "./Explorer/Controls/CommandButton/CommandButton.less";
|
||||
import "./Explorer/Controls/ErrorDisplayComponent/ErrorDisplayComponent.less";
|
||||
import "./Explorer/Menus/NotificationConsole/NotificationConsole.less";
|
||||
import "./Explorer/Menus/CommandBar/CommandBarComponent.less";
|
||||
|
@ -128,15 +128,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- Collections Window Title/Command Bar - End -->
|
||||
<!-- ko if: !enableLegacyResourceTree() && !isAuthWithResourceToken() -->
|
||||
<!-- ko if: !isAuthWithResourceToken() -->
|
||||
<div style="overflow-y: auto" data-bind="react:resourceTree"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: !enableLegacyResourceTree() && isAuthWithResourceToken() -->
|
||||
<!-- ko if: isAuthWithResourceToken() -->
|
||||
<div style="overflow-y: auto" data-bind="react:resourceTreeForResourceToken"></div>
|
||||
<!-- /ko -->
|
||||
<!-- ko if: enableLegacyResourceTree -->
|
||||
<resource-tree class="resourceTreeScroll" params="{data: $data}"></resource-tree>
|
||||
<!-- /ko -->
|
||||
</div>
|
||||
<!-- Collections Window - End -->
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user