Merge branch 'master' of https://github.com/Azure/cosmos-explorer
This commit is contained in:
commit
5042f28229
|
@ -124,6 +124,34 @@ export enum MongoBackendEndpointType {
|
|||
remote,
|
||||
}
|
||||
|
||||
export enum BackendApi {
|
||||
GenerateToken,
|
||||
}
|
||||
|
||||
export class PortalBackendEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7235";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-pbe.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-pbe.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-pbe.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-pbe.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
export class MongoProxyEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7238";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-mp.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-mp.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-mp.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-mp.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
export class CassandraProxyEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7240";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-cp.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-cp.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-cp.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-cp.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
//TODO: Remove this when new backend is migrated over
|
||||
export class CassandraBackend {
|
||||
public static readonly createOrDeleteApi: string = "api/cassandra/createordelete";
|
||||
|
@ -446,22 +474,6 @@ export class JunoEndpoints {
|
|||
public static readonly Stage = "https://tools-staging.cosmos.azure.com";
|
||||
}
|
||||
|
||||
export class MongoProxyEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7238";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-mp.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-mp.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-mp.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-mp.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
export class CassandraProxyEndpoints {
|
||||
public static readonly Development: string = "https://localhost:7240";
|
||||
public static readonly Mpac: string = "https://cdb-ms-mpac-cp.cosmos.azure.com";
|
||||
public static readonly Prod: string = "https://cdb-ms-prod-cp.cosmos.azure.com";
|
||||
public static readonly Fairfax: string = "https://cdb-ff-prod-cp.cosmos.azure.us";
|
||||
public static readonly Mooncake: string = "https://cdb-mc-prod-cp.cosmos.azure.cn";
|
||||
}
|
||||
|
||||
export class PriorityLevel {
|
||||
public static readonly High = "high";
|
||||
public static readonly Low = "low";
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import * as Cosmos from "@azure/cosmos";
|
||||
import { sendCachedDataMessage } from "Common/MessageHandler";
|
||||
import { getAuthorizationTokenUsingResourceTokens } from "Common/getAuthorizationTokenUsingResourceTokens";
|
||||
import { AuthorizationToken, MessageTypes } from "Contracts/MessageTypes";
|
||||
import { AuthorizationToken } from "Contracts/MessageTypes";
|
||||
import { checkDatabaseResourceTokensValidity } from "Platform/Fabric/FabricUtil";
|
||||
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
|
||||
import { AuthType } from "../AuthType";
|
||||
|
@ -51,6 +50,13 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
|||
case Cosmos.ResourceType.offer:
|
||||
case Cosmos.ResourceType.user:
|
||||
case Cosmos.ResourceType.permission:
|
||||
// For now, these operations aren't used, so fetching the authorization token is commented out.
|
||||
// This provider must return a real token to pass validation by the client, so we return the cached resource token
|
||||
// (which is a valid token, but won't work for these operations).
|
||||
const resourceTokens2 = userContext.fabricContext.databaseConnectionInfo.resourceTokens;
|
||||
return getAuthorizationTokenUsingResourceTokens(resourceTokens2, requestInfo.path, requestInfo.resourceId);
|
||||
|
||||
/* ************** TODO: Uncomment this code if we need to support these operations **************
|
||||
// User master tokens
|
||||
const authorizationToken = await sendCachedDataMessage<AuthorizationToken>(
|
||||
MessageTypes.GetAuthorizationToken,
|
||||
|
@ -60,6 +66,7 @@ export const tokenProvider = async (requestInfo: Cosmos.RequestInfo) => {
|
|||
console.log("Response from Fabric: ", authorizationToken);
|
||||
headers[HttpHeaders.msDate] = authorizationToken.XDate;
|
||||
return decodeURIComponent(authorizationToken.PrimaryReadWriteToken);
|
||||
***********************************************************************************************/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -690,6 +690,7 @@ export function getARMCreateCollectionEndpoint(params: DataModels.MongoParameter
|
|||
}
|
||||
|
||||
function useMongoProxyEndpoint(api: string): boolean {
|
||||
const activeMongoProxyEndpoints: string[] = [MongoProxyEndpoints.Development];
|
||||
let canAccessMongoProxy: boolean = userContext.databaseAccount.properties.publicNetworkAccess === "Enabled";
|
||||
if (userContext.databaseAccount.properties.ipRules?.length > 0) {
|
||||
canAccessMongoProxy = canAccessMongoProxy && configContext.MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED;
|
||||
|
@ -698,6 +699,6 @@ function useMongoProxyEndpoint(api: string): boolean {
|
|||
return (
|
||||
canAccessMongoProxy &&
|
||||
configContext.NEW_MONGO_APIS?.includes(api) &&
|
||||
[MongoProxyEndpoints.Development, MongoProxyEndpoints.Mpac].includes(configContext.MONGO_PROXY_ENDPOINT)
|
||||
activeMongoProxyEndpoints.includes(configContext.MONGO_PROXY_ENDPOINT)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -122,14 +122,21 @@ const pollDataTransferJobOperation = async (
|
|||
|
||||
updateDataTransferJob(body);
|
||||
|
||||
if (status === "Cancelled" || status === "Failed" || status === "Faulted") {
|
||||
if (status === "Cancelled") {
|
||||
removeFromPolling(jobName);
|
||||
clearMessage && clearMessage();
|
||||
const cancelMessage = `Data transfer job ${jobName} cancelled`;
|
||||
NotificationConsoleUtils.logConsoleError(cancelMessage);
|
||||
throw new AbortError(cancelMessage);
|
||||
}
|
||||
if (status === "Failed" || status === "Faulted") {
|
||||
removeFromPolling(jobName);
|
||||
const errorMessage = body?.properties?.error
|
||||
? JSON.stringify(body?.properties?.error)
|
||||
: "Operation could not be completed";
|
||||
const error = new Error(errorMessage);
|
||||
clearMessage && clearMessage();
|
||||
NotificationConsoleUtils.logConsoleError(`Data transfer job ${jobName} Failed`);
|
||||
NotificationConsoleUtils.logConsoleError(`Data transfer job ${jobName} failed: ${errorMessage}`);
|
||||
throw new AbortError(error);
|
||||
}
|
||||
if (status === "Completed") {
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
import { CassandraProxyEndpoints, JunoEndpoints, MongoProxyEndpoints } from "Common/Constants";
|
||||
import {
|
||||
BackendApi,
|
||||
CassandraProxyEndpoints,
|
||||
JunoEndpoints,
|
||||
MongoProxyEndpoints,
|
||||
PortalBackendEndpoints,
|
||||
} from "Common/Constants";
|
||||
import {
|
||||
allowedAadEndpoints,
|
||||
allowedArcadiaEndpoints,
|
||||
|
@ -39,6 +45,8 @@ export interface ConfigContext {
|
|||
ARCADIA_ENDPOINT: string;
|
||||
ARCADIA_LIVY_ENDPOINT_DNS_ZONE: string;
|
||||
BACKEND_ENDPOINT?: string;
|
||||
PORTAL_BACKEND_ENDPOINT?: string;
|
||||
NEW_BACKEND_APIS?: BackendApi[];
|
||||
MONGO_BACKEND_ENDPOINT?: string;
|
||||
MONGO_PROXY_ENDPOINT?: string;
|
||||
MONGO_PROXY_OUTBOUND_IPS_ALLOWLISTED?: boolean;
|
||||
|
@ -90,6 +98,8 @@ let configContext: Readonly<ConfigContext> = {
|
|||
GITHUB_TEST_ENV_CLIENT_ID: "b63fc8cbf87fd3c6e2eb", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1777772
|
||||
JUNO_ENDPOINT: JunoEndpoints.Prod,
|
||||
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
|
||||
PORTAL_BACKEND_ENDPOINT: PortalBackendEndpoints.Prod,
|
||||
NEW_BACKEND_APIS: [BackendApi.GenerateToken],
|
||||
MONGO_PROXY_ENDPOINT: MongoProxyEndpoints.Prod,
|
||||
NEW_MONGO_APIS: [
|
||||
// "resourcelist",
|
||||
|
|
|
@ -136,15 +136,15 @@ export const PartitionKeyComponent: React.FC<PartitionKeyComponentProps> = ({ da
|
|||
};
|
||||
|
||||
const getPercentageComplete = () => {
|
||||
const jobStatus = portalDataTransferJob?.properties?.status;
|
||||
const isCompleted = jobStatus === "Completed";
|
||||
if (isCompleted) {
|
||||
return 1;
|
||||
}
|
||||
const processedCount = portalDataTransferJob?.properties?.processedCount;
|
||||
const totalCount = portalDataTransferJob?.properties?.totalCount;
|
||||
const jobStatus = portalDataTransferJob?.properties?.status;
|
||||
const isCancelled = jobStatus === "Cancelled";
|
||||
const isCompleted = jobStatus === "Completed";
|
||||
if (totalCount <= 0 && !isCompleted) {
|
||||
return isCancelled ? 0 : null;
|
||||
}
|
||||
return isCompleted ? 1 : processedCount / totalCount;
|
||||
const isJobInProgress = isCurrentJobInProgress(portalDataTransferJob);
|
||||
return isJobInProgress ? (totalCount > 0 ? processedCount / totalCount : null) : 0;
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
@ -149,7 +149,7 @@ export const getTabTitle = (tab: SettingsV2TabTypes): string => {
|
|||
case SettingsV2TabTypes.IndexingPolicyTab:
|
||||
return "Indexing Policy";
|
||||
case SettingsV2TabTypes.PartitionKeyTab:
|
||||
return "Partition Keys";
|
||||
return "Partition Keys (preview)";
|
||||
case SettingsV2TabTypes.ComputedPropertiesTab:
|
||||
return "Computed Properties (preview)";
|
||||
default:
|
||||
|
|
|
@ -207,7 +207,7 @@ exports[`SettingsComponent renders 1`] = `
|
|||
/>
|
||||
</PivotItem>
|
||||
<PivotItem
|
||||
headerText="Partition Keys"
|
||||
headerText="Partition Keys (preview)"
|
||||
itemKey="PartitionKeyTab"
|
||||
key="PartitionKeyTab"
|
||||
style={
|
||||
|
|
|
@ -58,10 +58,10 @@ export function createStaticCommandBarButtons(
|
|||
}
|
||||
};
|
||||
|
||||
if (configContext.platform !== Platform.Fabric) {
|
||||
const homeBtn = createHomeButton();
|
||||
buttons.push(homeBtn);
|
||||
|
||||
if (configContext.platform !== Platform.Fabric) {
|
||||
const newCollectionBtn = createNewCollectionGroup(container);
|
||||
buttons.push(newCollectionBtn);
|
||||
if (userContext.apiType !== "Tables" && userContext.apiType !== "Cassandra") {
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
Icon,
|
||||
IconButton,
|
||||
Link,
|
||||
MessageBar,
|
||||
Stack,
|
||||
Text,
|
||||
TooltipHost,
|
||||
|
@ -207,6 +208,7 @@ export const ChangePartitionKeyPane: React.FC<ChangePartitionKeyPaneProps> = ({
|
|||
</Stack>
|
||||
{createNewContainer ? (
|
||||
<Stack>
|
||||
<MessageBar>All configurations except for unique keys will be copied from the source container</MessageBar>
|
||||
<Stack className="panelGroupSpacing">
|
||||
<Stack horizontal>
|
||||
<span className="mandatoryStar">* </span>
|
||||
|
|
|
@ -49,7 +49,7 @@ export const QueryCopilotFeedbackModal = ({
|
|||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen={showFeedbackModal}>
|
||||
<Modal isOpen={showFeedbackModal} styles={{ main: { borderRadius: 8, maxWidth: 600 } }}>
|
||||
<form onSubmit={handleSubmit}>
|
||||
<Stack style={{ padding: 24 }}>
|
||||
<Stack horizontal horizontalAlign="space-between">
|
||||
|
@ -68,9 +68,14 @@ export const QueryCopilotFeedbackModal = ({
|
|||
rows={3}
|
||||
/>
|
||||
<TextField
|
||||
styles={{ root: { marginBottom: 14 } }}
|
||||
styles={{
|
||||
root: { marginBottom: 14 },
|
||||
fieldGroup: { backgroundColor: "#F3F2F1", borderRadius: 4, borderColor: "#D1D1D1" },
|
||||
}}
|
||||
label="Query generated"
|
||||
defaultValue={generatedQuery}
|
||||
multiline
|
||||
rows={3}
|
||||
readOnly
|
||||
/>
|
||||
<Text style={{ fontSize: 12, marginBottom: 14 }}>
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
exports[`Query Copilot Feedback Modal snapshot test shoud render and match snapshot 1`] = `
|
||||
<Modal
|
||||
isOpen={true}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -67,9 +75,16 @@ exports[`Query Copilot Feedback Modal snapshot test shoud render and match snaps
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
@ -125,6 +140,14 @@ exports[`Query Copilot Feedback Modal snapshot test shoud render and match snaps
|
|||
exports[`Query Copilot Feedback Modal snapshot test should cancel submission 1`] = `
|
||||
<Modal
|
||||
isOpen={false}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -189,9 +212,16 @@ exports[`Query Copilot Feedback Modal snapshot test should cancel submission 1`]
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
@ -247,6 +277,14 @@ exports[`Query Copilot Feedback Modal snapshot test should cancel submission 1`]
|
|||
exports[`Query Copilot Feedback Modal snapshot test should close on cancel click 1`] = `
|
||||
<Modal
|
||||
isOpen={false}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -311,9 +349,16 @@ exports[`Query Copilot Feedback Modal snapshot test should close on cancel click
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
@ -369,6 +414,14 @@ exports[`Query Copilot Feedback Modal snapshot test should close on cancel click
|
|||
exports[`Query Copilot Feedback Modal snapshot test should get user unput 1`] = `
|
||||
<Modal
|
||||
isOpen={false}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -433,9 +486,16 @@ exports[`Query Copilot Feedback Modal snapshot test should get user unput 1`] =
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
@ -491,6 +551,14 @@ exports[`Query Copilot Feedback Modal snapshot test should get user unput 1`] =
|
|||
exports[`Query Copilot Feedback Modal snapshot test should not render dont show again button 1`] = `
|
||||
<Modal
|
||||
isOpen={false}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -555,9 +623,16 @@ exports[`Query Copilot Feedback Modal snapshot test should not render dont show
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
@ -613,6 +688,14 @@ exports[`Query Copilot Feedback Modal snapshot test should not render dont show
|
|||
exports[`Query Copilot Feedback Modal snapshot test should render dont show again button and check it 1`] = `
|
||||
<Modal
|
||||
isOpen={true}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -677,9 +760,16 @@ exports[`Query Copilot Feedback Modal snapshot test should render dont show agai
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
@ -750,6 +840,14 @@ exports[`Query Copilot Feedback Modal snapshot test should render dont show agai
|
|||
exports[`Query Copilot Feedback Modal snapshot test should submit submission 1`] = `
|
||||
<Modal
|
||||
isOpen={false}
|
||||
styles={
|
||||
Object {
|
||||
"main": Object {
|
||||
"borderRadius": 8,
|
||||
"maxWidth": 600,
|
||||
},
|
||||
}
|
||||
}
|
||||
>
|
||||
<form
|
||||
onSubmit={[Function]}
|
||||
|
@ -814,9 +912,16 @@ exports[`Query Copilot Feedback Modal snapshot test should submit submission 1`]
|
|||
<StyledTextFieldBase
|
||||
defaultValue="test query"
|
||||
label="Query generated"
|
||||
multiline={true}
|
||||
readOnly={true}
|
||||
rows={3}
|
||||
styles={
|
||||
Object {
|
||||
"fieldGroup": Object {
|
||||
"backgroundColor": "#F3F2F1",
|
||||
"borderColor": "#D1D1D1",
|
||||
"borderRadius": 4,
|
||||
},
|
||||
"root": Object {
|
||||
"marginBottom": 14,
|
||||
},
|
||||
|
|
|
@ -11,8 +11,8 @@ import {
|
|||
Link,
|
||||
MessageBar,
|
||||
MessageBarType,
|
||||
ProgressIndicator,
|
||||
Separator,
|
||||
Spinner,
|
||||
Stack,
|
||||
TeachingBubble,
|
||||
Text,
|
||||
|
@ -36,7 +36,6 @@ import { userContext } from "UserContext";
|
|||
import { useQueryCopilot } from "hooks/useQueryCopilot";
|
||||
import React, { useRef, useState } from "react";
|
||||
import HintIcon from "../../../images/Hint.svg";
|
||||
import CopilotIcon from "../../../images/QueryCopilotNewLogo.svg";
|
||||
import RecentIcon from "../../../images/Recent.svg";
|
||||
import errorIcon from "../../../images/close-black.svg";
|
||||
import * as TelemetryProcessor from "../../Shared/Telemetry/TelemetryProcessor";
|
||||
|
@ -215,12 +214,12 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
const generateSQLQueryResponse: GenerateSQLQueryResponse = await response?.json();
|
||||
if (response.ok) {
|
||||
if (generateSQLQueryResponse?.sql !== "N/A") {
|
||||
let query = `-- **Prompt:** ${userPrompt}\r\n`;
|
||||
if (generateSQLQueryResponse.explanation) {
|
||||
query += `-- **Explanation of query:** ${generateSQLQueryResponse.explanation}\r\n`;
|
||||
}
|
||||
query += generateSQLQueryResponse.sql;
|
||||
setQuery(query);
|
||||
const queryExplanation = `-- **Explanation of query:** ${
|
||||
generateSQLQueryResponse.explanation ? generateSQLQueryResponse.explanation : "N/A"
|
||||
}\r\n`;
|
||||
const currentGeneratedQuery = queryExplanation + generateSQLQueryResponse.sql;
|
||||
const lastQuery = generatedQuery && query ? `${query}\r\n` : "";
|
||||
setQuery(`${lastQuery}${currentGeneratedQuery}`);
|
||||
setGeneratedQuery(generateSQLQueryResponse.sql);
|
||||
setGeneratedQueryComments(generateSQLQueryResponse.explanation);
|
||||
setShowFeedbackBar(true);
|
||||
|
@ -310,29 +309,24 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
return (
|
||||
<Stack
|
||||
className="copilot-prompt-pane"
|
||||
styles={{ root: { backgroundColor: "#FAFAFA", padding: "16px 24px 0px" } }}
|
||||
styles={{ root: { backgroundColor: "#FAFAFA", padding: "8px" } }}
|
||||
id="copilot-textfield-label"
|
||||
>
|
||||
<Stack horizontal>
|
||||
<Image src={CopilotIcon} style={{ width: 24, height: 24 }} alt="Copilot" role="none" />
|
||||
<Text style={{ marginLeft: 8, fontWeight: 600, fontSize: 16 }}>Copilot</Text>
|
||||
<IconButton
|
||||
iconProps={{ imageProps: { src: errorIcon } }}
|
||||
onClick={() => {
|
||||
toggleCopilot(false);
|
||||
clearFeedback();
|
||||
resetMessageStates();
|
||||
}}
|
||||
<Stack
|
||||
horizontal
|
||||
styles={{
|
||||
root: {
|
||||
marginLeft: "auto !important",
|
||||
width: "100%",
|
||||
borderWidth: 1,
|
||||
borderStyle: "solid",
|
||||
borderColor: "#D1D1D1",
|
||||
borderRadius: 8,
|
||||
boxShadow: "0px 4px 8px 0px #00000024",
|
||||
},
|
||||
}}
|
||||
ariaLabel="Close"
|
||||
title="Close copilot"
|
||||
/>
|
||||
</Stack>
|
||||
<Stack horizontal verticalAlign="center">
|
||||
>
|
||||
<Stack style={{ width: "100%" }}>
|
||||
<Stack horizontal verticalAlign="center" style={{ padding: "8px 8px 0px 8px" }}>
|
||||
<TextField
|
||||
id="naturalLanguageInput"
|
||||
value={userPrompt}
|
||||
|
@ -348,11 +342,38 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
}
|
||||
}}
|
||||
style={{ lineHeight: 30 }}
|
||||
styles={{ root: { width: "95%" }, fieldGroup: { borderRadius: 6 } }}
|
||||
styles={{
|
||||
root: { width: "100%" },
|
||||
suffix: {
|
||||
background: "none",
|
||||
padding: 0,
|
||||
},
|
||||
fieldGroup: {
|
||||
borderRadius: 4,
|
||||
borderColor: "#D1D1D1",
|
||||
"::after": {
|
||||
border: "inherit",
|
||||
borderWidth: 2,
|
||||
borderBottomColor: "#464FEB",
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
}}
|
||||
disabled={isGeneratingQuery}
|
||||
autoComplete="off"
|
||||
placeholder="Ask a question in natural language and we’ll generate the query for you."
|
||||
aria-labelledby="copilot-textfield-label"
|
||||
onRenderSuffix={() => {
|
||||
return (
|
||||
<IconButton
|
||||
iconProps={{ iconName: "Send" }}
|
||||
disabled={isGeneratingQuery || !userPrompt.trim()}
|
||||
style={{ background: "none" }}
|
||||
onClick={() => startGenerateQueryProcess()}
|
||||
aria-label="Send"
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
{showPromptTeachingBubble && copilotTeachingBubbleVisible && (
|
||||
<TeachingBubble
|
||||
|
@ -377,16 +398,6 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
or write your own query
|
||||
</TeachingBubble>
|
||||
)}
|
||||
<IconButton
|
||||
iconProps={{ iconName: "Send" }}
|
||||
disabled={isGeneratingQuery || !userPrompt.trim()}
|
||||
style={{ marginLeft: 8 }}
|
||||
onClick={() => startGenerateQueryProcess()}
|
||||
aria-label="Send"
|
||||
/>
|
||||
<div role="alert" aria-label={getAriaLabel()}>
|
||||
{isGeneratingQuery && <Spinner style={{ marginLeft: 8 }} />}
|
||||
</div>
|
||||
{showSamplePrompts && (
|
||||
<Callout
|
||||
styles={{ root: { minWidth: 400, maxWidth: "70vw" } }}
|
||||
|
@ -488,8 +499,9 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
</Callout>
|
||||
)}
|
||||
</Stack>
|
||||
|
||||
<Stack style={{ margin: "8px 0" }}>
|
||||
{!isGeneratingQuery && (
|
||||
<Stack style={{ padding: 8 }}>
|
||||
{!showFeedbackBar && (
|
||||
<Text style={{ fontSize: 12 }}>
|
||||
AI-generated content can have mistakes. Make sure it's accurate and appropriate before using it.{" "}
|
||||
<Link href="https://aka.ms/cdb-copilot-preview-terms" target="_blank" style={{ color: "#0072D4" }}>
|
||||
|
@ -505,8 +517,8 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
messageBarType={MessageBarType.info}
|
||||
styles={{ root: { backgroundColor: "#F0F6FF" }, icon: { color: "#015CDA" } }}
|
||||
>
|
||||
We were unable to generate a query based upon the prompt provided. Please modify the prompt and try again.
|
||||
For examples of how to write a good prompt, please read
|
||||
We were unable to generate a query based upon the prompt provided. Please modify the prompt and
|
||||
try again. For examples of how to write a good prompt, please read
|
||||
<Link href="https://aka.ms/cdb-copilot-writing" target="_blank">
|
||||
this article.
|
||||
</Link>{" "}
|
||||
|
@ -517,21 +529,27 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
</MessageBar>
|
||||
)}
|
||||
</Text>
|
||||
</Stack>
|
||||
|
||||
)}
|
||||
{showFeedbackBar && (
|
||||
<Stack
|
||||
style={{ backgroundColor: "#FFF8F0", padding: "2px 8px", minHeight: 32 }}
|
||||
horizontal
|
||||
verticalAlign="center"
|
||||
>
|
||||
<Stack horizontal verticalAlign="center" style={{ maxHeight: 20 }}>
|
||||
{userContext.feedbackPolicies?.policyAllowFeedback && (
|
||||
<Stack horizontal verticalAlign="center">
|
||||
<Text style={{ fontWeight: 600, fontSize: 12 }}>Provide feedback on the query generated</Text>
|
||||
<Text style={{ fontSize: 12 }}>Provide feedback</Text>
|
||||
{showCallout && !hideFeedbackModalForLikedQueries && (
|
||||
<Callout
|
||||
role="status"
|
||||
style={{ padding: 8 }}
|
||||
style={{ padding: "6px 12px" }}
|
||||
styles={{
|
||||
root: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
beakCurtain: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
calloutMain: {
|
||||
borderRadius: 8,
|
||||
},
|
||||
}}
|
||||
target="#likeBtn"
|
||||
onDismiss={() => {
|
||||
setShowCallout(false);
|
||||
|
@ -565,7 +583,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
)}
|
||||
<IconButton
|
||||
id="likeBtn"
|
||||
style={{ marginLeft: 20 }}
|
||||
style={{ marginLeft: 10 }}
|
||||
aria-label="Like"
|
||||
role="toggle"
|
||||
iconProps={{ iconName: likeQuery === true ? "LikeSolid" : "Like" }}
|
||||
|
@ -584,7 +602,7 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
}}
|
||||
/>
|
||||
<IconButton
|
||||
style={{ margin: "0 10px" }}
|
||||
style={{ margin: "0 4px" }}
|
||||
role="toggle"
|
||||
aria-label="Dislike"
|
||||
iconProps={{ iconName: dislikeQuery === true ? "DislikeSolid" : "Dislike" }}
|
||||
|
@ -601,16 +619,30 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
}}
|
||||
/>
|
||||
<span role="status" style={{ position: "absolute", left: "-9999px" }} id="likeStatus"></span>
|
||||
<Separator vertical style={{ color: "#EDEBE9" }} />
|
||||
<Separator
|
||||
vertical
|
||||
styles={{
|
||||
root: {
|
||||
"::after": {
|
||||
backgroundColor: "#767676",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Stack>
|
||||
)}
|
||||
<CommandBarButton
|
||||
className="copyQuery"
|
||||
onClick={copyGeneratedCode}
|
||||
iconProps={{ iconName: "Copy" }}
|
||||
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
||||
style={{ fontSize: 12, transition: "background-color 0.3s ease", height: "100%" }}
|
||||
styles={{
|
||||
root: {
|
||||
backgroundColor: "inherit",
|
||||
},
|
||||
}}
|
||||
>
|
||||
Copy query
|
||||
Copy code
|
||||
</CommandBarButton>
|
||||
<CommandBarButton
|
||||
className="deleteQuery"
|
||||
|
@ -618,12 +650,58 @@ export const QueryCopilotPromptbar: React.FC<QueryCopilotPromptProps> = ({
|
|||
setShowDeletePopup(true);
|
||||
}}
|
||||
iconProps={{ iconName: "Delete" }}
|
||||
style={{ margin: "0 10px", backgroundColor: "#FFF8F0", transition: "background-color 0.3s ease" }}
|
||||
style={{ fontSize: 12, transition: "background-color 0.3s ease", height: "100%" }}
|
||||
styles={{
|
||||
root: {
|
||||
backgroundColor: "inherit",
|
||||
},
|
||||
}}
|
||||
>
|
||||
Delete query
|
||||
Clear editor
|
||||
</CommandBarButton>
|
||||
</Stack>
|
||||
)}
|
||||
</Stack>
|
||||
)}
|
||||
{isGeneratingQuery && (
|
||||
<ProgressIndicator
|
||||
label="Thinking..."
|
||||
ariaLabel={getAriaLabel()}
|
||||
barHeight={4}
|
||||
styles={{
|
||||
root: {
|
||||
fontSize: 12,
|
||||
width: "100%",
|
||||
bottom: 0,
|
||||
},
|
||||
itemName: {
|
||||
padding: "0px 8px",
|
||||
},
|
||||
itemProgress: {
|
||||
borderBottomLeftRadius: 8,
|
||||
borderBottomRightRadius: 8,
|
||||
padding: 0,
|
||||
},
|
||||
progressBar: {
|
||||
backgroundImage:
|
||||
"linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, rgb(24, 90, 189) 35%, rgb(71, 207, 250) 70%, rgb(180, 124, 248) 92%, rgba(0, 0, 0, 0))",
|
||||
animationDuration: "5s",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
<IconButton
|
||||
iconProps={{ imageProps: { src: errorIcon } }}
|
||||
onClick={() => {
|
||||
toggleCopilot(false);
|
||||
clearFeedback();
|
||||
resetMessageStates();
|
||||
}}
|
||||
ariaLabel="Close"
|
||||
title="Close copilot"
|
||||
/>
|
||||
</Stack>
|
||||
{isSamplePromptsOpen && <SamplePrompts sampleProps={sampleProps} />}
|
||||
{query !== "" && query.trim().length !== 0 && (
|
||||
<DeletePopup
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { useBoolean } from "@fluentui/react-hooks";
|
||||
import { userContext } from "UserContext";
|
||||
import { usePortalBackendEndpoint } from "Utils/EndpointUtils";
|
||||
import * as React from "react";
|
||||
import ConnectImage from "../../../../images/HdeConnectCosmosDB.svg";
|
||||
import ErrorImage from "../../../../images/error.svg";
|
||||
import { AuthType } from "../../../AuthType";
|
||||
import { HttpHeaders } from "../../../Common/Constants";
|
||||
import { BackendApi, HttpHeaders } from "../../../Common/Constants";
|
||||
import { configContext } from "../../../ConfigContext";
|
||||
import { GenerateTokenResponse } from "../../../Contracts/DataModels";
|
||||
import { isResourceTokenConnectionString } from "../Helpers/ResourceTokenUtils";
|
||||
|
@ -18,6 +19,23 @@ interface Props {
|
|||
}
|
||||
|
||||
export const fetchEncryptedToken = async (connectionString: string): Promise<string> => {
|
||||
if (!usePortalBackendEndpoint(BackendApi.GenerateToken)) {
|
||||
return await fetchEncryptedToken_ToBeDeprecated(connectionString);
|
||||
}
|
||||
|
||||
const headers = new Headers();
|
||||
headers.append(HttpHeaders.connectionString, connectionString);
|
||||
const url = configContext.PORTAL_BACKEND_ENDPOINT + "/api/connectionstring/token/generatetoken";
|
||||
const response = await fetch(url, { headers, method: "POST" });
|
||||
if (!response.ok) {
|
||||
throw response;
|
||||
}
|
||||
|
||||
const encryptedTokenResponse: string = await response.json();
|
||||
return decodeURIComponent(encryptedTokenResponse);
|
||||
};
|
||||
|
||||
export const fetchEncryptedToken_ToBeDeprecated = async (connectionString: string): Promise<string> => {
|
||||
const headers = new Headers();
|
||||
headers.append(HttpHeaders.connectionString, connectionString);
|
||||
const url = configContext.BACKEND_ENDPOINT + "/api/guest/tokens/generateToken";
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
import { CassandraProxyEndpoints, JunoEndpoints, MongoProxyEndpoints } from "Common/Constants";
|
||||
import {
|
||||
BackendApi,
|
||||
CassandraProxyEndpoints,
|
||||
JunoEndpoints,
|
||||
MongoProxyEndpoints,
|
||||
PortalBackendEndpoints,
|
||||
} from "Common/Constants";
|
||||
import { configContext } from "ConfigContext";
|
||||
import * as Logger from "../Common/Logger";
|
||||
|
||||
export function validateEndpoint(
|
||||
|
@ -137,3 +144,9 @@ export const allowedJunoOrigins: ReadonlyArray<string> = [
|
|||
];
|
||||
|
||||
export const allowedNotebookServerUrls: ReadonlyArray<string> = [];
|
||||
|
||||
export function usePortalBackendEndpoint(backendApi: BackendApi): boolean {
|
||||
const activePortalBackendEndpoints: string[] = [PortalBackendEndpoints.Development];
|
||||
const activeBackendApi: boolean = configContext.NEW_BACKEND_APIS?.includes(backendApi) || false;
|
||||
return activeBackendApi && activePortalBackendEndpoints.includes(configContext.PORTAL_BACKEND_ENDPOINT as string);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue