GUI enhancement: handle descriptions for visualizations (#20936) (#44702)

* Adds descriptions to visualizations

* Adds descriptions to visualizations

* Tests on the saved object (visualization) modal
This commit is contained in:
friol 2019-09-12 17:08:13 +02:00 committed by Liza Katz
parent 7506c7fd76
commit df21530c88
6 changed files with 115 additions and 10 deletions

View file

@ -17,12 +17,14 @@
* under the License.
*/
import { i18n } from '@kbn/i18n';
import { EuiContextMenuPanelDescriptor, EuiBadge } from '@elastic/eui';
import { EuiContextMenuPanelDescriptor, EuiBadge, EuiIcon, EuiToolTip } from '@elastic/eui';
import classNames from 'classnames';
import React from 'react';
import { PanelOptionsMenu } from './panel_options_menu';
import { Action } from '../../actions';
import { IEmbeddable } from '../../embeddables';
import { VisualizeEmbeddable } from '../../../../../../../kibana/public/visualize/embeddable/visualize_embeddable';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../../kibana/public/visualize/embeddable/constants';
export interface PanelHeaderProps {
title?: string;
@ -47,6 +49,12 @@ function renderBadges(badges: Action[], embeddable: IEmbeddable) {
));
}
function isVisualizeEmbeddable(
embeddable: IEmbeddable | VisualizeEmbeddable
): embeddable is VisualizeEmbeddable {
return embeddable.type === VISUALIZE_EMBEDDABLE_TYPE;
}
export function PanelHeader({
title,
isViewMode,
@ -75,6 +83,16 @@ export function PanelHeader({
);
}
let viewDescr = '';
if (isVisualizeEmbeddable(embeddable)) {
const vd = (embeddable as VisualizeEmbeddable).getVisualizationDescription();
if (vd) {
viewDescr = vd;
}
} else {
viewDescr = '';
}
return (
<div
className={classes}
@ -83,16 +101,25 @@ export function PanelHeader({
<div
data-test-subj="dashboardPanelTitle"
className="embPanel__title embPanel__dragger"
title={title}
aria-label={i18n.translate('embeddableApi.panel.dashboardPanelAriaLabel', {
defaultMessage: 'Dashboard panel: {title}',
values: {
title,
},
})}
/* title={title} */ /* this is redundant - it shows a tooltip with the view title - and clutters the UI */ aria-label={i18n.translate(
'embeddableApi.panel.dashboardPanelAriaLabel',
{
defaultMessage: 'Dashboard panel: {title}',
values: {
title,
},
}
)}
>
{showTitle ? `${title} ` : ''}
{renderBadges(badges, embeddable)}
{viewDescr !== '' ? (
<EuiToolTip content={viewDescr} delay="regular" position="right">
<EuiIcon type="iInCircle" />
</EuiToolTip>
) : (
''
)}
</div>
<PanelOptionsMenu

View file

@ -187,10 +187,11 @@ function VisEditor(
}
},
run: async () => {
const onSave = ({ newTitle, newCopyOnSave, isTitleDuplicateConfirmed, onTitleDuplicate }) => {
const onSave = ({ newTitle, newCopyOnSave, isTitleDuplicateConfirmed, onTitleDuplicate, newDescription }) => {
const currentTitle = savedVis.title;
savedVis.title = newTitle;
savedVis.copyOnSave = newCopyOnSave;
savedVis.description = newDescription;
const saveOptions = {
confirmOverwrite: false,
isTitleDuplicateConfirmed,
@ -220,6 +221,7 @@ function VisEditor(
showCopyOnSave={savedVis.id ? true : false}
objectType="visualization"
confirmButtonLabel={confirmButtonLabel}
description={savedVis.description}
/>);
showSaveModal(saveModal);
}

View file

@ -119,6 +119,10 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
});
}
public getVisualizationDescription() {
return this.savedVisualization.description;
}
public getInspectorAdapters() {
if (!this.handler) {
return undefined;

View file

@ -108,6 +108,19 @@ class VisualizeListingTableUi extends Component {
</span>
)
},
{
field: 'description',
name: intl.formatMessage({
id: 'kbn.dashboard.listing.table.descriptionColumnName',
defaultMessage: 'Description',
}),
sortable: true,
render: (field, record) => (
<span>
{record.description}
</span>
)
},
];
return tableColumns;

View file

@ -50,6 +50,27 @@ exports[`SavedObjectSaveModal should render matching snapshot 1`] = `
value="Saved Object title"
/>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
fullWidth={true}
hasEmptyLabelSpace={false}
label={
<FormattedMessage
defaultMessage="Description"
id="kibana-react.savedObjects.saveModal.descriptionLabel"
values={Object {}}
/>
}
labelType="label"
>
<EuiTextArea
data-test-subj="viewDescription"
fullWidth={false}
onChange={[Function]}
resize="vertical"
value=""
/>
</EuiFormRow>
</EuiForm>
</EuiModalBody>
<EuiModalFooter>

View file

@ -31,17 +31,20 @@ import {
EuiOverlayMask,
EuiSpacer,
EuiSwitch,
EuiTextArea,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import { EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../legacy/core_plugins/kibana/public/visualize/embeddable/constants';
export interface OnSaveProps {
newTitle: string;
newCopyOnSave: boolean;
isTitleDuplicateConfirmed: boolean;
onTitleDuplicate: () => void;
newDescription: string;
}
interface Props {
@ -61,6 +64,7 @@ interface State {
isTitleDuplicateConfirmed: boolean;
hasTitleDuplicate: boolean;
isLoading: boolean;
visualizationDescription: string;
}
export class SavedObjectSaveModal extends React.Component<Props, State> {
@ -70,6 +74,7 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
isTitleDuplicateConfirmed: false,
hasTitleDuplicate: false,
isLoading: false,
visualizationDescription: this.props.description ? this.props.description : '',
};
public render() {
@ -97,7 +102,7 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
{this.renderDuplicateTitleCallout()}
<EuiForm>
{this.props.description && (
{this.props.objectType !== VISUALIZE_EMBEDDABLE_TYPE && this.props.description && (
<EuiFormRow>
<EuiText color="subdued">{this.props.description}</EuiText>
</EuiFormRow>
@ -125,6 +130,8 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
/>
</EuiFormRow>
{this.renderViewDescription()}
{this.props.options}
</EuiForm>
</EuiModalBody>
@ -145,6 +152,36 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
);
}
private renderViewDescription = () => {
if (this.props.objectType !== VISUALIZE_EMBEDDABLE_TYPE) {
return;
}
return (
<EuiFormRow
fullWidth
label={
<FormattedMessage
id="kibana-react.savedObjects.saveModal.descriptionLabel"
defaultMessage="Description"
/>
}
>
<EuiTextArea
data-test-subj="viewDescription"
value={this.state.visualizationDescription}
onChange={this.onDescriptionChange}
/>
</EuiFormRow>
);
};
private onDescriptionChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
this.setState({
visualizationDescription: event.target.value,
});
};
private onTitleDuplicate = () => {
this.setState({
isLoading: false,
@ -168,6 +205,7 @@ export class SavedObjectSaveModal extends React.Component<Props, State> {
newCopyOnSave: this.state.copyOnSave,
isTitleDuplicateConfirmed: this.state.isTitleDuplicateConfirmed,
onTitleDuplicate: this.onTitleDuplicate,
newDescription: this.state.visualizationDescription,
});
};