Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace WzSearchBar component #5366

Closed
wants to merge 40 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e9f5923
feat: add a search bar component
Desvelao Feb 16, 2023
eff5d2b
feat(search-bar): change the AQL implemenation to use the regular exp…
Desvelao Mar 1, 2023
0923569
fix(search-bar): fixes a problem hidding the suggestion popover when …
Desvelao Mar 2, 2023
83c05cf
feat(search-bar): add the ability to update the input of example
Desvelao Mar 3, 2023
0b0b451
feat(search-bar): add initial suggestions to AQL
Desvelao Mar 6, 2023
ab8a555
feat(search-bar): add target and rel attributes to the documentation
Desvelao Mar 7, 2023
8d9f746
feat(search-bar): enhancements in AQL and search bar documentation
Desvelao Mar 7, 2023
9c01c8e
feat(search-bar): Add HAQL
Desvelao Mar 7, 2023
b6f0d6d
feat(search-bar): add test to HAQL and AQL query languages
Desvelao Mar 14, 2023
22676d4
feat(search-bar): Rename HAQL query language to WQL
Desvelao Mar 15, 2023
459a932
feat(search-bar): Add more use cases to the tests of WQL query language
Desvelao Mar 15, 2023
315932a
feat(search-bar): enhance the documenation of query languages
Desvelao Mar 15, 2023
4303a1a
feat(search-bar): Add a popover title to replicate similar UI to the …
Desvelao Mar 15, 2023
5e1485c
feat(search-bar): wrap the user input with group operators when there…
Desvelao Mar 15, 2023
9983153
feat(search-bar): add implicit query mode to WQL
Desvelao Mar 16, 2023
1eaf944
feat(search-bar): set the width of the syntax options popover
Desvelao Mar 23, 2023
d9abea0
feat(search-bar): unify suggestion descriptions in WQL
Desvelao Mar 23, 2023
c221f97
feat(search-bar): add enhancements to WQL
Desvelao Apr 10, 2023
8123d6e
Merge branch '4.5' of https://github.com/wazuh/wazuh-kibana-app into …
Desvelao Apr 10, 2023
cdbbb6d
feat(search-bar): rename previousField and previousOperatorCompare in…
Desvelao Apr 10, 2023
c300fa3
fix(tests): update snapshot
Desvelao Apr 11, 2023
ef85c54
fix(search-bar): fix documentation link for WQL
Desvelao Apr 11, 2023
17053c0
fix(search-bar): remove example usage of SearchBar component in Agents
Desvelao Apr 11, 2023
cfbf19b
fix(search-bar): fix an error using the value suggestions in WQL
Desvelao Apr 12, 2023
929b47b
feat(search-bar): replace search bar in agent selection modal
Desvelao Apr 12, 2023
4f175fb
fix(search-bar): enhance and unify the logic of agent selection modal
Desvelao Apr 14, 2023
f571f3f
feat(search-bar): replace WzSearchBar by SearchBar in Agents section
Desvelao Apr 14, 2023
d1222dc
fix(search-bar): restrict the search in Agents section table to the
Desvelao Apr 14, 2023
fb00c42
changelog: add entry
Desvelao Apr 18, 2023
b4359ce
Merge branch '4.5' into feat/4312-poc-search-bar-component-multiple-q…
Desvelao Apr 20, 2023
8438cd8
Merge branch '4.5' into feat/4312-poc-search-bar-component-multiple-q…
Desvelao Apr 20, 2023
a7d6be7
Merge branch '4.5' into feat/4312-replace-wzsearchbar
Desvelao Apr 20, 2023
57d11d6
feat(search-bar): add search function suggestion when the input is empty
Desvelao Apr 25, 2023
ce4bc92
fix(search-bar): ensure the query language output changed to trigger …
Desvelao Apr 25, 2023
4273b70
Merge branch 'feat/4312-poc-search-bar-component-multiple-query-langu…
Desvelao Apr 25, 2023
b547d98
feat(search-bar): allow the API query output can be redone when the s…
Desvelao Apr 27, 2023
a7bfc10
Merge branch 'feat/4312-poc-search-bar-component-multiple-query-langu…
Desvelao Apr 27, 2023
a3c3681
feat(search-bar): enhance the validation of value token in WQL
Desvelao Apr 27, 2023
92f1711
Merge branch 'feat/4312-poc-search-bar-component-multiple-query-langu…
Desvelao Apr 27, 2023
6678f6c
feat(search-bar): adapt the replacement of search bar in `Agents` and…
Desvelao May 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ All notable changes to the Wazuh app project will be documented in this file.
### Changed

- Changed of regular expression in RBAC. [#5201](https://github.com/wazuh/wazuh-kibana-app/pull/5201)
- Changed the search bar of agent selector modal and Agents section [#5366](https://github.com/wazuh/wazuh-kibana-app/pull/5366)
- Migrate the timeFilter, metaFields, maxBuckets health checks inside the pattern check. [#5384](https://github.com/wazuh/wazuh-kibana-app/pull/5384)

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ exports[`Table With Search Bar component renders correctly to match the snapshot
anchorPosition="downLeft"
attachToAnchor={true}
closePopover={[Function]}
disableFocusTrap={false}
display="block"
fullWidth={true}
id="popover"
Expand Down
2 changes: 2 additions & 0 deletions public/components/eui-suggest/suggest_input.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class EuiSuggestInput extends Component {
onPopoverFocus,
isPopoverOpen,
onClosePopover,
disableFocusTrap = false,
...rest
} = this.props;

Expand Down Expand Up @@ -108,6 +109,7 @@ export class EuiSuggestInput extends Component {
panelPaddingSize="none"
fullWidth
closePopover={onClosePopover}
disableFocusTrap={disableFocusTrap}
>
<div>{suggestions}</div>
</EuiInputPopover>
Expand Down
201 changes: 201 additions & 0 deletions public/components/search-bar/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Component

The `SearchBar` component is a base component of a search bar.

It is designed to be extensible through the self-contained query language implementations. This means
the behavior of the search bar depends on the business logic of each query language. For example, a
query language can display suggestions according to the user input or prepend some buttons to the search bar.

It is based on a custom `EuiSuggest` component defined in `public/components/eui-suggest/suggest.js`. So the
abilities are restricted by this one.

## Features

- Supports multiple query languages.
- Switch the selected query language.
- Self-contained query language implementation and ability to interact with the search bar component.
- React to external changes to set the new input. This enables to change the input from external components.

# Usage

Basic usage:

```tsx
<SearchBar
// Define the query languages. Required.
// The ID of them should be registered previously. See How to add a new query language documentation.
modes={[
{
id: 'wql',
// specific query language parameters
options: {
// implicit query. Optional
// Set a implicit query that can't be changed by the user.
// Use the UQL (Unified Query Language) syntax.
implicitQuery: {
query: 'id!=000',
conjunction: ';'
},
searchTermFields: ['id', 'ip']
},
suggestions: {
field(currentValue) {
return [
{ label: 'configSum', description: 'Config sum' },
{ label: 'dateAdd', description: 'Date add' },
{ label: 'id', description: 'ID' },
{ label: 'ip', description: 'IP address' },
{ label: 'group', description: 'Group' },
{ label: 'group_config_status', description: 'Synced configuration status' },
{ label: 'lastKeepAline', description: 'Date add' },
{ label: 'manager', description: 'Manager' },
{ label: 'mergedSum', description: 'Merged sum' },
{ label: 'name', description: 'Agent name' },
{ label: 'node_name', description: 'Node name' },
{ label: 'os.platform', description: 'Operating system platform' },
{ label: 'status', description: 'Status' },
{ label: 'version', description: 'Version' },
];
},
value: async (currentValue, { field }) => {
switch (field) {
case 'configSum':
return [
{ label: 'configSum1' },
{ label: 'configSum2' },
];
break;
case 'dateAdd':
return [
{ label: 'dateAdd1' },
{ label: 'dateAdd2' },
];
break;
case 'status':
return UI_ORDER_AGENT_STATUS.map(
(status) => ({
label: status,
}),
);
break;
default:
return [];
break;
}
},
}
},
]}
// Handler fired when the input handler changes. Optional.
onChange={onChange}
// Handler fired when the user press the Enter key or custom implementations. Required.
onSearch={onSearch}
// Used to define the internal input. Optional.
// This could be used to change the input text from the external components.
// Use the UQL (Unified Query Language) syntax.
input=''
// Define the default mode. Optional. If not defined, it will use the first one mode.
defaultMode=''
></SearchBar>
```

# Query languages

The built-in query languages are:

- AQL: API Query Language. Based on https://documentation.wazuh.com/current/user-manual/api/queries.html.

## How to add a new query language

### Definition

The language expects to take the interface:

```ts
type SearchBarQueryLanguage = {
description: string;
documentationLink?: string;
id: string;
label: string;
getConfiguration?: () => any;
run: (input: string | undefined, params: any) => Promise<{
searchBarProps: any,
output: {
language: string,
apiQuery: string,
query: string
}
}>;
transformUQLToQL: (unifiedQuery: string) => string;
};
```

where:

- `description`: is the description of the query language. This is displayed in a query language popover
on the right side of the search bar. Required.
- `documentationLink`: URL to the documentation link. Optional.
- `id`: identification of the query language.
- `label`: name
- `getConfiguration`: method that returns the configuration of the language. This allows custom behavior.
- `run`: method that returns:
- `searchBarProps`: properties to be passed to the search bar component. This allows the
customization the properties that will used by the base search bar component and the output used when searching
- `output`:
- `language`: query language ID
- `apiQuery`: API query.
- `query`: current query in the specified language
- `transformUQLToQL`: method that transforms the UQL (Unified Query Language) to the specific query
language. This is used when receives a external input in the Unified Query Language, the returned
value is converted to the specific query language to set the new input text of the search bar
component.

Create a new file located in `public/components/search-bar/query-language` and define the expected interface;

### Register

Go to `public/components/search-bar/query-language/index.ts` and add the new query language:

```ts
import { AQL } from './aql';

// Import the custom query language
import { CustomQL } from './custom';

// [...]

// Register the query languages
export const searchBarQueryLanguages: {
[key: string]: SearchBarQueryLanguage;
} = [
AQL,
CustomQL, // Add the new custom query language
].reduce((accum, item) => {
if (accum[item.id]) {
throw new Error(`Query language with id: ${item.id} already registered.`);
}
return {
...accum,
[item.id]: item,
};
}, {});
```

## Unified Query Language - UQL

This is an unified syntax used by the search bar component that provides a way to communicate
with the different query language implementations.

The input and output parameters of the search bar component must use this syntax.

This is used in:
- input:
- `input` component property
- output:
- `onChange` component handler
- `onSearch` component handler

Its syntax is equal to Wazuh API Query Language
https://wazuh.com/<major_version>.<minor_version>/user-manual/api/queries.html

> The AQL query language is a implementation of this syntax.
59 changes: 59 additions & 0 deletions public/components/search-bar/__snapshots__/index.test.tsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`SearchBar component Renders correctly the initial render 1`] = `
<div>
<div>
<div
class="euiSuggestInput"
>
<div
class="euiPopover euiPopover--anchorDownLeft euiPopover--displayBlock euiInputPopover euiInputPopover--fullWidth"
id="popover"
>
<div
class="euiPopover__anchor"
>
<div>
<div
class="euiFormControlLayout euiFormControlLayout--fullWidth euiFormControlLayout--group"
>
<div
class="euiFormControlLayout__childrenWrapper"
>
<input
class="euiFieldText euiFieldText--fullWidth euiFieldText--inGroup"
placeholder="Search"
type="text"
value=""
/>
</div>
<div
class="euiPopover euiPopover--anchorDownCenter euiFormControlLayout__append"
>
<div
class="euiPopover__anchor"
>
<button
class="euiButtonEmpty euiButtonEmpty--primary"
type="button"
>
<span
class="euiButtonContent euiButtonEmpty__content"
>
<span
class="euiButtonEmpty__text"
>
WQL
</span>
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
57 changes: 57 additions & 0 deletions public/components/search-bar/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React from 'react';
import { render } from '@testing-library/react';
import { SearchBar } from './index';

describe('SearchBar component', () => {
const componentProps = {
defaultMode: 'wql',
input: '',
modes: [
{
id: 'aql',
implicitQuery: 'id!=000;',
suggestions: {
field(currentValue) {
return [];
},
value(currentValue, { field }){
return [];
},
},
},
{
id: 'wql',
implicitQuery: {
query: 'id!=000',
conjunction: ';'
},
suggestions: {
field(currentValue) {
return [];
},
value(currentValue, { field }){
return [];
},
},
},
],
/* eslint-disable @typescript-eslint/no-empty-function */
onChange: () => {},
onSearch: () => {}
/* eslint-enable @typescript-eslint/no-empty-function */
};

it('Renders correctly the initial render', async () => {
const wrapper = render(
<SearchBar
{...componentProps}
defaultMode='wql'
/>
);

/* This test causes a warning about act. This is intentional, because the test pretends to get
the first rendering of the component that doesn't have the component properties coming of the
selected query language */
expect(wrapper.container).toMatchSnapshot();
});
});
Loading