[Query Copilot] Query Copilot button dropdown and shortcut (#1582)

* Copilot dropdown implementation

* additional changes

* added unit test for key event

* Additional test changes

---------

Co-authored-by: Predrag Klepic <v-prklepic@microsoft.com>
This commit is contained in:
Predrag Klepic 2023-08-21 16:17:06 +02:00 committed by GitHub
parent 986dbe7d54
commit ebd40cb9b0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 73 additions and 9 deletions

View File

@ -0,0 +1,34 @@
import { fireEvent, render } from "@testing-library/react";
import QueryTabComponent, { IQueryTabComponentProps } from "Explorer/Tabs/QueryTab/QueryTabComponent";
import { useQueryCopilot } from "hooks/useQueryCopilot";
import React from "react";
jest.mock("Explorer/Controls/Editor/EditorReact");
describe("QueryTabComponent", () => {
const mockStore = useQueryCopilot.getState();
beforeEach(() => {
mockStore.showCopilotSidebar = false;
mockStore.setShowCopilotSidebar = jest.fn();
});
beforeEach(() => jest.clearAllMocks());
it("should launch Copilot when ALT+C is pressed", () => {
const propsMock: Readonly<IQueryTabComponentProps> = ({
collection: { databaseId: "CopilotSampleDb" },
onTabAccessor: () => jest.fn(),
isExecutionError: false,
tabId: "mockTabId",
tabsBaseInstance: {
updateNavbarWithTabsButtons: () => jest.fn(),
},
} as unknown) as IQueryTabComponentProps;
const { container } = render(<QueryTabComponent {...propsMock} />);
const launchCopilotButton = container.querySelector(".queryEditorWatermarkText");
fireEvent.keyDown(launchCopilotButton, { key: "c", altKey: true });
expect(mockStore.setShowCopilotSidebar).toHaveBeenCalledWith(true);
});
});

View File

@ -184,6 +184,12 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
}); });
} }
public handleCopilotKeyDown = (event: KeyboardEvent): void => {
if (this.isCopilotTabActive && event.altKey && event.key === "c") {
this.launchQueryCopilotChat();
}
};
public onToggleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): boolean => { public onToggleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>): boolean => {
if (event.key === NormalizedEventKey.LeftArrow) { if (event.key === NormalizedEventKey.LeftArrow) {
this.toggleResult(); this.toggleResult();
@ -290,15 +296,36 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
} }
if (this.launchCopilotButton.visible && this.isCopilotTabActive) { if (this.launchCopilotButton.visible && this.isCopilotTabActive) {
const label = "Launch Copilot"; const mainButtonLabel = "Launch Copilot";
buttons.push({ const chatPaneLabel = "Open Copilot in chat pane (ALT+C)";
iconSrc: LaunchCopilot, const copilotSettingLabel = "Copilot settings";
iconAlt: label,
const openCopilotChatButton: CommandButtonComponentProps = {
iconAlt: chatPaneLabel,
onCommandClick: this.launchQueryCopilotChat, onCommandClick: this.launchQueryCopilotChat,
commandButtonLabel: label, commandButtonLabel: chatPaneLabel,
ariaLabel: label, ariaLabel: chatPaneLabel,
hasPopup: false, hasPopup: false,
}); };
const copilotSettingsButton: CommandButtonComponentProps = {
iconAlt: copilotSettingLabel,
onCommandClick: () => undefined,
commandButtonLabel: copilotSettingLabel,
ariaLabel: copilotSettingLabel,
hasPopup: false,
};
const launchCopilotButton = {
iconSrc: LaunchCopilot,
iconAlt: mainButtonLabel,
onCommandClick: this.launchQueryCopilotChat,
commandButtonLabel: mainButtonLabel,
ariaLabel: mainButtonLabel,
hasPopup: false,
children: [openCopilotChatButton, copilotSettingsButton],
};
buttons.push(launchCopilotButton);
} }
return buttons; return buttons;
@ -348,10 +375,12 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
}); });
useCommandBar.getState().setContextButtons(this.getTabsButtons()); useCommandBar.getState().setContextButtons(this.getTabsButtons());
document.addEventListener("keydown", this.handleCopilotKeyDown);
} }
componentWillUnmount(): void { componentWillUnmount(): void {
this.unsubscribeCopilotSidebar(); this.unsubscribeCopilotSidebar();
document.removeEventListener("keydown", this.handleCopilotKeyDown);
} }
private getEditorAndQueryResult(): JSX.Element { private getEditorAndQueryResult(): JSX.Element {
@ -389,12 +418,13 @@ export default class QueryTabComponent extends React.Component<IQueryTabComponen
} }
render(): JSX.Element { render(): JSX.Element {
const shouldScaleElements = this.state.showCopilotSidebar && this.isCopilotTabActive;
return ( return (
<div style={{ display: "flex", flexDirection: "row", height: "100%" }}> <div style={{ display: "flex", flexDirection: "row", height: "100%" }}>
<div style={{ width: this.state.showCopilotSidebar ? "70%" : "100%", height: "100%" }}> <div style={{ width: shouldScaleElements ? "70%" : "100%", height: "100%" }}>
{this.getEditorAndQueryResult()} {this.getEditorAndQueryResult()}
</div> </div>
{this.state.showCopilotSidebar && this.isCopilotTabActive && ( {shouldScaleElements && (
<div style={{ width: "30%", height: "100%" }}> <div style={{ width: "30%", height: "100%" }}>
<QueryCopilotSidebar /> <QueryCopilotSidebar />
</div> </div>