Skip to content

Commit

Permalink
Merge branch 'main' into set-serverless-public-apis
Browse files Browse the repository at this point in the history
  • Loading branch information
jeramysoucy authored Sep 30, 2024
2 parents 7e17054 + b79855d commit a855b6a
Show file tree
Hide file tree
Showing 215 changed files with 5,384 additions and 3,695 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -1239,6 +1239,7 @@ x-pack/test/observability_ai_assistant_functional @elastic/obs-ai-assistant
/x-pack/test/functional/apps/canvas/ @elastic/kibana-presentation
/x-pack/test_serverless/functional/test_suites/search/dashboards/ @elastic/kibana-presentation
/test/plugin_functional/test_suites/panel_actions @elastic/kibana-presentation
/x-pack/test/functional/es_archives/canvas/logstash_lens @elastic/kibana-presentation
#CC# /src/plugins/kibana_react/public/code_editor/ @elastic/kibana-presentation

# Machine Learning
Expand Down
4 changes: 2 additions & 2 deletions oas_docs/output/kibana.staging.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6948,7 +6948,7 @@ paths:
feature privileges, depending on the owner of the cases you're seeking.
operationId: findCasesDefaultSpace
parameters:
- $ref: '#/components/parameters/Cases_assignees'
- $ref: '#/components/parameters/Cases_assignees_filter'
- $ref: '#/components/parameters/Cases_category'
- $ref: '#/components/parameters/Cases_defaultSearchOperator'
- $ref: '#/components/parameters/Cases_from'
Expand Down Expand Up @@ -24388,7 +24388,7 @@ components:
schema:
example: 09f0c261e39e36351d75995b78bb83673774d1bc2cca9df2d15f0e5c0a99a540
type: string
Cases_assignees:
Cases_assignees_filter:
description: >
Filters the returned cases by assignees. Valid values are `none` or
unique identifiers for the user profiles. These identifiers can be found
Expand Down
4 changes: 2 additions & 2 deletions oas_docs/output/kibana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6684,7 +6684,7 @@ paths:
feature privileges, depending on the owner of the cases you're seeking.
operationId: findCasesDefaultSpace
parameters:
- $ref: '#/components/parameters/Cases_assignees'
- $ref: '#/components/parameters/Cases_assignees_filter'
- $ref: '#/components/parameters/Cases_category'
- $ref: '#/components/parameters/Cases_defaultSearchOperator'
- $ref: '#/components/parameters/Cases_from'
Expand Down Expand Up @@ -16415,7 +16415,7 @@ components:
schema:
example: 09f0c261e39e36351d75995b78bb83673774d1bc2cca9df2d15f0e5c0a99a540
type: string
Cases_assignees:
Cases_assignees_filter:
description: >
Filters the returned cases by assignees. Valid values are `none` or
unique identifiers for the user profiles. These identifiers can be found
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1222,37 +1222,41 @@ describe('TableListView', () => {
describe('url state', () => {
let router: Router | undefined;

const setupTagFiltering = registerTestBed<string, TableListViewTableProps>(
WithServices<TableListViewTableProps>(TableListViewTable, {
getTagList: () => [
{
id: 'id-tag-1',
name: 'tag-1',
type: 'tag',
description: '',
color: '',
managed: false,
},
{
id: 'id-tag-2',
name: 'tag-2',
type: 'tag',
description: '',
color: '',
managed: false,
},
],
}),
{
defaultProps: { ...requiredProps, urlStateEnabled: true },
memoryRouter: {
wrapComponent: true,
onRouter: (_router: Router) => {
router = _router;
const setupInitialUrl = (initialSearchQuery: string = '') =>
registerTestBed<string, TableListViewTableProps>(
WithServices<TableListViewTableProps>(TableListViewTable, {
getTagList: () => [
{
id: 'id-tag-1',
name: 'tag-1',
type: 'tag',
description: '',
color: '',
managed: false,
},
{
id: 'id-tag-2',
name: 'tag-2',
type: 'tag',
description: '',
color: '',
managed: false,
},
],
}),
{
defaultProps: { ...requiredProps, urlStateEnabled: true },
memoryRouter: {
wrapComponent: true,
initialEntries: [{ search: initialSearchQuery }],
onRouter: (_router: Router) => {
router = _router;
},
},
},
}
);
}
);

const setupTagFiltering = setupInitialUrl();

const hits: UserContentCommonSchema[] = [
{
Expand All @@ -1277,13 +1281,13 @@ describe('TableListView', () => {
},
];

test('should read search term from URL', async () => {
test('should read the initial search term from URL', async () => {
let testBed: TestBed;

const findItems = jest.fn().mockResolvedValue({ total: hits.length, hits: [...hits] });

await act(async () => {
testBed = await setupTagFiltering({
testBed = await setupInitialUrl('?s=hello')({
findItems,
});
});
Expand All @@ -1294,22 +1298,23 @@ describe('TableListView', () => {
const getSearchBoxValue = () => find('tableListSearchBox').props().defaultValue;

// Start with empty search box
expect(getSearchBoxValue()).toBe('');
expect(router?.history.location?.search).toBe('');
expect(getSearchBoxValue()).toBe('hello');
expect(router?.history.location?.search).toBe('?s=hello');

// Change the URL
await act(async () => {
if (router?.history.push) {
router.history.push({
search: `?${queryString.stringify({ s: 'hello' }, { encode: false })}`,
search: `?${queryString.stringify({ s: '' }, { encode: false })}`,
});
}
});

component.update();

// Search box is updated
// Search box is not updated
expect(getSearchBoxValue()).toBe('hello');
expect(router?.history.location?.search).toBe('?s=hello');
expect(router?.history.location?.search).toBe('?s=');
});

test('should update the URL when changing the search term', async () => {
Expand Down Expand Up @@ -1338,13 +1343,15 @@ describe('TableListView', () => {
expect(router?.history.location?.search).toBe('?s=search-changed');
});

test('should filter by tag from the URL', async () => {
test('should filter by initial tag from the URL', async () => {
let testBed: TestBed;

const findItems = jest.fn().mockResolvedValue({ total: hits.length, hits: [...hits] });

await act(async () => {
testBed = await setupTagFiltering({
testBed = await setupInitialUrl(
`?${queryString.stringify({ s: 'tag:(tag-2)' }, { encode: false })}`
)({
findItems,
});
});
Expand All @@ -1357,7 +1364,7 @@ describe('TableListView', () => {

const getSearchBoxValue = () => find('tableListSearchBox').props().defaultValue;

let expected = '';
let expected = 'tag:(tag-2)';
let [searchTerm] = getLastCallArgsFromFindItems();
expect(getSearchBoxValue()).toBe(expected);
expect(searchTerm).toBe(expected);
Expand All @@ -1366,13 +1373,13 @@ describe('TableListView', () => {
await act(async () => {
if (router?.history.push) {
router.history.push({
search: `?${queryString.stringify({ s: 'tag:(tag-2)' }, { encode: false })}`,
search: `?${queryString.stringify({ s: '' }, { encode: false })}`,
});
}
});
component.update();

// The search bar should be updated
// The search bar shouldn't be updated
expected = 'tag:(tag-2)';
[searchTerm] = getLastCallArgsFromFindItems();
expect(getSearchBoxValue()).toBe(expected);
Expand Down Expand Up @@ -1413,51 +1420,34 @@ describe('TableListView', () => {
expect(router?.history.location?.search).toBe('?s=tag:(tag-2)');
});

test('should set sort column and direction from URL', async () => {
test('should set initial sort column and direction from URL', async () => {
let testBed: TestBed;

const findItems = jest.fn().mockResolvedValue({ total: hits.length, hits: [...hits] });

await act(async () => {
testBed = await setupTagFiltering({
testBed = await setupInitialUrl(
`?${queryString.stringify({ sort: 'updatedAt', sortdir: 'asc' })}`
)({
findItems,
});
});

const { component, table } = testBed!;
component.update();

// Start with empty search box
expect(router?.history.location?.search).toBe('');

let { tableCellsValues } = table.getMetaData('itemsInMemTable');

expect(tableCellsValues).toEqual([
['Item 1tag-1', yesterdayToString],
['Item 2tag-2', twoDaysAgoToString],
]);

// Change the URL
await act(async () => {
if (router?.history.push) {
router.history.push({
search: `?${queryString.stringify({ sort: 'updatedAt', sortdir: 'asc' })}`,
});
}
});
component.update();

({ tableCellsValues } = table.getMetaData('itemsInMemTable'));

expect(tableCellsValues).toEqual([
['Item 2tag-2', twoDaysAgoToString], // Sort got inverted
['Item 1tag-1', yesterdayToString],
]);

// Change the URL
await act(async () => {
if (router?.history.push) {
router.history.push({
search: `?${queryString.stringify({ sort: 'title' })}`, // if dir not specified, asc by default
search: `?${queryString.stringify({ sort: 'updatedAt', sortdir: 'desc' })}`,
});
}
});
Expand All @@ -1466,8 +1456,8 @@ describe('TableListView', () => {
({ tableCellsValues } = table.getMetaData('itemsInMemTable'));

expect(tableCellsValues).toEqual([
['Item 1tag-1', yesterdayToString],
['Item 2tag-2', twoDaysAgoToString],
['Item 1tag-1', yesterdayToString], // Sort stayed the same
]);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
);
}

const [urlState, setUrlState] = useUrlState<URLState, URLQueryParams>({
const [initialUrlState, setUrlState] = useUrlState<URLState, URLQueryParams>({
queryParamsDeserializer: urlStateDeserializer,
queryParamsSerializer: urlStateSerializer,
});
Expand Down Expand Up @@ -495,7 +495,6 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
(query: Query) => {
if (urlStateEnabled) {
setUrlState({ s: query.text });
return;
}

dispatch({
Expand Down Expand Up @@ -849,12 +848,10 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
});
}

if (data.page || !urlStateEnabled) {
dispatch({
type: 'onTableChange',
data,
});
}
dispatch({
type: 'onTableChange',
data,
});
},
[setUrlState, urlStateEnabled]
);
Expand Down Expand Up @@ -1024,6 +1021,7 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
// ------------
useDebounce(fetchItems, 300, [fetchItems, refreshListBouncer]);

// set the initial state from the URL
useEffect(() => {
if (!urlStateEnabled) {
return;
Expand Down Expand Up @@ -1075,10 +1073,10 @@ function TableListViewTableComp<T extends UserContentCommonSchema>({
});
};

updateQueryFromURL(urlState.s);
updateSortFromURL(urlState.sort);
updateFilterFromURL(urlState.filter);
}, [urlState, buildQueryFromText, urlStateEnabled]);
updateQueryFromURL(initialUrlState.s);
updateSortFromURL(initialUrlState.sort);
updateFilterFromURL(initialUrlState.filter);
}, [initialUrlState, buildQueryFromText, urlStateEnabled]);

useEffect(() => {
isMounted.current = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
*/

import queryString from 'query-string';
import { useCallback, useMemo, useState, useEffect } from 'react';
import { useLocation, useHistory } from 'react-router-dom';
import { useCallback, useState } from 'react';
import { useHistory, useLocation } from 'react-router-dom';

export function useInRouterContext() {
try {
Expand All @@ -20,11 +20,6 @@ export function useInRouterContext() {
}
}

function useQuery<T extends Record<string, unknown> = {}>() {
const { search } = useLocation();
return useMemo<T>(() => queryString.parse(search) as T, [search]);
}

export function useUrlState<
T extends Record<string, unknown> = {},
Q extends Record<string, unknown> = {}
Expand All @@ -36,29 +31,26 @@ export function useUrlState<
queryParamsSerializer: (params: Record<string, unknown>) => Partial<Q>;
}): [T, (updated: Record<string, unknown>) => void] {
const history = useHistory();
const params = useQuery<Q>();
const [urlState, setUrlState] = useState<T>({} as T);

const updateQuerParams = useCallback(
const [initialUrlState] = useState(() =>
queryParamsDeserializer(queryString.parse(history.location.search) as Q)
);

const updateQueryParams = useCallback(
(updated: Record<string, unknown>) => {
const updatedQuery = queryParamsSerializer(updated);

const queryParams = {
...params,
...queryString.parse(history.location.search),
...updatedQuery,
};

history.replace({
search: `?${queryString.stringify(queryParams, { encode: false })}`,
});
},
[history, params, queryParamsSerializer]
[history, queryParamsSerializer]
);

useEffect(() => {
const updatedState = queryParamsDeserializer(params);
setUrlState(updatedState);
}, [params, queryParamsDeserializer]);

return [urlState, updateQuerParams];
return [initialUrlState, updateQueryParams];
}
Loading

0 comments on commit a855b6a

Please sign in to comment.