import { AuthError as msalAuthError, BrowserAuthErrorMessage as msalBrowserAuthErrorMessage, } from "@azure/msal-browser"; import { Checkbox, ChoiceGroup, DefaultButton, Dropdown, IChoiceGroupOption, IDropdownOption, ISpinButtonStyles, IToggleStyles, Position, SpinButton, Toggle, } from "@fluentui/react"; import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, makeStyles } from "@fluentui/react-components"; import { AuthType } from "AuthType"; import * as Constants from "Common/Constants"; import { SplitterDirection } from "Common/Splitter"; import { InfoTooltip } from "Common/Tooltip/InfoTooltip"; import { Platform, configContext } from "ConfigContext"; import { useDialog } from "Explorer/Controls/Dialog"; import { useDatabases } from "Explorer/useDatabases"; import { isFabric, isFabricNative } from "Platform/Fabric/FabricUtil"; import { AppStateComponentNames, deleteAllStates, deleteState, hasState, loadState, saveState, } from "Shared/AppStatePersistenceUtility"; import { DefaultRUThreshold, LocalStorageUtility, StorageKey, getDefaultQueryResultsView, getRUThreshold, ruThresholdEnabled as isRUThresholdEnabled, } from "Shared/StorageUtility"; import * as StringUtility from "Shared/StringUtility"; import { updateUserContext, userContext } from "UserContext"; import { isDataplaneRbacSupported } from "Utils/APITypeUtils"; import { acquireMsalTokenForAccount } from "Utils/AuthorizationUtils"; import { logConsoleError, logConsoleInfo } from "Utils/NotificationConsoleUtils"; import * as PriorityBasedExecutionUtils from "Utils/PriorityBasedExecutionUtils"; import { getReadOnlyKeys, listKeys } from "Utils/arm/generatedClients/cosmos/databaseAccounts"; import { useClientWriteEnabled } from "hooks/useClientWriteEnabled"; import { useQueryCopilot } from "hooks/useQueryCopilot"; import { useSidePanel } from "hooks/useSidePanel"; import React, { FunctionComponent, useState } from "react"; import create, { UseStore } from "zustand"; import Explorer from "../../Explorer"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; export interface DataPlaneRbacState { dataPlaneRbacEnabled: boolean; aadTokenUpdated: boolean; getState?: () => DataPlaneRbacState; setDataPlaneRbacEnabled: (dataPlaneRbacEnabled: boolean) => void; setAadDataPlaneUpdated: (aadTokenUpdated: boolean) => void; } type DataPlaneRbacStore = UseStore>; const useStyles = makeStyles({ bulletList: { listStyleType: "disc", paddingLeft: "20px", }, container: { display: "flex", flexDirection: "column", height: "100%", }, firstItem: { flex: "1", }, header: { marginRight: "5px", }, headerIcon: { paddingTop: "4px", cursor: "pointer", }, settingsSectionContainer: { paddingLeft: "15px", }, settingsSectionDescription: { paddingBottom: "10px", fontSize: "12px", }, subHeader: { marginRight: "5px", fontSize: "12px", }, }); export const useDataPlaneRbac: DataPlaneRbacStore = create(() => ({ dataPlaneRbacEnabled: false, })); export const SettingsPane: FunctionComponent<{ explorer: Explorer }> = ({ explorer, }: { explorer: Explorer; }): JSX.Element => { const closeSidePanel = useSidePanel((state) => state.closeSidePanel); const [isExecuting, setIsExecuting] = useState(false); const [refreshExplorer, setRefreshExplorer] = useState(false); const [pageOption, setPageOption] = useState( LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) === Constants.Queries.unlimitedItemsPerPage ? Constants.Queries.UnlimitedPageOption : Constants.Queries.CustomPageOption, ); const [enableDataPlaneRBACOption, setEnableDataPlaneRBACOption] = useState( LocalStorageUtility.hasItem(StorageKey.DataPlaneRbacEnabled) ? LocalStorageUtility.getEntryString(StorageKey.DataPlaneRbacEnabled) : Constants.RBACOptions.setAutomaticRBACOption, ); const [ruThresholdEnabled, setRUThresholdEnabled] = useState(isRUThresholdEnabled()); const [ruThreshold, setRUThreshold] = useState(getRUThreshold()); const [queryTimeoutEnabled, setQueryTimeoutEnabled] = useState( LocalStorageUtility.getEntryBoolean(StorageKey.QueryTimeoutEnabled), ); const [queryTimeout, setQueryTimeout] = useState(LocalStorageUtility.getEntryNumber(StorageKey.QueryTimeout)); const [defaultQueryResultsView, setDefaultQueryResultsView] = useState( getDefaultQueryResultsView(), ); const [automaticallyCancelQueryAfterTimeout, setAutomaticallyCancelQueryAfterTimeout] = useState( LocalStorageUtility.getEntryBoolean(StorageKey.AutomaticallyCancelQueryAfterTimeout), ); const [customItemPerPage, setCustomItemPerPage] = useState( LocalStorageUtility.getEntryNumber(StorageKey.CustomItemPerPage) || 0, ); const [containerPaginationEnabled, setContainerPaginationEnabled] = useState( LocalStorageUtility.hasItem(StorageKey.ContainerPaginationEnabled) ? LocalStorageUtility.getEntryString(StorageKey.ContainerPaginationEnabled) === "true" : false, ); const [crossPartitionQueryEnabled, setCrossPartitionQueryEnabled] = useState( LocalStorageUtility.hasItem(StorageKey.IsCrossPartitionQueryEnabled) ? LocalStorageUtility.getEntryString(StorageKey.IsCrossPartitionQueryEnabled) === "true" : false, ); const [graphAutoVizDisabled, setGraphAutoVizDisabled] = useState( LocalStorageUtility.hasItem(StorageKey.IsGraphAutoVizDisabled) ? LocalStorageUtility.getEntryString(StorageKey.IsGraphAutoVizDisabled) : "false", ); const [selectedRegionalEndpoint, setSelectedRegionalEndpoint] = useState( hasState({ componentName: AppStateComponentNames.SelectedRegionalEndpoint, globalAccountName: userContext.databaseAccount?.name, }) ? (loadState({ componentName: AppStateComponentNames.SelectedRegionalEndpoint, globalAccountName: userContext.databaseAccount?.name, }) as string) : undefined, ); const [retryAttempts, setRetryAttempts] = useState( LocalStorageUtility.hasItem(StorageKey.RetryAttempts) ? LocalStorageUtility.getEntryNumber(StorageKey.RetryAttempts) : Constants.Queries.DefaultRetryAttempts, ); const [retryInterval, setRetryInterval] = useState( LocalStorageUtility.hasItem(StorageKey.RetryInterval) ? LocalStorageUtility.getEntryNumber(StorageKey.RetryInterval) : Constants.Queries.DefaultRetryIntervalInMs, ); const [MaxWaitTimeInSeconds, setMaxWaitTimeInSeconds] = useState( LocalStorageUtility.hasItem(StorageKey.MaxWaitTimeInSeconds) ? LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds) : Constants.Queries.DefaultMaxWaitTimeInSeconds, ); const [maxDegreeOfParallelism, setMaxDegreeOfParallelism] = useState( LocalStorageUtility.hasItem(StorageKey.MaxDegreeOfParellism) ? LocalStorageUtility.getEntryNumber(StorageKey.MaxDegreeOfParellism) : Constants.Queries.DefaultMaxDegreeOfParallelism, ); const [priorityLevel, setPriorityLevel] = useState( LocalStorageUtility.hasItem(StorageKey.PriorityLevel) ? LocalStorageUtility.getEntryString(StorageKey.PriorityLevel) : Constants.PriorityLevel.Default, ); const [copilotSampleDBEnabled, setCopilotSampleDBEnabled] = useState( LocalStorageUtility.getEntryString(StorageKey.CopilotSampleDBEnabled) === "true", ); const styles = useStyles(); const explorerVersion = configContext.gitSha; const isEmulator = configContext.platform === Platform.Emulator; const shouldShowQueryPageOptions = userContext.apiType === "SQL"; const showRetrySettings = (userContext.apiType === "SQL" || userContext.apiType === "Tables" || userContext.apiType === "Gremlin") && !isEmulator; const shouldShowGraphAutoVizOption = userContext.apiType === "Gremlin" && !isEmulator; const shouldShowCrossPartitionOption = userContext.apiType !== "Gremlin" && !isEmulator; const shouldShowParallelismOption = userContext.apiType !== "Gremlin" && !isEmulator; const showEnableEntraIdRbac = isDataplaneRbacSupported(userContext.apiType) && userContext.authType === AuthType.AAD && configContext.platform !== Platform.Fabric && !isEmulator; const shouldShowPriorityLevelOption = PriorityBasedExecutionUtils.isFeatureEnabled() && !isEmulator; const uniqueAccountRegions = new Set(); const regionOptions: IDropdownOption[] = []; regionOptions.push({ key: userContext?.databaseAccount?.properties?.documentEndpoint, text: `Global (Default)`, data: { isGlobal: true, writeEnabled: true, }, }); userContext?.databaseAccount?.properties?.writeLocations?.forEach((loc) => { if (!uniqueAccountRegions.has(loc.locationName)) { uniqueAccountRegions.add(loc.locationName); regionOptions.push({ key: loc.documentEndpoint, text: `${loc.locationName} (Read/Write)`, data: { isGlobal: false, writeEnabled: true, }, }); } }); userContext?.databaseAccount?.properties?.readLocations?.forEach((loc) => { if (!uniqueAccountRegions.has(loc.locationName)) { uniqueAccountRegions.add(loc.locationName); regionOptions.push({ key: loc.documentEndpoint, text: `${loc.locationName} (Read)`, data: { isGlobal: false, writeEnabled: false, }, }); } }); const shouldShowCopilotSampleDBOption = userContext.apiType === "SQL" && useQueryCopilot.getState().copilotEnabled && useDatabases.getState().sampleDataResourceTokenCollection && !isEmulator; const handlerOnSubmit = async () => { setIsExecuting(true); LocalStorageUtility.setEntryNumber( StorageKey.ActualItemPerPage, isCustomPageOptionSelected() ? customItemPerPage : Constants.Queries.unlimitedItemsPerPage, ); LocalStorageUtility.setEntryNumber(StorageKey.CustomItemPerPage, customItemPerPage); if ( enableDataPlaneRBACOption !== LocalStorageUtility.getEntryString(StorageKey.DataPlaneRbacEnabled) || retryAttempts !== LocalStorageUtility.getEntryNumber(StorageKey.RetryAttempts) || retryInterval !== LocalStorageUtility.getEntryNumber(StorageKey.RetryInterval) || MaxWaitTimeInSeconds !== LocalStorageUtility.getEntryNumber(StorageKey.MaxWaitTimeInSeconds) ) { updateUserContext({ refreshCosmosClient: true, }); } if (configContext.platform !== Platform.Fabric) { LocalStorageUtility.setEntryString(StorageKey.DataPlaneRbacEnabled, enableDataPlaneRBACOption); if ( enableDataPlaneRBACOption === Constants.RBACOptions.setTrueRBACOption || (enableDataPlaneRBACOption === Constants.RBACOptions.setAutomaticRBACOption && userContext.databaseAccount.properties.disableLocalAuth) ) { updateUserContext({ dataPlaneRbacEnabled: true, }); useDataPlaneRbac.setState({ dataPlaneRbacEnabled: true }); try { const aadToken = await acquireMsalTokenForAccount(userContext.databaseAccount, true); updateUserContext({ aadToken: aadToken }); useDataPlaneRbac.setState({ aadTokenUpdated: true }); } catch (authError) { if ( authError instanceof msalAuthError && authError.errorCode === msalBrowserAuthErrorMessage.popUpWindowError.code ) { logConsoleError( `We were unable to establish authorization for this account, due to pop-ups being disabled in the browser.\nPlease enable pop-ups for this site and click on "Login for Entra ID" button`, ); } else { logConsoleError( `"Failed to acquire authorization token automatically. Please click on "Login for Entra ID" button to enable Entra ID RBAC operations`, ); } } } else { updateUserContext({ dataPlaneRbacEnabled: false, }); const { databaseAccount: account, subscriptionId, resourceGroup } = userContext; if (!userContext.features.enableAadDataPlane && !userContext.masterKey) { let keys; try { keys = await listKeys(subscriptionId, resourceGroup, account.name); updateUserContext({ masterKey: keys.primaryMasterKey, }); } catch (error) { // if listKeys fail because of permissions issue, then make call to get ReadOnlyKeys if (error.code === "AuthorizationFailed") { keys = await getReadOnlyKeys(subscriptionId, resourceGroup, account.name); updateUserContext({ masterKey: keys.primaryReadonlyMasterKey, }); } else { logConsoleError(`Error occurred fetching keys for the account." ${error.message}`); throw error; } } useDataPlaneRbac.setState({ dataPlaneRbacEnabled: false }); } } } const storedRegionalEndpoint = loadState({ componentName: AppStateComponentNames.SelectedRegionalEndpoint, globalAccountName: userContext.databaseAccount?.name, }) as string; const selectedRegionIsGlobal = selectedRegionalEndpoint === userContext?.databaseAccount?.properties?.documentEndpoint; if (selectedRegionIsGlobal && storedRegionalEndpoint) { deleteState({ componentName: AppStateComponentNames.SelectedRegionalEndpoint, globalAccountName: userContext.databaseAccount?.name, }); updateUserContext({ selectedRegionalEndpoint: undefined, writeEnabledInSelectedRegion: true, refreshCosmosClient: true, }); useClientWriteEnabled.setState({ clientWriteEnabled: true }); } else if ( selectedRegionalEndpoint && !selectedRegionIsGlobal && selectedRegionalEndpoint !== storedRegionalEndpoint ) { saveState( { componentName: AppStateComponentNames.SelectedRegionalEndpoint, globalAccountName: userContext.databaseAccount?.name, }, selectedRegionalEndpoint, ); const validWriteEndpoint = userContext.databaseAccount?.properties?.writeLocations?.find( (loc) => loc.documentEndpoint === selectedRegionalEndpoint, ); updateUserContext({ selectedRegionalEndpoint: selectedRegionalEndpoint, writeEnabledInSelectedRegion: !!validWriteEndpoint, refreshCosmosClient: true, }); useClientWriteEnabled.setState({ clientWriteEnabled: !!validWriteEndpoint }); } LocalStorageUtility.setEntryBoolean(StorageKey.RUThresholdEnabled, ruThresholdEnabled); LocalStorageUtility.setEntryBoolean(StorageKey.QueryTimeoutEnabled, queryTimeoutEnabled); LocalStorageUtility.setEntryNumber(StorageKey.RetryAttempts, retryAttempts); LocalStorageUtility.setEntryNumber(StorageKey.RetryInterval, retryInterval); LocalStorageUtility.setEntryNumber(StorageKey.MaxWaitTimeInSeconds, MaxWaitTimeInSeconds); LocalStorageUtility.setEntryString(StorageKey.ContainerPaginationEnabled, containerPaginationEnabled.toString()); LocalStorageUtility.setEntryString(StorageKey.IsCrossPartitionQueryEnabled, crossPartitionQueryEnabled.toString()); LocalStorageUtility.setEntryNumber(StorageKey.MaxDegreeOfParellism, maxDegreeOfParallelism); LocalStorageUtility.setEntryString(StorageKey.PriorityLevel, priorityLevel.toString()); LocalStorageUtility.setEntryString(StorageKey.CopilotSampleDBEnabled, copilotSampleDBEnabled.toString()); LocalStorageUtility.setEntryString(StorageKey.DefaultQueryResultsView, defaultQueryResultsView); if (shouldShowGraphAutoVizOption) { LocalStorageUtility.setEntryBoolean( StorageKey.IsGraphAutoVizDisabled, StringUtility.toBoolean(graphAutoVizDisabled), ); } if (ruThresholdEnabled) { LocalStorageUtility.setEntryNumber(StorageKey.RUThreshold, ruThreshold); } if (queryTimeoutEnabled) { LocalStorageUtility.setEntryNumber(StorageKey.QueryTimeout, queryTimeout); LocalStorageUtility.setEntryBoolean( StorageKey.AutomaticallyCancelQueryAfterTimeout, automaticallyCancelQueryAfterTimeout, ); } setIsExecuting(false); logConsoleInfo( `Updated items per page setting to ${LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage)}`, ); logConsoleInfo(`${crossPartitionQueryEnabled ? "Enabled" : "Disabled"} cross-partition query feed option`); logConsoleInfo( `Updated the max degree of parallelism query feed option to ${LocalStorageUtility.getEntryNumber( StorageKey.MaxDegreeOfParellism, )}`, ); logConsoleInfo(`Updated priority level setting to ${LocalStorageUtility.getEntryString(StorageKey.PriorityLevel)}`); if (shouldShowGraphAutoVizOption) { logConsoleInfo( `Graph result will be displayed as ${ LocalStorageUtility.getEntryBoolean(StorageKey.IsGraphAutoVizDisabled) ? "JSON" : "Graph" }`, ); } logConsoleInfo( `Updated query setting to ${LocalStorageUtility.getEntryString(StorageKey.SetPartitionKeyUndefined)}`, ); refreshExplorer && (await explorer.refreshExplorer()); closeSidePanel(); }; const isCustomPageOptionSelected = () => { return pageOption === Constants.Queries.CustomPageOption; }; const handleOnGremlinChange = (ev: React.FormEvent, option: IChoiceGroupOption): void => { setGraphAutoVizDisabled(option.key); }; const genericPaneProps: RightPaneFormProps = { formError: "", isExecuting, submitButtonText: "Apply", onSubmit: () => handlerOnSubmit(), }; const pageOptionList: IChoiceGroupOption[] = [ { key: Constants.Queries.CustomPageOption, text: "Custom" }, { key: Constants.Queries.UnlimitedPageOption, text: "Unlimited" }, ]; const graphAutoOptionList: IChoiceGroupOption[] = [ { key: "false", text: "Graph" }, { key: "true", text: "JSON" }, ]; const priorityLevelOptionList: IChoiceGroupOption[] = [ { key: Constants.PriorityLevel.Low, text: "Low" }, { key: Constants.PriorityLevel.High, text: "High" }, ]; const dataPlaneRBACOptionsList: IChoiceGroupOption[] = [ { key: Constants.RBACOptions.setAutomaticRBACOption, text: "Automatic" }, { key: Constants.RBACOptions.setTrueRBACOption, text: "True" }, { key: Constants.RBACOptions.setFalseRBACOption, text: "False" }, ]; const defaultQueryResultsViewOptionList: IChoiceGroupOption[] = [ { key: SplitterDirection.Vertical, text: "Vertical" }, { key: SplitterDirection.Horizontal, text: "Horizontal" }, ]; const handleOnPriorityLevelOptionChange = ( ev: React.FormEvent, option: IChoiceGroupOption, ): void => { setPriorityLevel(option.key); }; const handleOnPageOptionChange = (ev: React.FormEvent, option: IChoiceGroupOption): void => { setPageOption(option.key); }; const handleOnDataPlaneRBACOptionChange = ( ev: React.FormEvent, option: IChoiceGroupOption, ): void => { setEnableDataPlaneRBACOption(option.key); }; const handleOnRUThresholdToggleChange = (ev: React.MouseEvent, checked?: boolean): void => { setRUThresholdEnabled(checked); }; const handleOnRUThresholdSpinButtonChange = (ev: React.MouseEvent, newValue?: string): void => { const ruThreshold = Number(newValue); if (!isNaN(ruThreshold)) { setRUThreshold(ruThreshold); } }; const handleOnQueryTimeoutToggleChange = (ev: React.MouseEvent, checked?: boolean): void => { setQueryTimeoutEnabled(checked); }; const handleOnAutomaticallyCancelQueryToggleChange = (ev: React.MouseEvent, checked?: boolean): void => { setAutomaticallyCancelQueryAfterTimeout(checked); }; const handleOnQueryTimeoutSpinButtonChange = (ev: React.MouseEvent, newValue?: string): void => { const queryTimeout = Number(newValue); if (!isNaN(queryTimeout)) { setQueryTimeout(queryTimeout); } }; const handleOnDefaultQueryResultsViewChange = ( ev: React.MouseEvent, option: IChoiceGroupOption, ): void => { setDefaultQueryResultsView(option.key as SplitterDirection); }; const handleOnSelectedRegionOptionChange = (ev: React.FormEvent, option: IDropdownOption): void => { setSelectedRegionalEndpoint(option.key as string); }; const handleOnQueryRetryAttemptsSpinButtonChange = (ev: React.MouseEvent, newValue?: string): void => { const retryAttempts = Number(newValue); if (!isNaN(retryAttempts)) { setRetryAttempts(retryAttempts); } }; const handleOnRetryIntervalSpinButtonChange = (ev: React.MouseEvent, newValue?: string): void => { const retryInterval = Number(newValue); if (!isNaN(retryInterval)) { setRetryInterval(retryInterval); } }; const handleOnMaxWaitTimeSpinButtonChange = (ev: React.MouseEvent, newValue?: string): void => { const MaxWaitTimeInSeconds = Number(newValue); if (!isNaN(MaxWaitTimeInSeconds)) { setMaxWaitTimeInSeconds(MaxWaitTimeInSeconds); } }; const handleSampleDatabaseChange = async (ev: React.MouseEvent, checked?: boolean): Promise => { setCopilotSampleDBEnabled(checked); useQueryCopilot.getState().setCopilotSampleDBEnabled(checked); setRefreshExplorer(false); }; const choiceButtonStyles = { root: { clear: "both", }, flexContainer: [ { selectors: { ".ms-ChoiceFieldGroup root-133": { clear: "both", }, ".ms-ChoiceField-wrapper label": { fontSize: 12, paddingTop: 0, }, ".ms-ChoiceField": { marginTop: 0, }, }, }, ], }; const toggleStyles: IToggleStyles = { label: { fontSize: 12, fontWeight: 400, display: "block", }, root: {}, container: {}, pill: {}, thumb: {}, text: {}, }; const spinButtonStyles: ISpinButtonStyles = { label: { fontSize: 12, fontWeight: 400, }, root: { paddingBottom: 10, }, labelWrapper: {}, icon: {}, spinButtonWrapper: {}, input: {}, arrowButtonsContainer: {}, }; return (
{!isFabricNative() && ( {shouldShowQueryPageOptions && (
Page Options
Choose Custom to specify a fixed amount of query results to show, or choose Unlimited to show as many query results per page.
{isCustomPageOptionSelected() && (
Query results per page{" "} Enter the number of query results that should be shown per page.
{ setCustomItemPerPage(parseInt(newValue) + 1 || customItemPerPage); }} onDecrement={(newValue) => setCustomItemPerPage(parseInt(newValue) - 1 || customItemPerPage)} onValidate={(newValue) => setCustomItemPerPage(parseInt(newValue) || customItemPerPage)} min={1} step={1} className="textfontclr" incrementButtonAriaLabel="Increase value by 1" decrementButtonAriaLabel="Decrease value by 1" />
)}
)} {showEnableEntraIdRbac && (
Enable Entra ID RBAC
Choose Automatic to enable Entra ID RBAC automatically. True/False to force enable/disable Entra ID RBAC. {" "} Learn more{" "}
)} {userContext.apiType === "SQL" && userContext.authType === AuthType.AAD && !isFabric() && (
Region Selection
Changes region the Cosmos Client uses to access account.
Select Region Changes the account endpoint used to perform client operations.
option.key === selectedRegionalEndpoint)?.text : regionOptions[0]?.text } onChange={handleOnSelectedRegionOptionChange} options={regionOptions} styles={{ root: { marginBottom: "10px" } }} />
)} {userContext.apiType === "SQL" && !isEmulator && ( <>
Query Timeout
When a query reaches a specified time limit, a popup with an option to cancel the query will show unless automatic cancellation has been enabled.
{queryTimeoutEnabled && (
)}
RU Limit
If a query exceeds a configured RU limit, the query will be aborted.
{ruThresholdEnabled && (
)}
Default Query Results View
Select the default view to use when displaying query results.
)} {showRetrySettings && (
Retry Settings
Retry policy associated with throttled requests during CosmosDB queries.
Max retry attempts Max number of retries to be performed for a request. Default value 9.
setRetryAttempts(parseInt(newValue) + 1 || retryAttempts)} onDecrement={(newValue) => setRetryAttempts(parseInt(newValue) - 1 || retryAttempts)} onValidate={(newValue) => setRetryAttempts(parseInt(newValue) || retryAttempts)} styles={spinButtonStyles} />
Fixed retry interval (ms) Fixed retry interval in milliseconds to wait between each retry ignoring the retryAfter returned as part of the response. Default value is 0 milliseconds.
setRetryInterval(parseInt(newValue) + 1000 || retryInterval)} onDecrement={(newValue) => setRetryInterval(parseInt(newValue) - 1000 || retryInterval)} onValidate={(newValue) => setRetryInterval(parseInt(newValue) || retryInterval)} styles={spinButtonStyles} />
Max wait time (s) Max wait time in seconds to wait for a request while the retries are happening. Default value 30 seconds.
setMaxWaitTimeInSeconds(parseInt(newValue) + 1 || MaxWaitTimeInSeconds) } onDecrement={(newValue) => setMaxWaitTimeInSeconds(parseInt(newValue) - 1 || MaxWaitTimeInSeconds) } onValidate={(newValue) => setMaxWaitTimeInSeconds(parseInt(newValue) || MaxWaitTimeInSeconds)} styles={spinButtonStyles} />
)} {!isEmulator && (
Enable container pagination
Load 50 containers at a time. Currently, containers are not pulled in alphanumeric order.
setContainerPaginationEnabled(!containerPaginationEnabled)} label="Enable container pagination" />
)} {shouldShowCrossPartitionOption && (
Enable cross-partition query
Send more than one request while executing a query. More than one request is necessary if the query is not scoped to single partition key value.
setCrossPartitionQueryEnabled(!crossPartitionQueryEnabled)} label="Enable cross-partition query" />
)} {shouldShowParallelismOption && (
Max degree of parallelism
Gets or sets the number of concurrent operations run client side during parallel query execution. A positive property value limits the number of concurrent operations to the set value. If it is set to less than 0, the system automatically decides the number of concurrent operations to run.
setMaxDegreeOfParallelism(parseInt(newValue) + 1 || maxDegreeOfParallelism) } onDecrement={(newValue) => setMaxDegreeOfParallelism(parseInt(newValue) - 1 || maxDegreeOfParallelism) } onValidate={(newValue) => setMaxDegreeOfParallelism(parseInt(newValue) || maxDegreeOfParallelism)} ariaLabel="Max degree of parallelism" label="Max degree of parallelism" />
)} {shouldShowPriorityLevelOption && (
Priority Level
Sets the priority level for data-plane requests from Data Explorer when using Priority-Based Execution. If "None" is selected, Data Explorer will not specify priority level, and the server-side default priority level will be used.
)} {shouldShowGraphAutoVizOption && (
Display Gremlin query results as: 
Select Graph to automatically visualize the query results as a Graph or JSON to display the results as JSON.
)} {shouldShowCopilotSampleDBOption && (
Enable sample database
This is a sample database and collection with synthetic product data you can use to explore using NoSQL queries and Query Advisor. This will appear as another database in the Data Explorer UI, and is created by, and maintained by Microsoft at no cost to you.
)}
)}
{ useDialog.getState().showOkCancelModalDialog( "Clear History", undefined, "Are you sure you want to proceed?", () => { deleteAllStates(); updateUserContext({ selectedRegionalEndpoint: undefined, writeEnabledInSelectedRegion: true, refreshCosmosClient: true, }); useClientWriteEnabled.setState({ clientWriteEnabled: true }); }, "Cancel", undefined, <> This action will clear the all customizations for this account in this browser, including:
  • Reset your customized tab layout, including the splitter positions
  • Erase your table column preferences, including any custom columns
  • Clear your filter history
  • Reset region selection to global
, ); }} > Clear History
Explorer Version
{explorerVersion}
); };