Skip to content

Commit

Permalink
Fix PR comments and add unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Anan Zhuang <ananzh@amazon.com>
  • Loading branch information
ananzh committed Dec 21, 2022
1 parent 73a636a commit d891efc
Show file tree
Hide file tree
Showing 10 changed files with 330 additions and 18 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [I18n] Register ru, ru-RU locale ([#2817](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2817))
- Add yarn opensearch arg to setup plugin dependencies ([#2544](https://github.com/opensearch-project/OpenSearch-Dashboards/issues/2544))
- [Multi DataSource] Test the connection to an external data source when creating or updating ([#2973](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2973))
- [Table Visualization] Replace table visualization using React and DataGrid component ([#2863](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2863))
- [Table Visualization] Refactor table visualization using React and DataGrid component ([#2863](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2863))

### 🐛 Bug Fixes

Expand Down
14 changes: 7 additions & 7 deletions src/plugins/vis_type_table/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ To create a data table in OpenSearch Dashboards, first select `Visualize` from t
## Select Metrics

### Metrics Aggregation
At the `Metrics`, select the metric aggregation type from the menu and config it accordinly.
At the `Metrics`, select the metric aggregation type from the menu and configure it accordingly. You could also add multiple metrics and each metrics is a separate column in table visualization.

### Buckets Aggregation
At the `Buckets`, config the columns to be displayed in the table visualization.
- `Split Rows` is used when you want to divide one row into more categories. It splits one row into multiple and add columns based on the categories you choose to split. For example, if you split the data based on gender then you want to know more on each gender's clothing preference. You could click `Split Rows` and input `clothing.category` in terms. Each genger's data is now splitted to multiple rows based on a new added column `clothing.category`.
- `Split Table` splits the table into seperate tables for the aggregation you choose. It is similar to `Split Rows`, but this time you will see multiple tables.
At the `Buckets`, configure the columns to be displayed in the table visualization.
- `Split Rows` is used when you want to divide one row into more based on some category. It splits one row into multiple and add columns based on the categories you choose to split. For example, if you split the data based on gender then you want to know more on each gender's clothing preference. You could click `Split Rows` and input `clothing.category` in terms. Each gender's data is now split across to multiple rows based on a new added column `clothing.category`.
- `Split Table` splits the table into separate tables for the aggregation you choose. It is similar to `Split Rows`, but this time each row becomes a single table with aggregation columns arranged horizontally or vertically.

## Select Options
In the `Options` tab, you could config more options.
In the `Options` tab, you can configure more options.
- `Max rows per page` is the maximum number of rows displayed per page.
- `Show metrics for every bucket/level` adds metrics aggregation to every columns.
- `Show metrics for every bucket/level` adds metrics aggregation to every column.
- `Show partial rows` will include data with missing columns.
- `Show total` calculates the selected metrics per column and displays the result at the bottom.
- `Show total` calculates the selected metrics per column and displays the result at the bottom. Warning - depending on your columns and the total aggregation function selected, this may generate statistically invalid results. For example, avoid summing or averaging averages.
- `Percentage column` adds one percentage column based on the chosen metrics aggregation.

## Example
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

115 changes: 115 additions & 0 deletions src/plugins/vis_type_table/public/__snapshots__/to_ast.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { I18nProvider } from '@osd/i18n/react';
import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
import { OpenSearchDashboardsContextProvider } from '../../../opensearch_dashboards_react/public';
import { TableContext } from '../table_vis_response_handler';
import { TableVisConfig, SortColumn, ColumnWidth, TableUiState } from '../types';
import { TableVisConfig, ColumnSort, ColumnWidth, TableUiState } from '../types';
import { TableVisComponent } from './table_vis_component';
import { TableVisComponentGroup } from './table_vis_component_group';

Expand Down Expand Up @@ -40,7 +40,7 @@ export const TableVisApp = ({

// TODO: remove duplicate sort and width state
// Issue: https://github.com/opensearch-project/OpenSearch-Dashboards/issues/2704#issuecomment-1299380818
const [sort, setSort] = useState<SortColumn>({ colIndex: null, direction: null });
const [sort, setSort] = useState<ColumnSort>({ colIndex: null, direction: null });
const [width, setWidth] = useState<ColumnWidth[]>([]);

const tableUiState: TableUiState = { sort, setSort, width, setWidth };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { EuiDataGridProps, EuiDataGrid, EuiDataGridSorting, EuiTitle } from '@el

import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
import { Table } from '../table_vis_response_handler';
import { TableVisConfig, ColumnWidth, SortColumn, TableUiState } from '../types';
import { TableVisConfig, ColumnWidth, ColumnSort, TableUiState } from '../types';
import { getDataGridColumns } from './table_vis_grid_columns';
import { usePagination } from '../utils';
import { convertToFormattedData } from '../utils/convert_to_formatted_data';
Expand Down Expand Up @@ -79,7 +79,7 @@ export const TableVisComponent = ({
const onSort = useCallback(
(sortingCols: EuiDataGridSorting['columns'] | []) => {
const nextSortValue = sortingCols[sortingCols.length - 1];
const nextSort: SortColumn =
const nextSort: ColumnSort =
sortingCols.length > 0
? {
colIndex: dataGridColumns.findIndex((col) => col.id === nextSortValue?.id),
Expand Down
89 changes: 89 additions & 0 deletions src/plugins/vis_type_table/public/table_vis_fn.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Any modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { createTableVisFn } from './table_vis_fn';
import { tableVisResponseHandler } from './table_vis_response_handler';

import { functionWrapper } from '../../expressions/common/expression_functions/specs/tests/utils';

jest.mock('./table_vis_response_handler', () => ({
tableVisResponseHandler: jest.fn().mockReturnValue({
tables: [{ columns: [], rows: [] }],
}),
}));

describe('interpreter/functions#table', () => {
const fn = functionWrapper(createTableVisFn());
const context = {
type: 'opensearch_dashboards_datatable',
rows: [{ 'col-0-1': 0 }],
columns: [{ id: 'col-0-1', name: 'Count' }],
};
const visConfig = {
title: 'My Chart title',
perPage: 10,
showPartialRows: false,
showMetricsAtAllLevels: false,
sort: {
columnIndex: null,
direction: null,
},
showTotal: false,
totalFunc: 'sum',
dimensions: {
metrics: [
{
accessor: 0,
format: {
id: 'number',
},
params: {},
aggType: 'count',
},
],
buckets: [],
},
};

beforeEach(() => {
jest.clearAllMocks();
});

it('returns an object with the correct structure', async () => {
const actual = await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined);
expect(actual).toMatchSnapshot();
});

it('calls response handler with correct values', async () => {
await fn(context, { visConfig: JSON.stringify(visConfig) }, undefined);
expect(tableVisResponseHandler).toHaveBeenCalledTimes(1);
expect(tableVisResponseHandler).toHaveBeenCalledWith(context, visConfig);
});
});
58 changes: 58 additions & 0 deletions src/plugins/vis_type_table/public/to_ast.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { toExpressionAst } from './to_ast';
import { Vis } from '../../visualizations/public';

describe('table vis toExpressionAst function', () => {
let vis: Vis;

beforeEach(() => {
vis = {
isHierarchical: () => false,
type: {},
params: {},
data: {
indexPattern: { id: '123' } as any,
aggs: {
getResponseAggs: () => [],
aggs: [],
} as any,
},
} as any;
});

it('without params', () => {
vis.params = { table: {} };
const actual = toExpressionAst(vis, {});
expect(actual).toMatchSnapshot();
});

it('with default params', () => {
vis.params = {
perPage: 10,
showPartialRows: false,
showMetricsAtAllLevels: false,
showTotal: false,
totalFunc: 'sum',
percentageCol: '',
};
const actual = toExpressionAst(vis, {});
expect(actual).toMatchSnapshot();
});

it('with customized params', () => {
vis.params = {
perPage: 5,
showPartialRows: false,
showMetricsAtAllLevels: false,
showTotal: true,
totalFunc: 'min',
percentageCol: 'Count',
};
const actual = toExpressionAst(vis, {});
expect(actual).toMatchSnapshot();
});
});
5 changes: 4 additions & 1 deletion src/plugins/vis_type_table/public/to_ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ export const toExpressionAst = (vis: Vis, params: any) => {
);

const schemas = getVisSchemas(vis, params);
// remove duplicate metrics
// if customer selects showPartialRows without showMetricsAtAllLevels,
// we need to remove the duplicated metrics.
// First, we need to calculate the required number of metrics
// Then, we return one copy of the required metrics from metric array
const metrics =
schemas.bucket && vis.params.showPartialRows && !vis.params.showMetricsAtAllLevels
? schemas.metric.slice(-1 * (schemas.metric.length / schemas.bucket.length))
Expand Down
Loading

0 comments on commit d891efc

Please sign in to comment.