diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.fixture.ts b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.fixture.ts index 402d7e6a1ce6..0332b5ad5f4a 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.fixture.ts +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.fixture.ts @@ -271,6 +271,7 @@ const statementsPagePropsFixture: StatementsPageProps = { ascending: false, columnTitle: "executionCount" }, + search: "", filters: { app: "", timeNumber: "0", diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.selectors.ts b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.selectors.ts index 782f0a57f952..c6bdd1575405 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.selectors.ts +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.selectors.ts @@ -250,3 +250,8 @@ export const selectFilters = createSelector( localStorageSelector, localStorage => localStorage["filters/StatementsPage"], ); + +export const selectSearch = createSelector( + localStorageSelector, + localStorage => localStorage["search/StatementsPage"], +); diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx index 39bd693a019e..5c70e4f567c8 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPage.tsx @@ -86,7 +86,7 @@ export interface StatementsPageDispatchProps { dismissAlertMessage: () => void; onActivateStatementDiagnostics: (statement: string) => void; onDiagnosticsModalOpen?: (statement: string) => void; - onSearchComplete?: (results: AggregateStatistics[]) => void; + onSearchComplete?: (query: string) => void; onPageChanged?: (newPage: number) => void; onSortingChange?: ( name: string, @@ -112,11 +112,11 @@ export interface StatementsPageStateProps { nodeRegions: { [key: string]: string }; sortSetting: SortSetting; filters: Filters; + search: string; isTenant?: UIConfigState["isTenant"]; } export interface StatementsPageState { - search?: string; pagination: ISortedTablePagination; filters?: Filters; activeFilters?: number; @@ -148,7 +148,6 @@ export class StatementsPage extends React.Component< pageSize: 20, current: 1, }, - search: "", }; const stateFromHistory = this.getStateFromHistory(); this.state = merge(defaultState, stateFromHistory); @@ -156,29 +155,39 @@ export class StatementsPage extends React.Component< } getStateFromHistory = (): Partial => { - const { history, sortSetting, filters } = this.props; + const { + history, + search, + sortSetting, + filters, + onSearchComplete, + onFilterChange, + onSortingChange, + } = this.props; const searchParams = new URLSearchParams(history.location.search); // Search query. const searchQuery = searchParams.get("q") || undefined; + if (onSearchComplete && searchQuery && search != searchQuery) { + onSearchComplete(searchQuery); + } // Sort Settings. handleSortSettingFromQueryString( "Statements", history.location.search, sortSetting, - this.props.onSortingChange, + onSortingChange, ); // Filters. const latestFilter = handleFiltersFromQueryString( history, filters, - this.props.onFilterChange, + onFilterChange, ); return { - search: searchQuery, filters: latestFilter, activeFilters: calculateActiveFilters(latestFilter), }; @@ -235,31 +244,39 @@ export class StatementsPage extends React.Component< } updateQueryParamsOnTabSwitch(): void { - updateFiltersQueryParamsOnTab( - "Statements", - this.state.filters, - this.props.history, - ); + const { history, search, sortSetting } = this.props; + const tab = "Statements"; + // Search. + const searchParams = new URLSearchParams(history.location.search); + const currentTab = searchParams.get("tab") || ""; + const searchQueryString = searchParams.get("q") || ""; + if (currentTab === tab && search && search != searchQueryString) { + syncHistory( + { + q: search, + }, + history, + ); + } + + // Filters. + updateFiltersQueryParamsOnTab(tab, this.state.filters, history); + + // Sort Setting. updateSortSettingQueryParamsOnTab( - "Statements", - this.props.sortSetting, + tab, + sortSetting, { ascending: false, columnTitle: "executionCount", }, - this.props.history, + history, ); } - componentDidUpdate = ( - __: StatementsPageProps, - prevState: StatementsPageState, - ): void => { + componentDidUpdate = (): void => { this.updateQueryParamsOnTabSwitch(); - if (this.state.search && this.state.search !== prevState.search) { - this.props.onSearchComplete(this.filteredStatementsData()); - } this.refreshStatements(); if (!this.props.isTenant) { this.props.refreshStatementDiagnosticsRequests(); @@ -277,7 +294,9 @@ export class StatementsPage extends React.Component< }; onSubmitSearchField = (search: string): void => { - this.setState({ search }); + if (this.props.onSearchComplete) { + this.props.onSearchComplete(search); + } this.resetPagination(); syncHistory( { @@ -314,7 +333,9 @@ export class StatementsPage extends React.Component< }; onClearSearchField = (): void => { - this.setState({ search: "" }); + if (this.props.onSearchComplete) { + this.props.onSearchComplete(""); + } syncHistory( { q: undefined, @@ -339,6 +360,7 @@ export class StatementsPage extends React.Component< app: undefined, timeNumber: undefined, timeUnit: undefined, + fullScan: undefined, sqlType: undefined, database: undefined, regions: undefined, @@ -349,8 +371,8 @@ export class StatementsPage extends React.Component< }; filteredStatementsData = (): AggregateStatistics[] => { - const { search, filters } = this.state; - const { statements, nodeRegions, isTenant } = this.props; + const { filters } = this.state; + const { search, statements, nodeRegions, isTenant } = this.props; const timeValue = getTimeValueInSeconds(filters); const sqlTypes = filters.sqlType.length > 0 @@ -382,7 +404,7 @@ export class StatementsPage extends React.Component< .filter(statement => (filters.fullScan ? statement.fullScan : true)) .filter(statement => search - .split(" ") + ?.split(" ") .every(val => statement.label.toLowerCase().includes(val.toLowerCase()), ), @@ -430,7 +452,7 @@ export class StatementsPage extends React.Component< }; renderStatements = (): React.ReactElement => { - const { pagination, search, filters, activeFilters } = this.state; + const { pagination, filters, activeFilters } = this.state; const { statements, apps, @@ -443,6 +465,7 @@ export class StatementsPage extends React.Component< nodeRegions, isTenant, sortSetting, + search, } = this.props; const data = this.filteredStatementsData(); const totalWorkload = calculateTotalWorkload(data); diff --git a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx index 7c37c0526309..36d9d55c1cf8 100644 --- a/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx +++ b/pkg/ui/workspaces/cluster-ui/src/statementsPage/statementsPageConnected.tsx @@ -36,9 +36,9 @@ import { selectDateRange, selectSortSetting, selectFilters, + selectSearch, } from "./statementsPage.selectors"; import { selectIsTenant } from "../store/uiConfig"; -import { AggregateStatistics } from "../statementsTable"; import { nodeRegionsByIDSelector } from "../store/nodes"; import { StatementsRequest } from "src/api/statementsApi"; @@ -49,18 +49,19 @@ export const ConnectedStatementsPage = withRouter( RouteComponentProps >( (state: AppState, props: StatementsPageProps) => ({ - statements: selectStatements(state, props), - statementsError: selectStatementsLastError(state), apps: selectApps(state), + columns: selectColumns(state), databases: selectDatabases(state), - totalFingerprints: selectTotalFingerprints(state), + dateRange: selectDateRange(state), + filters: selectFilters(state), + isTenant: selectIsTenant(state), lastReset: selectLastReset(state), - columns: selectColumns(state), nodeRegions: selectIsTenant(state) ? {} : nodeRegionsByIDSelector(state), - dateRange: selectDateRange(state), + search: selectSearch(state), sortSetting: selectSortSetting(state), - isTenant: selectIsTenant(state), - filters: selectFilters(state), + statements: selectStatements(state, props), + statementsError: selectStatementsLastError(state), + totalFingerprints: selectTotalFingerprints(state), }), (dispatch: Dispatch) => ({ refreshStatements: (req?: StatementsRequest) => @@ -103,13 +104,20 @@ export const ConnectedStatementsPage = withRouter( action: "Downloaded", }), ), - onSearchComplete: (_results: AggregateStatistics[]) => + onSearchComplete: (query: string) => { dispatch( analyticsActions.track({ name: "Keyword Searched", page: "Statements", }), - ), + ); + dispatch( + localStorageActions.update({ + key: "search/StatementsPage", + value: query, + }), + ); + }, onFilterChange: value => { dispatch( analyticsActions.track({ diff --git a/pkg/ui/workspaces/cluster-ui/src/store/localStorage/localStorage.reducer.ts b/pkg/ui/workspaces/cluster-ui/src/store/localStorage/localStorage.reducer.ts index b93687e56f0a..d9850bdf55ed 100644 --- a/pkg/ui/workspaces/cluster-ui/src/store/localStorage/localStorage.reducer.ts +++ b/pkg/ui/workspaces/cluster-ui/src/store/localStorage/localStorage.reducer.ts @@ -33,6 +33,7 @@ export type LocalStorageState = { "sortSetting/SessionsPage": SortSetting; "filters/StatementsPage": Filters; "filters/TransactionsPage": Filters; + "search/StatementsPage": string; }; type Payload = { @@ -85,6 +86,8 @@ const initialState: LocalStorageState = { "filters/TransactionsPage": JSON.parse(localStorage.getItem("filters/TransactionsPage")) || defaultFilters, + "search/StatementsPage": + JSON.parse(localStorage.getItem("search/StatementsPage")) || null, }; const localStorageSlice = createSlice({ diff --git a/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.fixture.ts b/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.fixture.ts index c11f11d5845f..8d406e4f073d 100644 --- a/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.fixture.ts +++ b/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.fixture.ts @@ -184,6 +184,7 @@ const statementsPagePropsFixture: StatementsPageProps = { ascending: false, columnTitle: "executionCount", }, + search: "", filters: { app: "", timeNumber: "0", diff --git a/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.tsx b/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.tsx index 8970f6471b26..4ee33d52120d 100644 --- a/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.tsx +++ b/pkg/ui/workspaces/db-console/src/views/statements/statementsPage.tsx @@ -50,7 +50,6 @@ import { import { trackDownloadDiagnosticsBundleAction, trackStatementsPaginationAction, - trackStatementsSearchAction, } from "src/redux/analyticsActions"; import { resetSQLStatsAction } from "src/redux/sqlStats"; import { LocalSetting } from "src/redux/localsettings"; @@ -251,20 +250,27 @@ export const filtersLocalSetting = new LocalSetting( defaultFilters, ); +export const searchLocalSetting = new LocalSetting( + "search/StatementsPage", + (state: AdminUIState) => state.localSettings, + null, +); + export default withRouter( connect( (state: AdminUIState, props: RouteComponentProps) => ({ - statements: selectStatements(state, props), - statementsError: state.cachedData.statements.lastError, apps: selectApps(state), + columns: statementColumnsLocalSetting.selectorToArray(state), databases: selectDatabases(state), - totalFingerprints: selectTotalFingerprints(state), + dateRange: selectDateRange(state), + filters: filtersLocalSetting.selector(state), lastReset: selectLastReset(state), - columns: statementColumnsLocalSetting.selectorToArray(state), nodeRegions: nodeRegionsByIDSelector(state), - dateRange: selectDateRange(state), + search: searchLocalSetting.selector(state), sortSetting: sortSettingLocalSetting.selector(state), - filters: filtersLocalSetting.selector(state), + statements: selectStatements(state, props), + statementsError: state.cachedData.statements.lastError, + totalFingerprints: selectTotalFingerprints(state), }), { refreshStatements: refreshStatements, @@ -275,8 +281,7 @@ export default withRouter( createStatementDiagnosticsAlertLocalSetting.set({ show: false }), onActivateStatementDiagnostics: createStatementDiagnosticsReportAction, onDiagnosticsModalOpen: createOpenDiagnosticsModalAction, - onSearchComplete: (results: AggregateStatistics[]) => - trackStatementsSearchAction(results.length), + onSearchComplete: (query: string) => searchLocalSetting.set(query), onPageChanged: trackStatementsPaginationAction, onSortingChange: ( _tableName: string,