Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions localization/l10n/bundle.l10n.json
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,16 @@
"comment": ["{0} is the number of selected rows"]
},
"Sort": "Sort",
"Resize": "Resize",
"Resize column '{0}'/{0} is the name of the column": {
"message": "Resize column '{0}'",
"comment": ["{0} is the name of the column"]
},
"Enter desired column width in pixels": "Enter desired column width in pixels",
"Column width must be at least {0} pixels./{0} is the minimum column width in pixels": {
"message": "Column width must be at least {0} pixels.",
"comment": ["{0} is the minimum column width in pixels"]
},
"Add new column": "Add new column",
"Table": "Table",
"Save": "Save",
Expand Down
14 changes: 14 additions & 0 deletions localization/xliff/vscode-mssql.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,10 @@
<trans-unit id="++CODE++bb7bef87d3a1f764c39c6df670038039c136d360153a1ced5c633afa9590fd36">
<source xml:lang="en">Column name cannot be empty</source>
</trans-unit>
<trans-unit id="++CODE++79304c2a3f7dd799711c04e0513ca9fce1762fbdbf0e8dbd378987d42e35fee5">
<source xml:lang="en">Column width must be at least {0} pixels.</source>
<note>{0} is the minimum column width in pixels</note>
</trans-unit>
<trans-unit id="++CODE++53aade77cd69a77bbb51bf8ca4e7ea8b282db75edce8883775e47042478d35b5">
<source xml:lang="en">Columns</source>
</trans-unit>
Expand Down Expand Up @@ -1174,6 +1178,9 @@
<trans-unit id="++CODE++91cf329b31a4b1a6c0bdec6de797b6a90ab9309490bd62ec38f98f2d0f6db423">
<source xml:lang="en">Enter description (optional)</source>
</trans-unit>
<trans-unit id="++CODE++657e6ba252bef59f38c0dbaab7e8e25d55503ba3a41d6ce527f92c88baea3576">
<source xml:lang="en">Enter desired column width in pixels</source>
</trans-unit>
<trans-unit id="++CODE++caaac8aa0d0641aea8406e7f1011aaeab33423fdd4ee9b3354ee88cc1487b0bf">
<source xml:lang="en">Enter hostname</source>
</trans-unit>
Expand Down Expand Up @@ -2602,6 +2609,13 @@
<trans-unit id="++CODE++daee7606b339f3c339076fe2c9f372a3ff40c8ee896005d829c7481b64ca5303">
<source xml:lang="en">Reset</source>
</trans-unit>
<trans-unit id="++CODE++2956e06ac0651084bbd5558dfe469615e9a5fc3072f60a09a9cb3c597a19324c">
<source xml:lang="en">Resize</source>
</trans-unit>
<trans-unit id="++CODE++fc71b6e1d435d817984f9c7394f47e21505efa2a9f81b5f3e17082ced1432cc7">
<source xml:lang="en">Resize column &apos;{0}&apos;</source>
<note>{0} is the name of the column</note>
</trans-unit>
<trans-unit id="++CODE++ae6d9c313ef115d3be932d158acd74f5ab4db5c068cdc2c10ade081168b185d5">
<source xml:lang="en">Resource Group</source>
</trans-unit>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
"@dagrejs/dagre": "^1.1.4",
"@eslint/compat": "^1.1.0",
"@fluentui-contrib/react-data-grid-react-window": "^1.2.0",
"@fluentui/react-components": "^9.72.2",
"@fluentui/react-components": "^9.72.3",
"@istanbuljs/nyc-config-typescript": "^1.0.2",
"@monaco-editor/react": "^4.6.0",
"@playwright/test": "^1.45.0",
Expand Down
3 changes: 2 additions & 1 deletion src/reactviews/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export const cmdAKeyboardShortcut = "⌘A";
export const ctrlAKeyboardShortcut = "Ctrl+A";
export const cmdCKeyboardShortcut = "⌘C";
export const ctrlCKeyboardShortcut = "Ctrl+C";
export const altShiftOKeyboardShortcut = "Shift+Alt+O";
export const altShiftOKeyboardShortcut = "Alt+Shift+O";
export const altShiftSKeyboardShortcut = "Alt+Shift+S";
16 changes: 16 additions & 0 deletions src/reactviews/common/locConstants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,22 @@ export class LocConstants {
}),
sort: l10n.t("Sort"),
filter: l10n.t("Filter"),
resize: l10n.t("Resize"),
resizeColumn: (columnName: string) => {
return l10n.t({
message: "Resize column '{0}'",
args: [columnName],
comment: ["{0} is the name of the column"],
});
},
enterDesiredColumnWidth: l10n.t("Enter desired column width in pixels"),
resizeValidationError: (minWidth: number) => {
return l10n.t({
message: "Column width must be at least {0} pixels.",
args: [minWidth],
comment: ["{0} is the minimum column width in pixels"],
});
},
};
}

Expand Down
6 changes: 4 additions & 2 deletions src/reactviews/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,13 @@ export function isMac(): boolean {
}

/**
* Checks if the meta key is pressed based on the user's OS.
* Checks if the meta key on Mac or Ctrl key on Windows/Linux is pressed.
* @param e The keyboard or mouse event to check.
* @returns True if the meta key is pressed, false otherwise.
*/
export function isMetaKeyPressed(e: KeyboardEvent | MouseEvent | React.KeyboardEvent): boolean {
export function isMetaOrCtrlKeyPressed(
e: KeyboardEvent | MouseEvent | React.KeyboardEvent,
): boolean {
return isMac() ? e.metaKey : e.ctrlKey;
}

Expand Down
4 changes: 2 additions & 2 deletions src/reactviews/pages/QueryResult/queryResultPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { makeStyles, shorthands } from "@fluentui/react-components";
import { useEffect } from "react";
import { QueryResultPane } from "./queryResultPane";
import { KeyCode } from "../../common/keys";
import { isMetaKeyPressed } from "../../common/utils";
import { isMetaOrCtrlKeyPressed } from "../../common/utils";

const useStyles = makeStyles({
root: {
Expand Down Expand Up @@ -95,7 +95,7 @@ export const QueryResult = () => {
// This is needed to stop the browser from selecting all the raw text in the webview when ctrl+a is pressed
useEffect(() => {
const handleKeyDown = async (e: KeyboardEvent): Promise<void> => {
if (isMetaKeyPressed(e) && e.code === KeyCode.KeyA) {
if (isMetaOrCtrlKeyPressed(e) && e.code === KeyCode.KeyA) {
e.preventDefault();
e.stopPropagation();
}
Expand Down
57 changes: 57 additions & 0 deletions src/reactviews/pages/QueryResult/queryResultStateProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import ColumnMenuPopup, {
FilterListItem,
FilterValue,
} from "./table/plugins/ColumnMenuPopup";
import { TableColumnResizeDialog } from "./table/TableColumnResizeDialog";

export interface ColumnFilterPopupOptions {
columnId: string;
Expand All @@ -36,8 +37,22 @@ export interface ColumnFilterPopupOptions {
onSortAscending: () => Promise<void>;
onSortDescending: () => Promise<void>;
currentSort: SortProperties;
onResize: () => void;
}

/**
* Options for opening the resize column dialog
*/
type ResizeColumnDialogState = {
open: boolean;
columnId: string;
columnName: string;
initialWidth: number;
gridId: string;
onSubmit: (width: number) => Promise<void> | void;
onDismiss: () => void;
};

export interface QueryResultReactProvider
extends Omit<ExecutionPlanProvider, "getExecutionPlan">,
CoreRPCs {
Expand Down Expand Up @@ -65,6 +80,12 @@ export interface QueryResultReactProvider
* @param type the type of file to open
*/
openFileThroughLink(content: string, type: string): void;
/**
* Opens the resize column dialog
* @param options options for the resize dialog
* @returns void
*/
openResizeDialog: (options: Partial<ResizeColumnDialogState>) => void;
}

export const QueryResultCommandsContext = createContext<QueryResultReactProvider | undefined>(
Expand All @@ -89,6 +110,16 @@ const QueryResultStateProvider: React.FC<QueryResultProviderProps> = ({ children
undefined,
);

const [resizeDialogState, setResizeDialogState] = useState<ResizeColumnDialogState>({
open: false,
columnId: "",
columnName: "",
initialWidth: 0,
gridId: "",
onDismiss: () => {},
onSubmit: () => {},
});

const hideFilterPopup = useCallback(() => {
setFilterPopupState((state) => {
if (state?.onDismiss) {
Expand Down Expand Up @@ -171,6 +202,13 @@ const QueryResultStateProvider: React.FC<QueryResultProviderProps> = ({ children
updateTotalCost: (addedCost: number) => {
extensionRpc.action("updateTotalCost", { addedCost });
},
openResizeDialog: (options: Partial<ResizeColumnDialogState>) => {
setResizeDialogState((state) => ({
...state,
...options,
open: true,
}));
},
}),
[extensionRpc, hideFilterPopup],
);
Expand Down Expand Up @@ -227,9 +265,28 @@ const QueryResultStateProvider: React.FC<QueryResultProviderProps> = ({ children
onClearSort={filterPopupState.onClearSort}
onSortAscending={filterPopupState.onSortAscending}
onSortDescending={filterPopupState.onSortDescending}
onResize={() => {
hideFilterPopup();
filterPopupState.onResize();
}}
currentSort={filterPopupState.currentSort}
/>
)}
{resizeDialogState.open && (
<TableColumnResizeDialog
open={resizeDialogState.open}
columnName={resizeDialogState.columnName}
initialWidth={resizeDialogState.initialWidth}
onSubmit={async (newWidth: number) => {
await resizeDialogState.onSubmit(newWidth);
setResizeDialogState((state) => ({ ...state, open: false }));
}}
onDismiss={() => {
resizeDialogState.onDismiss();
setResizeDialogState((state) => ({ ...state, open: false }));
}}
/>
)}
</QueryResultCommandsContext.Provider>
);
};
Expand Down
110 changes: 110 additions & 0 deletions src/reactviews/pages/QueryResult/table/TableColumnResizeDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import {
Button,
Dialog,
DialogActions,
DialogBody,
DialogContent,
DialogSurface,
DialogTitle,
Field,
Input,
} from "@fluentui/react-components";
import { useEffect, useState } from "react";
import { locConstants } from "../../../common/locConstants";
import { MAX_COLUMN_WIDTH_PX as maxWidth, MIN_COLUMN_WIDTH_PX as minWidth } from "../table/table";

interface TableColumnResizeDialogProps {
open: boolean;
columnName: string;
initialWidth: number;
onSubmit: (width: number) => Promise<void> | void;
onDismiss: () => void;
}

export const TableColumnResizeDialog: React.FC<TableColumnResizeDialogProps> = ({
open,
columnName,
initialWidth,
onSubmit,
onDismiss,
}) => {
const [inputValue, setInputValue] = useState<string>(Math.round(initialWidth).toString());

useEffect(() => {
if (open) {
setInputValue(Math.round(initialWidth).toString());
}
}, [initialWidth, open]);

const isValid = (inputValue: string) => {
const parsedWidth = parseInt(inputValue);
const isValid = Number.isFinite(parsedWidth) && parsedWidth >= minWidth;
return isValid;
};

if (!open) {
return null;
}

const handleSubmit = () => {
if (!isValid(inputValue)) {
return;
}
void onSubmit(parseInt(inputValue));
};

return (
<Dialog
open={open}
onOpenChange={(_, data) => {
if (!data.open) {
onDismiss();
}
}}>
<DialogSurface>
<DialogBody>
<DialogTitle>{locConstants.queryResult.resizeColumn(columnName)}</DialogTitle>
<DialogContent>
<Field
label={locConstants.queryResult.enterDesiredColumnWidth}
validationMessage={
isValid(inputValue)
? undefined
: locConstants.queryResult.resizeValidationError(minWidth)
}>
<Input
type="number"
value={inputValue}
min={minWidth}
max={maxWidth}
onChange={(_, data) => setInputValue(data.value)}
onKeyDown={(event) => {
if (event.key === "Enter") {
event.preventDefault();
handleSubmit();
}
}}
/>
</Field>
</DialogContent>
<DialogActions>
<Button
appearance="primary"
onClick={handleSubmit}
disabled={!isValid(inputValue)}>
{locConstants.queryResult.resize}
</Button>
<Button appearance="secondary" onClick={onDismiss}>
{locConstants.common.cancel}
</Button>
</DialogActions>
</DialogBody>
</DialogSurface>
</Dialog>
);
};
Loading