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

[Lens] Fix embeddable title and description for reporting and dashboard tooltip #78767

Merged
merged 10 commits into from
Oct 1, 2020
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,10 @@ function renderTooltip(description: string) {
);
}

const VISUALIZE_EMBEDDABLE_TYPE = 'visualization';
type VisualizeEmbeddable = any;
Copy link
Contributor

@ThomThomson ThomThomson Sep 30, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this wasn't added in this PR, but I'm not a huge fan of using any like this. Now that this description is added to both lens and visualize, I wonder if it would be worth adding an optional getDescription function to IEmbeddable.

If not, at least the any could be removed with something like:

type EmbeddableWithDescription = IEmbeddable & { getDescription: () => string };

function getViewDescription(embeddable: IEmbeddable) {
  return (embeddable as EmbeddableWithDescription).getDescription?.() || '';
}


function getViewDescription(embeddable: IEmbeddable | VisualizeEmbeddable) {
if (embeddable.type === VISUALIZE_EMBEDDABLE_TYPE) {
if (embeddable.getVisualizationDescription) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be embeddable.getDescription instead? Not all embeddables are visualizations

const description = embeddable.getVisualizationDescription();

if (description) {
Expand Down

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 @@ -33,6 +33,7 @@ export interface DatatableColumns {

interface Args {
title: string;
description?: string;
columns: DatatableColumns & { type: 'lens_datatable_columns' };
}

Expand Down Expand Up @@ -72,6 +73,10 @@ export const datatable: ExpressionFunctionDefinition<
defaultMessage: 'Title',
}),
},
description: {
types: ['string'],
help: '',
},
columns: {
types: ['lens_datatable_columns'],
help: '',
Expand Down Expand Up @@ -207,7 +212,10 @@ export function DatatableComponent(props: DatatableRenderProps) {
}

return (
<VisualizationContainer>
<VisualizationContainer
reportTitle={props.args.title}
reportDescription={props.args.description}
>
<EuiBasicTable
className="lnsDataTable"
data-test-subj="lnsDataTable"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export interface LayerState {
}

export interface DatatableVisualizationState {
title?: string;
description?: string;
layers: LayerState[];
}

Expand Down Expand Up @@ -211,6 +213,8 @@ export const datatableVisualization: Visualization<DatatableVisualizationState>
type: 'function',
function: 'lens_datatable',
arguments: {
title: [state.title || ''],
description: [state.description || ''],
columns: [
{
type: 'expression',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export async function persistedStateToExpression(
state: { visualization: visualizationState, datasourceStates: persistedDatasourceStates },
visualizationType,
references,
title,
description,
} = doc;
if (!visualizationType) return null;
const visualization = visualizations[visualizationType!];
Expand All @@ -79,7 +81,7 @@ export async function persistedStateToExpression(

return buildExpression({
visualization,
visualizationState,
visualizationState: { ...(visualizationState as object), title, description },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I like this approach - it assumes a certain state structure we don't guarantee and it seems like it's breaking the current isolation between frame and individual visualizations to magically set state.

datasourceMap: datasources,
datasourceStates,
datasourceLayers,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ export class Embeddable
return this.deps.attributeService.getInputAsValueType(input);
};

// same API as Visualize
public getVisualizationDescription() {
// mind that savedViz is loaded in async way here
return this.savedVis && this.savedVis.description;
}

destroy() {
super.destroy();
if (this.domNode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function sampleArgs() {
accessor: 'a',
layerId: 'l1',
title: 'My fanci metric chart',
metricTitle: 'My fanci metric chart',
mode: 'full',
};

Expand Down
24 changes: 20 additions & 4 deletions x-pack/plugins/lens/public/metric_visualization/expression.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ export const metricChart: ExpressionFunctionDefinition<
types: ['string'],
help: 'The chart title.',
},
description: {
types: ['string'],
help: '',
},
metricTitle: {
types: ['string'],
help: 'The title of the metric shown.',
},
accessor: {
types: ['string'],
help: 'The column whose value is being displayed',
Expand Down Expand Up @@ -98,12 +106,16 @@ export function MetricChart({
args,
formatFactory,
}: MetricChartProps & { formatFactory: FormatFactory }) {
const { title, accessor, mode } = args;
const { metricTitle, title, description, accessor, mode } = args;
let value = '-';
const firstTable = Object.values(data.tables)[0];
if (!accessor) {
return (
<VisualizationContainer reportTitle={title} className="lnsMetricExpression__container" />
<VisualizationContainer
reportTitle={title}
reportDescription={description}
className="lnsMetricExpression__container"
/>
);
}

Expand All @@ -119,14 +131,18 @@ export function MetricChart({
}

return (
<VisualizationContainer reportTitle={title} className="lnsMetricExpression__container">
<VisualizationContainer
reportTitle={title}
reportDescription={description}
className="lnsMetricExpression__container"
>
<AutoScale>
<div data-test-subj="lns_metric_value" style={{ fontSize: '60pt', fontWeight: 600 }}>
{value}
</div>
{mode === 'full' && (
<div data-test-subj="lns_metric_title" style={{ fontSize: '24pt' }}>
{title}
{metricTitle}
</div>
)}
</AutoScale>
Expand Down
4 changes: 3 additions & 1 deletion x-pack/plugins/lens/public/metric_visualization/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
*/

export interface State {
title?: string;
description?: string;
layerId: string;
accessor?: string;
}

export interface MetricConfig extends State {
title: string;
metricTitle: string;
mode: 'reduced' | 'full';
}
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,17 @@ describe('metric_visualization', () => {
"accessor": Array [
"a",
],
"description": Array [
"",
],
"metricTitle": Array [
"shazm",
],
"mode": Array [
"full",
],
"title": Array [
"shazm",
"",
],
},
"function": "lens_metric_chart",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ const toExpression = (
type: 'function',
function: 'lens_metric_chart',
arguments: {
title: [(operation && operation.label) || ''],
title: [state.title || ''],
description: [state.description || ''],
metricTitle: [(operation && operation.label) || ''],
accessor: [state.accessor],
mode: [mode],
},
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/lens/public/pie_visualization/expression.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ export const pie: ExpressionFunctionDefinition<
defaultMessage: 'Pie renderer',
}),
args: {
title: {
types: ['string'],
help: 'The chart title.',
},
description: {
types: ['string'],
help: '',
},
groups: {
types: ['string'],
multi: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,12 @@ export function PieComponent(
);
}
return (
<VisualizationContainer className="lnsPieExpression__container" isReady={state.isReady}>
<VisualizationContainer
reportTitle={props.args.title}
reportDescription={props.args.description}
className="lnsPieExpression__container"
isReady={state.isReady}
>
<Chart>
<Settings
// Legend is hidden in many scenarios
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/lens/public/pie_visualization/to_expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ function expressionHelper(
type: 'function',
function: 'lens_pie',
arguments: {
title: [state.title || ''],
description: [state.description || ''],
shape: [state.shape],
hideLabels: [isPreview],
groups: operations.map((o) => o.columnId),
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/lens/public/pie_visualization/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@ export type LayerState = SharedLayerState & {
};

export interface PieVisualizationState {
title?: string;
description?: string;
shape: 'donut' | 'pie' | 'treemap';
layers: LayerState[];
}

export type PieExpressionArgs = SharedLayerState & {
title?: string;
description?: string;
shape: 'pie' | 'donut' | 'treemap';
hideLabels: boolean;
};
Expand Down
7 changes: 5 additions & 2 deletions x-pack/plugins/lens/public/visualization_container.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,16 @@ describe('VisualizationContainer', () => {
expect(reportingEl.prop('data-shared-item')).toBeTruthy();
});

test('renders title for reporting, if provided', () => {
test('renders title and description for reporting, if provided', () => {
const component = mount(
<VisualizationContainer reportTitle="shazam!">Hello!</VisualizationContainer>
<VisualizationContainer reportTitle="shazam!" reportDescription="Description">
Hello!
</VisualizationContainer>
);
const reportingEl = component.find('[data-shared-item]').first();

expect(reportingEl.prop('data-title')).toEqual('shazam!');
expect(reportingEl.prop('data-description')).toEqual('Description');
});

test('renders style', () => {
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/lens/public/visualization_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import classNames from 'classnames';
interface Props extends React.HTMLAttributes<HTMLDivElement> {
isReady?: boolean;
reportTitle?: string;
reportDescription?: string;
}

/**
Expand All @@ -21,6 +22,7 @@ interface Props extends React.HTMLAttributes<HTMLDivElement> {
export function VisualizationContainer({
isReady = true,
reportTitle,
reportDescription,
children,
className,
...rest
Expand All @@ -31,6 +33,7 @@ export function VisualizationContainer({
data-render-complete={isReady}
className={classNames(className, 'lnsVisualizationContainer')}
data-title={reportTitle}
data-description={reportDescription}
{...rest}
>
{children}
Expand Down

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

15 changes: 14 additions & 1 deletion x-pack/plugins/lens/public/xy_visualization/expression.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ export const xyChart: ExpressionFunctionDefinition<
defaultMessage: 'An X/Y chart',
}),
args: {
title: {
types: ['string'],
help: 'The chart title.',
},
description: {
types: ['string'],
help: '',
},
xTitle: {
types: ['string'],
help: i18n.translate('xpack.lens.xyChart.xTitle.help', {
Expand Down Expand Up @@ -215,7 +223,12 @@ export function XYChartReportable(props: XYChartRenderProps) {
}, [setState]);

return (
<VisualizationContainer className="lnsXyExpression__container" isReady={state.isReady}>
<VisualizationContainer
className="lnsXyExpression__container"
isReady={state.isReady}
reportTitle={props.args.title}
reportDescription={props.args.description}
>
<MemoizedChart {...props} />
</VisualizationContainer>
);
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/lens/public/xy_visualization/to_expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export const buildExpression = (
type: 'function',
function: 'lens_xy_chart',
arguments: {
title: [state.title || ''],
description: [state.description || ''],
xTitle: [state.xTitle || ''],
yTitle: [state.yTitle || ''],
yRightTitle: [state.yRightTitle || ''],
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/lens/public/xy_visualization/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ export type LayerArgs = LayerConfig & {

// Arguments to XY chart expression, with computed properties
export interface XYArgs {
title?: string;
description?: string;
xTitle: string;
yTitle: string;
yRightTitle: string;
Expand All @@ -398,6 +400,8 @@ export interface XYArgs {

// Persisted parts of the state
export interface XYState {
title?: string;
description?: string;
preferredSeriesType: SeriesType;
legend: LegendConfig;
fittingFunction?: FittingFunction;
Expand Down