Skip to content

Commit

Permalink
[Vis Builder] Add an experimental table visualization in vis builder (o…
Browse files Browse the repository at this point in the history
…pensearch-project#2705)

* [Vis Builder] Add an experimental table visualization in vis builder

In this PR, we hook up an experimental table vis in vis builder. This
table vis is a refactor of previous table. It is written in React and
DataGrid component.

In this PR, we did two main things:
* add an experimental table visualization
* enable it in vis builder

Issue Resolved (hook up table in vis builder):
opensearch-project#2704

The experimental table vis has all the features from current table, including
* restore table vis in react using a Datagrid component
* datagrid component does not support splitted grids. For future transfer
to OUI Datagrid, we create a tableGroup in visData for splitted grids.
* restore basic pagenation, sort and format.
* implement datagrid columns
* display column title correctly
* deangular and re-use formatted column
* convert formatted column to data grid column
* restore filter in and filter out value functions
* format table cell to show Date and percent
* restore showTotal feature: it allows table vis to show total,
avg, min, max and count statics on count
* restore export csv feature to table vis
* split table in rows and columns

Beside of restoring original features, there are some changes:

* [IMPROVE] remove repeated column from split tables
Currently, when we split table by columns, the split column is shown
both in the table title and as a separate column. This is not needed.
In this PR, we remove the repeated column in split tables in col.
* [NEW FEATURE] adjustable table column width
In the new table visualization, customer can adjust the column width
as needed.

Issue Resolved:
opensearch-project#2212
opensearch-project#2213
opensearch-project#2305
opensearch-project#2379
opensearch-project#2579

Since this is a hookup PR, we remove un-used table vis types and options
because they could be defined in vis builder.

We also create follow up issues for some un-resolved PR comments.

Signed-off-by: Anan Zhuang <ananzh@amazon.com>

* remove unused scss tyle

Signed-off-by: Anan Zhuang <ananzh@amazon.com>

* remove total func and percentage col

total func and percentage col are two features that we might
need to remove or re-invent for future table vis. For hookup
purpose, it doesn't make sense to include some features that
we would like to remove.

this PR removes total func and percentage col in both table
vis and vis builder

Signed-off-by: Anan Zhuang <ananzh@amazon.com>

* comment out cellActions
currently filter in/out cell doesn't function in vis builder.
we will coumment out cell actions for now.

Signed-off-by: Anan Zhuang <ananzh@amazon.com>

Signed-off-by: Anan Zhuang <ananzh@amazon.com>
Signed-off-by: Ajay Gupta <ajyg@amazon.com>
  • Loading branch information
ananzh authored and Ajay Gupta committed Nov 25, 2022
1 parent b4c0478 commit 8654086
Show file tree
Hide file tree
Showing 28 changed files with 1,380 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
- [Multi DataSource] Update MD data source documentation link ([#2693](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2693))
- [Save Object Aggregation View] Add extension point in saved object management to register namespaces and show filter ([#2656](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2656))
- [Save Object Aggregation View] Fix for export all after scroll count response changed in PR#2656 ([#2696](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2696))
- [Vis Builder] Add an experimental table visualization in vis builder ([#2705](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/2705))

### 🐛 Bug Fixes

Expand Down
2 changes: 1 addition & 1 deletion src/plugins/vis_builder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ Outline:

**Notes:**

- Currently only the metric viz is defined, so schema properties that other vis types might need may be missing and require further setup.
- Currently only the metric and table viz are defined, so schema properties that other vis types might need may be missing and require further setup.
- `to_expression` has not yet been abstracted into a common utility for different visualizations. Adding more visualization types should make it easier to identify which parts of expression creation are common, and which are visualization-specific.

Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import {
} from '../../../../../opensearch_dashboards_utils/public';
import { EDIT_PATH, PLUGIN_ID } from '../../../../common';
import { VisBuilderServices } from '../../../types';
import { MetricOptionsDefaults } from '../../../visualizations/metric/metric_viz_type';
import { getCreateBreadcrumbs, getEditBreadcrumbs } from '../breadcrumbs';
import { getSavedVisBuilderVis } from '../get_saved_vis_builder_vis';
import {
Expand Down Expand Up @@ -81,7 +80,7 @@ export const useSavedVisBuilderVis = (visualizationIdFromUrl: string | undefined
}
}

dispatch(setStyleState<MetricOptionsDefaults>(styleState));
dispatch(setStyleState(styleState));
dispatch(setVisualizationState(visualizationState));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import { ExpressionFunctionOpenSearchDashboards } from '../../../../expressions'
import { buildExpressionFunction } from '../../../../expressions/public';
import { VisualizationState } from '../../application/utils/state_management';
import { getSearchService, getIndexPatterns } from '../../plugin_services';
import { StyleState } from '../../application/utils/state_management';

export const getAggExpressionFunctions = async (visualization: VisualizationState) => {
export const getAggExpressionFunctions = async (
visualization: VisualizationState,
style?: StyleState
) => {
const { activeVisualization, indexPattern: indexId = '' } = visualization;
const { aggConfigParams } = activeVisualization || {};

Expand All @@ -32,8 +36,8 @@ export const getAggExpressionFunctions = async (visualization: VisualizationStat
'opensearchaggs',
{
index: indexId,
metricsAtAllLevels: false,
partialRows: false,
metricsAtAllLevels: style?.showMetricsAtAllLevels || false,
partialRows: style?.showPartialRows || false,
aggConfigs: JSON.stringify(aggConfigs.aggs),
includeFormatHints: false,
}
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/vis_builder/public/visualizations/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import type { TypeServiceSetup } from '../services/type_service';
import { createMetricConfig } from './metric';
import { createTableConfig } from './table';
import { createHistogramConfig, createLineConfig, createAreaConfig } from './vislib';

export function registerDefaultTypes(typeServiceSetup: TypeServiceSetup) {
Expand All @@ -13,6 +14,7 @@ export function registerDefaultTypes(typeServiceSetup: TypeServiceSetup) {
createLineConfig,
createAreaConfig,
createMetricConfig,
createTableConfig,
];

visualizationTypes.forEach((createTypeConfig) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { get } from 'lodash';
import React, { useCallback, useEffect, useMemo } from 'react';
import { i18n } from '@osd/i18n';
import { FormattedMessage } from '@osd/i18n/react';
import produce from 'immer';
import { Draft } from 'immer';
import { EuiIconTip } from '@elastic/eui';
import { search } from '../../../../../data/public';
import { NumberInputOption, SwitchOption } from '../../../../../charts/public';
import {
useTypedDispatch,
useTypedSelector,
setStyleState,
} from '../../../application/utils/state_management';
import { TableOptionsDefaults } from '../table_viz_type';
import { Option } from '../../../application/app';

function TableVizOptions() {
const styleState = useTypedSelector((state) => state.style) as TableOptionsDefaults;
const dispatch = useTypedDispatch();

const setOption = useCallback(
(callback: (draft: Draft<typeof styleState>) => void) => {
const newState = produce(styleState, callback);
dispatch(setStyleState<TableOptionsDefaults>(newState));
},
[dispatch, styleState]
);

const isPerPageValid = styleState.perPage === '' || styleState.perPage > 0;

return (
<>
<Option
title={i18n.translate('visTypeTableNewNew.params.settingsTitle', {
defaultMessage: 'Settings',
})}
initialIsOpen
>
<NumberInputOption
label={
<>
{i18n.translate('visTypeTableNewNew.params.perPageLabel', {
defaultMessage: 'Max rows per page',
})}
<EuiIconTip
content={
<FormattedMessage
id="visTypeTableNewNews.field.emptyTooltip"
defaultMessage="Leaving this field empty means it will use number of buckets from the response."
/>
}
position="right"
/>
</>
}
isInvalid={!isPerPageValid}
min={1}
paramName="perPage"
value={styleState.perPage}
setValue={(_, value) =>
setOption((draft) => {
draft.perPage = value;
})
}
/>

<SwitchOption
label={i18n.translate('visTypeTableNewNew.params.showMetricsLabel', {
defaultMessage: 'Show metrics for every bucket/level',
})}
paramName="showMetricsAtAllLevels"
value={styleState.showMetricsAtAllLevels}
setValue={(_, value) =>
setOption((draft) => {
draft.showMetricsAtAllLevels = value;
})
}
data-test-subj="showMetricsAtAllLevels"
/>

<SwitchOption
label={i18n.translate('visTypeTableNewNew.params.showPartialRowsLabel', {
defaultMessage: 'Show partial rows',
})}
tooltip={i18n.translate('visTypeTableNewNew.params.showPartialRowsTip', {
defaultMessage:
'Show rows that have partial data. This will still calculate metrics for every bucket/level, even if they are not displayed.',
})}
paramName="showPartialRows"
value={styleState.showPartialRows}
setValue={(_, value) =>
setOption((draft) => {
draft.showPartialRows = value;
})
}
data-test-subj="showPartialRows"
/>
</Option>
</>
);
}

export { TableVizOptions };
6 changes: 6 additions & 0 deletions src/plugins/vis_builder/public/visualizations/table/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

export { createTableConfig } from './table_viz_type';
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { i18n } from '@osd/i18n';
import { Schemas } from '../../../../vis_default_editor/public';
import { AggGroupNames } from '../../../../data/public';
import { TableVizOptions } from './components/table_viz_options';
import { VisualizationTypeOptions } from '../../services/type_service';
import { toExpression } from './to_expression';

export interface TableOptionsDefaults {
perPage: number | '';
showPartialRows: boolean;
showMetricsAtAllLevels: boolean;
}

export const createTableConfig = (): VisualizationTypeOptions<TableOptionsDefaults> => ({
name: 'table',
title: 'Table',
icon: 'visTable',
description: 'Display table visualizations',
toExpression,
ui: {
containerConfig: {
data: {
schemas: new Schemas([
{
group: AggGroupNames.Metrics,
name: 'metric',
title: i18n.translate('visTypeTableNewNew.tableVisEditorConfig.schemas.metricTitle', {
defaultMessage: 'Metric',
}),
min: 1,
aggFilter: ['!geo_centroid', '!geo_bounds'],
aggSettings: {
top_hits: {
allowStrings: true,
},
},
defaults: {
aggTypes: ['avg', 'cardinality'],
},
},
{
group: AggGroupNames.Buckets,
name: 'bucket',
title: i18n.translate('visTypeTableNewNew.tableVisEditorConfig.schemas.bucketTitle', {
defaultMessage: 'Split rows',
}),
aggFilter: ['!filter'],
defaults: {
aggTypes: ['terms'],
},
},
{
group: AggGroupNames.Buckets,
name: 'split_row',
title: i18n.translate('visTypeTableNewNew.tableVisEditorConfig.schemas.splitTitle', {
defaultMessage: 'Split table in rows',
}),
min: 0,
max: 1,
aggFilter: ['!filter'],
defaults: {
aggTypes: ['terms'],
},
},
{
group: AggGroupNames.Buckets,
name: 'split_column',
title: i18n.translate('visTypeTableNewNew.tableVisEditorConfig.schemas.splitTitle', {
defaultMessage: 'Split table in columns',
}),
min: 0,
max: 1,
aggFilter: ['!filter'],
defaults: {
aggTypes: ['terms'],
},
},
]),
},
style: {
defaults: {
perPage: 10,
showPartialRows: false,
showMetricsAtAllLevels: false,
},
render: TableVizOptions,
},
},
},
});
Loading

0 comments on commit 8654086

Please sign in to comment.