From b508553425313f52cf518ff952b0212095eb7e0f Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Fri, 8 Dec 2023 11:51:36 -0500 Subject: [PATCH] feat(slo): store view and compact mode in URL state (#172878) (cherry picked from commit 4eea0d6118cd4d5c4d7a9fa8474f514ee9ee9dab) --- .../public/locators/slo_list.test.ts | 8 ++-- .../public/pages/slos/components/slo_list.tsx | 40 +++++++++++-------- .../slos/components/slo_list_search_bar.tsx | 1 + .../pages/slos/components/toggle_slo_view.tsx | 20 ++++++---- .../pages/slos/hooks/use_url_search_state.ts | 11 +++-- 5 files changed, 48 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/observability/public/locators/slo_list.test.ts b/x-pack/plugins/observability/public/locators/slo_list.test.ts index 68bf2c2589fea..5a63a0b8c8c14 100644 --- a/x-pack/plugins/observability/public/locators/slo_list.test.ts +++ b/x-pack/plugins/observability/public/locators/slo_list.test.ts @@ -13,8 +13,8 @@ describe('SloListLocator', () => { it("returns the correct url with the default search state when no 'kqlQuery' provided", async () => { const location = await locator.getLocation({}); expect(location.app).toEqual('observability'); - expect(location.path).toEqual( - "/slos?search=(kqlQuery:'',page:0,sort:(by:status,direction:desc),viewMode:compact)" + expect(location.path).toMatchInlineSnapshot( + `"/slos?search=(compact:!t,kqlQuery:'',page:0,sort:(by:status,direction:desc),view:cardView)"` ); }); @@ -23,8 +23,8 @@ describe('SloListLocator', () => { kqlQuery: 'slo.name: "Service Availability" and slo.indicator.type : "sli.kql.custom"', }); expect(location.app).toEqual('observability'); - expect(location.path).toEqual( - "/slos?search=(kqlQuery:'slo.name:%20%22Service%20Availability%22%20and%20slo.indicator.type%20:%20%22sli.kql.custom%22',page:0,sort:(by:status,direction:desc),viewMode:compact)" + expect(location.path).toMatchInlineSnapshot( + `"/slos?search=(compact:!t,kqlQuery:'slo.name:%20%22Service%20Availability%22%20and%20slo.indicator.type%20:%20%22sli.kql.custom%22',page:0,sort:(by:status,direction:desc),view:cardView)"` ); }); }); diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx index 4714cd4c2355f..6d3f13ceb6763 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list.tsx @@ -8,13 +8,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiPagination } from '@elastic/eui'; import { useIsMutating } from '@tanstack/react-query'; import React, { useState } from 'react'; -import useLocalStorage from 'react-use/lib/useLocalStorage'; -import { SlosView } from './slos_view'; -import { SLO_LIST_IS_COMPACT } from './slo_view_settings'; -import { SLOViewType, ToggleSLOView } from './toggle_slo_view'; import { useFetchSloList } from '../../../hooks/slo/use_fetch_slo_list'; import { useUrlSearchState } from '../hooks/use_url_search_state'; -import { SloListSearchBar, SortField } from './slo_list_search_bar'; +import { SlosView } from './slos_view'; +import { SloListSearchBar, SortDirection, SortField } from './slo_list_search_bar'; +import { SLOView, ToggleSLOView } from './toggle_slo_view'; export interface Props { autoRefresh: boolean; @@ -25,8 +23,9 @@ export function SloList({ autoRefresh }: Props) { const [page, setPage] = useState(state.page); const [query, setQuery] = useState(state.kqlQuery); const [sort, setSort] = useState(state.sort.by); - const [direction] = useState<'asc' | 'desc'>(state.sort.direction); - const [sloView, setSLOView] = useState('cardView'); + const [direction] = useState(state.sort.direction); + const [view, setView] = useState(state.view); + const [isCompact, setCompact] = useState(state.compact); const { isLoading, @@ -47,8 +46,6 @@ export function SloList({ autoRefresh }: Props) { const isCloningSlo = Boolean(useIsMutating(['cloningSlo'])); const isUpdatingSlo = Boolean(useIsMutating(['updatingSlo'])); const isDeletingSlo = Boolean(useIsMutating(['deleteSlo'])); - const [isCompact, setIsCompact] = useLocalStorage<'true' | 'false'>(SLO_LIST_IS_COMPACT, 'true'); - const isCompactView = isCompact === 'true'; const handlePageClick = (pageNumber: number) => { setPage(pageNumber); @@ -67,6 +64,17 @@ export function SloList({ autoRefresh }: Props) { storeState({ page: 0, sort: { by: newSort, direction: state.sort.direction } }); }; + const handleChangeView = (newView: SLOView) => { + setView(newView); + storeState({ view: newView }); + }; + + const handleToggleCompactView = () => { + const newCompact = !isCompact; + setCompact(newCompact); + storeState({ compact: newCompact }); + }; + return ( @@ -79,20 +87,18 @@ export function SloList({ autoRefresh }: Props) { - isCompact === 'true' ? setIsCompact('false') : setIsCompact('true') - } - isCompact={isCompactView} + sloView={view} + onChangeView={handleChangeView} + onToggleCompactView={handleToggleCompactView} + isCompact={isCompact} /> {total > 0 ? ( diff --git a/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx b/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx index f4d251d063490..b06a2f3fea478 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/slo_list_search_bar.tsx @@ -32,6 +32,7 @@ export interface Props { } export type SortField = 'sli_value' | 'error_budget_consumed' | 'error_budget_remaining' | 'status'; +export type SortDirection = 'asc' | 'desc'; export type Item = EuiSelectableOption & { label: string; diff --git a/x-pack/plugins/observability/public/pages/slos/components/toggle_slo_view.tsx b/x-pack/plugins/observability/public/pages/slos/components/toggle_slo_view.tsx index d7e3f6df00422..e5881e8f1ff4c 100644 --- a/x-pack/plugins/observability/public/pages/slos/components/toggle_slo_view.tsx +++ b/x-pack/plugins/observability/public/pages/slos/components/toggle_slo_view.tsx @@ -10,14 +10,15 @@ import { i18n } from '@kbn/i18n'; import { EuiButtonGroup, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { SLOViewSettings } from './slo_view_settings'; -export type SLOViewType = 'cardView' | 'listView'; +export type SLOView = 'cardView' | 'listView'; interface Props { - toggleCompactView: () => void; + onToggleCompactView: () => void; + onChangeView: (view: SLOView) => void; isCompact: boolean; - setSLOView: (view: SLOViewType) => void; - sloView: SLOViewType; + sloView: SLOView; } + const toggleButtonsIcons = [ { id: `cardView`, @@ -33,7 +34,12 @@ const toggleButtonsIcons = [ }, ]; -export function ToggleSLOView({ sloView, setSLOView, toggleCompactView, isCompact = true }: Props) { +export function ToggleSLOView({ + sloView, + onChangeView, + onToggleCompactView, + isCompact = true, +}: Props) { return ( @@ -43,12 +49,12 @@ export function ToggleSLOView({ sloView, setSLOView, toggleCompactView, isCompac })} options={toggleButtonsIcons} idSelected={sloView} - onChange={(id) => setSLOView(id as SLOViewType)} + onChange={(id) => onChangeView(id as SLOView)} isIconOnly /> - + ); diff --git a/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts b/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts index e3c8449444a1d..4bccc105c718d 100644 --- a/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts +++ b/x-pack/plugins/observability/public/pages/slos/hooks/use_url_search_state.ts @@ -8,7 +8,8 @@ import { createKbnUrlStateStorage } from '@kbn/kibana-utils-plugin/public'; import deepmerge from 'deepmerge'; import { useHistory } from 'react-router-dom'; -import type { SortField, ViewMode } from '../components/slo_list_search_bar'; +import type { SortField, SortDirection } from '../components/slo_list_search_bar'; +import type { SLOView } from '../components/toggle_slo_view'; export const SLO_LIST_SEARCH_URL_STORAGE_KEY = 'search'; @@ -17,16 +18,18 @@ export interface SearchState { page: number; sort: { by: SortField; - direction: 'asc' | 'desc'; + direction: SortDirection; }; - viewMode: ViewMode; + view: SLOView; + compact: boolean; } export const DEFAULT_STATE = { kqlQuery: '', page: 0, sort: { by: 'status' as const, direction: 'desc' as const }, - viewMode: 'compact' as const, + view: 'cardView' as const, + compact: true, }; export function useUrlSearchState(): {