Compare commits

..

4 Commits

Author SHA1 Message Date
Ashley Stanton-Nurse
08d3318a87 remove QueryEditor component 2024-03-29 11:47:45 -07:00
Ashley Stanton-Nurse
8b6d857ddb focus on the Copilotv2 editor 2024-03-28 15:26:13 -07:00
Ashley Stanton-Nurse
2598760a11 tinker with an "Execute Query" action in Monaco 2024-03-28 13:08:15 -07:00
Ashley Stanton-Nurse
44d886b4a0 restore some Monaco styles clobbered by our global styles 2024-03-28 10:26:52 -07:00
54 changed files with 229 additions and 324 deletions

3
.gitignore vendored
View File

@@ -16,5 +16,4 @@ Contracts/*
.env
failure.png
screenshots/*
GettingStarted-ignore*.ipynb
.vscode/
GettingStarted-ignore*.ipynb

View File

@@ -2296,6 +2296,17 @@ a:link {
display: none !important;
}
.monaco-editor .quick-input-list-label {
/* Restore some of Monaco's default styles that are clobbered by our global styles */
padding: 0;
line-height: 22px;
}
.monaco-editor .quick-input-list .highlight {
/* Padding in highlighted text within the quick input list breaks the flow of the text */
padding: 0;
}
td a {
color: #393939;
}

View File

@@ -85,8 +85,6 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
return decodeURIComponent(result.PrimaryReadWriteToken);
};
// TODO
// Need to create separate plugins or change endpoint logic to return the correct write or read endpoint.
export const requestPlugin: Cosmos.Plugin<any> = async (requestContext, diagnosticNode, next) => {
requestContext.endpoint = new URL(configContext.PROXY_PATH, window.location.href).href;
requestContext.headers["x-ms-proxy-target"] = endpoint();
@@ -136,32 +134,9 @@ enum SDKSupportedCapabilities {
PartitionMerge = 1 << 0,
}
// Client Management
let _client: Cosmos.CosmosClient;
let _readClients: Map<string, Cosmos.CosmosClient> = new Map();
export enum ClientOperationType {
READ,
WRITE,
}
export function client(clientOperationType: ClientOperationType): Cosmos.CosmosClient {
switch (clientOperationType) {
case ClientOperationType.READ:
return readClients();
case ClientOperationType.WRITE:
return writeClient();
default:
throw new Error("Invalid operation type");
}
}
export function writeClient(): Cosmos.CosmosClient {
console.log(`Called primary client`);
const currentUserContextDocumentEndpoint = userContext?.databaseAccount?.properties?.documentEndpoint;
console.log(`Current selected endpoint in userContext: ${currentUserContextDocumentEndpoint}`);
export function client(): Cosmos.CosmosClient {
if (_client) return _client;
let _defaultHeaders: Cosmos.CosmosHeaders = {};
@@ -208,61 +183,3 @@ export function writeClient(): Cosmos.CosmosClient {
_client = new Cosmos.CosmosClient(options);
return _client;
}
export function readClients(): Cosmos.CosmosClient {
console.log(`Called read only client`);
const currentUserContextDocumentEndpoint = userContext?.databaseAccount?.properties?.documentEndpoint;
console.log(`Current selected read endpoint in userContext: ${currentUserContextDocumentEndpoint}`);
3;
const selectedEndpoint = endpoint() || "https://cosmos.azure.com";
if (_readClients.has(selectedEndpoint)) {
return _readClients.get(selectedEndpoint);
}
let _defaultHeaders: Cosmos.CosmosHeaders = {};
_defaultHeaders["x-ms-cosmos-sdk-supportedcapabilities"] =
SDKSupportedCapabilities.None | SDKSupportedCapabilities.PartitionMerge;
if (
userContext.authType === AuthType.ConnectionString ||
userContext.authType === AuthType.EncryptedToken ||
userContext.authType === AuthType.ResourceToken
) {
// Default to low priority. Needed for non-AAD-auth scenarios
// where we cannot use RP API, and thus, cannot detect whether priority
// based execution is enabled.
// The header will be ignored if priority based execution is disabled on the account.
_defaultHeaders["x-ms-cosmos-priority-level"] = PriorityLevel.Default;
}
const options: Cosmos.CosmosClientOptions = {
endpoint: selectedEndpoint, // CosmosClient gets upset if we pass a bad URL. This should never actually get called
key: userContext.masterKey,
tokenProvider,
userAgentSuffix: "Azure Portal",
defaultHeaders: _defaultHeaders,
connectionPolicy: {
retryOptions: {
maxRetryAttemptCount: LocalStorageUtility.getEntryNumber(StorageKey.RetryAttempts),
fixedRetryIntervalInMilliseconds: LocalStorageUtility.getEntryNumber(StorageKey.RetryInterval),
maxWaitTimeInSeconds: LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds),
},
},
};
if (configContext.PROXY_PATH !== undefined) {
(options as any).plugins = [{ on: "request", plugin: requestPlugin }];
}
if (PriorityBasedExecutionUtils.isFeatureEnabled()) {
const plugins = (options as any).plugins || [];
plugins.push({ on: "request", plugin: PriorityBasedExecutionUtils.requestPlugin });
(options as any).plugins = plugins;
}
_readClients.set(selectedEndpoint, new Cosmos.CosmosClient(options));
return _readClients.get(selectedEndpoint);
}

View File

@@ -0,0 +1,25 @@
import { KeyMap } from "react-hotkeys";
export const keyMap: KeyMap = {
NEW_QUERY: {
name: "New Query",
sequence: "ctrl+j",
action: "keydown",
},
CANCEL_QUERY: {
name: "Cancel Query",
sequence: "f8",
action: "keydown",
},
DISCARD: {
name: "Discard Changes",
sequence: "ctrl+x",
action: "keydown"
}
};
export type KeyboardShortcutName = keyof typeof keyMap;
export type KeyboardShortcutHandlers = Partial<{
[key in KeyboardShortcutName]: (keyEvent?: KeyboardEvent) => void;
}>;

View File

@@ -1,7 +1,7 @@
import { JSONObject, OperationResponse } from "@azure/cosmos";
import { CollectionBase } from "../../Contracts/ViewModels";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export const bulkCreateDocument = async (
@@ -13,7 +13,7 @@ export const bulkCreateDocument = async (
);
try {
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.items.bulk(

View File

@@ -6,14 +6,14 @@ import { Action, ActionModifiers } from "../../Shared/Telemetry/TelemetryConstan
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../UserContext";
import { getCollectionName } from "../../Utils/APITypeUtils";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { createUpdateCassandraTable } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
import { createUpdateGremlinGraph } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
import { createUpdateMongoDBCollection } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
import { createUpdateSqlContainer } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { createUpdateTable } from "../../Utils/arm/generatedClients/cosmos/tableResources";
import * as ARMTypes from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
import { createMongoCollectionWithProxy } from "../MongoProxyClient";
import { createDatabase } from "./createDatabase";
@@ -284,9 +284,7 @@ const createCollectionWithSDK = async (params: DataModels.CreateCollectionParams
}
}
const databaseResponse: DatabaseResponse = await client(ClientOperationType.WRITE).databases.createIfNotExists(
createDatabaseBody,
);
const databaseResponse: DatabaseResponse = await client().databases.createIfNotExists(createDatabaseBody);
const collectionResponse: ContainerResponse = await databaseResponse?.database.containers.create(
createCollectionBody,
collectionOptions,

View File

@@ -4,7 +4,6 @@ import * as DataModels from "../../Contracts/DataModels";
import { useDatabases } from "../../Explorer/useDatabases";
import { userContext } from "../../UserContext";
import { getDatabaseName } from "../../Utils/APITypeUtils";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { createUpdateCassandraKeyspace } from "../../Utils/arm/generatedClients/cosmos/cassandraResources";
import { createUpdateGremlinDatabase } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
import { createUpdateMongoDBDatabase } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
@@ -16,7 +15,8 @@ import {
MongoDBDatabaseCreateUpdateParameters,
SqlDatabaseCreateUpdateParameters,
} from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function createDatabase(params: DataModels.CreateDatabaseParams): Promise<DataModels.Database> {
@@ -153,7 +153,7 @@ async function createDatabaseWithSDK(params: DataModels.CreateDatabaseParams): P
}
}
const response: DatabaseResponse = await client(ClientOperationType.WRITE).databases.create(createBody);
const response: DatabaseResponse = await client().databases.create(createBody);
return response.resource;
}

View File

@@ -1,6 +1,6 @@
import { CollectionBase } from "../../Contracts/ViewModels";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
@@ -9,7 +9,7 @@ export const createDocument = async (collection: CollectionBase, newDocument: un
const clearMessage = logConsoleProgress(`Creating new ${entityName} for container ${collection.id()}`);
try {
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.items.create(newDocument);

View File

@@ -1,7 +1,6 @@
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import {
createUpdateSqlStoredProcedure,
getSqlStoredProcedure,
@@ -10,7 +9,8 @@ import {
SqlStoredProcedureCreateUpdateParameters,
SqlStoredProcedureResource,
} from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function createStoredProcedure(
@@ -63,7 +63,7 @@ export async function createStoredProcedure(
return rpResponse && (rpResponse.properties?.resource as StoredProcedureDefinition & Resource);
}
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.storedProcedures.create(storedProcedure);

View File

@@ -1,10 +1,10 @@
import { TriggerDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { SqlTriggerCreateUpdateParameters, SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function createTrigger(
@@ -55,7 +55,7 @@ export async function createTrigger(
return rpResponse && rpResponse.properties?.resource;
}
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.triggers.create(trigger as unknown as TriggerDefinition); // TODO: TypeScript does not like the SQL SDK trigger type

View File

@@ -1,7 +1,6 @@
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import {
createUpdateSqlUserDefinedFunction,
getSqlUserDefinedFunction,
@@ -10,7 +9,8 @@ import {
SqlUserDefinedFunctionCreateUpdateParameters,
SqlUserDefinedFunctionResource,
} from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function createUserDefinedFunction(
@@ -63,7 +63,7 @@ export async function createUserDefinedFunction(
return rpResponse && (rpResponse.properties?.resource as UserDefinedFunctionDefinition & Resource);
}
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.userDefinedFunctions.create(userDefinedFunction);

View File

@@ -6,7 +6,7 @@ import { deleteMongoDBCollection } from "../../Utils/arm/generatedClients/cosmos
import { deleteSqlContainer } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { deleteTable } from "../../Utils/arm/generatedClients/cosmos/tableResources";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client, ClientOperationType } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function deleteCollection(databaseId: string, collectionId: string): Promise<void> {
@@ -15,7 +15,7 @@ export async function deleteCollection(databaseId: string, collectionId: string)
if (userContext.authType === AuthType.AAD && !userContext.features.enableSDKoperations) {
await deleteCollectionWithARM(databaseId, collectionId);
} else {
await client(ClientOperationType.WRITE).database(databaseId).container(collectionId).delete();
await client().database(databaseId).container(collectionId).delete();
}
logConsoleInfo(`Successfully deleted container ${collectionId}`);
} catch (error) {

View File

@@ -1,9 +1,9 @@
import { RequestOptions } from "@azure/cosmos";
import { CollectionBase } from "../../Contracts/ViewModels";
import ConflictId from "../../Explorer/Tree/ConflictId";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { CollectionBase } from "../../Contracts/ViewModels";
import { RequestOptions } from "@azure/cosmos";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
export const deleteConflict = async (collection: CollectionBase, conflictId: ConflictId): Promise<void> => {
const clearMessage = logConsoleProgress(`Deleting conflict ${conflictId.id()}`);
@@ -13,7 +13,7 @@ export const deleteConflict = async (collection: CollectionBase, conflictId: Con
partitionKey: getPartitionKeyHeaderForConflict(conflictId),
};
await client(ClientOperationType.WRITE)
await client()
.database(collection.databaseId)
.container(collection.id())
.conflict(conflictId.id())

View File

@@ -5,7 +5,7 @@ import { deleteGremlinDatabase } from "../../Utils/arm/generatedClients/cosmos/g
import { deleteMongoDBDatabase } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
import { deleteSqlDatabase } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client, ClientOperationType } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function deleteDatabase(databaseId: string): Promise<void> {
@@ -15,7 +15,7 @@ export async function deleteDatabase(databaseId: string): Promise<void> {
if (userContext.authType === AuthType.AAD && !userContext.features.enableSDKoperations) {
await deleteDatabaseWithARM(databaseId);
} else {
await client(ClientOperationType.WRITE).database(databaseId).delete();
await client().database(databaseId).delete();
}
logConsoleInfo(`Successfully deleted database ${databaseId}`);
} catch (error) {

View File

@@ -1,7 +1,7 @@
import { CollectionBase } from "../../Contracts/ViewModels";
import DocumentId from "../../Explorer/Tree/DocumentId";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
import { getPartitionKeyValue } from "./getPartitionKeyValue";
@@ -11,7 +11,7 @@ export const deleteDocument = async (collection: CollectionBase, documentId: Doc
const clearMessage = logConsoleProgress(`Deleting ${entityName} ${documentId.id()}`);
try {
await client(ClientOperationType.WRITE)
await client()
.database(collection.databaseId)
.container(collection.id())
.item(documentId.id(), getPartitionKeyValue(documentId))

View File

@@ -2,7 +2,7 @@ import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { deleteSqlStoredProcedure } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client, ClientOperationType } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function deleteStoredProcedure(
@@ -26,11 +26,7 @@ export async function deleteStoredProcedure(
storedProcedureId,
);
} else {
await client(ClientOperationType.WRITE)
.database(databaseId)
.container(collectionId)
.scripts.storedProcedure(storedProcedureId)
.delete();
await client().database(databaseId).container(collectionId).scripts.storedProcedure(storedProcedureId).delete();
}
} catch (error) {
handleError(error, "DeleteStoredProcedure", `Error while deleting stored procedure ${storedProcedureId}`);

View File

@@ -2,7 +2,7 @@ import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { deleteSqlTrigger } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client, ClientOperationType } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function deleteTrigger(databaseId: string, collectionId: string, triggerId: string): Promise<void> {
@@ -22,11 +22,7 @@ export async function deleteTrigger(databaseId: string, collectionId: string, tr
triggerId,
);
} else {
await client(ClientOperationType.WRITE)
.database(databaseId)
.container(collectionId)
.scripts.trigger(triggerId)
.delete();
await client().database(databaseId).container(collectionId).scripts.trigger(triggerId).delete();
}
} catch (error) {
handleError(error, "DeleteTrigger", `Error while deleting trigger ${triggerId}`);

View File

@@ -2,7 +2,7 @@ import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { deleteSqlUserDefinedFunction } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client, ClientOperationType } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function deleteUserDefinedFunction(databaseId: string, collectionId: string, id: string): Promise<void> {
@@ -22,11 +22,7 @@ export async function deleteUserDefinedFunction(databaseId: string, collectionId
id,
);
} else {
await client(ClientOperationType.WRITE)
.database(databaseId)
.container(collectionId)
.scripts.userDefinedFunction(id)
.delete();
await client().database(databaseId).container(collectionId).scripts.userDefinedFunction(id).delete();
}
} catch (error) {
handleError(error, "DeleteUserDefinedFunction", `Error while deleting user defined function ${id}`);

View File

@@ -1,9 +1,9 @@
import { Collection } from "../../Contracts/ViewModels";
import StoredProcedure from "../../Explorer/Tree/StoredProcedure";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientDefaults, HttpHeaders } from "../Constants";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress, logConsoleInfo } from "../../Utils/NotificationConsoleUtils";
import StoredProcedure from "../../Explorer/Tree/StoredProcedure";
export interface ExecuteSprocResult {
result: StoredProcedure;
@@ -22,7 +22,7 @@ export const executeStoredProcedure = async (
}, ClientDefaults.requestTimeoutMs);
try {
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.scripts.storedProcedure(storedProcedure.id())

View File

@@ -1,9 +1,9 @@
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import * as Constants from "../Constants";
import { ClientOperationType, client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
export async function getIndexTransformationProgress(databaseId: string, collectionId: string): Promise<number> {
if (userContext.authType !== AuthType.AAD) {
@@ -12,10 +12,7 @@ export async function getIndexTransformationProgress(databaseId: string, collect
let indexTransformationPercentage: number;
const clearMessage = logConsoleProgress(`Reading container ${collectionId}`);
try {
const response = await client(ClientOperationType.READ)
.database(databaseId)
.container(collectionId)
.read({ populateQuotaInfo: true });
const response = await client().database(databaseId).container(collectionId).read({ populateQuotaInfo: true });
indexTransformationPercentage = parseInt(
response.headers[Constants.HttpHeaders.collectionIndexTransformationProgress] as string,

View File

@@ -1,5 +1,5 @@
import { ConflictDefinition, FeedOptions, QueryIterator, Resource } from "@azure/cosmos";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
export const queryConflicts = (
databaseId: string,
@@ -7,5 +7,5 @@ export const queryConflicts = (
query: string,
options: FeedOptions,
): QueryIterator<ConflictDefinition & Resource> => {
return client(ClientOperationType.READ).database(databaseId).container(containerId).conflicts.query(query, options);
return client().database(databaseId).container(containerId).conflicts.query(query, options);
};

View File

@@ -1,7 +1,7 @@
import { FeedOptions, ItemDefinition, QueryIterator, Resource } from "@azure/cosmos";
import { LocalStorageUtility, StorageKey } from "../../Shared/StorageUtility";
import { Queries } from "../Constants";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
export const queryDocuments = (
databaseId: string,
@@ -10,7 +10,7 @@ export const queryDocuments = (
options: FeedOptions,
): QueryIterator<ItemDefinition & Resource> => {
options = getCommonQueryOptions(options);
return client(ClientOperationType.READ).database(databaseId).container(containerId).items.query(query, options);
return client().database(databaseId).container(containerId).items.query(query, options);
};
export const getCommonQueryOptions = (options: FeedOptions): FeedOptions => {

View File

@@ -3,11 +3,11 @@ import { sampleDataClient } from "Common/SampleDataClient";
import { userContext } from "UserContext";
import * as DataModels from "../../Contracts/DataModels";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function readCollection(databaseId: string, collectionId: string): Promise<DataModels.Collection> {
const cosmosClient = client(ClientOperationType.READ);
const cosmosClient = client();
return await readCollectionInternal(cosmosClient, databaseId, collectionId);
}

View File

@@ -10,7 +10,7 @@ import { listGremlinGraphs } from "../../Utils/arm/generatedClients/cosmos/greml
import { listMongoDBCollections } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
import { listSqlContainers } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { listTables } from "../../Utils/arm/generatedClients/cosmos/tableResources";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function readCollections(databaseId: string): Promise<DataModels.Collection[]> {
@@ -31,7 +31,7 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
const tokenCollectionId = resourceIdObj[3];
if (tokenDatabaseId === databaseId) {
promises.push(client(ClientOperationType.READ).database(databaseId).container(tokenCollectionId).read());
promises.push(client().database(databaseId).container(tokenCollectionId).read());
}
}
@@ -61,7 +61,7 @@ export async function readCollections(databaseId: string): Promise<DataModels.Co
return await readCollectionsWithARM(databaseId);
}
const sdkResponse = await client(ClientOperationType.READ).database(databaseId).containers.readAll().fetchAll();
const sdkResponse = await client().database(databaseId).containers.readAll().fetchAll();
return sdkResponse.resources as DataModels.Collection[];
} catch (error) {
handleError(error, "ReadCollections", `Error while querying containers for database ${databaseId}`);
@@ -77,7 +77,7 @@ export async function readCollectionsWithPagination(
): Promise<DataModels.CollectionsWithPagination> {
const clearMessage = logConsoleProgress(`Querying containers for database ${databaseId}`);
try {
const sdkResponse = await client(ClientOperationType.READ)
const sdkResponse = await client()
.database(databaseId)
.containers.query(
{ query: "SELECT * FROM c" },

View File

@@ -7,7 +7,7 @@ import { listCassandraKeyspaces } from "../../Utils/arm/generatedClients/cosmos/
import { listGremlinDatabases } from "../../Utils/arm/generatedClients/cosmos/gremlinResources";
import { listMongoDBDatabases } from "../../Utils/arm/generatedClients/cosmos/mongoDBResources";
import { listSqlDatabases } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function readDatabases(): Promise<DataModels.Database[]> {
@@ -56,7 +56,7 @@ export async function readDatabases(): Promise<DataModels.Database[]> {
) {
databases = await readDatabasesWithARM();
} else {
const sdkResponse = await client(ClientOperationType.READ).databases.readAll().fetchAll();
const sdkResponse = await client().databases.readAll().fetchAll();
databases = sdkResponse.resources as DataModels.Database[];
}
} catch (error) {

View File

@@ -3,7 +3,7 @@ import { CollectionBase } from "../../Contracts/ViewModels";
import DocumentId from "../../Explorer/Tree/DocumentId";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { HttpHeaders } from "../Constants";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
import { getPartitionKeyValue } from "./getPartitionKeyValue";
@@ -19,7 +19,7 @@ export const readDocument = async (collection: CollectionBase, documentId: Docum
[HttpHeaders.partitionKey]: documentId.partitionKeyValue,
}
: {};
const response = await client(ClientOperationType.READ)
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.item(documentId.id(), getPartitionKeyValue(documentId))

View File

@@ -1,7 +1,7 @@
import { RequestOptions } from "@azure/cosmos";
import { Offer } from "../../Contracts/DataModels";
import { HttpHeaders } from "../Constants";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { parseSDKOfferResponse } from "../OfferUtility";
import { readOffers } from "./readOffers";
@@ -21,7 +21,7 @@ export const readOfferWithSDK = async (offerId: string, resourceId: string): Pro
[HttpHeaders.populateCollectionThroughputInfo]: true,
},
};
const response = await client(ClientOperationType.READ).offer(offerId).read(options);
const response = await client().offer(offerId).read(options);
return parseSDKOfferResponse(response);
};

View File

@@ -1,13 +1,13 @@
import { SDKOfferDefinition } from "../../Contracts/DataModels";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { getErrorMessage, handleError } from "../ErrorHandlingUtils";
import { client } from "../CosmosClient";
import { handleError, getErrorMessage } from "../ErrorHandlingUtils";
export const readOffers = async (): Promise<SDKOfferDefinition[]> => {
const clearMessage = logConsoleProgress(`Querying offers`);
try {
const response = await client(ClientOperationType.READ).offers.readAll().fetchAll();
const response = await client().offers.readAll().fetchAll();
return response?.resources;
} catch (error) {
// This should be removed when we can correctly identify if an account is serverless when connected using connection string too.

View File

@@ -4,7 +4,7 @@ import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { listSqlStoredProcedures } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function readStoredProcedures(
@@ -34,7 +34,7 @@ export async function readStoredProcedures(
throw new Error(cloudError?.error?.message);
}
const response = await client(ClientOperationType.READ)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.storedProcedures.readAll()

View File

@@ -1,10 +1,10 @@
import { TriggerDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { listSqlTriggers } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function readTriggers(
@@ -28,11 +28,7 @@ export async function readTriggers(
return rpResponse?.value?.map((trigger) => trigger.properties?.resource);
}
const response = await client(ClientOperationType.READ)
.database(databaseId)
.container(collectionId)
.scripts.triggers.readAll()
.fetchAll();
const response = await client().database(databaseId).container(collectionId).scripts.triggers.readAll().fetchAll();
return response?.resources;
} catch (error) {
handleError(error, "ReadTriggers", `Failed to query triggers for container ${collectionId}`);

View File

@@ -1,9 +1,9 @@
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { listSqlUserDefinedFunctions } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function readUserDefinedFunctions(
@@ -24,7 +24,7 @@ export async function readUserDefinedFunctions(
return rpResponse?.value?.map((udf) => udf.properties?.resource as UserDefinedFunctionDefinition & Resource);
}
const response = await client(ClientOperationType.READ)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.userDefinedFunctions.readAll()

View File

@@ -2,7 +2,6 @@ import { ContainerDefinition, RequestOptions } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { Collection } from "../../Contracts/DataModels";
import { userContext } from "../../UserContext";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import {
createUpdateCassandraTable,
getCassandraTable,
@@ -20,7 +19,8 @@ import {
SqlContainerCreateUpdateParameters,
SqlContainerResource,
} from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function updateCollection(
@@ -40,7 +40,7 @@ export async function updateCollection(
) {
collection = await updateCollectionWithARM(databaseId, collectionId, newCollection);
} else {
const sdkResponse = await client(ClientOperationType.WRITE)
const sdkResponse = await client()
.database(databaseId)
.container(collectionId)
.replace(newCollection as ContainerDefinition, options);

View File

@@ -3,7 +3,7 @@ import { HttpHeaders } from "Common/Constants";
import { CollectionBase } from "../../Contracts/ViewModels";
import DocumentId from "../../Explorer/Tree/DocumentId";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { getEntityName } from "../DocumentUtility";
import { handleError } from "../ErrorHandlingUtils";
import { getPartitionKeyValue } from "./getPartitionKeyValue";
@@ -23,7 +23,7 @@ export const updateDocument = async (
[HttpHeaders.partitionKey]: documentId.partitionKeyValue,
}
: {};
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(collection.databaseId)
.container(collection.id())
.item(documentId.id(), getPartitionKeyValue(documentId))

View File

@@ -2,7 +2,6 @@ import { OfferDefinition, RequestOptions } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { Offer, SDKOfferDefinition, UpdateOfferParams } from "../../Contracts/DataModels";
import { userContext } from "../../UserContext";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import {
migrateCassandraKeyspaceToAutoscale,
migrateCassandraKeyspaceToManualThroughput,
@@ -41,8 +40,9 @@ import {
updateTableThroughput,
} from "../../Utils/arm/generatedClients/cosmos/tableResources";
import { ThroughputSettingsUpdateParameters } from "../../Utils/arm/generatedClients/cosmos/types";
import { logConsoleInfo, logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { HttpHeaders } from "../Constants";
import { ClientOperationType, client } from "../CosmosClient";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
import { parseSDKOfferResponse } from "../OfferUtility";
import { readCollectionOffer } from "./readCollectionOffer";
@@ -401,7 +401,7 @@ const updateOfferWithSDK = async (params: UpdateOfferParams): Promise<Offer> =>
newOffer.content.offerAutopilotSettings = { maxThroughput: 0 };
}
const sdkResponse = await client(ClientOperationType.WRITE)
const sdkResponse = await client()
.offer(params.currentOffer.id)
// TODO Remove casting when SDK types are fixed (https://github.com/Azure/azure-sdk-for-js/issues/10660)
.replace(newOffer as unknown as OfferDefinition, options);

View File

@@ -1,7 +1,6 @@
import { Resource, StoredProcedureDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import {
createUpdateSqlStoredProcedure,
getSqlStoredProcedure,
@@ -10,7 +9,8 @@ import {
SqlStoredProcedureCreateUpdateParameters,
SqlStoredProcedureResource,
} from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function updateStoredProcedure(
@@ -54,7 +54,7 @@ export async function updateStoredProcedure(
throw new Error(`Failed to update stored procedure: ${storedProcedure.id} does not exist.`);
}
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.storedProcedure(storedProcedure.id)

View File

@@ -1,10 +1,10 @@
import { TriggerDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { createUpdateSqlTrigger, getSqlTrigger } from "../../Utils/arm/generatedClients/cosmos/sqlResources";
import { SqlTriggerCreateUpdateParameters, SqlTriggerResource } from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function updateTrigger(
@@ -47,7 +47,7 @@ export async function updateTrigger(
throw new Error(`Failed to update trigger: ${trigger.id} does not exist.`);
}
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.trigger(trigger.id)

View File

@@ -1,7 +1,6 @@
import { Resource, UserDefinedFunctionDefinition } from "@azure/cosmos";
import { AuthType } from "../../AuthType";
import { userContext } from "../../UserContext";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import {
createUpdateSqlUserDefinedFunction,
getSqlUserDefinedFunction,
@@ -10,7 +9,8 @@ import {
SqlUserDefinedFunctionCreateUpdateParameters,
SqlUserDefinedFunctionResource,
} from "../../Utils/arm/generatedClients/cosmos/types";
import { ClientOperationType, client } from "../CosmosClient";
import { logConsoleProgress } from "../../Utils/NotificationConsoleUtils";
import { client } from "../CosmosClient";
import { handleError } from "../ErrorHandlingUtils";
export async function updateUserDefinedFunction(
@@ -53,7 +53,7 @@ export async function updateUserDefinedFunction(
throw new Error(`Failed to update user defined function: ${userDefinedFunction.id} does not exist.`);
}
const response = await client(ClientOperationType.WRITE)
const response = await client()
.database(databaseId)
.container(collectionId)
.scripts.userDefinedFunction(userDefinedFunction.id)

View File

@@ -1,6 +1,7 @@
/**
* React component for Command button component.
*/
import { KeyboardShortcutName } from "Common/KeyboardShortcuts";
import * as React from "react";
import CollapseChevronDownIcon from "../../../../images/QueryBuilder/CollapseChevronDown_16x.png";
import { KeyCodes } from "../../../Common/Constants";
@@ -30,7 +31,7 @@ export interface CommandButtonComponentProps {
/**
* Click handler for command button click
*/
onCommandClick: (e: React.SyntheticEvent) => void;
onCommandClick: (e: React.SyntheticEvent | KeyboardEvent) => void;
/**
* Label for the button
@@ -107,10 +108,16 @@ export interface CommandButtonComponentProps {
* Vertical bar to divide buttons
*/
isDivider?: boolean;
/**
* Aria-label for the button
*/
ariaLabel: string;
/**
* A keyboard shortcut that can be used to activate this button.
*/
keyboardShortcut?: KeyboardShortcutName;
}
export class CommandButtonComponent extends React.Component<CommandButtonComponentProps> {

View File

@@ -1,6 +1,6 @@
import { Spinner, SpinnerSize } from "@fluentui/react";
import * as React from "react";
import { loadMonaco, monaco } from "../../LazyMonaco";
import { MonacoNamespace, loadMonaco, monaco } from "../../LazyMonaco";
// import "./EditorReact.less";
interface EditorReactStates {
@@ -21,6 +21,7 @@ export interface EditorReactProps {
minimap?: monaco.editor.IEditorOptions["minimap"];
scrollBeyondLastLine?: monaco.editor.IEditorOptions["scrollBeyondLastLine"];
monacoContainerStyles?: React.CSSProperties;
configureEditor?: (monaco: MonacoNamespace, editor: monaco.editor.IStandaloneCodeEditor) => void;
}
export class EditorReact extends React.Component<EditorReactProps, EditorReactStates> {
@@ -69,7 +70,7 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
);
}
protected configureEditor(editor: monaco.editor.IStandaloneCodeEditor) {
protected configureEditor(monaco: MonacoNamespace, editor: monaco.editor.IStandaloneCodeEditor) {
this.editor = editor;
const queryEditorModel = this.editor.getModel();
if (!this.props.isReadOnly && this.props.onContentChanged) {
@@ -87,12 +88,16 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
},
);
}
if (this.props.configureEditor) {
this.props.configureEditor(monaco, this.editor);
}
}
/**
* Create the monaco editor and attach to DOM
*/
private async createEditor(createCallback: (e: monaco.editor.IStandaloneCodeEditor) => void) {
private async createEditor(createCallback: (monaco: MonacoNamespace, e: monaco.editor.IStandaloneCodeEditor) => void) {
const options: monaco.editor.IStandaloneEditorConstructionOptions = {
language: this.props.language,
value: this.props.content,
@@ -111,7 +116,7 @@ export class EditorReact extends React.Component<EditorReactProps, EditorReactSt
this.rootNode.innerHTML = "";
const monaco = await loadMonaco();
createCallback(monaco?.editor?.create(this.rootNode, options));
createCallback(monaco, monaco?.editor?.create(this.rootNode, options));
if (this.rootNode.innerHTML) {
this.setState({

View File

@@ -754,6 +754,7 @@ export class SettingsComponent extends React.Component<SettingsComponentProps, S
buttons.push({
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onRevertClick,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -3,3 +3,4 @@ export type { monaco };
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const loadMonaco = () => import(/* webpackChunkName: "lazy-monaco" */ "monaco-editor/esm/vs/editor/editor.api");
export type MonacoNamespace = Awaited<ReturnType<typeof loadMonaco>>;

View File

@@ -4,9 +4,11 @@
* and update any knockout observables passed from the parent.
*/
import { CommandBar as FluentCommandBar, ICommandBarItemProps } from "@fluentui/react";
import { keyMap } from "Common/KeyboardShortcuts";
import { useNotebook } from "Explorer/Notebook/useNotebook";
import { userContext } from "UserContext";
import * as React from "react";
import { GlobalHotKeys } from "react-hotkeys";
import create, { UseStore } from "zustand";
import { ConnectionStatusType, PoolIdType } from "../../../Common/Constants";
import { StyleConstants } from "../../../Common/StyleConstants";
@@ -105,8 +107,13 @@ export const CommandBar: React.FC<Props> = ({ container }: Props) => {
},
};
const handlers = CommandBarUtil.createKeyboardHandlers(staticButtons.concat(contextButtons).concat(controlButtons));
return (
<div className="commandBarContainer" style={{ display: isHidden ? "none" : "initial" }}>
{/* Handles keyboard shortcuts for command bar buttons when focus is OUTSIDE monaco. Even though it's placed here in the DOM, it hooks keydown on 'document' */}
<GlobalHotKeys keyMap={keyMap} handlers={handlers} allowChanges={true} />
<FluentCommandBar
ariaLabel="Use left and right arrow keys to navigate between commands"
items={uiFabricStaticButtons.concat(uiFabricTabsButtons)}

View File

@@ -23,7 +23,7 @@ import * as Constants from "../../../Common/Constants";
import { Platform, configContext } from "../../../ConfigContext";
import * as ViewModels from "../../../Contracts/ViewModels";
import { JunoClient } from "../../../Juno/JunoClient";
import { updateUserContext, userContext } from "../../../UserContext";
import { userContext } from "../../../UserContext";
import { getCollectionName, getDatabaseName } from "../../../Utils/APITypeUtils";
import { isRunningOnNationalCloud } from "../../../Utils/CloudUtils";
import { useSidePanel } from "../../../hooks/useSidePanel";
@@ -168,14 +168,6 @@ export function createStaticCommandBarButtons(
}
}
// Attempting to add region selection button here.
addDivider();
const [selectedRegion, setSelectedRegion] = React.useState(
userContext.databaseAccount.properties.locations[0].locationName,
);
const newReadRegionSelectionBtn = createReadRegionSelectionGroup(container, selectedRegion, setSelectedRegion);
buttons.push(newReadRegionSelectionBtn);
return buttons;
}
@@ -362,6 +354,7 @@ function createNewSQLQueryButton(selectedNodeState: SelectedNodeState): CommandB
id: "newQueryBtn",
iconSrc: AddSqlQueryIcon,
iconAlt: label,
keyboardShortcut: "NEW_QUERY",
onCommandClick: () => {
const selectedCollection: ViewModels.Collection = selectedNodeState.findSelectedCollection();
selectedCollection && selectedCollection.onNewQueryClick(selectedCollection);
@@ -377,6 +370,7 @@ function createNewSQLQueryButton(selectedNodeState: SelectedNodeState): CommandB
id: "newQueryBtn",
iconSrc: AddSqlQueryIcon,
iconAlt: label,
keyboardShortcut: "NEW_QUERY",
onCommandClick: () => {
const selectedCollection: ViewModels.Collection = selectedNodeState.findSelectedCollection();
selectedCollection && selectedCollection.onNewMongoQueryClick(selectedCollection);
@@ -609,103 +603,6 @@ function createManageGitHubAccountButton(container: Explorer): CommandButtonComp
};
}
// function createReadRegionSelectionGroup(container: Explorer): CommandButtonComponentProps {
// const label = "Select a Read Region";
// return {
// iconAlt: label,
// commandButtonLabel: label,
// hasPopup: false,
// disabled: false,
// ariaLabel: label,
// onCommandClick: async () => {
// console.log(
// `CURRENT DOCUMENT ENDPOINT: ${JSON.stringify(userContext.databaseAccount.properties.documentEndpoint)}`,
// );
// userContext.databaseAccount.properties.readLocations.forEach((readLocation) => {
// console.log(`CURRENT READ ENDPOINT(S): ${JSON.stringify(readLocation)}`);
// });
// const updatedDatabaseAccount = {
// ...userContext.databaseAccount,
// properties: {
// ...userContext.databaseAccount.properties,
// documentEndpoint: "https://test-craig-nosql-periodic-eastus.documents.azure.com:443/",
// },
// };
// updateUserContext({
// databaseAccount: updatedDatabaseAccount,
// });
// },
// };
// }
function createReadRegionSelectionGroup(
container: Explorer,
selectedRegion: string,
setSelectedRegion: (region: string) => void,
): CommandButtonComponentProps {
const children = userContext.databaseAccount.properties.readLocations.map((readLocation) => ({
commandButtonLabel: readLocation.locationName,
onCommandClick: async () => {
const updatedDatabaseAccount = {
...userContext.databaseAccount,
properties: {
...userContext.databaseAccount.properties,
documentEndpoint: readLocation.documentEndpoint,
},
};
updateUserContext({
databaseAccount: updatedDatabaseAccount,
});
setSelectedRegion(readLocation.locationName);
},
hasPopup: false,
ariaLabel: `Select ${readLocation.locationName}`,
}));
const label = selectedRegion || "Select a Read Region";
return {
iconAlt: label,
commandButtonLabel: label,
onCommandClick: () => {},
hasPopup: true,
ariaLabel: label,
isDropdown: true,
children,
dropdownWidth: 100,
};
}
// function createAccountRegionSelectionButton(container: Explorer): JSX.Element {
// const [selectedEndpoint, setSelectedEndpoint] = useState(userContext.databaseAccount.properties.documentEndpoint);
// const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
// const endpoint = event.target.value as string;
// setSelectedEndpoint(endpoint);
// const updatedDatabaseAccount = {
// ...userContext.databaseAccount,
// properties: {
// ...userContext.databaseAccount.properties,
// documentEndpoint: endpoint,
// },
// };
// updateUserContext({
// databaseAccount: updatedDatabaseAccount,
// });
// };
// return (
// <Select
// value={selectedEndpoint}
// onChange={handleChange}
// displayEmpty
// >
// {userContext.databaseAccount.properties.readLocations.map((readLocation) => (
// <MenuItem value={readLocation}>{readLocation}</MenuItem>
// ))}
// </Select>
// );
// }
function createStaticCommandBarButtonsForResourceToken(
container: Explorer,
selectedNodeState: SelectedNodeState,

View File

@@ -6,6 +6,7 @@ import {
IDropdownOption,
IDropdownStyles,
} from "@fluentui/react";
import { KeyboardShortcutHandlers } from "Common/KeyboardShortcuts";
import { useQueryCopilot } from "hooks/useQueryCopilot";
import * as React from "react";
import _ from "underscore";
@@ -233,3 +234,16 @@ export const createConnectionStatus = (container: Explorer, poolId: PoolIdType,
onRender: () => <ConnectionStatus container={container} poolId={poolId} />,
};
};
export const createKeyboardHandlers = (buttons: CommandButtonComponentProps[]): KeyboardShortcutHandlers => {
const handlers: KeyboardShortcutHandlers = {};
buttons.forEach((button) => {
if (button.keyboardShortcut) {
handlers[button.keyboardShortcut] = (e) => {
button.onCommandClick(e);
e.preventDefault();
};
}
});
return handlers;
}

View File

@@ -104,15 +104,16 @@ export const QueryCopilotTab: React.FC<QueryCopilotProps> = ({ explorer }: Query
)}
<Stack className="tabPaneContentContainer">
<SplitterLayout percentage={true} vertical={true} primaryIndex={0} primaryMinSize={30} secondaryMinSize={70}>
COPILOT
<EditorReact
language={"sql"}
content={query}
isReadOnly={false}
wordWrap={"on"}
ariaLabel={"Editing Query"}
lineNumbers={"on"}
onContentChanged={(newQuery: string) => setQuery(newQuery)}
onContentSelected={(selectedQuery: string) => setSelectedQuery(selectedQuery)}
language={"sql"}
content={query}
isReadOnly={false}
wordWrap={"on"}
ariaLabel={"Editing Query"}
lineNumbers={"on"}
onContentChanged={(newQuery: string) => setQuery(newQuery)}
onContentSelected={(selectedQuery: string) => setSelectedQuery(selectedQuery)}
/>
<QueryCopilotResults />
</SplitterLayout>

View File

@@ -6,16 +6,16 @@ import DiscardIcon from "../../../images/discard.svg";
import SaveIcon from "../../../images/save-cosmos.svg";
import * as Constants from "../../Common/Constants";
import { DocumentsGridMetrics, KeyCodes } from "../../Common/Constants";
import { createDocument } from "../../Common/dataAccess/createDocument";
import { deleteConflict } from "../../Common/dataAccess/deleteConflict";
import { deleteDocument } from "../../Common/dataAccess/deleteDocument";
import { queryConflicts } from "../../Common/dataAccess/queryConflicts";
import { updateDocument } from "../../Common/dataAccess/updateDocument";
import editable from "../../Common/EditableUtility";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import * as HeadersUtility from "../../Common/HeadersUtility";
import { MinimalQueryIterator } from "../../Common/IteratorUtilities";
import { Splitter, SplitterBounds, SplitterDirection } from "../../Common/Splitter";
import { createDocument } from "../../Common/dataAccess/createDocument";
import { deleteConflict } from "../../Common/dataAccess/deleteConflict";
import { deleteDocument } from "../../Common/dataAccess/deleteDocument";
import { queryConflicts } from "../../Common/dataAccess/queryConflicts";
import { updateDocument } from "../../Common/dataAccess/updateDocument";
import * as DataModels from "../../Contracts/DataModels";
import * as ViewModels from "../../Contracts/ViewModels";
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
@@ -621,6 +621,7 @@ export default class ConflictsTab extends TabsBase {
buttons.push({
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onDiscardClick,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -921,6 +921,7 @@ export default class DocumentsTab extends TabsBase {
buttons.push({
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onRevertNewDocumentClick,
commandButtonLabel: label,
ariaLabel: label,
@@ -950,6 +951,7 @@ export default class DocumentsTab extends TabsBase {
buttons.push({
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onRevertExisitingDocumentClick,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -3,6 +3,8 @@
import { FeedOptions, QueryOperationOptions } from "@azure/cosmos";
import { Platform, configContext } from "ConfigContext";
import { useDialog } from "Explorer/Controls/Dialog";
import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
import { MonacoNamespace, monaco } from "Explorer/LazyMonaco";
import { QueryCopilotFeedbackModal } from "Explorer/QueryCopilot/Modal/QueryCopilotFeedbackModal";
import { useCopilotStore } from "Explorer/QueryCopilot/QueryCopilotContext";
import { QueryCopilotPromptbar } from "Explorer/QueryCopilot/QueryCopilotPromptbar";
@@ -39,7 +41,6 @@ import { userContext } from "../../../UserContext";
import * as QueryUtils from "../../../Utils/QueryUtils";
import { useSidePanel } from "../../../hooks/useSidePanel";
import { CommandButtonComponentProps } from "../../Controls/CommandButton/CommandButtonComponent";
import { EditorReact } from "../../Controls/Editor/EditorReact";
import Explorer from "../../Explorer";
import { useCommandBar } from "../../Menus/CommandBar/CommandBarComponentAdapter";
import { BrowseQueriesPane } from "../../Panes/BrowseQueriesPane/BrowseQueriesPane";
@@ -468,6 +469,7 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
buttons.push({
iconSrc: CancelQueryIcon,
iconAlt: label,
keyboardShortcut: "CANCEL_QUERY",
onCommandClick: () => this.queryAbortController.abort(),
commandButtonLabel: label,
ariaLabel: label,
@@ -584,6 +586,15 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
}
private getEditorAndQueryResult(): JSX.Element {
const configureEditor = (monaco: MonacoNamespace, editor: monaco.editor.IStandaloneCodeEditor) => {
editor.addAction({
id: "execute-query",
label: "Execute Query",
keybindings: [monaco.KeyMod.Shift | monaco.KeyCode.Enter],
run: () => this.onExecuteQueryClick(),
});
}
return (
<Fragment>
<div className="tab-pane" id={this.props.tabId} role="tabpanel">
@@ -608,7 +619,8 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
lineNumbers={"on"}
onContentChanged={(newContent: string) => this.onChangeContent(newContent)}
onContentSelected={(selectedContent: string) => this.onSelectedContent(selectedContent)}
/>
configureEditor={configureEditor}
/>;
</div>
</Fragment>
{this.props.isSampleCopilotActive ? (

View File

@@ -238,6 +238,7 @@ export default abstract class ScriptTabBase extends TabsBase implements ViewMode
buttons.push({
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onDiscard,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -347,6 +347,7 @@ export default class StoredProcedureTabComponent extends React.Component<
buttons.push({
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onDiscard,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -256,6 +256,7 @@ export class TriggerTabContent extends Component<TriggerTab, ITriggerTabContentS
...this,
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onDiscard,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -4,9 +4,9 @@ import React, { Component } from "react";
import DiscardIcon from "../../../images/discard.svg";
import SaveIcon from "../../../images/save-cosmos.svg";
import * as Constants from "../../Common/Constants";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import { createUserDefinedFunction } from "../../Common/dataAccess/createUserDefinedFunction";
import { updateUserDefinedFunction } from "../../Common/dataAccess/updateUserDefinedFunction";
import { getErrorMessage, getErrorStack } from "../../Common/ErrorHandlingUtils";
import * as ViewModels from "../../Contracts/ViewModels";
import { Action } from "../../Shared/Telemetry/TelemetryConstants";
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
@@ -109,6 +109,7 @@ export default class UserDefinedFunctionTabContent extends Component<
...this,
iconSrc: DiscardIcon,
iconAlt: label,
keyboardShortcut: "DISCARD",
onCommandClick: this.onDiscard,
commandButtonLabel: label,
ariaLabel: label,

View File

@@ -18,6 +18,7 @@ import "../externals/jquery.typeahead.min.js";
// Image Dependencies
import { Platform } from "ConfigContext";
import { QueryCopilotCarousel } from "Explorer/QueryCopilot/CopilotCarousel";
import * as ReactHotkeys from "react-hotkeys";
import "../images/CosmosDB_rgb_ui_lighttheme.ico";
import hdeConnectImage from "../images/HdeConnectCosmosDB.svg";
import "../images/favicon.ico";
@@ -61,6 +62,28 @@ import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
initializeIcons();
const tagsIgnoredByReactHotkeys = ["INPUT", "SELECT"];
ReactHotkeys.configure({
ignoreEventsCondition: (evt) => {
// The default react-hotkeys behavior is to ignore events targetting a textarea, but we want the monaco editor's key events to bubble up
// So, we configure it to ignore all events targetting a textarea except when the target is a monaco editor's text area
if (!(evt.target instanceof HTMLElement)) {
return true;
}
if (tagsIgnoredByReactHotkeys.includes(evt.target.tagName)) {
return true;
}
if (evt.target.tagName === "TEXTAREA" && !evt.target.matches(".monaco-editor textarea")) {
return true;
}
return false;
}
})
const App: React.FunctionComponent = () => {
const [isLeftPaneExpanded, setIsLeftPaneExpanded] = useState<boolean>(true);
const isCarouselOpen = useCarousel((state) => state.shouldOpen);

View File

@@ -302,7 +302,6 @@ module.exports = function (_env = {}, argv = {}) {
pathRewrite: { "^/proxy": "" },
router: (req) => {
let newTarget = req.headers["x-ms-proxy-target"];
console.log(`Proxy path used. New target is: ${newTarget}`);
return newTarget;
},
},