Skip to content

Commit

Permalink
[Backport 4.4-7.16] Refactor ruleset management (#4486)
Browse files Browse the repository at this point in the history
Refactor ruleset management (#4174)

* Refactored implementation of wazuh table

* Refactored action buttons

* Partial commit ruleset views segregation

* Added searchbar input custom filter buttons

* Added Custom Field Filter to table & removed redux from action buttons

* Segregated file tables

* set showingFiles locally

* Fixed details flyout

* Segregate views

* Removed redux from ruleset editor

* refactored Decoders section

* delete obsolete decoder-info

* Fixed decoder flyout

* Added decoder info.tsx

* Remove unused files

* Set CDBList views

* Dynamically build table custom action buttons

* Deleted hardcoded export csv filename

* Fix CDB List row click handler

* Fixed suggestions and custom actions responsive styles

* columns configuration fix

* wzApiTable optimization + obsolete redux cleaning

* Implemented Wazuh flyouts

* Convert to typescript

* Extracted tables components

* Fix mapStateToProps to null

* Removed ruleset redux files

* Removed Add CDB List button in ruleset and decoders views

* Fix missing updateListContent

* Added external reload to the tables

* Fixed redirectRule url cleaning

* Fix onClose modal preventDefault

* Fix reload props

* Fix onClick modal preventDefault

* Clean code comments

* Added error handling to tables columns

* removed deprecated code

* Fixed file description and objects destructuring

* Refactored class components to functional

* Changed file view state handling

* Refactored implementation of wazuh table

* Refactored action buttons

* Partial commit ruleset views segregation

* Added searchbar input custom filter buttons

* Added Custom Field Filter to table & removed redux from action buttons

* Segregated file tables

* set showingFiles locally

* Fixed details flyout

* Segregate views

* Removed redux from ruleset editor

* refactored Decoders section

* delete obsolete decoder-info

* Fixed decoder flyout

* Added decoder info.tsx

* Remove unused files

* Set CDBList views

* Dynamically build table custom action buttons

* Deleted hardcoded export csv filename

* Fix CDB List row click handler

* Fixed suggestions and custom actions responsive styles

* columns configuration fix

* wzApiTable optimization + obsolete redux cleaning

* Implemented Wazuh flyouts

* Convert to typescript

* Extracted tables components

* Fix mapStateToProps to null

* Removed ruleset redux files

* Removed Add CDB List button in ruleset and decoders views

* Fix missing updateListContent

* Added external reload to the tables

* Fixed redirectRule url cleaning

* Fix onClose modal preventDefault

* Fix reload props

* Fix onClick modal preventDefault

* Clean code comments

* Added error handling to tables columns

* removed deprecated code

* Fixed file description and objects destructuring

* Refactored class components to functional

* Changed file view state handling

* Remove unused imports

* Fixed ResourcesHandler

* Added interfaces and fixed comments

* Add section contants

* Code styling

* Replaced string for constants

Co-authored-by: Alex Ruiz Becerra <alejandro.ruiz.becerra@wazuh.com>
(cherry picked from commit 5db8ae0)

Co-authored-by: Federico Rodriguez <federico.rodriguez@wazuh.com>
  • Loading branch information
github-actions[bot] and asteriscos authored Sep 9, 2022
1 parent 9a63395 commit 127e4e1
Show file tree
Hide file tree
Showing 57 changed files with 3,142 additions and 3,266 deletions.
8 changes: 4 additions & 4 deletions public/components/common/buttons/modal-confirm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ interface WzButtonModalConfirmProps{
};

const renderModal = ({onConfirm, onCancel, modalTitle, modalConfirmText, modalCancelText, modalProps }) => ({close}) => {
const onModalConfirm = () => {
close();
const onModalConfirm = (ev) => {
close(ev);
onConfirm && onConfirm();
};
const onModalCancel = () => {
close();
const onModalCancel = (ev) => {
close(ev);
onCancel && onCancel();
};
return (
Expand Down
12 changes: 9 additions & 3 deletions public/components/common/hocs/withButtonOpenOnClick.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@
import React, { useState } from 'react';


export const withButtonOpenOnClick = WrappedComponent => ({render, ...rest} : {render?:any, [x:string]: any}) => {
export const withButtonOpenOnClick = WrappedComponent => ({render, onClick, onClose, ...rest} : {render?:any, [x:string]: any}) => {
const [isOpen, setIsOpen] = useState(false);

const open = ev => setIsOpen(true);
const close = ev => setIsOpen(false);
const open = ev => {
typeof onClick === 'function' && onClick(ev);
setIsOpen(true);
};
const close = ev => {
typeof onClose === 'function' && onClose(ev);
setIsOpen(false)
};

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { UI_ERROR_SEVERITIES } from '../../../../react-services/error-orchestrat
import { UI_LOGGER_LEVELS } from '../../../../../common/constants';
import { getErrorOrchestrator } from '../../../../react-services/common-services';

export function ExportTableCsv({endpoint,totalItems,filters,title}){
export function ExportTableCsv({ endpoint, totalItems, filters, title }) {

const showToast = (color, title, time) => {
getToasts().add({
Expand All @@ -42,7 +42,7 @@ export function ExportTableCsv({endpoint,totalItems,filters,title}){
[
...formatedFilters
],
`vuls-${(title).toLowerCase()}`
`${(title).toLowerCase()}`
);
} catch (error) {
const options = {
Expand Down
21 changes: 18 additions & 3 deletions public/components/common/tables/table-default.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/

import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import { EuiBasicTable } from '@elastic/eui';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
Expand Down Expand Up @@ -43,6 +43,8 @@ export function TableDefault({
}
});

const isMounted = useRef(false);

function tableOnChange({ page = {}, sort = {} }){
const { index: pageIndex, size: pageSize } = page;
const { field, direction } = sort;
Expand All @@ -59,9 +61,14 @@ export function TableDefault({
};

useEffect(() => {
// Reset the page index when the endpoint changes.
// This will cause that onSearch function is triggered because to changes in pagination in the another effect.
// This effect is triggered when the component is mounted because of how to the useEffect hook works.
// We don't want to set the pagination state because there is another effect that has this dependency
// and will cause the effect is triggered (redoing the onSearch function).
if (isMounted.current) {
// Reset the page index when the endpoint changes.
// This will cause that onSearch function is triggered because to changes in pagination in the another effect.
setPagination({pageIndex: 0, pageSize: pagination.pageSize});
}
}, [endpoint]);

useEffect(() => {
Expand Down Expand Up @@ -90,6 +97,14 @@ export function TableDefault({
})()
}, [endpoint, pagination, sorting, reload]);


// It is required that this effect runs after other effects that use isMounted
// to avoid that these effects run when the component is mounted, only running
// when one of its dependencies changes.
useEffect(() => {
isMounted.current = true;
}, []);

const tablePagination = {
...pagination,
totalItemCount: totalItems,
Expand Down
64 changes: 43 additions & 21 deletions public/components/common/tables/table-with-search-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
* Find more information about this on the LICENSE file.
*/

import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import { EuiBasicTable, EuiSpacer } from '@elastic/eui';
import _ from 'lodash';
import { WzSearchBar } from '../../wz-search-bar/';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
Expand Down Expand Up @@ -48,29 +49,38 @@ export function TableWithSearchBar({
},
});

const isMounted = useRef(false);

function tableOnChange({ page = {}, sort = {} }) {
const { index: pageIndex, size: pageSize } = page;
const { field, direction } = sort;
setPagination({
pageIndex,
pageSize,
});
setSorting({
sort: {
field,
direction,
},
});
if (isMounted.current) {
const { index: pageIndex, size: pageSize } = page;
const { field, direction } = sort;
setPagination({
pageIndex,
pageSize,
});
setSorting({
sort: {
field,
direction,
},
});
}
}

useEffect(() => {
// Reset the page index when the endpoint changes.
// This will cause that onSearch function is triggered because to changes in pagination in the another effect.
setPagination({pageIndex: 0, pageSize: pagination.pageSize});
}, [endpoint]);
// This effect is triggered when the component is mounted because of how to the useEffect hook works.
// We don't want to set the pagination state because there is another effect that has this dependency
// and will cause the effect is triggered (redoing the onSearch function).
if (isMounted.current) {
// Reset the page index when the endpoint changes.
// This will cause that onSearch function is triggered because to changes in pagination in the another effect.
setPagination({ pageIndex: 0, pageSize: pagination.pageSize });
}
}, [endpoint, reload]);

useEffect(() => {
(async function () {
useEffect(function () {
(async () => {
try {
setLoading(true);
const { items, totalItems } = await onSearch(endpoint, filters, pagination, sorting);
Expand All @@ -93,12 +103,24 @@ export function TableWithSearchBar({
}
setLoading(false);
})();
}, [filters, pagination, sorting, reload]);
}, [filters, pagination, sorting]);

useEffect(() => {
setFilters(rest.filters || []);
// This effect is triggered when the component is mounted because of how to the useEffect hook works.
// We don't want to set the filters state because there is another effect that has this dependency
// and will cause the effect is triggered (redoing the onSearch function).
if (isMounted.current && !_.isEqual(rest.filters, filters)) {
setFilters(rest.filters || []);
}
}, [rest.filters]);

// It is required that this effect runs after other effects that use isMounted
// to avoid that these effects run when the component is mounted, only running
// when one of its dependencies changes.
useEffect(() => {
isMounted.current = true;
}, []);

const tablePagination = {
...pagination,
totalItemCount: totalItems,
Expand Down
119 changes: 96 additions & 23 deletions public/components/common/tables/table-wz-api.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,59 @@
* Find more information about this on the LICENSE file.
*/

import React, { useCallback, useState } from 'react';
import React, { ReactNode, useCallback, useEffect, useState } from 'react';
import {
EuiTitle,
EuiLoadingSpinner,
EuiFlexGroup,
EuiFlexItem,
EuiText,
EuiButtonEmpty
} from '@elastic/eui';
import { filtersToObject } from '../../wz-search-bar';
import { TableWithSearchBar } from './table-with-search-bar';
import { TableDefault } from './table-default'
import { WzRequest } from '../../../react-services/wz-request';
import { ExportTableCsv } from './components/export-table-csv';
import { ExportTableCsv } from './components/export-table-csv';
import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import { getErrorOrchestrator } from '../../../react-services/common-services';

export function TableWzAPI({...rest}){
/**
* Search input custom filter button
*/
interface CustomFilterButton {
label: string
field: string
value: string
}

export function TableWzAPI({ actionButtons, ...rest }: {
actionButtons?: ReactNode | ReactNode[]
title?: string
description?: string
downloadCsv?: boolean
searchTable?: boolean
endpoint: string
buttonOptions?: CustomFilterButton[]
onFiltersChange?: Function,
showReload?: boolean
searchBarProps?: any
reload?: any
}) {

const [totalItems, setTotalItems] = useState(0);
const [filters, setFilters] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const onFiltersChange = filters => typeof rest.onFiltersChange === 'function' ? rest.onFiltersChange(filters) : null;

const onSearch = useCallback(async function(endpoint, filters, pagination, sorting){
/**
* Changing the reloadFootprint timestamp will trigger reloading the table
*/
const [reloadFootprint, setReloadFootprint] = useState(rest.reload || 0);


const onSearch = useCallback(async function (endpoint, filters, pagination, sorting) {
try {
const { pageIndex, pageSize } = pagination;
const { field, direction } = sorting.sort;
Expand Down Expand Up @@ -68,36 +97,80 @@ export function TableWzAPI({...rest}){
};
getErrorOrchestrator().handleError(options);
};
},[]);
}, []);

const renderActionButtons = (<>
{Array.isArray(actionButtons) ?
actionButtons.map((button, key) => <EuiFlexItem key={key} grow={false}>{button}</EuiFlexItem>) :
(typeof actionButtons === 'object') && <EuiFlexItem grow={false}>{actionButtons}</EuiFlexItem>}
</>)

/**
* Generate a new reload footprint
*/
const triggerReload = () => {
setReloadFootprint(Date.now());
}

useEffect(() => {
if (rest.reload)
triggerReload();
}, [rest.reload])

const ReloadButton = (
<EuiFlexItem grow={false}>
<EuiButtonEmpty isDisabled={(totalItems == 0)} iconType="refresh" onClick={() => triggerReload()}>
Refresh
</EuiButtonEmpty>
</EuiFlexItem>
)

const header = (
<EuiFlexGroup>
<EuiFlexItem>
<EuiFlexGroup wrap>
<EuiFlexItem className="wz-flex-basis-auto" grow={false}>
{rest.title && (
<EuiTitle size="s">
<h1>{rest.title} {isLoading ? <EuiLoadingSpinner size="s" /> : <span>({ totalItems })</span>}</h1>
<h1>{rest.title} {isLoading ? <EuiLoadingSpinner size="s" /> : <span>({totalItems})</span>}</h1>
</EuiTitle>
)}
{rest.description && (
<EuiText color="subdued">
{rest.description}
</EuiText>
)}
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup
wrap
justifyContent={'flexEnd'}
alignItems={'center'}
>
{/* Render optional custom action button */}
{renderActionButtons}
{/* Render optional reload button */}
{rest.showReload && ReloadButton}
{/* Render optional export to CSV button */}
{rest.downloadCsv && <ExportTableCsv endpoint={rest.endpoint} totalItems={totalItems} filters={filters} title={rest.title} />}
</EuiFlexGroup>
</EuiFlexItem>
{rest.downloadCsv && <ExportTableCsv endpoint={rest.endpoint} totalItems={totalItems} filters={filters} title={rest.title}/>}
</EuiFlexGroup>
)

const table = rest.searchTable ?
<TableWithSearchBar
onSearch={onSearch}
{...rest}
/> :
<TableDefault
onSearch={onSearch}
{...rest}
/>
const table = rest.searchTable ?
<TableWithSearchBar
onSearch={onSearch}
{...{...rest, reload: reloadFootprint}}
/> :
<TableDefault
onSearch={onSearch}
{...{...rest, reload: reloadFootprint}}
/>

return (
<>
{header}
{table}
</>)
<>
{header}
{table}
</>)
}

// Set default props
Expand Down
1 change: 0 additions & 1 deletion public/components/common/welcome/components/menu-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,6 @@ class WzMenuAgent extends Component {

const mapStateToProps = (state) => {
return {
state: state.rulesetReducers,
currentAgentData: state.appStateReducers.currentAgentData,
currentTab: state.appStateReducers.currentTab,
};
Expand Down
1 change: 0 additions & 1 deletion public/components/wz-menu/wz-menu-agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,6 @@ class WzMenuAgent extends Component {

const mapStateToProps = state => {
return {
state: state.rulesetReducers,
currentAgentData: state.appStateReducers.currentAgentData,
currentTab: state.appStateReducers.currentTab
};
Expand Down
2 changes: 1 addition & 1 deletion public/components/wz-menu/wz-menu-management.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ class WzMenuManagement extends Component {

const mapStateToProps = state => {
return {
state: state.rulesetReducers,
state: state.managementReducers,
};
};

Expand Down
1 change: 0 additions & 1 deletion public/components/wz-menu/wz-menu-overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ class WzMenuOverview extends Component {

const mapStateToProps = state => {
return {
state: state.rulesetReducers,
currentAgentData: state.appStateReducers.currentAgentData,
currentTab: state.appStateReducers.currentTab
};
Expand Down
Loading

0 comments on commit 127e4e1

Please sign in to comment.