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

Create Wazuh Searchbar component #6716

Merged
merged 18 commits into from
May 30, 2024
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
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 @@ -41,6 +41,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Upgraded versions of `follow-redirects` and `es5-ext` [#6626](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6626)
- Changed agent log collector socket API response controller component [#6660](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6660)
- Improve margins and paddins in the Events, Inventory and Control tabs [#6708](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6708)
- Refactored the search bar to correctly handle fixed and user-added filters [#6716](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6716)

### Fixed

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState, useEffect, useLayoutEffect } from 'react';
import React, { useState, useEffect } from 'react';
import {
Filter,
IndexPattern,
Expand All @@ -14,8 +14,8 @@ import { tFilter } from '../data-source';
import { MultiSelect } from './components';
import { getCustomValueSuggestion } from '../../../components/overview/office/panel/config/helpers/helper-value-suggestion';
import { I18nProvider } from '@osd/i18n/react';
import { getPlugins } from '../../../kibana-services';
import { tUseSearchBarProps } from '../search-bar/use-search-bar';
import { WzSearchBar } from '../search-bar/search-bar';

type CustomSearchBarProps = {
filterInputs: {
Expand All @@ -29,16 +29,15 @@ type CustomSearchBarProps = {
setFilters: (filters: tFilter[]) => void;
};

const SearchBar = getPlugins().data.ui.SearchBar;

export const CustomSearchBar = ({
filterInputs,
filterDrillDownValue = { field: '', value: '' },
searchBarProps,
indexPattern,
setFilters
setFilters,
}: CustomSearchBarProps) => {
const { filters } = searchBarProps;
const { filters, fixedFilters } = searchBarProps;

const defaultSelectedOptions = () => {
const array = [];
filterInputs.forEach(item => {
Expand All @@ -60,7 +59,7 @@ export const CustomSearchBar = ({
}, [values]);

useEffect(() => {
onFiltersUpdated();
refreshCustomSelectedFilter();
}, [filters]);

const checkSelectDrillDownValue = key => {
Expand All @@ -69,8 +68,9 @@ export const CustomSearchBar = ({
? true
: false;
};
const onFiltersUpdated = () => {
refreshCustomSelectedFilter();

const onFiltersUpdated = (filters?: Filter[]) => {
setFilters([...fixedFilters, filters]);
};

const changeSwitch = () => {
Expand Down Expand Up @@ -138,7 +138,16 @@ export const CustomSearchBar = ({

const getFilterCustom = item => {
// ToDo: Make this generic, without office 365 hardcode
return item.params.map((element) => ({ checked: 'on', label: item.key === 'data.office365.UserType' ? getLabelUserType(element) : element, value: item.key, key: element, filterByKey: item.key === 'data.office365.UserType' ? true : false }));
return item.params.map(element => ({
checked: 'on',
label:
item.key === 'data.office365.UserType'
? getLabelUserType(element)
: element,
value: item.key,
key: element,
filterByKey: item.key === 'data.office365.UserType' ? true : false,
}));
};
const getLabelUserType = element => {
const userTypeOptions = getCustomValueSuggestion(
Expand All @@ -148,7 +157,8 @@ export const CustomSearchBar = ({
(item, index) => index.toString() === element,
);
};
const filterCustom = currentFilters.map(item => getFilterCustom(item)) || [];
const filterCustom =
currentFilters.map(item => getFilterCustom(item)) || [];
if (filterCustom.length != 0) {
filterCustom.forEach(item => {
item.forEach(element => {
Expand Down Expand Up @@ -191,46 +201,33 @@ export const CustomSearchBar = ({

return (
<I18nProvider>
<EuiFlexGroup
className='custom-kbn-search-bar'
alignItems='center'
style={{ margin: '0 8px' }}
>
{!avancedFiltersState
? filterInputs.map((item, key) => (
<EuiFlexItem key={key}>{getComponent(item)}</EuiFlexItem>
))
: ''}
<EuiFlexItem>
<div className='wz-search-bar hide-filter-control'>
<SearchBar
{...searchBarProps}
showFilterBar={false}
showQueryInput={avancedFiltersState}
onFiltersUpdated={onFiltersUpdated}
/>
</div>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup justifyContent='flexEnd' style={{ margin: '0 20px' }}>
<EuiFlexItem className={'filters-search-bar'} style={{ margin: '0px' }}>
<div className='wz-search-bar hide-filter-control'>
<SearchBar
{...searchBarProps}
showDatePicker={false}
showQueryInput={false}
onFiltersUpdated={onFiltersUpdated}
<div style={{ margin: '20px 20px 0px 20px' }}>
<WzSearchBar
{...searchBarProps}
showQueryInput={avancedFiltersState}
onFiltersUpdated={onFiltersUpdated}
preQueryBar={
!avancedFiltersState ? (
<EuiFlexGroup
className='custom-kbn-search-bar'
alignItems='center'
gutterSize='s'
>
{filterInputs.map((item, key) => (
<EuiFlexItem key={key}>{getComponent(item)}</EuiFlexItem>
))}
</EuiFlexGroup>
) : null
}
postFilters={
<EuiSwitch
label='Advanced filters'
checked={avancedFiltersState}
onChange={() => changeSwitch()}
/>
</div>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSwitch
label='Advanced filters'
checked={avancedFiltersState}
onChange={() => changeSwitch()}
/>
</EuiFlexItem>
</EuiFlexGroup>
}
/>
</div>
</I18nProvider>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,3 @@ describe('useDataSource hook', () => {


})

Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ type tUseDataSourceLoadedReturns<K> = {
dataSource: K;
filters: tFilter[];
fetchFilters: tFilter[];
fixedFilters: tFilter[];
fetchData: (params: Omit<tSearchParams, 'filters'>) => Promise<any>;
setFilters: (filters: tFilter[]) => void;
filterManager: PatternDataSourceFilterManager;
Expand All @@ -38,7 +37,6 @@ type tUseDataSourceNotLoadedReturns = {
dataSource: undefined;
filters: [];
fetchFilters: [];
fixedFilters: [];
fetchData: (params: Omit<tSearchParams, 'filters'>) => Promise<any>;
setFilters: (filters: tFilter[]) => void;
filterManager: null;
Expand Down Expand Up @@ -126,7 +124,7 @@ export function useDataSource<
setDataSourceFilterManager(dataSourceFilterManager);
setIsLoading(false);
})();

return () => subscription && subscription.unsubscribe();
}, []);

Expand Down Expand Up @@ -161,7 +159,6 @@ export function useDataSource<
dataSource: undefined,
filters: [],
fetchFilters: [],
fixedFilters: [],
fetchData,
setFilters,
filterManager: null,
Expand All @@ -172,7 +169,6 @@ export function useDataSource<
dataSource: dataSource as K,
filters: allFilters,
fetchFilters,
fixedFilters: dataSourceFilterManager?.getFixedFilters() || [],
fetchData,
setFilters,
filterManager: dataSourceFilterManager as PatternDataSourceFilterManager,
Expand Down
1 change: 1 addition & 0 deletions plugins/main/public/components/common/search-bar/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './search-bar-service';
export * from './use-search-bar';
export * from './search-bar';
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.wz-search-bar-no-padding .globalQueryBar:not(:empty) {
padding: 0px !important;
}
99 changes: 99 additions & 0 deletions plugins/main/public/components/common/search-bar/search-bar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React from 'react';
import { getPlugins } from '../../../kibana-services';
import './search-bar.scss';
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiBadge } from '@elastic/eui';
import {
SearchBarProps,
Filter,
} from '../../../../../../src/plugins/data/public';

export interface WzSearchBarProps extends SearchBarProps {
fixedFilters?: Filter[];
userFilters?: Filter[];
preQueryBar?: React.ReactElement;
postFilters?: React.ReactElement;
}

export const WzSearchBar = ({
fixedFilters = [],
userFilters = [],
preQueryBar,
postFilters,
...restProps
}: WzSearchBarProps) => {
const SearchBar = getPlugins().data.ui.SearchBar;

const showQuery =
restProps.showQueryBar ||
restProps.showQueryInput ||
restProps.showDatePicker !== false;
const showFilters = restProps.showFilterBar !== false;

return (
<EuiPanel
className='wz-search-bar wz-search-bar-no-padding'
paddingSize='s'
hasShadow={false}
hasBorder={false}
color='transparent'
grow={false}
>
{showQuery ? (
<EuiFlexGroup
gutterSize='s'
alignItems='center'
responsive={false}
wrap={true}
>
{preQueryBar ? <EuiFlexItem>{preQueryBar}</EuiFlexItem> : null}
<EuiFlexItem grow={!preQueryBar}>
<SearchBar {...restProps} showFilterBar={false} />
</EuiFlexItem>
</EuiFlexGroup>
) : null}
{showFilters ? (
<EuiFlexGroup gutterSize='s'>
<EuiFlexItem grow={false}>
<EuiFlexGroup
gutterSize='xs'
className='globalFilterBar globalFilterGroup__filterBar'
responsive={false}
wrap={true}
>
{fixedFilters?.map((filter, idx) => (
<EuiFlexItem grow={false} key={idx}>
<EuiBadge className='globalFilterItem' color='hollow'>
{`${filter.meta.key}: ${typeof filter.meta.value === 'function'
? filter.meta.value()
: filter.meta.value
}`}
</EuiBadge>
</EuiFlexItem>
))}
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup
gutterSize='s'
alignItems='center'
responsive={false}
wrap={true}
>
<EuiFlexItem>
<SearchBar
{...restProps}
filters={userFilters}
showQueryBar={false}
useDefaultBehaviors={false}
/>
</EuiFlexItem>
{postFilters ? (
<EuiFlexItem grow={false}>{postFilters}</EuiFlexItem>
) : null}
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
) : null}
</EuiPanel>
);
};
Loading
Loading