import { Checkbox, ChoiceGroup, IChoiceGroupOption, ISpinButtonStyles, IToggleStyles, Position, SpinButton, Toggle, } from "@fluentui/react"; import * as Constants from "Common/Constants"; import { InfoTooltip } from "Common/Tooltip/InfoTooltip"; import { configContext } from "ConfigContext"; import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility"; import * as StringUtility from "Shared/StringUtility"; import { userContext } from "UserContext"; import { logConsoleInfo } from "Utils/NotificationConsoleUtils"; import * as PriorityBasedExecutionUtils from "Utils/PriorityBasedExecutionUtils"; import { useSidePanel } from "hooks/useSidePanel"; import React, { FunctionComponent, useState } from "react"; import { RightPaneForm, RightPaneFormProps } from "../RightPaneForm/RightPaneForm"; export const SettingsPane: FunctionComponent = () => { const closeSidePanel = useSidePanel((state) => state.closeSidePanel); const [isExecuting, setIsExecuting] = useState(false); const [pageOption, setPageOption] = useState( LocalStorageUtility.getEntryNumber(StorageKey.ActualItemPerPage) === Constants.Queries.unlimitedItemsPerPage ? Constants.Queries.UnlimitedPageOption : Constants.Queries.CustomPageOption, ); const [queryTimeoutEnabled, setQueryTimeoutEnabled] = useState( LocalStorageUtility.getEntryBoolean(StorageKey.QueryTimeoutEnabled), ); const [queryTimeout, setQueryTimeout] = useState(LocalStorageUtility.getEntryNumber(StorageKey.QueryTimeout)); 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 [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 explorerVersion = configContext.gitSha; const shouldShowQueryPageOptions = userContext.apiType === "SQL"; const shouldShowGraphAutoVizOption = userContext.apiType === "Gremlin"; const shouldShowCrossPartitionOption = userContext.apiType !== "Gremlin"; const shouldShowParallelismOption = userContext.apiType !== "Gremlin"; const shouldShowPriorityLevelOption = PriorityBasedExecutionUtils.isFeatureEnabled(); const handlerOnSubmit = () => { setIsExecuting(true); LocalStorageUtility.setEntryNumber( StorageKey.ActualItemPerPage, isCustomPageOptionSelected() ? customItemPerPage : Constants.Queries.unlimitedItemsPerPage, ); LocalStorageUtility.setEntryNumber(StorageKey.CustomItemPerPage, customItemPerPage); 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()); if (shouldShowGraphAutoVizOption) { LocalStorageUtility.setEntryBoolean( StorageKey.IsGraphAutoVizDisabled, StringUtility.toBoolean(graphAutoVizDisabled), ); } 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)}`, ); 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 handleOnPriorityLevelOptionChange = ( ev: React.FormEvent, option: IChoiceGroupOption, ): void => { setPriorityLevel(option.key); }; const handleOnPageOptionChange = (ev: React.FormEvent, option: IChoiceGroupOption): void => { setPageOption(option.key); }; 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 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 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 queryTimeoutToggleStyles: IToggleStyles = { label: { fontSize: 12, fontWeight: 400, display: "block", }, root: {}, container: {}, pill: {}, thumb: {}, text: {}, }; const queryTimeoutSpinButtonStyles: ISpinButtonStyles = { label: { fontSize: 12, fontWeight: 400, }, root: { paddingBottom: 10, }, labelWrapper: {}, icon: {}, spinButtonWrapper: {}, input: {}, arrowButtonsContainer: {}, }; return (
{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" />
)}
)} {userContext.apiType === "SQL" && (
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 && (
)}
)}
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={queryTimeoutSpinButtonStyles} />
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={queryTimeoutSpinButtonStyles} />
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={queryTimeoutSpinButtonStyles} />
Enable container pagination Load 50 containers at a time. Currently, containers are not pulled in alphanumeric order.
setContainerPaginationEnabled(!containerPaginationEnabled)} />
{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)} />
)} {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" />
)} {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.
)}
Explorer Version
{explorerVersion}
); };