* remove query result auto focus after tab switch

* fix multi result in one batch

* fix grid f font

* message styling

* fix grgird header styling

* improve placeholder msg styling

* add a button to reveal query result panel

* hide message line

* add config check altlthough not actually needed

* use focus command insttead of show()
This commit is contained in:
Hai Cao 2024-10-15 23:01:06 -07:00 коммит произвёл Benjin Dubishar (from Dev Box)
Родитель d4e89e9b5d
Коммит 08c50e8ffa
12 изменённых файлов: 110 добавлений и 31 удалений

Просмотреть файл

@ -1682,6 +1682,9 @@
<trans-unit id="mssql.removeAadAccount"> <trans-unit id="mssql.removeAadAccount">
<source xml:lang="en">Remove Microsoft Entra Account</source> <source xml:lang="en">Remove Microsoft Entra Account</source>
</trans-unit> </trans-unit>
<trans-unit id="mssql.revealQueryResultPanel">
<source xml:lang="en">Reveal Query Result Panel</source>
</trans-unit>
<trans-unit id="mssql.runQueryHistory"> <trans-unit id="mssql.runQueryHistory">
<source xml:lang="en">Run Query</source> <source xml:lang="en">Run Query</source>
</trans-unit> </trans-unit>

Просмотреть файл

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><style type="text/css">.icon-canvas-transparent{opacity:0;fill:#F6F6F6;} .icon-vs-out{fill:#F6F6F6;} .icon-vs-bg{fill:#424242;} .icon-vs-fg{fill:#F0EFF1;}</style><path class="icon-canvas-transparent" d="M16 16h-16v-16h16v16z" id="canvas"/><path class="icon-vs-out" d="M16 15h-15v-14h15v14z" id="outline"/><path class="icon-vs-bg" d="M2 2v12h13v-12h-13zm4 11h-3v-2h3v2zm0-3h-3v-2h3v2zm0-3h-3v-2h3v2zm4 6h-3v-2h3v2zm0-3h-3v-2h3v2zm0-3h-3v-2h3v2zm4 6h-3v-2h3v2zm0-3h-3v-2h3v2zm0-3h-3v-2h3v2z" id="iconBg"/><path class="icon-vs-fg" d="M14 7h-3v-2h3v2zm0 1h-3v2h3v-2zm-4-3h-3v2h3v-2zm0 3h-3v2h3v-2zm-4-3h-3v2h3v-2zm0 3h-3v2h3v-2zm8 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0h-3v2h3v-2z" id="iconFg"/></svg>

После

Ширина:  |  Высота:  |  Размер: 755 B

Просмотреть файл

@ -308,6 +308,11 @@
"when": "editorLangId == sql && resourcePath in mssql.runningQueries", "when": "editorLangId == sql && resourcePath in mssql.runningQueries",
"group": "navigation@2" "group": "navigation@2"
}, },
{
"command": "mssql.revealQueryResultPanel",
"when": "editorLangId == sql && config.mssql.enableRichExperiences && view.queryResult.visible == false",
"group": "navigation@2"
},
{ {
"command": "mssql.connect", "command": "mssql.connect",
"when": "editorLangId == sql && resource not in mssql.connections", "when": "editorLangId == sql && resource not in mssql.connections",
@ -571,6 +576,12 @@
"category": "MS SQL", "category": "MS SQL",
"icon": "$(debug-stop)" "icon": "$(debug-stop)"
}, },
{
"command": "mssql.revealQueryResultPanel",
"title": "%mssql.revealQueryResultPanel%",
"category": "MS SQL",
"icon": "media/revealQueryResult.svg"
},
{ {
"command": "mssql.connect", "command": "mssql.connect",
"title": "%mssql.connect%", "title": "%mssql.connect%",

Просмотреть файл

@ -2,6 +2,7 @@
"mssql.runQuery":"Execute Query", "mssql.runQuery":"Execute Query",
"mssql.runCurrentStatement":"Execute Current Statement", "mssql.runCurrentStatement":"Execute Current Statement",
"mssql.cancelQuery":"Cancel Query", "mssql.cancelQuery":"Cancel Query",
"mssql.revealQueryResultPanel":"Reveal Query Result Panel",
"mssql.changeDatabase":"Change Database", "mssql.changeDatabase":"Change Database",
"mssql.addObjectExplorer":"Add Connection", "mssql.addObjectExplorer":"Add Connection",
"mssql.scriptSelect":"Select Top 1000", "mssql.scriptSelect":"Select Top 1000",

Просмотреть файл

@ -23,6 +23,7 @@ export const folderLabel = "Folder";
export const cmdRunQuery = "mssql.runQuery"; export const cmdRunQuery = "mssql.runQuery";
export const cmdRunCurrentStatement = "mssql.runCurrentStatement"; export const cmdRunCurrentStatement = "mssql.runCurrentStatement";
export const cmdCancelQuery = "mssql.cancelQuery"; export const cmdCancelQuery = "mssql.cancelQuery";
export const cmdrevealQueryResultPanel = "mssql.revealQueryResultPanel";
export const cmdConnect = "mssql.connect"; export const cmdConnect = "mssql.connect";
export const cmdDisconnect = "mssql.disconnect"; export const cmdDisconnect = "mssql.disconnect";
export const cmdChangeDatabase = "mssql.changeDatabase"; export const cmdChangeDatabase = "mssql.changeDatabase";

Просмотреть файл

@ -1080,6 +1080,16 @@ export default class MainController implements vscode.Disposable {
}, },
), ),
); );
// Reveal Query Results command
this._context.subscriptions.push(
vscode.commands.registerCommand(
Constants.cmdrevealQueryResultPanel,
() => {
vscode.commands.executeCommand("queryResult.focus");
},
),
);
} }
/** /**

Просмотреть файл

@ -38,12 +38,17 @@ export class ReactWebviewViewController<State, Reducers>
} }
/** /**
* Displays the webview in the foreground * returns if the webview is visible
* @param viewColumn The view column that the webview will be displayed in
*/ */
public revealToForeground( public isVisible(): boolean {
viewColumn: vscode.ViewColumn = vscode.ViewColumn.One, return this._webviewView.visible;
): void {} }
/**
* Displays the webview in the foreground
*/
public revealToForeground(): void {
this._webviewView.show(true);
}
public resolveWebviewView( public resolveWebviewView(
webviewView: vscode.WebviewView, webviewView: vscode.WebviewView,

Просмотреть файл

@ -425,9 +425,10 @@ export class SqlOutputContentProvider {
.get(uri) .get(uri)
.proxy.sendEvent("resultSet", resultSet); .proxy.sendEvent("resultSet", resultSet);
} else { } else {
this._queryResultWebviewController.getQueryResultState( this._queryResultWebviewController.addResultSetSummary(
uri, uri,
).resultSetSummaries[resultSet.batchId] = resultSet; resultSet,
);
} }
}, },
); );

Просмотреть файл

@ -48,7 +48,6 @@ export class QueryResultWebviewController extends ReactWebviewViewController<
const uri = editor?.document?.uri?.toString(true); const uri = editor?.document?.uri?.toString(true);
if (uri && this._queryResultStateMap.has(uri)) { if (uri && this._queryResultStateMap.has(uri)) {
this.state = this.getQueryResultState(uri); this.state = this.getQueryResultState(uri);
vscode.commands.executeCommand("queryResult.focus");
} else { } else {
this.state = { this.state = {
resultSetSummaries: {}, resultSetSummaries: {},
@ -259,6 +258,19 @@ export class QueryResultWebviewController extends ReactWebviewViewController<
return res; return res;
} }
public addResultSetSummary(
uri: string,
resultSetSummary: qr.ResultSetSummary,
) {
let state = this.getQueryResultState(uri);
const batchId = resultSetSummary.batchId;
const resultId = resultSetSummary.id;
if (!state.resultSetSummaries[batchId]) {
state.resultSetSummaries[batchId] = {};
}
state.resultSetSummaries[batchId][resultId] = resultSetSummary;
}
public setSqlOutputContentProvider( public setSqlOutputContentProvider(
provider: SqlOutputContentProvider, provider: SqlOutputContentProvider,
): void { ): void {

Просмотреть файл

@ -62,6 +62,9 @@ const useStyles = makeStyles({
width: "100%", width: "100%",
position: "relative", position: "relative",
display: "flex", display: "flex",
fontFamily: "Menlo, Monaco, 'Courier New', monospace",
fontWeight: "normal",
fontSize: "12px",
}, },
queryResultPaneOpenButton: { queryResultPaneOpenButton: {
position: "absolute", position: "absolute",
@ -77,11 +80,23 @@ const useStyles = makeStyles({
}, },
}, },
messagesRows: { messagesRows: {
height: "18px",
fontSize: "12px",
flexDirection: "row", flexDirection: "row",
...shorthands.padding("10px"), ...shorthands.padding("10px"),
"> *": { "> *": {
marginRight: "10px", marginRight: "10px",
}, },
borderBottom: "none",
},
noResultMessage: {
fontSize: "14px",
margin: "10px 0 0 10px",
},
hidePanelLink: {
fontSize: "14px",
margin: "10px 0 0 10px",
cursor: "pointer",
}, },
}); });
@ -178,23 +193,22 @@ export const QueryResultPane = () => {
const gridRefs = useRef<ResultGridHandle[]>([]); const gridRefs = useRef<ResultGridHandle[]>([]);
const renderGrid = (idx: number) => { const renderGrid = (
const divId = `grid-parent-${idx}`; batchId: number,
resultId: number,
gridCount: number,
totalResultCount: number,
) => {
const divId = `grid-parent-${batchId}-${resultId}`;
return ( return (
<div <div
id={divId} id={divId}
className={classes.queryResultContainer} className={classes.queryResultContainer}
style={{ style={{
height: height:
Object.keys(metadata?.resultSetSummaries ?? []) totalResultCount === 1
.length === 1
? "100%" ? "100%"
: ( : (100 / totalResultCount).toString() + "%",
100 /
Object.keys(
metadata?.resultSetSummaries ?? [],
).length
).toString() + "%",
}} }}
> >
<ResultGrid <ResultGrid
@ -205,9 +219,8 @@ export const QueryResultPane = () => {
return webViewState.extensionRpc return webViewState.extensionRpc
.call("getRows", { .call("getRows", {
uri: metadata?.uri, uri: metadata?.uri,
batchId: batchId: batchId,
metadata?.resultSetSummaries[idx]?.batchId, resultId: resultId,
resultId: metadata?.resultSetSummaries[idx]?.id,
rowStart: offset, rowStart: offset,
numberOfRows: count, numberOfRows: count,
}) })
@ -217,8 +230,9 @@ export const QueryResultPane = () => {
} }
let r = response as qr.ResultSetSubset; let r = response as qr.ResultSetSubset;
var columnLength = var columnLength =
metadata?.resultSetSummaries[idx] metadata?.resultSetSummaries[batchId][
?.columnInfo?.length; resultId
]?.columnInfo?.length;
// if the result is an execution plan xml, // if the result is an execution plan xml,
// get the execution plan graph from it // get the execution plan graph from it
if (metadata?.isExecutionPlan) { if (metadata?.isExecutionPlan) {
@ -251,15 +265,19 @@ export const QueryResultPane = () => {
}); });
}); });
}} }}
ref={(gridRef) => (gridRefs.current[idx] = gridRef!)} ref={(gridRef) => (gridRefs.current[gridCount] = gridRef!)}
resultSetSummary={metadata?.resultSetSummaries[idx]} resultSetSummary={
metadata?.resultSetSummaries[batchId][resultId]
}
divId={divId} divId={divId}
uri={metadata?.uri} uri={metadata?.uri}
webViewState={webViewState} webViewState={webViewState}
/> />
<CommandBar <CommandBar
uri={metadata?.uri} uri={metadata?.uri}
resultSetSummary={metadata?.resultSetSummaries[idx]} resultSetSummary={
metadata?.resultSetSummaries[batchId][resultId]
}
/> />
</div> </div>
); );
@ -268,12 +286,22 @@ export const QueryResultPane = () => {
const renderGridPanel = () => { const renderGridPanel = () => {
const grids = []; const grids = [];
gridRefs.current.forEach((r) => r?.refreshGrid()); gridRefs.current.forEach((r) => r?.refreshGrid());
let totalResultCount = 0;
Object.values(metadata?.resultSetSummaries ?? []).forEach((v) => {
totalResultCount += Object.keys(v).length;
});
let count = 0;
for ( for (
let i = 0; let i = 0;
i < Object.keys(metadata?.resultSetSummaries ?? []).length; i < Object.keys(metadata?.resultSetSummaries ?? []).length;
i++ i++
) { ) {
grids.push(renderGrid(i)); var batch = metadata?.resultSetSummaries[i];
for (let j = 0; j < Object.keys(batch ?? []).length; j++) {
grids.push(renderGrid(i, j, count, totalResultCount));
count++;
}
} }
return grids; return grids;
}; };
@ -304,9 +332,12 @@ export const QueryResultPane = () => {
return !metadata || !hasResultsOrMessages(metadata) ? ( return !metadata || !hasResultsOrMessages(metadata) ? (
<div> <div>
<div>{locConstants.queryResult.noResultMessage}</div> <div className={classes.noResultMessage}>
{locConstants.queryResult.noResultMessage}
</div>
<div> <div>
<Link <Link
className={classes.hidePanelLink}
onClick={async () => { onClick={async () => {
await webViewState.extensionRpc.call("executeCommand", { await webViewState.extensionRpc.call("executeCommand", {
command: "workbench.action.togglePanel", command: "workbench.action.togglePanel",
@ -391,7 +422,10 @@ export const QueryResultPane = () => {
<TableBody> <TableBody>
{rows.map((row, index) => { {rows.map((row, index) => {
return ( return (
<TableRow key={index}> <TableRow
key={index}
className={classes.messagesRows}
>
<TableCell <TableCell
{...columnSizing_unstable.getTableCellProps( {...columnSizing_unstable.getTableCellProps(
"time", "time",

Просмотреть файл

@ -74,6 +74,6 @@ export const defaultTableStyles: ITableStyles = {
listSelectionOutline: "var(--vscode-contrastActiveBorder)", listSelectionOutline: "var(--vscode-contrastActiveBorder)",
listHoverOutline: "var(--vscode-contrastActiveBorder)", listHoverOutline: "var(--vscode-contrastActiveBorder)",
listInactiveFocusOutline: "var(--vscode-list-inactiveFocusOutline)", listInactiveFocusOutline: "var(--vscode-list-inactiveFocusOutline)",
tableHeaderBackground: "var(--vscode-table-headerBackground)", tableHeaderBackground: "var(--vscode-badge-background)",
tableHeaderForeground: "var(--vscode-table-headerForeground)", tableHeaderForeground: "var(--vscode-table-headerForeground)",
}; };

Просмотреть файл

@ -44,7 +44,7 @@ export interface QueryResultTabStates {
export interface QueryResultWebviewState extends ExecutionPlanWebviewState { export interface QueryResultWebviewState extends ExecutionPlanWebviewState {
uri?: string; uri?: string;
resultSetSummaries: { [key: number]: ResultSetSummary }; resultSetSummaries: Record<number, Record<number, ResultSetSummary>>;
messages: IMessage[]; messages: IMessage[];
tabStates?: QueryResultTabStates; tabStates?: QueryResultTabStates;
isExecutionPlan?: boolean; isExecutionPlan?: boolean;