[8.12] feat(slo): store view and compact mode in URL state (#172878) (#172977)

# Backport

This will backport the following commits from `main` to `8.12`:
- [feat(slo): store view and compact mode in URL state
(#172878)](https://github.com/elastic/kibana/pull/172878)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Kevin
Delemme","email":"kevin.delemme@elastic.co"},"sourceCommit":{"committedDate":"2023-12-08T16:51:36Z","message":"feat(slo):
store view and compact mode in URL state
(#172878)","sha":"4eea0d6118cd4d5c4d7a9fa8474f514ee9ee9dab","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:prev-minor","Feature:SLO","v8.12.0","Team:obs-ux-management","v8.13.0"],"number":172878,"url":"https://github.com/elastic/kibana/pull/172878","mergeCommit":{"message":"feat(slo):
store view and compact mode in URL state
(#172878)","sha":"4eea0d6118cd4d5c4d7a9fa8474f514ee9ee9dab"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/172878","number":172878,"mergeCommit":{"message":"feat(slo):
store view and compact mode in URL state
(#172878)","sha":"4eea0d6118cd4d5c4d7a9fa8474f514ee9ee9dab"}}]}]
BACKPORT-->

Co-authored-by: Kevin Delemme <kevin.delemme@elastic.co>
This commit is contained in:
Kibana Machine 2023-12-08 13:17:34 -05:00 committed by GitHub
parent 3913a86c94
commit ace69f7333
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 48 additions and 32 deletions

View file

@ -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)"`
);
});
});

View file

@ -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<SortField>(state.sort.by);
const [direction] = useState<'asc' | 'desc'>(state.sort.direction);
const [sloView, setSLOView] = useState<SLOViewType>('cardView');
const [direction] = useState<SortDirection>(state.sort.direction);
const [view, setView] = useState<SLOView>(state.view);
const [isCompact, setCompact] = useState<boolean>(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 (
<EuiFlexGroup direction="column" gutterSize="m" data-test-subj="sloList">
<EuiFlexItem grow>
@ -79,20 +87,18 @@ export function SloList({ autoRefresh }: Props) {
</EuiFlexItem>
<EuiFlexItem grow={false}>
<ToggleSLOView
sloView={sloView}
setSLOView={setSLOView}
toggleCompactView={() =>
isCompact === 'true' ? setIsCompact('false') : setIsCompact('true')
}
isCompact={isCompactView}
sloView={view}
onChangeView={handleChangeView}
onToggleCompactView={handleToggleCompactView}
isCompact={isCompact}
/>
</EuiFlexItem>
<SlosView
sloList={results}
loading={isLoading || isRefetching}
error={isError}
isCompact={isCompactView}
sloView={sloView}
isCompact={isCompact}
sloView={view}
/>
{total > 0 ? (

View file

@ -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<T> = EuiSelectableOption & {
label: string;

View file

@ -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 (
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
@ -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
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<SLOViewSettings toggleCompactView={toggleCompactView} isCompact={isCompact} />
<SLOViewSettings toggleCompactView={onToggleCompactView} isCompact={isCompact} />
</EuiFlexItem>
</EuiFlexGroup>
);

View file

@ -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(): {