Skip to content

Commit a4e15c3

Browse files
committed
Merge branch '136039-rules-status-deploy' of https://github.com/JiaweiWu/kibana into 136039-rules-status-frontend
2 parents 345c32a + 2de0983 commit a4e15c3

File tree

87 files changed

+2272
-757
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+2272
-757
lines changed

.github/CODEOWNERS

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,11 @@
117117
/docs/settings/reporting-settings.asciidoc @elastic/kibana-global-experience
118118
/docs/setup/configuring-reporting.asciidoc @elastic/kibana-global-experience
119119

120+
### Global Experience Tagging
121+
/src/plugins/saved_objects_tagging_oss @elastic/kibana-global-experience
122+
/x-pack/plugins/saved_objects_tagging/ @elastic/kibana-global-experience
123+
/x-pack/test/saved_object_tagging/ @elastic/kibana-global-experience
124+
120125
### Kibana React (to be deprecated)
121126
/src/plugins/kibana_react/ @elastic/kibana-global-experience
122127
/src/plugins/kibana_react/public/code_editor @elastic/kibana-global-experience @elastic/kibana-presentation
@@ -302,7 +307,6 @@
302307
# Core
303308
/examples/hello_world/ @elastic/kibana-core
304309
/src/core/ @elastic/kibana-core
305-
/src/plugins/saved_objects_tagging_oss @elastic/kibana-core
306310
/config/kibana.yml @elastic/kibana-core
307311
/typings/ @elastic/kibana-core
308312
/x-pack/plugins/global_search_providers @elastic/kibana-core
@@ -312,9 +316,7 @@
312316
/x-pack/plugins/global_search/ @elastic/kibana-core
313317
/x-pack/plugins/cloud/ @elastic/kibana-core
314318
/x-pack/plugins/cloud_integrations/ @elastic/kibana-core
315-
/x-pack/plugins/saved_objects_tagging/ @elastic/kibana-core
316319
/x-pack/test/saved_objects_field_count/ @elastic/kibana-core
317-
/x-pack/test/saved_object_tagging/ @elastic/kibana-core
318320
/src/plugins/saved_objects_management/ @elastic/kibana-core
319321
/src/plugins/advanced_settings/ @elastic/kibana-core
320322
/x-pack/plugins/global_search_bar/ @elastic/kibana-core

package.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,25 +684,25 @@
684684
"devDependencies": {
685685
"@apidevtools/swagger-parser": "^10.0.3",
686686
"@babel/cli": "^7.19.3",
687-
"@babel/core": "^7.19.6",
687+
"@babel/core": "^7.20.2",
688688
"@babel/eslint-parser": "^7.19.1",
689689
"@babel/eslint-plugin": "^7.19.1",
690-
"@babel/generator": "^7.20.1",
691-
"@babel/helper-plugin-utils": "^7.19.0",
692-
"@babel/parser": "^7.20.1",
690+
"@babel/generator": "^7.20.3",
691+
"@babel/helper-plugin-utils": "^7.20.2",
692+
"@babel/parser": "^7.20.3",
693693
"@babel/plugin-proposal-class-properties": "^7.18.6",
694694
"@babel/plugin-proposal-export-namespace-from": "^7.18.9",
695695
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
696-
"@babel/plugin-proposal-object-rest-spread": "^7.19.4",
696+
"@babel/plugin-proposal-object-rest-spread": "^7.20.2",
697697
"@babel/plugin-proposal-optional-chaining": "^7.18.9",
698698
"@babel/plugin-proposal-private-methods": "^7.18.6",
699699
"@babel/plugin-transform-runtime": "^7.19.6",
700-
"@babel/preset-env": "^7.19.4",
700+
"@babel/preset-env": "^7.20.2",
701701
"@babel/preset-react": "^7.18.6",
702702
"@babel/preset-typescript": "^7.18.6",
703703
"@babel/register": "^7.18.9",
704704
"@babel/traverse": "^7.20.1",
705-
"@babel/types": "^7.20.0",
705+
"@babel/types": "^7.20.2",
706706
"@bazel/ibazel": "^0.16.2",
707707
"@bazel/typescript": "4.6.2",
708708
"@cypress/code-coverage": "^3.10.0",

packages/content-management/table_list/src/__jest__/tests.helpers.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ export const getMockServices = (overrides?: Partial<Services>) => {
2121
currentAppId$: from('mockedApp'),
2222
navigateToUrl: () => undefined,
2323
TagList,
24+
getTagList: () => [],
2425
itemHasTags: () => true,
26+
getTagManagementUrl: () => '',
2527
getTagIdsFromReferences: () => [],
2628
...overrides,
2729
};

packages/content-management/table_list/src/actions.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Side Public License, v 1.
77
*/
88
import type { IHttpFetchError } from '@kbn/core-http-browser';
9-
import type { CriteriaWithPagination, Direction } from '@elastic/eui';
9+
import type { CriteriaWithPagination, Direction, Query } from '@elastic/eui';
1010

1111
import type { SortColumnField } from './components';
1212

@@ -71,7 +71,10 @@ export interface ShowConfirmDeleteItemsModalAction {
7171
/** Action to update the search bar query text */
7272
export interface OnSearchQueryChangeAction {
7373
type: 'onSearchQueryChange';
74-
data: string;
74+
data: {
75+
query: Query;
76+
text: string;
77+
};
7578
}
7679

7780
export type Action<T> =

packages/content-management/table_list/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ export { ConfirmDeleteModal } from './confirm_delete_modal';
1212
export { ListingLimitWarning } from './listing_limit_warning';
1313
export { ItemDetails } from './item_details';
1414
export { TableSortSelect } from './table_sort_select';
15+
export { TagFilterPanel } from './tag_filter_panel';
1516

1617
export type { SortColumnField } from './table_sort_select';

packages/content-management/table_list/src/components/item_details.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
*/
88

99
import React, { useCallback, useMemo } from 'react';
10-
import { EuiText, EuiLink, EuiTitle, EuiSpacer } from '@elastic/eui';
10+
import { EuiText, EuiLink, EuiTitle, EuiSpacer, EuiHighlight } from '@elastic/eui';
1111
import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
1212

13+
import type { Tag } from '../types';
1314
import { useServices } from '../services';
1415
import type { UserContentCommonSchema, Props as TableListViewProps } from '../table_list_view';
16+
import { TagBadge } from './tag_badge';
1517

1618
type InheritedProps<T extends UserContentCommonSchema> = Pick<
1719
TableListViewProps<T>,
@@ -20,21 +22,23 @@ type InheritedProps<T extends UserContentCommonSchema> = Pick<
2022
interface Props<T extends UserContentCommonSchema> extends InheritedProps<T> {
2123
item: T;
2224
searchTerm?: string;
25+
onClickTag: (tag: Tag, isCtrlKey: boolean) => void;
2326
}
2427

2528
/**
2629
* Copied from https://stackoverflow.com/a/9310752
2730
*/
28-
// const escapeRegExp = (text: string) => {
29-
// return text.replace(/[-\[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
30-
// };
31+
const escapeRegExp = (text: string) => {
32+
return text.replace(/[-\[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
33+
};
3134

3235
export function ItemDetails<T extends UserContentCommonSchema>({
3336
id,
3437
item,
3538
searchTerm = '',
3639
getDetailViewLink,
3740
onClickTitle,
41+
onClickTag,
3842
}: Props<T>) {
3943
const {
4044
references,
@@ -79,7 +83,9 @@ export function ItemDetails<T extends UserContentCommonSchema>({
7983
onClick={onClickTitleHandler}
8084
data-test-subj={`${id}ListingTitleLink-${item.attributes.title.split(' ').join('-')}`}
8185
>
82-
{title}
86+
<EuiHighlight highlightAll search={escapeRegExp(searchTerm)}>
87+
{title}
88+
</EuiHighlight>
8389
</EuiLink>
8490
</RedirectAppLinks>
8591
);
@@ -90,6 +96,7 @@ export function ItemDetails<T extends UserContentCommonSchema>({
9096
onClickTitle,
9197
onClickTitleHandler,
9298
redirectAppLinksCoreStart,
99+
searchTerm,
93100
title,
94101
]);
95102

@@ -100,13 +107,20 @@ export function ItemDetails<T extends UserContentCommonSchema>({
100107
<EuiTitle size="xs">{renderTitle()}</EuiTitle>
101108
{Boolean(description) && (
102109
<EuiText size="s">
103-
<p>{description!}</p>
110+
<p>
111+
<EuiHighlight highlightAll search={escapeRegExp(searchTerm)}>
112+
{description!}
113+
</EuiHighlight>
114+
</p>
104115
</EuiText>
105116
)}
106117
{hasTags && (
107118
<>
108119
<EuiSpacer size="s" />
109-
<TagList references={references} />
120+
<TagList
121+
references={references}
122+
tagRender={(tag) => <TagBadge key={tag.name} tag={tag} onClick={onClickTag} />}
123+
/>
110124
</>
111125
)}
112126
</div>

packages/content-management/table_list/src/components/table.tsx

Lines changed: 85 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import {
1616
PropertySort,
1717
SearchFilterConfig,
1818
Direction,
19+
Query,
20+
Ast,
1921
} from '@elastic/eui';
2022

2123
import { useServices } from '../services';
@@ -26,14 +28,22 @@ import type {
2628
UserContentCommonSchema,
2729
} from '../table_list_view';
2830
import { TableSortSelect } from './table_sort_select';
31+
import { TagFilterPanel } from './tag_filter_panel';
32+
import { useTagFilterPanel } from './use_tag_filter_panel';
33+
import type { Params as UseTagFilterPanelParams } from './use_tag_filter_panel';
2934
import type { SortColumnField } from './table_sort_select';
3035

3136
type State<T extends UserContentCommonSchema> = Pick<
3237
TableListViewState<T>,
3338
'items' | 'selectedIds' | 'searchQuery' | 'tableSort' | 'pagination'
3439
>;
3540

36-
interface Props<T extends UserContentCommonSchema> extends State<T> {
41+
type TagManagementProps = Pick<
42+
UseTagFilterPanelParams,
43+
'addOrRemoveIncludeTagFilter' | 'addOrRemoveExcludeTagFilter' | 'tagsToTableItemMap'
44+
>;
45+
46+
interface Props<T extends UserContentCommonSchema> extends State<T>, TagManagementProps {
3747
dispatch: Dispatch<Action<T>>;
3848
entityName: string;
3949
entityNamePlural: string;
@@ -44,6 +54,7 @@ interface Props<T extends UserContentCommonSchema> extends State<T> {
4454
deleteItems: TableListViewProps<T>['deleteItems'];
4555
onSortChange: (column: SortColumnField, direction: Direction) => void;
4656
onTableChange: (criteria: CriteriaWithPagination<T>) => void;
57+
clearTagSelection: () => void;
4758
}
4859

4960
export function Table<T extends UserContentCommonSchema>({
@@ -58,12 +69,16 @@ export function Table<T extends UserContentCommonSchema>({
5869
hasUpdatedAtMetadata,
5970
entityName,
6071
entityNamePlural,
72+
tagsToTableItemMap,
6173
deleteItems,
6274
tableCaption,
6375
onTableChange,
6476
onSortChange,
77+
addOrRemoveExcludeTagFilter,
78+
addOrRemoveIncludeTagFilter,
79+
clearTagSelection,
6580
}: Props<T>) {
66-
const { getSearchBarFilters } = useServices();
81+
const { getTagList } = useServices();
6782

6883
const renderToolsLeft = useCallback(() => {
6984
if (!deleteItems || selectedIds.length === 0) {
@@ -97,8 +112,37 @@ export function Table<T extends UserContentCommonSchema>({
97112
}
98113
: undefined;
99114

100-
const searchFilters = useMemo(() => {
101-
const tableSortSelectFilter: SearchFilterConfig = {
115+
const {
116+
isPopoverOpen,
117+
isInUse,
118+
closePopover,
119+
onFilterButtonClick,
120+
onSelectChange,
121+
options,
122+
totalActiveFilters,
123+
} = useTagFilterPanel({
124+
query: searchQuery.query,
125+
getTagList,
126+
tagsToTableItemMap,
127+
addOrRemoveExcludeTagFilter,
128+
addOrRemoveIncludeTagFilter,
129+
});
130+
131+
const onSearchQueryChange = useCallback(
132+
(arg: { query: Query | null; queryText: string }) => {
133+
dispatch({
134+
type: 'onSearchQueryChange',
135+
data: {
136+
query: arg.query ?? new Query(Ast.create([]), undefined, arg.queryText),
137+
text: arg.queryText,
138+
},
139+
});
140+
},
141+
[dispatch]
142+
);
143+
144+
const tableSortSelectFilter = useMemo<SearchFilterConfig>(() => {
145+
return {
102146
type: 'custom_component',
103147
component: () => {
104148
return (
@@ -110,25 +154,53 @@ export function Table<T extends UserContentCommonSchema>({
110154
);
111155
},
112156
};
157+
}, [hasUpdatedAtMetadata, onSortChange, tableSort]);
158+
159+
const tagFilterPanel = useMemo<SearchFilterConfig>(() => {
160+
return {
161+
type: 'custom_component',
162+
component: () => {
163+
return (
164+
<TagFilterPanel
165+
isPopoverOpen={isPopoverOpen}
166+
isInUse={isInUse}
167+
closePopover={closePopover}
168+
options={options}
169+
totalActiveFilters={totalActiveFilters}
170+
onFilterButtonClick={onFilterButtonClick}
171+
onSelectChange={onSelectChange}
172+
clearTagSelection={clearTagSelection}
173+
/>
174+
);
175+
},
176+
};
177+
}, [
178+
isPopoverOpen,
179+
isInUse,
180+
closePopover,
181+
options,
182+
totalActiveFilters,
183+
onFilterButtonClick,
184+
onSelectChange,
185+
clearTagSelection,
186+
]);
113187

114-
return getSearchBarFilters
115-
? [tableSortSelectFilter, ...getSearchBarFilters()]
116-
: [tableSortSelectFilter];
117-
}, [onSortChange, hasUpdatedAtMetadata, tableSort, getSearchBarFilters]);
188+
const searchFilters = useMemo(() => {
189+
return [tableSortSelectFilter, tagFilterPanel];
190+
}, [tableSortSelectFilter, tagFilterPanel]);
118191

119192
const search = useMemo(() => {
120193
return {
121-
onChange: ({ queryText }: { queryText: string }) =>
122-
dispatch({ type: 'onSearchQueryChange', data: queryText }),
194+
onChange: onSearchQueryChange,
123195
toolsLeft: renderToolsLeft(),
124-
defaultQuery: searchQuery,
196+
query: searchQuery.query ?? undefined,
125197
box: {
126198
incremental: true,
127199
'data-test-subj': 'tableListSearchBox',
128200
},
129201
filters: searchFilters,
130202
};
131-
}, [dispatch, renderToolsLeft, searchFilters, searchQuery]);
203+
}, [onSearchQueryChange, renderToolsLeft, searchFilters, searchQuery.query]);
132204

133205
const noItemsMessage = (
134206
<FormattedMessage
@@ -148,6 +220,7 @@ export function Table<T extends UserContentCommonSchema>({
148220
message={noItemsMessage}
149221
selection={selection}
150222
search={search}
223+
executeQueryOptions={{ enabled: false }}
151224
sorting={tableSort ? { sort: tableSort as PropertySort } : undefined}
152225
onChange={onTableChange}
153226
data-test-subj="itemsInMemTable"
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
import React, { FC } from 'react';
10+
import { EuiBadge } from '@elastic/eui';
11+
import { i18n } from '@kbn/i18n';
12+
13+
import type { Tag } from '../types';
14+
15+
const isMac = navigator.platform.toLowerCase().indexOf('mac') >= 0;
16+
17+
export interface Props {
18+
tag: Tag;
19+
onClick: (tag: Tag, withModifierKey: boolean) => void;
20+
}
21+
22+
/**
23+
* The badge representation of a Tag, which is the default display to be used for them.
24+
*/
25+
export const TagBadge: FC<Props> = ({ tag, onClick }) => {
26+
return (
27+
<EuiBadge
28+
color={tag.color}
29+
title={tag.description}
30+
data-test-subj={`tag-${tag.id}`}
31+
onClick={(e) => {
32+
const withModifierKey = (isMac && e.metaKey) || (!isMac && e.ctrlKey);
33+
onClick(tag, withModifierKey);
34+
}}
35+
onClickAriaLabel={i18n.translate('contentManagement.tableList.tagBadge.buttonLabel', {
36+
defaultMessage: '{tagName} tag button.',
37+
values: {
38+
tagName: tag.name,
39+
},
40+
})}
41+
>
42+
{tag.name}
43+
</EuiBadge>
44+
);
45+
};

0 commit comments

Comments
 (0)