Perf/copilot cleanup and optimizations (#2447)

* perf: remove deprecated copilot feature, add ARM timeouts, fix race conditions

- Remove entire QueryCopilot feature (~50 files deleted, ~30 files cleaned)
- Remove CopilotConfigured and SampleDataLoaded metric phases
- Fix DatabaseTreeRendered 76% stuck rate (remove one-shot guard in useMetricPhases)
- Add 8s default timeout to ARM requests (AbortController-based)
- Fix MSAL token forceRefresh (true -> false, use cache)
- Add concurrency limit of 5 to collection loading in Explorer
- Remove orphaned SampleDataClient.ts and queryCopilotSampleData.json
- Clean up dead sampleDataConnectionInfo field from UserContext

* Clean up copilot and optimize initialization

* Clean up copilot and optimize initialization
This commit is contained in:
sunghyunkang1111
2026-04-08 11:25:33 -05:00
committed by GitHub
parent ab4f1289e1
commit fb250259ed
126 changed files with 162 additions and 22486 deletions

View File

@@ -9,7 +9,6 @@ import {
makeStyles,
shorthands,
} from "@fluentui/react-components";
import { QueryCopilotSampleContainerId, QueryCopilotSampleDatabaseId } from "Common/Constants";
import { getErrorMessage, getErrorStack } from "Common/ErrorHandlingUtils";
import MongoUtility from "Common/MongoUtility";
import { createDocument } from "Common/dataAccess/createDocument";
@@ -27,7 +26,7 @@ import { EditorReact } from "Explorer/Controls/Editor/EditorReact";
import { InputDataList, InputDatalistDropdownOptionSection } from "Explorer/Controls/InputDataList/InputDataList";
import { ProgressModalDialog } from "Explorer/Controls/ProgressModalDialog";
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
import { querySampleDocuments, readSampleDocument } from "Explorer/QueryCopilot/QueryCopilotUtilities";
import {
ColumnsSelection,
FilterHistory,
@@ -360,10 +359,7 @@ export const getTabsButtons = ({
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled:
!getNewDocumentButtonState(editorState).enabled ||
!clientWriteEnabled ||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
disabled: !getNewDocumentButtonState(editorState).enabled || !clientWriteEnabled,
id: NEW_DOCUMENT_BUTTON_ID,
});
}
@@ -378,10 +374,7 @@ export const getTabsButtons = ({
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled:
!getSaveNewDocumentButtonState(editorState).enabled ||
!clientWriteEnabled ||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
disabled: !getSaveNewDocumentButtonState(editorState).enabled || !clientWriteEnabled,
id: SAVE_BUTTON_ID,
});
}
@@ -396,9 +389,7 @@ export const getTabsButtons = ({
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled:
!getDiscardNewDocumentChangesButtonState(editorState).enabled ||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
disabled: !getDiscardNewDocumentChangesButtonState(editorState).enabled,
id: DISCARD_BUTTON_ID,
});
}
@@ -413,10 +404,7 @@ export const getTabsButtons = ({
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled:
!getSaveExistingDocumentButtonState(editorState).enabled ||
!clientWriteEnabled ||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
disabled: !getSaveExistingDocumentButtonState(editorState).enabled || !clientWriteEnabled,
id: UPDATE_BUTTON_ID,
});
}
@@ -431,9 +419,7 @@ export const getTabsButtons = ({
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled:
!getDiscardExistingDocumentChangesButtonState(editorState).enabled ||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
disabled: !getDiscardExistingDocumentChangesButtonState(editorState).enabled,
id: DISCARD_BUTTON_ID,
});
}
@@ -448,7 +434,7 @@ export const getTabsButtons = ({
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
disabled: useSelectedNode.getState().isQueryCopilotCollectionSelected() || !clientWriteEnabled,
disabled: !clientWriteEnabled,
id: DELETE_BUTTON_ID,
});
}
@@ -465,8 +451,7 @@ export const getTabsButtons = ({
hasPopup: true,
disabled:
useSelectedNode.getState().isDatabaseNodeOrNoneSelected() ||
!useClientWriteEnabled.getState().clientWriteEnabled ||
useSelectedNode.getState().isQueryCopilotCollectionSelected(),
!useClientWriteEnabled.getState().clientWriteEnabled,
});
}
@@ -642,11 +627,6 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
}),
);
const isQueryCopilotSampleContainer =
_collection?.isSampleCollection &&
_collection?.databaseId === QueryCopilotSampleDatabaseId &&
_collection?.id() === QueryCopilotSampleContainerId;
// For Mongo only
const [continuationToken, setContinuationToken] = useState<string>(undefined);
@@ -1400,16 +1380,13 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
// Fixes compile error error TS2741: Property 'throwIfAborted' is missing in type 'AbortSignal' but required in type 'import("/home/runner/work/cosmos-explorer/cosmos-explorer/node_modules/node-abort-controller/index").AbortSignal'.
options.abortSignal = _queryAbortController.signal;
return isQueryCopilotSampleContainer
? querySampleDocuments(query, options)
: queryDocuments(_collection.databaseId, _collection.id(), query, options);
return queryDocuments(_collection.databaseId, _collection.id(), query, options);
}, [
filterContent,
isPreferredApiMongoDB,
partitionKeyProperties,
partitionKey,
resourceTokenPartitionKey,
isQueryCopilotSampleContainer,
_collection,
selectedColumnIds,
]);
@@ -1567,11 +1544,6 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
}
};
const _isQueryCopilotSampleContainer =
_collection?.isSampleCollection &&
_collection?.databaseId === QueryCopilotSampleDatabaseId &&
_collection?.id() === QueryCopilotSampleContainerId;
// Table config here
const tableItems: DocumentsTableComponentItem[] = documentIds.map((documentId) => {
const item: DocumentsTableComponentItem = documentId.tableFields || { id: documentId.id() };
@@ -1635,14 +1607,12 @@ export const DocumentsTabComponent: React.FunctionComponent<IDocumentsTabCompone
};
let loadDocument = (documentId: DocumentId) =>
(_isQueryCopilotSampleContainer ? readSampleDocument(documentId) : readDocument(_collection, documentId)).then(
(content) => {
initDocumentEditor(documentId, content);
readDocument(_collection, documentId).then((content) => {
initDocumentEditor(documentId, content);
// Update columns
setColumnDefinitionsFromDocument(content);
},
);
// Update columns
setColumnDefinitionsFromDocument(content);
});
const initDocumentEditor = (documentId: DocumentId, documentContent: unknown): void => {
if (documentId) {

View File

@@ -1,19 +1,12 @@
import { sendMessage } from "Common/MessageHandler";
import { ActionType, OpenQueryTab, TabKind } from "Contracts/ActionContracts";
import { MessageTypes } from "Contracts/MessageTypes";
import { CopilotProvider } from "Explorer/QueryCopilot/QueryCopilotContext";
import { userContext } from "UserContext";
import React from "react";
import * as DataModels from "../../../Contracts/DataModels";
import type { QueryTabOptions } from "../../../Contracts/ViewModels";
import { useTabs } from "../../../hooks/useTabs";
import Explorer from "../../Explorer";
import {
IQueryTabComponentProps,
ITabAccessor,
QueryTabComponent,
QueryTabCopilotComponent,
} from "../../Tabs/QueryTab/QueryTabComponent";
import { IQueryTabComponentProps, ITabAccessor, QueryTabComponent } from "../../Tabs/QueryTab/QueryTabComponent";
import TabsBase from "../TabsBase";
export interface IQueryTabProps {
@@ -80,13 +73,7 @@ export class NewQueryTab extends TabsBase {
}
public render(): JSX.Element {
return userContext.apiType === "SQL" ? (
<CopilotProvider>
<QueryTabCopilotComponent {...this.iQueryTabComponentProps} />
</CopilotProvider>
) : (
<QueryTabComponent {...this.iQueryTabComponentProps} />
);
return <QueryTabComponent {...this.iQueryTabComponentProps} />;
}
public onActivate(): void {

View File

@@ -1,60 +1,21 @@
import { fireEvent, render } from "@testing-library/react";
import { CollectionTabKind } from "Contracts/ViewModels";
import { CopilotProvider } from "Explorer/QueryCopilot/QueryCopilotContext";
import { QueryCopilotPromptbar } from "Explorer/QueryCopilot/QueryCopilotPromptbar";
import { CopilotSubComponentNames } from "Explorer/QueryCopilot/QueryCopilotUtilities";
import {
IQueryTabComponentProps,
QueryTabComponent,
QueryTabCopilotComponent,
} from "Explorer/Tabs/QueryTab/QueryTabComponent";
import TabsBase from "Explorer/Tabs/TabsBase";
import { AppStateComponentNames, StorePath } from "Shared/AppStatePersistenceUtility";
import { updateUserContext, userContext } from "UserContext";
import { mount } from "enzyme";
import { useQueryCopilot } from "hooks/useQueryCopilot";
import { useTabs } from "hooks/useTabs";
import { render } from "@testing-library/react";
import { IQueryTabComponentProps, QueryTabComponent } from "Explorer/Tabs/QueryTab/QueryTabComponent";
import React from "react";
jest.mock("Explorer/Controls/Editor/EditorReact");
const loadState = (path: StorePath) => {
if (
path.componentName === AppStateComponentNames.QueryCopilot &&
path.subComponentName === CopilotSubComponentNames.toggleStatus
) {
return true;
} else {
return undefined;
}
};
jest.mock("Shared/AppStatePersistenceUtility", () => ({
loadState,
AppStateComponentNames: {
QueryCopilot: "QueryCopilot",
},
loadState: jest.fn(),
AppStateComponentNames: {},
readSubComponentState: jest.fn(),
}));
describe("QueryTabComponent", () => {
const mockStore = useQueryCopilot.getState();
beforeEach(() => {
mockStore.showCopilotSidebar = false;
mockStore.setShowCopilotSidebar = jest.fn();
});
afterEach(() => jest.clearAllMocks());
it("should launch conversational Copilot when ALT+C is pressed and when copilot version is 3", () => {
updateUserContext({
features: {
...userContext.features,
copilotVersion: "v3.0",
},
});
it("should render without crashing", () => {
const propsMock: Readonly<IQueryTabComponentProps> = {
collection: { databaseId: "CopilotSampleDB", id: () => "CopilotContainer" },
collection: { databaseId: "testDb", id: () => "testContainer" },
onTabAccessor: () => jest.fn(),
isExecutionError: false,
tabId: "mockTabId",
@@ -64,49 +25,6 @@ describe("QueryTabComponent", () => {
} as unknown as IQueryTabComponentProps;
const { container } = render(<QueryTabComponent {...propsMock} />);
const launchCopilotButton = container.querySelector('[data-test="QueryTab/ResultsPane/ExecuteCTA"]');
fireEvent.keyDown(launchCopilotButton, { key: "c", altKey: true });
expect(mockStore.setShowCopilotSidebar).toHaveBeenCalledWith(true);
});
it("copilot should be enabled by default when tab is active", () => {
updateUserContext({
databaseAccount: {
name: "name",
properties: undefined,
id: "",
location: "",
type: "",
kind: "",
},
});
useQueryCopilot.getState().setCopilotEnabled(true);
useQueryCopilot.getState().setCopilotUserDBEnabled(true);
const activeTab = new TabsBase({
tabKind: CollectionTabKind.Query,
title: "Query",
tabPath: "",
});
activeTab.tabId = "mockTabId";
useTabs.getState().activeTab = activeTab;
const propsMock: Readonly<IQueryTabComponentProps> = {
collection: { databaseId: "CopilotUserDb", id: () => "CopilotUserContainer" },
onTabAccessor: () => jest.fn(),
isExecutionError: false,
tabId: "mockTabId",
tabsBaseInstance: {
updateNavbarWithTabsButtons: () => jest.fn(),
},
} as unknown as IQueryTabComponentProps;
const container = mount(
<CopilotProvider>
<QueryTabCopilotComponent {...propsMock} />
</CopilotProvider>,
);
expect(container.find(QueryCopilotPromptbar).exists()).toBe(false);
expect(container).toBeTruthy();
});
});

View File

@@ -7,32 +7,21 @@ import { SplitterDirection } from "Common/Splitter";
import { Platform, configContext } from "ConfigContext";
import { useDialog } from "Explorer/Controls/Dialog";
import { monaco } from "Explorer/LazyMonaco";
import { QueryCopilotFeedbackModal } from "Explorer/QueryCopilot/Modal/QueryCopilotFeedbackModal";
import { useCopilotStore } from "Explorer/QueryCopilot/QueryCopilotContext";
import { readCopilotToggleStatus, saveCopilotToggleStatus } from "Explorer/QueryCopilot/QueryCopilotUtilities";
import { OnExecuteQueryClick, QueryDocumentsPerPage } from "Explorer/QueryCopilot/Shared/QueryCopilotClient";
import { QueryCopilotSidebar } from "Explorer/QueryCopilot/V2/Sidebar/QueryCopilotSidebar";
import { QueryResultSection } from "Explorer/Tabs/QueryTab/QueryResultSection";
import { QueryTabStyles, useQueryTabStyles } from "Explorer/Tabs/QueryTab/Styles";
import { CosmosFluentProvider } from "Explorer/Theme/ThemeUtil";
import { useSelectedNode } from "Explorer/useSelectedNode";
import { KeyboardAction } from "KeyboardShortcuts";
import { Keys, t } from "Localization";
import { QueryConstants } from "Shared/Constants";
import { LocalStorageUtility, StorageKey } from "Shared/StorageUtility";
import { Action } from "Shared/Telemetry/TelemetryConstants";
import { Allotment } from "allotment";
import { useClientWriteEnabled } from "hooks/useClientWriteEnabled";
import { QueryCopilotState, useQueryCopilot } from "hooks/useQueryCopilot";
import { TabsState, useTabs } from "hooks/useTabs";
import { useMonacoTheme } from "hooks/useTheme";
import React, { Fragment, createRef } from "react";
import "react-splitter-layout/lib/index.css";
import { format } from "react-string-format";
import create from "zustand";
//TODO: Uncomment next two lines when query copilot is reinstated in DE
// import QueryCommandIcon from "../../../../images/CopilotCommand.svg";
// import LaunchCopilot from "../../../../images/CopilotTabIcon.svg";
import DownloadQueryIcon from "../../../../images/DownloadQuery.svg";
import CancelQueryIcon from "../../../../images/Entity_cancel.svg";
import ExecuteQueryIcon from "../../../../images/ExecuteQuery.svg";
@@ -46,7 +35,6 @@ import { queryDocuments } from "../../../Common/dataAccess/queryDocuments";
import { queryDocumentsPage } from "../../../Common/dataAccess/queryDocumentsPage";
import * as DataModels from "../../../Contracts/DataModels";
import * as ViewModels from "../../../Contracts/ViewModels";
import * as TelemetryProcessor from "../../../Shared/Telemetry/TelemetryProcessor";
import { userContext } from "../../../UserContext";
import * as QueryUtils from "../../../Utils/QueryUtils";
import { useSidePanel } from "../../../hooks/useSidePanel";
@@ -109,9 +97,6 @@ export interface IQueryTabComponentProps {
isPreferredApiMongoDB?: boolean;
monacoEditorSetting?: string;
viewModelcollection?: ViewModels.Collection;
copilotEnabled?: boolean;
isSampleCopilotActive?: boolean;
copilotStore?: Partial<QueryCopilotState>;
splitterDirection?: "horizontal" | "vertical";
queryViewSizePercent?: number;
onUpdatePersistedState: (state: {
@@ -130,10 +115,7 @@ interface IQueryTabStates {
queryResults: ViewModels.QueryResults;
isExecutionError: boolean;
isExecuting: boolean;
showCopilotSidebar: boolean;
queryCopilotGeneratedQuery: string;
cancelQueryTimeoutID: NodeJS.Timeout;
copilotActive: boolean;
currentTabActive: boolean;
queryResultsView: SplitterDirection;
errors?: QueryError[];
@@ -141,23 +123,6 @@ interface IQueryTabStates {
queryViewSizePercent: number;
}
export const QueryTabCopilotComponent = (props: IQueryTabComponentProps): any => {
const styles = useQueryTabStyles();
const monacoTheme = useMonacoTheme();
const copilotStore = useCopilotStore();
const isSampleCopilotActive = useSelectedNode.getState().isQueryCopilotCollectionSelected();
const queryTabProps = {
...props,
copilotEnabled:
useQueryCopilot().copilotEnabled &&
(useQueryCopilot().copilotUserDBEnabled || (isSampleCopilotActive && !!userContext.sampleDataConnectionInfo)),
isSampleCopilotActive: isSampleCopilotActive,
copilotStore: copilotStore,
};
return <QueryTabComponentImpl styles={styles} monacoTheme={monacoTheme} {...queryTabProps} />;
};
export const QueryTabComponent = (props: IQueryTabComponentProps): any => {
const styles = useQueryTabStyles();
const monacoTheme = useMonacoTheme();
@@ -176,11 +141,9 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
public queryEditorId: string;
public executeQueryButton: Button;
public saveQueryButton: Button;
public launchCopilotButton: Button;
public splitterId: string;
public isPreferredApiMongoDB: boolean;
public isCloseClicked: boolean;
public isCopilotTabActive: boolean;
private _iterator: MinimalQueryIterator;
private queryAbortController: AbortController;
queryEditor: React.RefObject<EditorReact>;
@@ -198,10 +161,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
errors: [],
isExecutionError: this.props.isExecutionError,
isExecuting: false,
showCopilotSidebar: useQueryCopilot.getState().showCopilotSidebar,
queryCopilotGeneratedQuery: useQueryCopilot.getState().query,
cancelQueryTimeoutID: undefined,
copilotActive: this._queryCopilotActive(),
currentTabActive: true,
queryResultsView:
props.splitterDirection === "vertical" ? SplitterDirection.Vertical : SplitterDirection.Horizontal,
@@ -211,7 +171,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
this.splitterId = this.props.tabId + "_splitter";
this.queryEditorId = `queryeditor${this.props.tabId}`;
this.isPreferredApiMongoDB = this.props.isPreferredApiMongoDB;
this.isCopilotTabActive = userContext.features.copilotVersion === "v3.0";
this.executeQueryButton = {
enabled: !!this.state.sqlQueryEditorContent && this.state.sqlQueryEditorContent.length > 0,
visible: true,
@@ -223,11 +182,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
visible: isSaveQueryBtnEnabled,
};
this.launchCopilotButton = {
enabled: userContext.apiType === "SQL" && true,
visible: userContext.apiType === "SQL" && true,
};
this.props.tabsBaseInstance.updateNavbarWithTabsButtons();
props.onTabAccessor({
onTabClickEvent: this.onTabClick.bind(this),
@@ -253,18 +207,8 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
}, QueryTabComponentImpl.DEBOUNCE_DELAY_MS);
};
private _queryCopilotActive(): boolean {
if (this.props.copilotEnabled) {
return readCopilotToggleStatus(userContext.databaseAccount);
}
return false;
}
public onCloseClick(isClicked: boolean): void {
this.isCloseClicked = isClicked;
if (useQueryCopilot.getState().wasCopilotUsed && this.isCopilotTabActive) {
useQueryCopilot.getState().resetQueryCopilotStates();
}
}
public getCurrentEditorQuery(): string {
@@ -289,16 +233,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
setTimeout(async () => {
await this._executeQueryDocumentsPage(0);
}, 100); // TODO: Revert this
if (this.state.copilotActive) {
const query = this.state.sqlQueryEditorContent.split("\r\n")?.pop();
const isqueryEdited = this.props.copilotStore.generatedQuery && this.props.copilotStore.generatedQuery !== query;
if (isqueryEdited) {
TelemetryProcessor.traceMark(Action.QueryEdited, {
databaseName: this.props.collection.databaseId,
collectionId: this.props.collection.id(),
});
}
}
};
public onDownloadQueryClick = (): void => {
@@ -321,10 +255,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
.openSidePanel(t(Keys.tabs.query.saveQuery), <SaveQueryPane explorer={this.props.collection.container} />);
};
public launchQueryCopilotChat = (): void => {
useQueryCopilot.getState().setShowCopilotSidebar(!useQueryCopilot.getState().showCopilotSidebar);
};
public onSavedQueriesClick = (): void => {
useSidePanel
.getState()
@@ -346,12 +276,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
});
}
public handleCopilotKeyDown = (event: KeyboardEvent): void => {
if (this.isCopilotTabActive && event.altKey && event.key === "c") {
this.launchQueryCopilotChat();
}
};
public onToggleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): boolean => {
if (event.key === NormalizedEventKey.LeftArrow) {
this.toggleResult();
@@ -485,9 +409,7 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
iconSrc: ExecuteQueryIcon,
iconAlt: label,
keyboardAction: KeyboardAction.EXECUTE_ITEM,
onCommandClick: this.props.isSampleCopilotActive
? () => OnExecuteQueryClick(this.props.copilotStore)
: this.onExecuteQueryClick,
onCommandClick: this.onExecuteQueryClick,
commandButtonLabel: label,
ariaLabel: label,
hasPopup: false,
@@ -524,56 +446,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
});
}
//TODO: Uncomment next section when query copilot is reinstated in DE
// if (this.launchCopilotButton.visible && this.isCopilotTabActive) {
// const mainButtonLabel = "Launch Copilot";
// const chatPaneLabel = "Open Copilot in chat pane (ALT+C)";
// const copilotSettingLabel = "Copilot settings";
// const openCopilotChatButton: CommandButtonComponentProps = {
// iconAlt: chatPaneLabel,
// onCommandClick: this.launchQueryCopilotChat,
// commandButtonLabel: chatPaneLabel,
// ariaLabel: chatPaneLabel,
// hasPopup: false,
// };
// const copilotSettingsButton: CommandButtonComponentProps = {
// iconAlt: copilotSettingLabel,
// onCommandClick: () => undefined,
// commandButtonLabel: copilotSettingLabel,
// ariaLabel: copilotSettingLabel,
// hasPopup: false,
// };
// const launchCopilotButton: CommandButtonComponentProps = {
// iconSrc: LaunchCopilot,
// iconAlt: mainButtonLabel,
// onCommandClick: this.launchQueryCopilotChat,
// commandButtonLabel: mainButtonLabel,
// ariaLabel: mainButtonLabel,
// hasPopup: false,
// children: [openCopilotChatButton, copilotSettingsButton],
// };
// buttons.push(launchCopilotButton);
// }
//TODO: Uncomment next section when query copilot is reinstated in DE
// if (this.props.copilotEnabled) {
// const toggleCopilotButton: CommandButtonComponentProps = {
// iconSrc: QueryCommandIcon,
// iconAlt: "Query Advisor",
// keyboardAction: KeyboardAction.TOGGLE_COPILOT,
// onCommandClick: () => {
// this._toggleCopilot(!this.state.copilotActive);
// },
// commandButtonLabel: this.state.copilotActive ? "Disable Query Advisor" : "Enable Query Advisor",
// ariaLabel: this.state.copilotActive ? "Disable Query Advisor" : "Enable Query Advisor",
// hasPopup: false,
// };
// buttons.push(toggleCopilotButton);
// }
if (!this.props.isPreferredApiMongoDB && this.state.isExecuting) {
const label = t(Keys.tabs.query.cancelQuery);
buttons.push({
@@ -626,34 +498,10 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
}, 100);
}
private _toggleCopilot = (active: boolean) => {
this.setState({ copilotActive: active });
useQueryCopilot.getState().setCopilotEnabledforExecution(active);
saveCopilotToggleStatus(userContext.databaseAccount, active);
TelemetryProcessor.traceSuccess(active ? Action.ActivateQueryCopilot : Action.DeactivateQueryCopilot, {
databaseName: this.props.collection.databaseId,
collectionId: this.props.collection.id(),
});
};
componentDidUpdate = (_prevProps: IQueryTabComponentProps, prevState: IQueryTabStates): void => {
if (prevState.copilotActive !== this.state.copilotActive) {
useCommandBar.getState().setContextButtons(this.getTabsButtons());
}
};
public onChangeContent(newContent: string): void {
// The copilot store's active query takes precedence over the local state,
// and we can't update both states in a single operation.
// So, we update the copilot store's state first, then update the local state.
if (this.state.copilotActive) {
this.props.copilotStore?.setQuery(newContent);
}
this.setState(
{
sqlQueryEditorContent: newContent,
queryCopilotGeneratedQuery: "",
// Clear the markers when the user edits the document.
modelMarkers: [],
@@ -692,28 +540,10 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
});
}
if (this.isCopilotTabActive) {
selectedContent.trim().length > 0
? useQueryCopilot.getState().setSelectedQuery(selectedContent)
: useQueryCopilot.getState().setSelectedQuery("");
}
if (this.state.copilotActive) {
this.props.copilotStore?.setSelectedQuery(selectedContent);
}
useCommandBar.getState().setContextButtons(this.getTabsButtons());
}
public getEditorContent(): string {
if (this.isCopilotTabActive && this.state.queryCopilotGeneratedQuery) {
return this.state.queryCopilotGeneratedQuery;
}
if (this.state.copilotActive) {
return this.props.copilotStore?.query;
}
return this.state.sqlQueryEditorContent;
}
@@ -721,7 +551,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
return !this.isPreferredApiMongoDB && LocalStorageUtility.getEntryBoolean(StorageKey.QueryTimeoutEnabled);
}
private unsubscribeCopilotSidebar: () => void;
private unsubscribeClientWriteEnabled: () => void;
componentDidMount(): void {
@@ -738,7 +567,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
});
useCommandBar.getState().setContextButtons(this.getTabsButtons());
document.addEventListener("keydown", this.handleCopilotKeyDown);
this.unsubscribeClientWriteEnabled = useClientWriteEnabled.subscribe(() => {
useCommandBar.getState().setContextButtons(this.getTabsButtons());
@@ -746,7 +574,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
}
componentWillUnmount(): void {
document.removeEventListener("keydown", this.handleCopilotKeyDown);
if (this.unsubscribeClientWriteEnabled) {
this.unsubscribeClientWriteEnabled();
}
@@ -757,15 +584,6 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
return (
<Fragment>
<CosmosFluentProvider id={this.props.tabId} className={this.props.styles.queryTab} role="tabpanel">
{/*TODO: Uncomment this section when query copilot is reinstated in DE
{this.props.copilotEnabled && this.state.currentTabActive && this.state.copilotActive && (
<QueryCopilotPromptbar
explorer={this.props.collection.container}
toggleCopilot={this._toggleCopilot}
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
></QueryCopilotPromptbar>
)} */}
{/* Set 'key' to the value of vertical to force re-rendering when vertical changes, to work around https://github.com/johnwalley/allotment/issues/457 */}
<Allotment
key={vertical.toString()}
@@ -799,64 +617,27 @@ class QueryTabComponentImpl extends React.Component<QueryTabComponentImplProps,
/>
</Allotment.Pane>
<Allotment.Pane>
{this.props.isSampleCopilotActive ? (
<QueryResultSection
isMongoDB={this.props.isPreferredApiMongoDB}
queryEditorContent={this.state.sqlQueryEditorContent}
errors={this.props.copilotStore?.errors}
isExecuting={this.props.copilotStore?.isExecuting}
queryResults={this.props.copilotStore?.queryResults}
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
executeQueryDocumentsPage={(firstItemIndex: number) =>
QueryDocumentsPerPage(
firstItemIndex,
this.props.copilotStore.queryIterator,
this.props.copilotStore,
)
}
/>
) : (
<QueryResultSection
isMongoDB={this.props.isPreferredApiMongoDB}
queryEditorContent={this.state.sqlQueryEditorContent}
errors={this.state.errors}
isExecuting={this.state.isExecuting}
queryResults={this.state.queryResults}
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
executeQueryDocumentsPage={(firstItemIndex: number) =>
this._executeQueryDocumentsPage(firstItemIndex)
}
/>
)}
<QueryResultSection
isMongoDB={this.props.isPreferredApiMongoDB}
queryEditorContent={this.state.sqlQueryEditorContent}
errors={this.state.errors}
isExecuting={this.state.isExecuting}
queryResults={this.state.queryResults}
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
executeQueryDocumentsPage={(firstItemIndex: number) => this._executeQueryDocumentsPage(firstItemIndex)}
/>
</Allotment.Pane>
</Allotment>
</CosmosFluentProvider>
{this.props.copilotEnabled && this.props.copilotStore?.showFeedbackModal && (
<QueryCopilotFeedbackModal
explorer={this.props.collection.container}
databaseId={this.props.collection.databaseId}
containerId={this.props.collection.id()}
mode={this.props.isSampleCopilotActive ? "Sample" : "User"}
/>
)}
</Fragment>
);
}
render(): JSX.Element {
const shouldScaleElements = this.state.showCopilotSidebar && this.isCopilotTabActive;
return (
<div data-test="QueryTab" style={{ display: "flex", flexDirection: "row", height: "100%" }}>
<div style={{ width: shouldScaleElements ? "70%" : "100%", height: "100%" }}>
{this.getEditorAndQueryResult()}
</div>
{shouldScaleElements && (
<div style={{ width: "30%", height: "100%" }}>
<QueryCopilotSidebar explorer={this.props.collection.container} />
</div>
)}
<div style={{ width: "100%", height: "100%" }}>{this.getEditorAndQueryResult()}</div>
</div>
);
}

View File

@@ -42,7 +42,6 @@ import { logConsoleProgress } from "Utils/NotificationConsoleUtils";
import create from "zustand";
import { client } from "../../../Common/CosmosClient";
import { handleError } from "../../../Common/ErrorHandlingUtils";
import { sampleDataClient } from "../../../Common/SampleDataClient";
import { ResultsViewProps } from "./QueryResultSection";
import { useIndexAdvisorStyles } from "./StylesAdvisor";
enum ResultsTabs {
@@ -583,8 +582,7 @@ export const IndexAdvisorTab: React.FC<{
query: queryEditorContent,
};
// Use sampleDataClient for CopilotSampleDB, regular client for other databases
const cosmosClient = databaseId === "CopilotSampleDB" ? sampleDataClient() : client();
const cosmosClient = client();
const sdkResponse = await cosmosClient
.database(databaseId)

View File

@@ -1,5 +1,5 @@
import { Spinner, SpinnerSize, Stack, Text } from "@fluentui/react";
import { PoolIdType } from "Common/Constants";
import { NotebookWorkspaceConnectionInfo } from "Contracts/DataModels";
import { MessageTypes } from "Contracts/ExplorerContracts";
import { NotebookTerminalComponent } from "Explorer/Controls/Notebook/NotebookTerminalComponent";
@@ -35,7 +35,7 @@ export const QuickstartTab: React.FC<QuickstartTabProps> = ({ explorer }: Quicks
});
useEffect(() => {
explorer.allocateContainer(PoolIdType.DefaultPoolId);
explorer.allocateContainer();
}, []);
return (

View File

@@ -2,7 +2,6 @@ import { Spinner, SpinnerSize, TooltipHost } from "@fluentui/react";
import { CollectionTabKind } from "Contracts/ViewModels";
import Explorer from "Explorer/Explorer";
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
import { QueryCopilotTab } from "Explorer/QueryCopilot/QueryCopilotTab";
import { FabricHomeScreen } from "Explorer/SplashScreen/FabricHome";
import { SplashScreen } from "Explorer/SplashScreen/SplashScreen";
import { ConnectTab } from "Explorer/Tabs/ConnectTab";
@@ -76,9 +75,6 @@ function TabNav({ tab, active, tabKind }: { tab?: Tab; active: boolean; tabKind?
const tabId = tab ? tab.tabId : "";
const getReactTabTitle = (): ko.Observable<string> => {
if (tabKind === ReactTabKind.QueryCopilot) {
return ko.observable("Query");
}
return ko.observable(ReactTabKind[tabKind]);
};
@@ -323,8 +319,6 @@ const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): J
) : (
<QuickstartTab explorer={explorer} />
);
case ReactTabKind.QueryCopilot:
return <QueryCopilotTab explorer={explorer} />;
default:
throw new Error(`Unsupported tab kind ${ReactTabKind[activeReactTab]}`);
}

View File

@@ -1,5 +1,5 @@
import { Spinner, SpinnerSize, Stack, Text } from "@fluentui/react";
import { PoolIdType } from "Common/Constants";
import { NotebookWorkspaceConnectionInfo } from "Contracts/DataModels";
import { MessageTypes } from "Contracts/ExplorerContracts";
import { NotebookTerminalComponent } from "Explorer/Controls/Notebook/NotebookTerminalComponent";
@@ -39,7 +39,7 @@ export const VcoreMongoQuickstartTab: React.FC<VCoreMongoQuickstartTabProps> = (
});
useEffect(() => {
explorer.allocateContainer(PoolIdType.DefaultPoolId);
explorer.allocateContainer();
}, []);
return (