diff --git a/CHANGELOG.md b/CHANGELOG.md
index b82c42fdf5..0566813cac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,11 +30,17 @@ All notable changes to the Wazuh app project will be documented in this file.
- Refined the layout of the agent details view [#7193](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7193)
- Changed the width of the command column, relocate argvs column and change the width of the rest of the columns in the table processes. [#7195](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7195)
-## Wazuh v4.10.1 - OpenSearch Dashboards 2.16.0 - Revision 00
+## Wazuh v4.10.1 - OpenSearch Dashboards 2.16.0 - Revision 01
### Added
- Support for Wazuh 4.10.1
+- Added comma separators to numbers [#7233](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7233)
+
+### Changed
+
+- Move the ability to manage the visibility of fields in `Events` and `Vulnerability Detection` > `Inventory` tables from `Columns` button to a new `Available fields` button enhancing the performance of the view [#7226](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7226)
+- Change the color of `Export formatted` button of data grid tables to match the color of the rest of table buttons [#7226](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7226)
## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 08
@@ -87,6 +93,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed error message to prevent pass no strings to the wazuh logger [#7167](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7167)
- Fixed the rendering of the `data.vunerability.reference` in the table and flyout [#7177](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7177)
- Fixed incorrect or empty Wazuh API version displayed after upgrade [#440](https://github.com/wazuh/wazuh-dashboard/issues/440)
+- Fixed typo in flyout title for available updates [#7235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7235)
### Removed
diff --git a/plugins/main/public/components/common/charts/visualizations/legend.tsx b/plugins/main/public/components/common/charts/visualizations/legend.tsx
index f3a2c6a6e8..b707a16c49 100644
--- a/plugins/main/public/components/common/charts/visualizations/legend.tsx
+++ b/plugins/main/public/components/common/charts/visualizations/legend.tsx
@@ -2,6 +2,7 @@ import React from 'react';
import { EuiIcon } from '@elastic/eui';
import { EuiListGroup } from '@elastic/eui';
import './legend.scss';
+import { formatUINumber } from '../../../../react-services/format-number';
type ChartLegendProps = {
data: {
@@ -24,7 +25,7 @@ export function ChartLegend({ data }: ChartLegendProps) {
textOverflow: 'ellipsis',
overflow: 'hidden',
}}
- >{`${label} (${value})`}
+ >{`${label} (${formatUINumber(value)})`}
),
icon: ,
...rest,
diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.tsx b/plugins/main/public/components/common/data-grid/use-data-grid.tsx
index 68ff88c09e..551b6107bd 100644
--- a/plugins/main/public/components/common/data-grid/use-data-grid.tsx
+++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx
@@ -247,7 +247,10 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => {
return {
'aria-labelledby': props.ariaLabelledBy,
- columns: orderFirstMatchedColumns(getColumns, visibleColumns),
+ columnsAvailable: orderFirstMatchedColumns(getColumns, visibleColumns), // This is a custom property used by the Available fields and is not part of EuiDataGrid component specification
+ columns: visibleColumns.map(columnId =>
+ getColumns.find(({ id }) => id === columnId),
+ ),
columnVisibility: {
visibleColumns,
setVisibleColumns,
diff --git a/plugins/main/public/components/common/tables/table-wz-api.tsx b/plugins/main/public/components/common/tables/table-wz-api.tsx
index f40e81b955..93b8641251 100644
--- a/plugins/main/public/components/common/tables/table-wz-api.tsx
+++ b/plugins/main/public/components/common/tables/table-wz-api.tsx
@@ -27,6 +27,8 @@ import { TableDefault } from './table-default';
import { WzRequest } from '../../../react-services/wz-request';
import { ExportTableCsv } from './components/export-table-csv';
import { useStateStorage, useAppConfig } from '../hooks';
+import { formatUINumber } from '../../../react-services/format-number';
+
/**
* Search input custom filter button
*/
@@ -217,7 +219,7 @@ export function TableWzAPI({
{isLoading ? (
) : (
- ({totalItems})
+ ({formatUINumber(totalItems)})
)}
diff --git a/plugins/main/public/components/common/wazuh-data-grid/wz-data-grid.tsx b/plugins/main/public/components/common/wazuh-data-grid/wz-data-grid.tsx
index ff1413aa35..fe643ca4fe 100644
--- a/plugins/main/public/components/common/wazuh-data-grid/wz-data-grid.tsx
+++ b/plugins/main/public/components/common/wazuh-data-grid/wz-data-grid.tsx
@@ -160,6 +160,10 @@ const WazuhDataGrid = (props: tWazuhDataGridProps) => {
{!isLoading && results?.hits?.total > 0 ? (
void;
maxEntriesPerQuery?: number;
dateRange: TimeRange;
+ columnsAvailable: EuiDataGridColumn[];
+ columnVisibility: EuiDataGridColumnVisibility;
};
const DiscoverDataGridAdditionalControls = (
@@ -27,8 +32,9 @@ const DiscoverDataGridAdditionalControls = (
maxEntriesPerQuery = MAX_ENTRIES_PER_QUERY,
onClickExportResults,
dateRange,
+ columnsAvailable,
+ columnVisibility,
} = props;
-
const onHandleExportResults = () => {
onClickExportResults && onClickExportResults();
};
@@ -69,13 +75,18 @@ const DiscoverDataGridAdditionalControls = (
disabled={totalHits === 0 || isExporting}
size='xs'
iconType='exportAction'
- color='primary'
+ color='text'
isLoading={isExporting}
className='euiDataGrid__controlBtn'
onClick={onHandleExportResults}
>
Export Formatted
+
+
>
);
};
diff --git a/plugins/main/public/components/common/wazuh-discover/components/visible-columns-selector.tsx b/plugins/main/public/components/common/wazuh-discover/components/visible-columns-selector.tsx
new file mode 100644
index 0000000000..71beaa14f8
--- /dev/null
+++ b/plugins/main/public/components/common/wazuh-discover/components/visible-columns-selector.tsx
@@ -0,0 +1,154 @@
+import React, { useState, ChangeEvent } from 'react';
+import { FormattedMessage } from '@osd/i18n/react';
+import classNames from 'classnames';
+import {
+ EuiPopover,
+ EuiPopoverTitle,
+ EuiButtonEmpty,
+ EuiFieldText,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiSwitch,
+ EuiDataGridColumn,
+ EuiDataGridColumnVisibility,
+ EuiToolTip,
+ EuiIcon,
+} from '@elastic/eui';
+
+// Based on https://github.com/opensearch-project/oui/blob/1.8.1/src/components/datagrid/column_selector.tsx
+// Only select visibility funcitonality
+// Replace OuiI18n by FormattedMessage
+export const DataGridVisibleColumnsSelector = ({
+ availableColumns,
+ columnVisibility,
+}: {
+ availableColumns: EuiDataGridColumn[];
+ columnVisibility: EuiDataGridColumnVisibility;
+}) => {
+ const [searchValue, setSearchValue] = useState('');
+ const [isOpen, setIsOpen] = useState(false);
+
+ const maxAvailableColumns = 500;
+
+ const { visibleColumns, setVisibleColumns } = columnVisibility;
+
+ const searchValueLowerCase = searchValue.toLowerCase();
+
+ const filteredColumns = (
+ searchValue
+ ? availableColumns.filter(({ name }) =>
+ name.toLowerCase().includes(searchValueLowerCase),
+ )
+ : availableColumns
+ ).slice(0, maxAvailableColumns);
+
+ const controlBtnClasses = classNames('euiDataGrid__controlBtn', {
+ // TODO: research if this is required
+ // 'euiDataGrid__controlBtn--active':
+ // availableColumns.length - visibleColumns.length > 0,
+ });
+
+ return (
+ setIsOpen(false)}
+ anchorPosition='downLeft'
+ panelPaddingSize='s'
+ panelClassName='euiDataGridColumnSelectorPopover'
+ button={
+ setIsOpen(!isOpen)}
+ >
+
+ {availableColumns.length > maxAvailableColumns && (
+
+ }
+ >
+
+
+ )}
+
+ }
+ >
+
+ ) =>
+ setSearchValue(e.currentTarget.value)
+ }
+ />
+
+
+ {filteredColumns.map(({ name, id }) => {
+ return (
+
+
+
+ {
+ const {
+ target: { checked },
+ } = event;
+
+ let nextVisibleColumns;
+
+ if (checked) {
+ if (!visibleColumns.includes(id)) {
+ nextVisibleColumns = [...visibleColumns, id];
+ }
+ } else {
+ if (visibleColumns.includes(id)) {
+ nextVisibleColumns = visibleColumns.filter(
+ (visibleColumnId: string) => visibleColumnId !== id,
+ );
+ }
+ }
+ if (nextVisibleColumns) {
+ setVisibleColumns(nextVisibleColumns);
+ }
+ }}
+ />
+
+
+
+ );
+ })}
+
+
+ );
+};
diff --git a/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx b/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx
index 8cffce3fed..75aa6c36d0 100644
--- a/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx
+++ b/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx
@@ -275,11 +275,14 @@ const WazuhDiscoverComponent = (props: WazuhDiscoverProps) => {
{...dataGridProps}
className={sideNavDocked ? 'dataGridDockedNav' : ''}
toolbarVisibility={{
+ showColumnSelector: { allowHide: false },
additionalControls: (
<>
{
const {
@@ -97,7 +98,7 @@ const VulsPanelContent = ({ agent }) => {
const value =
severityStats?.find(v => v.key.toUpperCase() === severity.toUpperCase())
?.doc_count || '0';
- return value ? `${value} ${severity}` : '0';
+ return value ? `${formatUINumber(value)} ${severity}` : '0';
};
const renderSeverityStats = (severity, index) => {
diff --git a/plugins/main/public/components/management/cluster/components/overview_cards.tsx b/plugins/main/public/components/management/cluster/components/overview_cards.tsx
index 5b6db7ac3f..7379d7d8c5 100644
--- a/plugins/main/public/components/management/cluster/components/overview_cards.tsx
+++ b/plugins/main/public/components/management/cluster/components/overview_cards.tsx
@@ -15,6 +15,7 @@ import '../dashboard/cluster_dashboard.scss';
import { getPlugins } from '../../../../kibana-services';
import { DiscoverNoResults } from '../../../common/no-results/no-results';
import { tFilter, tParsedIndexPattern } from '../../../common/data-source';
+import { formatUINumber } from '../../../../react-services/format-number';
interface OverviewCardsProps {
goAgents: () => void;
@@ -155,7 +156,7 @@ export const OverviewCards = ({
onClick={goNodes}
style={{ height: 'auto' }}
>
- {nodesCount}
+ {formatUINumber(nodesCount)}
),
@@ -187,7 +188,7 @@ export const OverviewCards = ({
onClick={goAgents}
style={{ height: 'auto' }}
>
- {agentsCount}
+ {formatUINumber(agentsCount)}
),
diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx b/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx
index 2497b0af16..9118a32785 100644
--- a/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx
+++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx
@@ -55,6 +55,7 @@ import VulsEvaluationFilter, {
excludeUnderEvaluationFilter,
getUnderEvaluationFilterValue,
} from '../../common/components/vuls-evaluation-filter';
+import { DataGridVisibleColumnsSelector } from '../../../../common/wazuh-discover/components/visible-columns-selector';
const InventoryVulsComponent = () => {
const {
@@ -255,6 +256,7 @@ const InventoryVulsComponent = () => {
{...dataGridProps}
className={sideNavDocked ? 'dataGridDockedNav' : ''}
toolbarVisibility={{
+ showColumnSelector: { allowHide: false },
additionalControls: (
<>
{
}
size='xs'
iconType='exportAction'
- color='primary'
+ color='text'
isLoading={isExporting}
className='euiDataGrid__controlBtn'
onClick={onClickExportResults}
>
Export Formatted
+
+
>
),
}}
diff --git a/plugins/main/public/components/settings/api/api-table.js b/plugins/main/public/components/settings/api/api-table.js
index a162154669..4ab3dc6c24 100644
--- a/plugins/main/public/components/settings/api/api-table.js
+++ b/plugins/main/public/components/settings/api/api-table.js
@@ -583,7 +583,7 @@ export const ApiTable = compose(withErrorBoundary)(
{
return ;
}}
diff --git a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx
index cf9258ca81..0e0e4435f4 100644
--- a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx
+++ b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx
@@ -20,6 +20,7 @@ import {
FILTER_OPERATOR,
PatternDataSourceFilterManager,
} from '../../../../components/common/data-source/pattern/pattern-data-source-filter-manager';
+import { formatUINumber } from '../../../../react-services/format-number';
type SeverityKey = 'low' | 'medium' | 'high' | 'critical';
@@ -155,7 +156,7 @@ export function LastAlertsStat({
}}
href={discoverLocation}
>
- {statValue}
+ {formatUINumber(statValue)}
}
diff --git a/plugins/main/public/react-services/format-number.ts b/plugins/main/public/react-services/format-number.ts
new file mode 100644
index 0000000000..2d065407c4
--- /dev/null
+++ b/plugins/main/public/react-services/format-number.ts
@@ -0,0 +1,18 @@
+/*
+ * Wazuh app - Time and date functions
+ * Copyright (C) 2015-2022 Wazuh, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Find more information about this on the LICENSE file.
+ */
+
+export function formatUINumber(value) {
+ if (Number.isNaN(Number(value))) {
+ return value;
+ }
+ return Number(value).toLocaleString('en-US');
+}
diff --git a/plugins/main/public/styles/layout.scss b/plugins/main/public/styles/layout.scss
index eec1878679..2cb2ae21e8 100644
--- a/plugins/main/public/styles/layout.scss
+++ b/plugins/main/public/styles/layout.scss
@@ -88,6 +88,10 @@
margin-left: 7px;
}
+.wz-margin-left-4 {
+ margin-left: 4px;
+}
+
.wz-margin-left-16 {
margin-left: 16px;
}