Skip to content

Commit

Permalink
refactory the results panel
Browse files Browse the repository at this point in the history
  • Loading branch information
Philip-Carneiro committed Sep 30, 2024
1 parent d23ded5 commit 7a09ec9
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 119 deletions.
2 changes: 1 addition & 1 deletion src/commands/serverCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ export function writeQueryResultsToView(
duration?: string,
isFromConnTree?: boolean,
): void {
commands.executeCommand("kdb.resultsPanel.update", result, isInsights, type);
commands.executeCommand("kdb.resultsPanel.update", result, isInsights);
if (!checkIfIsDatasource(type)) {
addQueryHistory(
query,
Expand Down
8 changes: 2 additions & 6 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -204,12 +204,8 @@ export async function activate(context: ExtensionContext) {
),
commands.registerCommand(
"kdb.resultsPanel.update",
(results: string, isInsights: boolean, dataSourceType?: string) => {
ext.resultsViewProvider.updateResults(
results,
isInsights,
dataSourceType,
);
(results: string, isInsights: boolean) => {
ext.resultsViewProvider.updateResults(results, isInsights);
},
),
commands.registerCommand("kdb.resultsPanel.clear", () => {
Expand Down
195 changes: 114 additions & 81 deletions src/services/resultsPanelProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@ import { ext } from "../extensionVariables";
import * as utils from "../utils/execution";
import { getNonce } from "../utils/getNonce";
import { getUri } from "../utils/getUri";
import { kdbOutputLog } from "../utils/core";

export class KdbResultsViewProvider implements WebviewViewProvider {
public static readonly viewType = "kdb-results";
private _view?: WebviewView;
public isInsights = false;
public _colorTheme: any;
private _view?: WebviewView;
private _results: string | string[] = "";

constructor(private readonly _extensionUri: Uri) {
Expand All @@ -48,10 +50,11 @@ export class KdbResultsViewProvider implements WebviewViewProvider {
localResourceRoots: [Uri.joinPath(this._extensionUri, "out")],
};

webviewView.webview.html = this._getWebviewContent("");
webviewView.webview.html = this._getWebviewContent();
this.updateWebView("");

webviewView.webview.onDidReceiveMessage((data) => {
webviewView.webview.html = this._getWebviewContent(data);
this.updateWebView(data);
});
webviewView.onDidChangeVisibility(() => {
ext.isResultsTabVisible = webviewView.visible;
Expand All @@ -62,19 +65,11 @@ export class KdbResultsViewProvider implements WebviewViewProvider {
});
}

public updateResults(
queryResults: any,
isInsights?: boolean,
dataSourceType?: string,
) {
public updateResults(queryResults: any, isInsights?: boolean) {
if (this._view) {
this._view.show?.(true);
this._view.webview.postMessage(queryResults);
this._view.webview.html = this._getWebviewContent(
queryResults,
isInsights,
dataSourceType,
);
this.isInsights = !!isInsights;
this.updateWebView(queryResults);
}
}

Expand Down Expand Up @@ -251,84 +246,122 @@ export class KdbResultsViewProvider implements WebviewViewProvider {
: "";
}

private _getWebviewContent(
queryResult: any,
isInsights?: boolean,
_dataSourceType?: string,
) {
public updateWebView(queryResult: any) {
ext.resultPanelCSV = "";
this._results = queryResult;
let result = "";
let gridOptions = undefined;
if (!this._view) {
kdbOutputLog("[Results Tab] No view to update", "ERROR");
return;
}
if (typeof queryResult === "string" || typeof queryResult === "number") {
result =
queryResult !== ""
? `<p class="results-txt">${queryResult
.toString()
.replace(/\n/g, "<br/>")}</p>`
: "<p>No results to show</p>";
} else if (queryResult) {
gridOptions = this.convertToGrid(queryResult, this.isInsights);
}
if (gridOptions) {
this._view.webview.postMessage({
command: "setGridOptions",
gridOptions: gridOptions,
});
} else {
this._view.webview.postMessage({
command: "setResultsContent",
results: result,
});
}
}

private _getWebviewContent() {
const agGridTheme = this.defineAgGridTheme();
if (this._view) {
const webviewUri = getUri(this._view.webview, this._extensionUri, [
"out",
"webview.js",
]);
const nonce = getNonce();
let result = "";
let gridOptions = undefined;
return /*html*/ `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="stylesheet" href="${this._getLibUri("reset.css")}" />
<link rel="stylesheet" href="${this._getLibUri("vscode.css")}" />
<link rel="stylesheet" href="${this._getLibUri("resultsPanel.css")}" />
<link rel="stylesheet" href="${this._getLibUri("ag-grid.min.css")}" />
<link rel="stylesheet" href="${this._getLibUri(
"ag-theme-alpine.min.css",
)}" />
<title>Q Results</title>
<script nonce="${nonce}" src="${this._getLibUri(
"ag-grid-community.min.js",
)}"></script>
</head>
<body>
<div id="results" class="results-view-container">
<div class="content-wrapper"></div>
</div>
<script type="module" nonce="${nonce}" src="${webviewUri}"></script>
<div id="grid" style="height: 100%; width:100%;" class="${agGridTheme}"></div>
<script nonce="${nonce}" >
const vscode = acquireVsCodeApi();
let gridApi;
let isGrid = false;
if (typeof queryResult === "string" || typeof queryResult === "number") {
result =
queryResult !== ""
? `<p class="results-txt">${queryResult
.toString()
.replace(/\n/g, "<br/>")}</p>`
: "<p>No results to show</p>";
} else if (queryResult) {
isGrid = true;
gridOptions = this.convertToGrid(queryResult, !!isInsights);
}
function saveColumnWidths() {
if (!gridApi) {return null};
return gridApi.getAllColumns().map(col => ({
colId: col.getColId(),
width: col.getActualWidth()
}));
}
result =
gridOptions === undefined
? result !== ""
? result
: "<p>No results to show</p>"
: "";
return /*html*/ `
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="stylesheet" href="${this._getLibUri("reset.css")}" />
<link rel="stylesheet" href="${this._getLibUri("vscode.css")}" />
<link rel="stylesheet" href="${this._getLibUri("resultsPanel.css")}" />
<link rel="stylesheet" href="${this._getLibUri("ag-grid.min.css")}" />
<link rel="stylesheet" href="${this._getLibUri(
"ag-theme-alpine.min.css",
)}" />
<title>Q Results</title>
<script nonce="${nonce}" src="${this._getLibUri(
"ag-grid-community.min.js",
)}"></script>
</head>
<body>
<div id="results" class="results-view-container">
<div class="content-wrapper">
${result}
</div>
</div>
<script type="module" nonce="${nonce}" src="${webviewUri}"></script>
<div id="grid" style="height: 100%; width:100%;" class="${agGridTheme}"></div>
<script nonce="${nonce}" >
document.addEventListener('DOMContentLoaded', () => {
if(${isGrid}){
const gridDiv = document.getElementById('grid');
const obj = ${JSON.stringify(gridOptions)};
const gridApi = agGrid.createGrid(gridDiv, obj);
document.getElementById("results").scrollIntoView();
}
});
document.addEventListener('contextmenu', (e) => {
e.stopImmediatePropagation()
}, true);
</script>
</body>
</html>
`;
function restoreColumnWidths(columnWidths) {
if (!gridApi || !columnWidths) return;
columnWidths.forEach(colWidth => {
gridApi.getColumnState().forEach(colState => {
if (colState.colId === colWidth.colId) {
colState.width = colWidth.width;
}
});
});
gridApi.setColumnState(gridApi.getColumnState());
}
window.addEventListener('message', event => {
const message = event.data;
if (message.command === 'setGridOptions') {
const columnWidths = saveColumnWidths();
const gridOptions = message.gridOptions;
const gridDiv = document.getElementById('grid');
const resultsDiv = document.querySelector('#results .content-wrapper');
resultsDiv.innerHTML = '';
gridDiv.innerHTML = '';
gridApi = agGrid.createGrid(gridDiv, gridOptions);
restoreColumnWidths(columnWidths);
document.getElementById("results").scrollIntoView();
} else if (message.command === 'setResultsContent') {
const resultsContent = message.results;
const resultsDiv = document.querySelector('#results .content-wrapper');
const gridDiv = document.getElementById('grid');
gridDiv.innerHTML = '';
resultsDiv.innerHTML = '';
resultsDiv.innerHTML = resultsContent;
}
});
document.addEventListener('contextmenu', (e) => {
e.stopImmediatePropagation();
}, true);
</script>
</body>
</html>
`;
} else {
return "";
}
Expand Down
3 changes: 2 additions & 1 deletion src/webview/styles/resultsPanel.css
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
html,
body {
height: 86vh;
width: 100%;
width: 99%;
padding: 0;
box-sizing: border-box;
-webkit-overflow-scrolling: touch;
}
Expand Down
1 change: 0 additions & 1 deletion test/suite/commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,6 @@ describe("serverCommand", () => {
"kdb.resultsPanel.update",
result,
false,
"WORKBOOK",
);

executeCommandStub.restore();
Expand Down
32 changes: 3 additions & 29 deletions test/suite/panels.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -411,35 +411,9 @@ describe("WebPanels", () => {
resultsPanel["_view"] = view;
});

it("returns a table", () => {
const input = [
{ id: 1, test: "test1" },
{ id: 2, test: "test2" },
];
const expectedOutput = `agGrid.createGrid(gridDiv, obj)`;
const stub = sinon
.stub(resultsPanel, "convertToGrid")
.returns(expectedOutput);
const actualOutput = resultsPanel["_getWebviewContent"](input);
console.log(actualOutput);
assert.strictEqual(typeof actualOutput, "string");
assert.ok(actualOutput.includes(expectedOutput));
stub.restore();
});

it("returns string results", () => {
const input = "Test";
const expectedOutput = `<p class="results-txt">Test</p>`;
const actualOutput = resultsPanel["_getWebviewContent"](input);
assert.strictEqual(typeof actualOutput, "string");
assert.ok(actualOutput.includes(expectedOutput));
});

it("returns no results", () => {
const input = "";
const expectedOutput = `<p>No results to show</p>`;
const actualOutput = resultsPanel["_getWebviewContent"](input);
assert.strictEqual(typeof actualOutput, "string");
it("should render the results tab", () => {
const expectedOutput = ` id="results" class="results-view-container"`;
const actualOutput = resultsPanel["_getWebviewContent"]();
assert.ok(actualOutput.includes(expectedOutput));
});
});
Expand Down

0 comments on commit 7a09ec9

Please sign in to comment.