Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filter state management #18602

Merged
merged 17 commits into from
Feb 5, 2025
1 change: 1 addition & 0 deletions src/controllers/mainController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1646,6 +1646,7 @@ export default class MainController implements vscode.Disposable {
if (editor.document.getText(selectionToTrim).trim().length === 0) {
return;
}
self._outputContentProvider.clearStorage(uri);

await self._outputContentProvider.runQuery(
self._statusview,
Expand Down
1 change: 1 addition & 0 deletions src/controllers/reactWebviewBaseController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ export abstract class ReactWebviewBaseController<State, Reducers>
export enum DefaultWebviewNotifications {
updateState = "updateState",
onDidChangeTheme = "onDidChangeTheme",
deleteFilters = "deleteFilters",
cssuh marked this conversation as resolved.
Show resolved Hide resolved
}

export type ReducerResponse<T> = T | Promise<T>;
8 changes: 8 additions & 0 deletions src/models/sqlOutputContentProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -868,4 +868,12 @@ export class SqlOutputContentProvider {
set setResultsMap(setMap: Map<string, QueryRunnerState>) {
this._queryResultsMap = setMap;
}

public clearStorage(uri: string) {
if (this.isOpenQueryResultsInTabByDefaultEnabled) {
this._queryResultWebviewController.clearStorage(uri, true);
} else {
this._queryResultWebviewController.clearStorage(uri, false);
}
}
}
29 changes: 26 additions & 3 deletions src/queryResult/queryResultWebViewController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
recordLength,
registerCommonRequestHandlers,
} from "./utils";
import { DefaultWebviewNotifications } from "../controllers/reactWebviewBaseController";

export class QueryResultWebviewController extends ReactWebviewViewController<
qr.QueryResultWebviewState,
Expand Down Expand Up @@ -54,7 +55,6 @@ export class QueryResultWebviewController extends ReactWebviewViewController<
resultPaneTab: qr.QueryResultPaneTabs.Messages,
},
executionPlanState: {},
filterState: {},
fontSettings: {},
});

Expand All @@ -72,7 +72,6 @@ export class QueryResultWebviewController extends ReactWebviewViewController<
tabStates: undefined,
isExecutionPlan: false,
executionPlanState: {},
filterState: {},
fontSettings: {
fontSize: this.getFontSizeConfig(),

Expand Down Expand Up @@ -264,7 +263,6 @@ export class QueryResultWebviewController extends ReactWebviewViewController<
xmlPlans: {},
},
}),
filterState: {},
fontSettings: {
fontSize: this.getFontSizeConfig(),
fontFamily: this.getFontFamilyConfig(),
Expand Down Expand Up @@ -412,4 +410,29 @@ export class QueryResultWebviewController extends ReactWebviewViewController<
});
return total;
}

public clearStorage(uri: string, usePanelController: boolean) {
if (usePanelController) {
this._queryResultWebviewPanelControllerMap
.get(uri)
.postNotification(
DefaultWebviewNotifications.deleteFilters,
uri,
);
} else {
try {
this._queryResultWebviewPanelControllerMap
.get(uri)
.postNotification(
DefaultWebviewNotifications.deleteFilters,
uri,
);
} catch {
cssuh marked this conversation as resolved.
Show resolved Hide resolved
this.postNotification(
DefaultWebviewNotifications.deleteFilters,
uri,
);
}
}
}
}
1 change: 0 additions & 1 deletion src/queryResult/queryResultWebviewPanelController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export class QueryResultWebviewPanelController extends ReactWebviewPanelControll
resultPaneTab: qr.QueryResultPaneTabs.Messages,
},
executionPlanState: {},
filterState: {},
fontSettings: {},
},
{
Expand Down
12 changes: 0 additions & 12 deletions src/queryResult/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,6 @@ export function registerCommonRequestHandlers(
return state;
},
);
webviewController.registerReducer(
"setFilterState",
async (state, payload) => {
state.filterState[payload.filterState.columnDef] = {
filterValues: payload.filterState.filterValues,
columnDef: payload.filterState.columnDef,
seachText: payload.filterState.seachText,
sorted: payload.filterState.sorted,
};
return state;
},
);
webviewController.registerReducer(
"getExecutionPlan",
async (state, payload) => {
Expand Down
51 changes: 51 additions & 0 deletions src/reactviews/common/singletonStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

class SingletonStore {
private static instance: SingletonStore;
private store: Map<string, any>;

// Private constructor to prevent instantiation from outside
private constructor() {
this.store = new Map<string, any>();
}

// Method to get the single instance of the store
public static getInstance(): SingletonStore {
if (!SingletonStore.instance) {
SingletonStore.instance = new SingletonStore();
}
return SingletonStore.instance;
}

// Method to set a value in the store
public set(key: string, value: any): void {
this.store.set(key, value);
}

// Method to get a value from the store
public get<T>(key: string): T | undefined {
return this.store.get(key);
}

// Method to check if a key exists
public has(key: string): boolean {
return this.store.has(key);
}

// Method to delete a key-value pair
public delete(key: string): boolean {
return this.store.delete(key);
}

// Method to clear the store
public clear(): void {
this.store.clear();
}
}

// Export the singleton instance
const store = SingletonStore.getInstance();
export default store;
9 changes: 9 additions & 0 deletions src/reactviews/common/vscodeWebviewProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { LocConstants } from "./locConstants";
import { WebviewApi } from "vscode-webview";
import { WebviewRpc } from "./rpc";
import { webviewTheme } from "./theme";
import singletonStore from "./singletonStore";
import {
LoggerLevel,
WebviewTelemetryActionEvent,
Expand Down Expand Up @@ -143,6 +144,14 @@ export function VscodeWebviewProvider<State, Reducers>({
setState(params as State);
});

extensionRpc.subscribe(
"vscodeWebviewProvider",
"deleteFilters",
(params) => {
singletonStore.delete(params as string);
},
);

function isInitialized(): boolean {
return state !== undefined;
}
Expand Down
2 changes: 2 additions & 0 deletions src/reactviews/pages/QueryResult/queryResultPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ export const QueryResultPane = () => {
gridCount: number,
) => {
const divId = `grid-parent-${batchId}-${resultId}`;
const gridId = `resultGrid-${batchId}-${resultId}`;
return (
<div
id={divId}
Expand Down Expand Up @@ -360,6 +361,7 @@ export const QueryResultPane = () => {
webViewState={webViewState}
state={state}
linkHandler={linkHandler}
gridId={gridId}
/>
<CommandBar
uri={metadata?.uri}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
WebviewContextProps,
} from "../../common/vscodeWebviewProvider";
import { ReactNode, createContext } from "react";
import { ColumnFilterState } from "./table/interfaces";
import { getCoreRPCs } from "../../common/utils";

export interface QueryResultState
Expand Down Expand Up @@ -46,13 +45,6 @@ const QueryResultStateProvider: React.FC<QueryResultContextProps> = ({
tabId: tabId,
});
},
setFilterState: function (
filterState: ColumnFilterState,
): void {
webViewState?.extensionRpc.action("setFilterState", {
filterState: filterState,
});
},
getExecutionPlan: function (uri: string): void {
webViewState?.extensionRpc.action("getExecutionPlan", {
uri: uri,
Expand Down
2 changes: 2 additions & 0 deletions src/reactviews/pages/QueryResult/resultGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface ResultGridProps {
gridParentRef?: React.RefObject<HTMLDivElement>;
state: QueryResultState;
linkHandler: (fileContent: string, fileType: string) => void;
gridId: string;
}

export interface ResultGridHandle {
Expand Down Expand Up @@ -288,6 +289,7 @@ const ResultGrid = forwardRef<ResultGridHandle, ResultGridProps>(
props.webViewState!,
props.state,
props.linkHandler!,
props.gridId,
{ dataProvider: dataProvider, columns: columns },
tableOptions,
props.gridParentRef,
Expand Down
15 changes: 15 additions & 0 deletions src/reactviews/pages/QueryResult/table/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ export interface ColumnFilterState {
columnDef: string;
}

/**
* Maps all the column filters for a specific grid ID
*/
export type GridColumnMap = Record<string, ColumnFilterMap[]>;

/**
* Maps the column filter state for a specific column
*/
export type ColumnFilterMap = Record<string, ColumnFilterState[]>;

export interface GridFilters {
gridId: string;
columnFilters: ColumnFilterState;
}

export interface GridSortState {
field: string;
sortAsc: boolean;
Expand Down
Loading
Loading