mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-05-04 07:24:52 +01:00
Merge branch 'master' into users/kcheekuri/updatePhoenixEndpoints
This commit is contained in:
commit
a9e1c2fba8
@ -2077,7 +2077,7 @@ a:link {
|
||||
.resourceTreeAndTabs {
|
||||
display: flex;
|
||||
flex: 1 1 auto;
|
||||
overflow-x: auto;
|
||||
overflow-x: clip;
|
||||
overflow-y: auto;
|
||||
height: 100%;
|
||||
}
|
||||
@ -2245,7 +2245,7 @@ a:link {
|
||||
}
|
||||
|
||||
.refreshColHeader {
|
||||
padding: 3px 6px 6px 6px;
|
||||
padding: 3px 6px 10px 0px !important;
|
||||
}
|
||||
|
||||
.refreshColHeader:hover {
|
||||
@ -2869,14 +2869,14 @@ a:link {
|
||||
}
|
||||
}
|
||||
|
||||
settings-pane {
|
||||
.settingsSection {
|
||||
.settingsSection {
|
||||
border-bottom: 1px solid @BaseMedium;
|
||||
margin-right: 24px;
|
||||
padding: @MediumSpace 0px;
|
||||
|
||||
&:first-child {
|
||||
padding-top: 0px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
@ -2889,12 +2889,12 @@ settings-pane {
|
||||
|
||||
.settingsSectionLabel {
|
||||
margin-bottom: @DefaultSpace;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.pageOptionsPart {
|
||||
padding-bottom: @MediumSpace;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove these styles once we refactor all buttons to use the command button component
|
||||
|
@ -412,3 +412,11 @@ export class TerminalQueryParams {
|
||||
public static readonly SubscriptionId = "subscriptionId";
|
||||
public static readonly TerminalEndpoint = "terminalEndpoint";
|
||||
}
|
||||
|
||||
export class JunoEndpoints {
|
||||
public static readonly Test = "https://juno-test.documents-dev.windows-int.net";
|
||||
public static readonly Test2 = "https://juno-test2.documents-dev.windows-int.net";
|
||||
public static readonly Test3 = "https://juno-test3.documents-dev.windows-int.net";
|
||||
public static readonly Prod = "https://tools.cosmos.azure.com";
|
||||
public static readonly Stage = "https://tools-staging.cosmos.azure.com";
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { JunoEndpoints } from "Common/Constants";
|
||||
|
||||
export enum Platform {
|
||||
Portal = "Portal",
|
||||
Hosted = "Hosted",
|
||||
@ -23,6 +25,7 @@ export interface ConfigContext {
|
||||
PROXY_PATH?: string;
|
||||
JUNO_ENDPOINT: string;
|
||||
GITHUB_CLIENT_ID: string;
|
||||
GITHUB_TEST_ENV_CLIENT_ID: string;
|
||||
GITHUB_CLIENT_SECRET?: string; // No need to inject secret for prod. Juno already knows it.
|
||||
IS_MPAC: boolean;
|
||||
hostedExplorerURL: string;
|
||||
@ -53,16 +56,17 @@ let configContext: Readonly<ConfigContext> = {
|
||||
GRAPH_API_VERSION: "1.6",
|
||||
ARCADIA_ENDPOINT: "https://workspaceartifacts.projectarcadia.net",
|
||||
ARCADIA_LIVY_ENDPOINT_DNS_ZONE: "dev.azuresynapse.net",
|
||||
GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/settings/applications/1189306
|
||||
GITHUB_CLIENT_ID: "6cb2f63cf6f7b5cbdeca", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1189306
|
||||
GITHUB_TEST_ENV_CLIENT_ID: "b63fc8cbf87fd3c6e2eb", // Registered OAuth app: https://github.com/organizations/AzureCosmosDBNotebooks/settings/applications/1777772
|
||||
IS_MPAC: false,
|
||||
JUNO_ENDPOINT: "https://tools.cosmos.azure.com",
|
||||
BACKEND_ENDPOINT: "https://main.documentdb.ext.azure.com",
|
||||
allowedJunoOrigins: [
|
||||
"https://juno-test.documents-dev.windows-int.net",
|
||||
"https://juno-test2.documents-dev.windows-int.net",
|
||||
"https://juno-test3.documents-dev.windows-int.net",
|
||||
"https://tools.cosmos.azure.com",
|
||||
"https://tools-staging.cosmos.azure.com",
|
||||
JunoEndpoints.Test,
|
||||
JunoEndpoints.Test2,
|
||||
JunoEndpoints.Test3,
|
||||
JunoEndpoints.Prod,
|
||||
JunoEndpoints.Stage,
|
||||
"https://localhost",
|
||||
],
|
||||
};
|
||||
@ -148,3 +152,4 @@ export async function initializeConfiguration(): Promise<ConfigContext> {
|
||||
}
|
||||
|
||||
export { configContext };
|
||||
|
||||
|
@ -7,7 +7,7 @@ import shallow from "zustand/shallow";
|
||||
import { AuthType } from "../AuthType";
|
||||
import { BindingHandlersRegisterer } from "../Bindings/BindingHandlersRegisterer";
|
||||
import * as Constants from "../Common/Constants";
|
||||
import { ConnectionStatusType, HttpStatusCodes, Notebook } from "../Common/Constants";
|
||||
import { Areas, ConnectionStatusType, HttpStatusCodes, Notebook } from "../Common/Constants";
|
||||
import { readCollection } from "../Common/dataAccess/readCollection";
|
||||
import { readDatabases } from "../Common/dataAccess/readDatabases";
|
||||
import { getErrorMessage, getErrorStack, handleError } from "../Common/ErrorHandlingUtils";
|
||||
@ -16,7 +16,6 @@ import { QueriesClient } from "../Common/QueriesClient";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
import {
|
||||
ContainerConnectionInfo,
|
||||
IContainerData,
|
||||
IPhoenixConnectionInfoResult,
|
||||
IProvisionData,
|
||||
IResponse,
|
||||
@ -377,28 +376,46 @@ export default class Explorer {
|
||||
};
|
||||
useNotebook.getState().setConnectionInfo(connectionStatus);
|
||||
try {
|
||||
TelemetryProcessor.traceStart(Action.PhoenixConnection, {
|
||||
dataExplorerArea: Areas.Notebook,
|
||||
});
|
||||
useNotebook.getState().setIsAllocating(true);
|
||||
const connectionInfo = await this.phoenixClient.allocateContainer(provisionData);
|
||||
if (connectionInfo.status !== HttpStatusCodes.OK) {
|
||||
throw new Error(`Received status code: ${connectionInfo?.status}`);
|
||||
}
|
||||
if (!connectionInfo?.data?.notebookServerUrl) {
|
||||
throw new Error(`NotebookServerUrl is invalid!`);
|
||||
}
|
||||
await this.setNotebookInfo(connectionInfo, connectionStatus);
|
||||
TelemetryProcessor.traceSuccess(Action.PhoenixConnection, {
|
||||
dataExplorerArea: Areas.Notebook,
|
||||
});
|
||||
} catch (error) {
|
||||
TelemetryProcessor.traceFailure(Action.PhoenixConnection, {
|
||||
dataExplorerArea: Areas.Notebook,
|
||||
error: getErrorMessage(error),
|
||||
errorStack: getErrorStack(error),
|
||||
});
|
||||
connectionStatus.status = ConnectionStatusType.Failed;
|
||||
useNotebook.getState().resetContainerConnection(connectionStatus);
|
||||
throw error;
|
||||
}
|
||||
} finally {
|
||||
useNotebook.getState().setIsAllocating(false);
|
||||
this.refreshCommandBarButtons();
|
||||
this.refreshNotebookList();
|
||||
|
||||
this._isInitializingNotebooks = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async setNotebookInfo(
|
||||
connectionInfo: IResponse<IPhoenixConnectionInfoResult>,
|
||||
connectionStatus: DataModels.ContainerConnectionInfo
|
||||
) {
|
||||
if (connectionInfo.status === HttpStatusCodes.OK && connectionInfo.data && connectionInfo.data.notebookServerUrl) {
|
||||
const containerData: IContainerData = {
|
||||
const containerData = {
|
||||
forwardingId: connectionInfo.data.forwardingId,
|
||||
dbAccountName: userContext.databaseAccount.name,
|
||||
};
|
||||
await this.phoenixClient.initiateContainerHeartBeat(containerData);
|
||||
|
||||
@ -412,11 +429,6 @@ export default class Explorer {
|
||||
this.notebookManager?.notebookClient
|
||||
.getMemoryUsage()
|
||||
.then((memoryUsageInfo) => useNotebook.getState().setMemoryUsageInfo(memoryUsageInfo));
|
||||
} else {
|
||||
connectionStatus.status = ConnectionStatusType.Failed;
|
||||
useNotebook.getState().resetContainerConnection(connectionStatus);
|
||||
}
|
||||
useNotebook.getState().setIsAllocating(false);
|
||||
}
|
||||
|
||||
public resetNotebookWorkspace(): void {
|
||||
@ -501,7 +513,9 @@ export default class Explorer {
|
||||
logConsoleError(error);
|
||||
return;
|
||||
}
|
||||
|
||||
TelemetryProcessor.traceStart(Action.PhoenixResetWorkspace, {
|
||||
dataExplorerArea: Areas.Notebook,
|
||||
});
|
||||
if (useNotebook.getState().isPhoenix) {
|
||||
useTabs.getState().closeAllNotebookTabs(true);
|
||||
connectionStatus = {
|
||||
@ -510,27 +524,24 @@ export default class Explorer {
|
||||
useNotebook.getState().setConnectionInfo(connectionStatus);
|
||||
}
|
||||
const connectionInfo = await this.notebookManager?.notebookClient.resetWorkspace();
|
||||
if (connectionInfo && connectionInfo.status && connectionInfo.status === HttpStatusCodes.OK) {
|
||||
if (useNotebook.getState().isPhoenix && connectionInfo.data && connectionInfo.data.notebookServerUrl) {
|
||||
if (connectionInfo?.status !== HttpStatusCodes.OK) {
|
||||
throw new Error(`Reset Workspace: Received status code- ${connectionInfo?.status}`);
|
||||
}
|
||||
if (!connectionInfo?.data?.notebookServerUrl) {
|
||||
throw new Error(`Reset Workspace: NotebookServerUrl is invalid!`);
|
||||
}
|
||||
if (useNotebook.getState().isPhoenix) {
|
||||
await this.setNotebookInfo(connectionInfo, connectionStatus);
|
||||
useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed);
|
||||
}
|
||||
logConsoleInfo("Successfully reset notebook workspace");
|
||||
TelemetryProcessor.traceSuccess(Action.ResetNotebookWorkspace);
|
||||
} else {
|
||||
logConsoleError(`Failed to reset notebook workspace`);
|
||||
TelemetryProcessor.traceFailure(Action.ResetNotebookWorkspace);
|
||||
if (useNotebook.getState().isPhoenix) {
|
||||
connectionStatus = {
|
||||
status: ConnectionStatusType.Reconnect,
|
||||
};
|
||||
useNotebook.getState().resetContainerConnection(connectionStatus);
|
||||
useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed);
|
||||
}
|
||||
}
|
||||
TelemetryProcessor.traceSuccess(Action.PhoenixResetWorkspace, {
|
||||
dataExplorerArea: Areas.Notebook,
|
||||
});
|
||||
} catch (error) {
|
||||
logConsoleError(`Failed to reset notebook workspace: ${error}`);
|
||||
TelemetryProcessor.traceFailure(Action.ResetNotebookWorkspace, {
|
||||
TelemetryProcessor.traceFailure(Action.PhoenixResetWorkspace, {
|
||||
dataExplorerArea: Areas.Notebook,
|
||||
error: getErrorMessage(error),
|
||||
errorStack: getErrorStack(error),
|
||||
});
|
||||
@ -538,7 +549,7 @@ export default class Explorer {
|
||||
connectionStatus = {
|
||||
status: ConnectionStatusType.Failed,
|
||||
};
|
||||
useNotebook.getState().setConnectionInfo(connectionStatus);
|
||||
useNotebook.getState().resetContainerConnection(connectionStatus);
|
||||
useNotebook.getState().setIsRefreshed(!useNotebook.getState().isRefreshed);
|
||||
}
|
||||
throw error;
|
||||
|
@ -23,10 +23,12 @@ import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneFor
|
||||
|
||||
export interface AddDatabasePaneProps {
|
||||
explorer: Explorer;
|
||||
buttonElement?: HTMLElement;
|
||||
}
|
||||
|
||||
export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
explorer: container,
|
||||
buttonElement,
|
||||
}: AddDatabasePaneProps) => {
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
let throughput: number;
|
||||
@ -78,6 +80,9 @@ export const AddDatabasePanel: FunctionComponent<AddDatabasePaneProps> = ({
|
||||
dataExplorerArea: Constants.Areas.ContextualPane,
|
||||
};
|
||||
TelemetryProcessor.trace(Action.CreateDatabase, ActionModifiers.Open, addDatabasePaneOpenMessage);
|
||||
if (buttonElement) {
|
||||
buttonElement.focus();
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onSubmit = () => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { IDropdownOption, IImageProps, Image, Stack, Text } from "@fluentui/react";
|
||||
import { useBoolean } from "@fluentui/react-hooks";
|
||||
import React, { FunctionComponent, useState } from "react";
|
||||
import React, { FunctionComponent, useRef, useState } from "react";
|
||||
import AddPropertyIcon from "../../../../images/Add-property.svg";
|
||||
import { useSidePanel } from "../../../hooks/useSidePanel";
|
||||
import { logConsoleError } from "../../../Utils/NotificationConsoleUtils";
|
||||
@ -25,19 +25,16 @@ interface UnwrappedExecuteSprocParam {
|
||||
export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPaneProps> = ({
|
||||
storedProcedure,
|
||||
}: ExecuteSprocParamsPaneProps): JSX.Element => {
|
||||
const paramKeyValuesRef = useRef<UnwrappedExecuteSprocParam[]>([{ key: "string", text: "" }]);
|
||||
const partitionValueRef = useRef<string>();
|
||||
const partitionKeyRef = useRef<string>("string");
|
||||
const closeSidePanel = useSidePanel((state) => state.closeSidePanel);
|
||||
const [numberOfParams, setNumberOfParams] = useState<number>(1);
|
||||
const [isLoading, { setTrue: setLoadingTrue, setFalse: setLoadingFalse }] = useBoolean(false);
|
||||
const [paramKeyValues, setParamKeyValues] = useState<UnwrappedExecuteSprocParam[]>([{ key: "string", text: "" }]);
|
||||
const [partitionValue, setPartitionValue] = useState<string>(); // Defaulting to undefined here is important. It is not the same partition key as ""
|
||||
const [selectedKey, setSelectedKey] = React.useState<IDropdownOption>({ key: "string", text: "" });
|
||||
const [formError, setFormError] = useState<string>("");
|
||||
|
||||
const onPartitionKeyChange = (event: React.FormEvent<HTMLDivElement>, item: IDropdownOption): void => {
|
||||
setSelectedKey(item);
|
||||
};
|
||||
|
||||
const validateUnwrappedParams = (): boolean => {
|
||||
const unwrappedParams: UnwrappedExecuteSprocParam[] = paramKeyValues;
|
||||
const unwrappedParams: UnwrappedExecuteSprocParam[] = paramKeyValuesRef.current;
|
||||
for (let i = 0; i < unwrappedParams.length; i++) {
|
||||
const { key: paramType, text: paramValue } = unwrappedParams[i];
|
||||
if (paramType === "custom" && (paramValue === "" || paramValue === undefined)) {
|
||||
@ -53,8 +50,9 @@ export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPanePro
|
||||
};
|
||||
|
||||
const submit = (): void => {
|
||||
const wrappedSprocParams: UnwrappedExecuteSprocParam[] = paramKeyValues;
|
||||
const { key: partitionKey } = selectedKey;
|
||||
const wrappedSprocParams: UnwrappedExecuteSprocParam[] = paramKeyValuesRef.current;
|
||||
const partitionValue: string = partitionValueRef.current;
|
||||
const partitionKey: string = partitionKeyRef.current;
|
||||
if (partitionKey === "custom" && (partitionValue === "" || partitionValue === undefined)) {
|
||||
setInvalidParamError(partitionValue);
|
||||
return;
|
||||
@ -78,37 +76,21 @@ export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPanePro
|
||||
};
|
||||
|
||||
const deleteParamAtIndex = (indexToRemove: number): void => {
|
||||
const cloneParamKeyValue = [...paramKeyValues];
|
||||
cloneParamKeyValue.splice(indexToRemove, 1);
|
||||
setParamKeyValues(cloneParamKeyValue);
|
||||
paramKeyValuesRef.current.splice(indexToRemove, 1);
|
||||
setNumberOfParams(numberOfParams - 1);
|
||||
};
|
||||
|
||||
const addNewParamAtIndex = (indexToAdd: number): void => {
|
||||
const cloneParamKeyValue = [...paramKeyValues];
|
||||
cloneParamKeyValue.splice(indexToAdd, 0, { key: "string", text: "" });
|
||||
setParamKeyValues(cloneParamKeyValue);
|
||||
};
|
||||
|
||||
const paramValueChange = (value: string, indexOfInput: number): void => {
|
||||
const cloneParamKeyValue = [...paramKeyValues];
|
||||
cloneParamKeyValue[indexOfInput].text = value;
|
||||
setParamKeyValues(cloneParamKeyValue);
|
||||
};
|
||||
|
||||
const paramKeyChange = (
|
||||
_event: React.FormEvent<HTMLDivElement>,
|
||||
selectedParam: IDropdownOption,
|
||||
indexOfParam: number
|
||||
): void => {
|
||||
const cloneParamKeyValue = [...paramKeyValues];
|
||||
cloneParamKeyValue[indexOfParam].key = selectedParam.key.toString();
|
||||
setParamKeyValues(cloneParamKeyValue);
|
||||
paramKeyValuesRef.current.splice(indexToAdd, 0, { key: "string", text: "" });
|
||||
setNumberOfParams(numberOfParams + 1);
|
||||
};
|
||||
|
||||
const addNewParamAtLastIndex = (): void => {
|
||||
const cloneParamKeyValue = [...paramKeyValues];
|
||||
cloneParamKeyValue.splice(cloneParamKeyValue.length, 0, { key: "string", text: "" });
|
||||
setParamKeyValues(cloneParamKeyValue);
|
||||
paramKeyValuesRef.current.push({
|
||||
key: "string",
|
||||
text: "",
|
||||
});
|
||||
setNumberOfParams(numberOfParams + 1);
|
||||
};
|
||||
|
||||
const props: RightPaneFormProps = {
|
||||
@ -118,47 +100,53 @@ export const ExecuteSprocParamsPane: FunctionComponent<ExecuteSprocParamsPanePro
|
||||
onSubmit: () => submit(),
|
||||
};
|
||||
|
||||
const getInputParameterComponent = (): JSX.Element[] => {
|
||||
const inputParameters: JSX.Element[] = [];
|
||||
for (let i = 0; i < numberOfParams; i++) {
|
||||
const paramKeyValue = paramKeyValuesRef.current[i];
|
||||
inputParameters.push(
|
||||
<InputParameter
|
||||
key={paramKeyValue.text + i}
|
||||
dropdownLabel={i === 0 ? "Key" : ""}
|
||||
inputParameterTitle={i === 0 ? "Enter input parameters (if any)" : ""}
|
||||
inputLabel={i === 0 ? "Param" : ""}
|
||||
isAddRemoveVisible={true}
|
||||
onDeleteParamKeyPress={() => deleteParamAtIndex(i)}
|
||||
onAddNewParamKeyPress={() => addNewParamAtIndex(i + 1)}
|
||||
onParamValueChange={(_event, newInput?: string) => (paramKeyValuesRef.current[i].text = newInput)}
|
||||
onParamKeyChange={(_event, selectedParam: IDropdownOption) =>
|
||||
(paramKeyValuesRef.current[i].key = selectedParam.key.toString())
|
||||
}
|
||||
paramValue={paramKeyValue.text}
|
||||
selectedKey={paramKeyValue.key}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return inputParameters;
|
||||
};
|
||||
|
||||
return (
|
||||
<RightPaneForm {...props}>
|
||||
<div className="panelFormWrapper">
|
||||
<div className="panelMainContent">
|
||||
<InputParameter
|
||||
dropdownLabel="Key"
|
||||
inputParameterTitle="Partition key value"
|
||||
inputLabel="Value"
|
||||
isAddRemoveVisible={false}
|
||||
onParamValueChange={(_event, newInput?: string) => {
|
||||
setPartitionValue(newInput);
|
||||
}}
|
||||
onParamKeyChange={onPartitionKeyChange}
|
||||
paramValue={partitionValue}
|
||||
selectedKey={selectedKey.key}
|
||||
onParamValueChange={(_event, newInput?: string) => (partitionValueRef.current = newInput)}
|
||||
onParamKeyChange={(_event: React.FormEvent<HTMLDivElement>, item: IDropdownOption) =>
|
||||
(partitionKeyRef.current = item.key.toString())
|
||||
}
|
||||
paramValue={partitionValueRef.current}
|
||||
selectedKey={partitionKeyRef.current}
|
||||
/>
|
||||
{paramKeyValues.map((paramKeyValue, index) => (
|
||||
<InputParameter
|
||||
key={paramKeyValue && paramKeyValue.text + index}
|
||||
dropdownLabel={!index && "Key"}
|
||||
inputParameterTitle={!index && "Enter input parameters (if any)"}
|
||||
inputLabel={!index && "Param"}
|
||||
isAddRemoveVisible={true}
|
||||
onDeleteParamKeyPress={() => deleteParamAtIndex(index)}
|
||||
onAddNewParamKeyPress={() => addNewParamAtIndex(index + 1)}
|
||||
onParamValueChange={(event, newInput?: string) => {
|
||||
paramValueChange(newInput, index);
|
||||
}}
|
||||
onParamKeyChange={(event: React.FormEvent<HTMLDivElement>, selectedParam: IDropdownOption) => {
|
||||
paramKeyChange(event, selectedParam, index);
|
||||
}}
|
||||
paramValue={paramKeyValue && paramKeyValue.text}
|
||||
selectedKey={paramKeyValue && paramKeyValue.key}
|
||||
/>
|
||||
))}
|
||||
<Stack horizontal onClick={addNewParamAtLastIndex} tabIndex={0}>
|
||||
{getInputParameterComponent()}
|
||||
<Stack horizontal onClick={() => addNewParamAtLastIndex()} tabIndex={0}>
|
||||
<Image {...imageProps} src={AddPropertyIcon} alt="Add param" />
|
||||
<Text className="addNewParamStyle">Add New Param</Text>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
</RightPaneForm>
|
||||
);
|
||||
};
|
||||
|
@ -55,7 +55,7 @@ export const InputParameter: FunctionComponent<InputParameterProps> = ({
|
||||
<Stack horizontal>
|
||||
<Dropdown
|
||||
label={dropdownLabel && dropdownLabel}
|
||||
selectedKey={selectedKey}
|
||||
defaultSelectedKey={selectedKey}
|
||||
onChange={onParamKeyChange}
|
||||
options={options}
|
||||
styles={dropdownStyles}
|
||||
@ -64,8 +64,9 @@ export const InputParameter: FunctionComponent<InputParameterProps> = ({
|
||||
<TextField
|
||||
label={inputLabel && inputLabel}
|
||||
id="confirmCollectionId"
|
||||
value={paramValue}
|
||||
defaultValue={paramValue}
|
||||
onChange={onParamValueChange}
|
||||
tabIndex={0}
|
||||
/>
|
||||
{isAddRemoveVisible && (
|
||||
<>
|
||||
|
@ -15,9 +15,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
<form
|
||||
className="panelFormWrapper"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div
|
||||
className="panelFormWrapper"
|
||||
>
|
||||
<div
|
||||
className="panelMainContent"
|
||||
@ -322,6 +319,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
className="ms-Stack css-54"
|
||||
>
|
||||
<Dropdown
|
||||
defaultSelectedKey="string"
|
||||
key=".0:$.0"
|
||||
label="Key"
|
||||
onChange={[Function]}
|
||||
@ -337,7 +335,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedKey="string"
|
||||
styles={
|
||||
Object {
|
||||
"dropdown": Object {
|
||||
@ -348,6 +345,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
tabIndex={0}
|
||||
>
|
||||
<DropdownBase
|
||||
defaultSelectedKey="string"
|
||||
label="Key"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
@ -362,7 +360,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedKey="string"
|
||||
styles={[Function]}
|
||||
tabIndex={0}
|
||||
theme={
|
||||
@ -640,6 +637,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
}
|
||||
>
|
||||
<DropdownInternal
|
||||
defaultSelectedKey="string"
|
||||
hoisted={
|
||||
Object {
|
||||
"rootRef": [Function],
|
||||
@ -664,7 +662,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
]
|
||||
}
|
||||
responsiveMode={3}
|
||||
selectedKey="string"
|
||||
styles={[Function]}
|
||||
tabIndex={0}
|
||||
theme={
|
||||
@ -1569,6 +1566,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
key=".0:$.1"
|
||||
label="Value"
|
||||
onChange={[Function]}
|
||||
tabIndex={0}
|
||||
>
|
||||
<TextFieldBase
|
||||
deferredValidationTime={200}
|
||||
@ -1577,6 +1575,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
onChange={[Function]}
|
||||
resizable={true}
|
||||
styles={[Function]}
|
||||
tabIndex={0}
|
||||
theme={
|
||||
Object {
|
||||
"disableGlobalClassNames": false,
|
||||
@ -2162,6 +2161,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
tabIndex={0}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -2477,6 +2477,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
className="ms-Stack css-54"
|
||||
>
|
||||
<Dropdown
|
||||
defaultSelectedKey="string"
|
||||
key=".0:$.0"
|
||||
label="Key"
|
||||
onChange={[Function]}
|
||||
@ -2492,7 +2493,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedKey="string"
|
||||
styles={
|
||||
Object {
|
||||
"dropdown": Object {
|
||||
@ -2503,6 +2503,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
tabIndex={0}
|
||||
>
|
||||
<DropdownBase
|
||||
defaultSelectedKey="string"
|
||||
label="Key"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
@ -2517,7 +2518,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
},
|
||||
]
|
||||
}
|
||||
selectedKey="string"
|
||||
styles={[Function]}
|
||||
tabIndex={0}
|
||||
theme={
|
||||
@ -2795,6 +2795,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
}
|
||||
>
|
||||
<DropdownInternal
|
||||
defaultSelectedKey="string"
|
||||
hoisted={
|
||||
Object {
|
||||
"rootRef": [Function],
|
||||
@ -2819,7 +2820,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
]
|
||||
}
|
||||
responsiveMode={3}
|
||||
selectedKey="string"
|
||||
styles={[Function]}
|
||||
tabIndex={0}
|
||||
theme={
|
||||
@ -3720,19 +3720,22 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
</DropdownBase>
|
||||
</Dropdown>
|
||||
<StyledTextFieldBase
|
||||
defaultValue=""
|
||||
id="confirmCollectionId"
|
||||
key=".0:$.1"
|
||||
label="Param"
|
||||
onChange={[Function]}
|
||||
value=""
|
||||
tabIndex={0}
|
||||
>
|
||||
<TextFieldBase
|
||||
defaultValue=""
|
||||
deferredValidationTime={200}
|
||||
id="confirmCollectionId"
|
||||
label="Param"
|
||||
onChange={[Function]}
|
||||
resizable={true}
|
||||
styles={[Function]}
|
||||
tabIndex={0}
|
||||
theme={
|
||||
Object {
|
||||
"disableGlobalClassNames": false,
|
||||
@ -4007,7 +4010,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
}
|
||||
}
|
||||
validateOnLoad={true}
|
||||
value=""
|
||||
>
|
||||
<div
|
||||
className="ms-TextField root-75"
|
||||
@ -4319,6 +4321,7 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
onChange={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
tabIndex={0}
|
||||
type="text"
|
||||
value=""
|
||||
/>
|
||||
@ -5302,7 +5305,6 @@ exports[`Excute Sproc Param Pane should render Default properly 1`] = `
|
||||
</div>
|
||||
</Stack>
|
||||
</div>
|
||||
</div>
|
||||
<PanelFooterComponent
|
||||
buttonLabel="Execute"
|
||||
isButtonDisabled={false}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton } from "@fluentui/react";
|
||||
import { Checkbox, ChoiceGroup, IChoiceGroupOption, SpinButton, Stack, Text } from "@fluentui/react";
|
||||
import * as Constants from "Common/Constants";
|
||||
import { InfoTooltip } from "Common/Tooltip/InfoTooltip";
|
||||
import { configContext } from "ConfigContext";
|
||||
@ -113,20 +113,44 @@ export const SettingsPane: FunctionComponent = () => {
|
||||
const handleOnPageOptionChange = (ev: React.FormEvent<HTMLInputElement>, option: IChoiceGroupOption): void => {
|
||||
setPageOption(option.key);
|
||||
};
|
||||
|
||||
const choiceButtonStyles = {
|
||||
flexContainer: [
|
||||
{
|
||||
selectors: {
|
||||
".ms-ChoiceField-wrapper label": {
|
||||
fontSize: 12,
|
||||
paddingTop: 0,
|
||||
},
|
||||
".ms-ChoiceField": {
|
||||
marginTop: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
return (
|
||||
<RightPaneForm {...genericPaneProps}>
|
||||
<div className="paneMainContent">
|
||||
{shouldShowQueryPageOptions && (
|
||||
<div className="settingsSection">
|
||||
<div className="settingsSectionPart pageOptionsPart">
|
||||
<div className="settingsSectionLabel">
|
||||
<div className="settingsSectionPart">
|
||||
<Stack horizontal>
|
||||
<Text id="pageOptions" className="settingsSectionLabel" variant="small">
|
||||
Page options
|
||||
</Text>
|
||||
<InfoTooltip>
|
||||
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many
|
||||
query results per page.
|
||||
</InfoTooltip>
|
||||
</div>
|
||||
<ChoiceGroup selectedKey={pageOption} options={pageOptionList} onChange={handleOnPageOptionChange} />
|
||||
</Stack>
|
||||
<ChoiceGroup
|
||||
ariaLabelledBy="pageOptions"
|
||||
selectedKey={pageOption}
|
||||
options={pageOptionList}
|
||||
styles={choiceButtonStyles}
|
||||
onChange={handleOnPageOptionChange}
|
||||
/>
|
||||
</div>
|
||||
<div className="tabs settingsSectionPart">
|
||||
{isCustomPageOptionSelected() && (
|
||||
|
@ -14,17 +14,24 @@ exports[`Settings Pane should render Default properly 1`] = `
|
||||
className="settingsSection"
|
||||
>
|
||||
<div
|
||||
className="settingsSectionPart pageOptionsPart"
|
||||
className="settingsSectionPart"
|
||||
>
|
||||
<div
|
||||
<Stack
|
||||
horizontal={true}
|
||||
>
|
||||
<Text
|
||||
className="settingsSectionLabel"
|
||||
id="pageOptions"
|
||||
variant="small"
|
||||
>
|
||||
Page options
|
||||
</Text>
|
||||
<InfoTooltip>
|
||||
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many query results per page.
|
||||
</InfoTooltip>
|
||||
</div>
|
||||
</Stack>
|
||||
<StyledChoiceGroup
|
||||
ariaLabelledBy="pageOptions"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
Array [
|
||||
@ -39,6 +46,23 @@ exports[`Settings Pane should render Default properly 1`] = `
|
||||
]
|
||||
}
|
||||
selectedKey="custom"
|
||||
styles={
|
||||
Object {
|
||||
"flexContainer": Array [
|
||||
Object {
|
||||
"selectors": Object {
|
||||
".ms-ChoiceField": Object {
|
||||
"marginTop": 0,
|
||||
},
|
||||
".ms-ChoiceField-wrapper label": Object {
|
||||
"fontSize": 12,
|
||||
"paddingTop": 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
|
@ -33,6 +33,7 @@ const {
|
||||
Inet,
|
||||
Smallint,
|
||||
Tinyint,
|
||||
Timestamp,
|
||||
} = TableConstants.CassandraType;
|
||||
export const cassandraOptions = [
|
||||
{ key: Text, text: Text },
|
||||
@ -50,6 +51,7 @@ export const cassandraOptions = [
|
||||
{ key: Inet, text: Inet },
|
||||
{ key: Smallint, text: Smallint },
|
||||
{ key: Tinyint, text: Tinyint },
|
||||
{ key: Timestamp, text: Timestamp },
|
||||
];
|
||||
|
||||
export const imageProps: IImageProps = {
|
||||
|
@ -314,7 +314,10 @@ export class SplashScreen extends React.Component<SplashScreenProps> {
|
||||
}
|
||||
useSidePanel
|
||||
.getState()
|
||||
.openSidePanel("New " + getDatabaseName(), <AddDatabasePanel explorer={this.container} />);
|
||||
.openSidePanel(
|
||||
"New " + getDatabaseName(),
|
||||
<AddDatabasePanel explorer={this.container} buttonElement={document.activeElement as HTMLElement} />
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ export const CassandraType = {
|
||||
Float: "Float",
|
||||
Int: "Int",
|
||||
Text: "Text",
|
||||
Timestamp: "Timestamp",
|
||||
Uuid: "Uuid",
|
||||
Varchar: "Varchar",
|
||||
Varint: "Varint",
|
||||
|
@ -431,7 +431,7 @@ export default class TableEntityListViewModel extends DataTableViewModel {
|
||||
if (newHeaders.length > 0) {
|
||||
// Any new columns found will be added into headers array, which will trigger a re-render of the DataTable.
|
||||
// So there is no need to call it here.
|
||||
this.updateHeaders(newHeaders, /* notifyColumnChanges */ true);
|
||||
this.updateHeaders(selectedHeadersUnion, /* notifyColumnChanges */ true);
|
||||
} else {
|
||||
if (columnSortOrder) {
|
||||
this.sortColumns(columnSortOrder, oSettings);
|
||||
|
@ -535,7 +535,8 @@ export class CassandraAPIDataClient extends TableDataClient {
|
||||
dataType === TableConstants.CassandraType.Text ||
|
||||
dataType === TableConstants.CassandraType.Inet ||
|
||||
dataType === TableConstants.CassandraType.Ascii ||
|
||||
dataType === TableConstants.CassandraType.Varchar
|
||||
dataType === TableConstants.CassandraType.Varchar ||
|
||||
dataType === TableConstants.CassandraType.Timestamp
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
import ko from "knockout";
|
||||
import postRobot from "post-robot";
|
||||
import { GetGithubClientId } from "Utils/GitHubUtils";
|
||||
import { HttpStatusCodes } from "../Common/Constants";
|
||||
import { handleError } from "../Common/ErrorHandlingUtils";
|
||||
import { configContext } from "../ConfigContext";
|
||||
import { AuthorizeAccessComponent } from "../Explorer/Controls/GitHub/AuthorizeAccessComponent";
|
||||
import { JunoClient } from "../Juno/JunoClient";
|
||||
import { logConsoleInfo } from "../Utils/NotificationConsoleUtils";
|
||||
@ -55,7 +55,7 @@ export class GitHubOAuthService {
|
||||
|
||||
const params = {
|
||||
scope,
|
||||
client_id: configContext.GITHUB_CLIENT_ID,
|
||||
client_id: GetGithubClientId(),
|
||||
redirect_uri: new URL("./connectToGitHub.html", window.location.href).href,
|
||||
state: this.resetState(),
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import ko from "knockout";
|
||||
import { GetGithubClientId } from "Utils/GitHubUtils";
|
||||
import { HttpHeaders, HttpStatusCodes } from "../Common/Constants";
|
||||
import { configContext } from "../ConfigContext";
|
||||
import * as DataModels from "../Contracts/DataModels";
|
||||
@ -522,7 +523,7 @@ export class JunoClient {
|
||||
|
||||
private static getGitHubClientParams(): URLSearchParams {
|
||||
const githubParams = new URLSearchParams({
|
||||
client_id: configContext.GITHUB_CLIENT_ID,
|
||||
client_id: GetGithubClientId(),
|
||||
});
|
||||
|
||||
if (configContext.GITHUB_CLIENT_SECRET) {
|
||||
|
@ -50,7 +50,6 @@ export enum Action {
|
||||
SubscriptionSwitch,
|
||||
TenantSwitch,
|
||||
DefaultTenantSwitch,
|
||||
ResetNotebookWorkspace,
|
||||
CreateNotebookWorkspace,
|
||||
NotebookErrorNotification,
|
||||
CreateSparkCluster,
|
||||
@ -82,6 +81,8 @@ export enum Action {
|
||||
NotebooksInsertTextCellBelowFromMenu,
|
||||
NotebooksMoveCellUpFromMenu,
|
||||
NotebooksMoveCellDownFromMenu,
|
||||
PhoenixConnection,
|
||||
PhoenixResetWorkspace,
|
||||
DeleteCellFromMenu,
|
||||
OpenTerminal,
|
||||
CreateMongoCollectionWithWildcardIndex,
|
||||
|
@ -1,4 +1,9 @@
|
||||
// https://github.com/<owner>/<repo>/tree/<branch>
|
||||
|
||||
import { JunoEndpoints } from "Common/Constants";
|
||||
import { configContext } from "ConfigContext";
|
||||
import { userContext } from "UserContext";
|
||||
|
||||
// The url when users visit a repo/branch on github.com
|
||||
export const RepoUriPattern = /https:\/\/github.com\/([^/]*)\/([^/]*)\/tree\/([^?]*)/;
|
||||
|
||||
@ -60,3 +65,15 @@ export function toContentUri(owner: string, repo: string, branch: string, path:
|
||||
export function toRawContentUri(owner: string, repo: string, branch: string, path: string): string {
|
||||
return `https://raw.githubusercontent.com/${owner}/${repo}/${branch}/${path}`;
|
||||
}
|
||||
|
||||
export function GetGithubClientId(): string {
|
||||
const junoEndpoint = userContext.features.junoEndpoint ?? configContext.JUNO_ENDPOINT;
|
||||
if (
|
||||
junoEndpoint === JunoEndpoints.Test ||
|
||||
junoEndpoint === JunoEndpoints.Test2 ||
|
||||
junoEndpoint === JunoEndpoints.Test3
|
||||
) {
|
||||
return configContext.GITHUB_TEST_ENV_CLIENT_ID;
|
||||
}
|
||||
return configContext.GITHUB_CLIENT_ID;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user