mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[home] display tutorial artifacts (#16000)
* display launch dashboard button at end of add data instructions * add 'View exported fields' button * view exported fields open in new tab * use Writer to avoid modifing global Mustache object
This commit is contained in:
parent
4b92c7481c
commit
6511fc264f
5 changed files with 95 additions and 6 deletions
|
@ -15,7 +15,7 @@ const dashboardSchema = Joi.object({
|
|||
const artifactsSchema = Joi.object({
|
||||
// Fields present in Elasticsearch documents created by this product.
|
||||
exportedFields: Joi.object({
|
||||
documentationUrl: Joi.string()
|
||||
documentationUrl: Joi.string().required()
|
||||
}),
|
||||
// Kibana dashboards created by this product.
|
||||
dashboards: Joi.array().items(dashboardSchema).required()
|
||||
|
|
|
@ -4,6 +4,7 @@ import PropTypes from 'prop-types';
|
|||
import {
|
||||
KuiBar,
|
||||
KuiBarSection,
|
||||
KuiLinkButton,
|
||||
} from 'ui_framework/components';
|
||||
import { Instruction } from './instruction';
|
||||
import { ParameterForm } from './parameter_form';
|
||||
|
@ -13,6 +14,10 @@ import {
|
|||
EuiTab,
|
||||
EuiSpacer,
|
||||
EuiSteps,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiHorizontalRule,
|
||||
EuiText,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export class InstructionSet extends React.Component {
|
||||
|
@ -143,6 +148,39 @@ export class InstructionSet extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
let launchDashboard;
|
||||
if (this.props.overviewDashboard) {
|
||||
launchDashboard = (
|
||||
<div>
|
||||
<EuiHorizontalRule />
|
||||
|
||||
<EuiFlexGroup justifyContent="spaceBetween" alignItems="flexEnd">
|
||||
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiText>
|
||||
<p>
|
||||
{`Once all steps are completed, you're ready to explore your data`}
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
>
|
||||
<KuiLinkButton
|
||||
buttonType="primary"
|
||||
href={`#/dashboards?title=${this.props.overviewDashboard.title}`}
|
||||
>
|
||||
{this.props.overviewDashboard.linkLabel}
|
||||
</KuiLinkButton>
|
||||
</EuiFlexItem>
|
||||
|
||||
</EuiFlexGroup>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="kuiVerticalRhythmLarge">
|
||||
|
||||
|
@ -158,6 +196,8 @@ export class InstructionSet extends React.Component {
|
|||
|
||||
{this.renderInstructions()}
|
||||
|
||||
{launchDashboard}
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -183,4 +223,8 @@ InstructionSet.propTypes = {
|
|||
paramValues: PropTypes.object.isRequired,
|
||||
setParameter: PropTypes.func,
|
||||
replaceTemplateStrings: PropTypes.func.isRequired,
|
||||
overviewDashboard: PropTypes.shape({
|
||||
title: PropTypes.string.isRequired,
|
||||
linkLabel: PropTypes.string.isRequired,
|
||||
}),
|
||||
};
|
||||
|
|
|
@ -3,11 +3,15 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import { Content } from './content';
|
||||
|
||||
import {
|
||||
KuiLinkButton,
|
||||
} from 'ui_framework/components';
|
||||
import {
|
||||
EuiImage,
|
||||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
|
||||
export function Introduction({ description, previewUrl, title }) {
|
||||
export function Introduction({ description, previewUrl, title, exportedFieldsUrl }) {
|
||||
let img;
|
||||
if (previewUrl) {
|
||||
img = (
|
||||
|
@ -21,6 +25,22 @@ export function Introduction({ description, previewUrl, title }) {
|
|||
/>
|
||||
);
|
||||
}
|
||||
let exportedFields;
|
||||
if (exportedFieldsUrl) {
|
||||
exportedFields = (
|
||||
<div>
|
||||
<EuiSpacer />
|
||||
<KuiLinkButton
|
||||
buttonType="secondary"
|
||||
href={exportedFieldsUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
View exported fields
|
||||
</KuiLinkButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="introduction kuiVerticalRhythm">
|
||||
<div className="kuiFlexGroup kuiFlexGroup--gutterLarge">
|
||||
|
@ -30,6 +50,7 @@ export function Introduction({ description, previewUrl, title }) {
|
|||
{title}
|
||||
</h1>
|
||||
<Content className="kuiVerticalRhythm" text={description}/>
|
||||
{exportedFields}
|
||||
</div>
|
||||
|
||||
<div className="kuiFlexItem kuiFlexItem--flexGrowZero">
|
||||
|
@ -44,5 +65,6 @@ export function Introduction({ description, previewUrl, title }) {
|
|||
Introduction.propTypes = {
|
||||
description: PropTypes.string.isRequired,
|
||||
title: PropTypes.string.isRequired,
|
||||
previewUrl: PropTypes.string
|
||||
previewUrl: PropTypes.string,
|
||||
exportedFieldsUrl: PropTypes.string,
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Mustache from 'mustache';
|
||||
import { Writer } from 'mustache';
|
||||
import chrome from 'ui/chrome';
|
||||
import { metadata } from 'ui/metadata';
|
||||
import {
|
||||
|
@ -9,6 +9,16 @@ import {
|
|||
|
||||
const TEMPLATE_TAGS = ['{', '}'];
|
||||
|
||||
// Can not use 'Mustache' since its a global object
|
||||
const mustacheWriter = new Writer();
|
||||
// do not html escape output
|
||||
mustacheWriter.escapedValue = function escapedValue(token, context) {
|
||||
const value = context.lookup(token[1]);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
export function replaceTemplateStrings(text, params = {}) {
|
||||
const variables = {
|
||||
config: {
|
||||
|
@ -30,6 +40,6 @@ export function replaceTemplateStrings(text, params = {}) {
|
|||
},
|
||||
params: params
|
||||
};
|
||||
Mustache.parse(text, TEMPLATE_TAGS);
|
||||
return Mustache.render(text, variables);
|
||||
mustacheWriter.parse(text, TEMPLATE_TAGS);
|
||||
return mustacheWriter.render(text, variables);
|
||||
}
|
||||
|
|
|
@ -126,6 +126,12 @@ export class Tutorial extends React.Component {
|
|||
}
|
||||
|
||||
renderInstructionSets = (instructions) => {
|
||||
let overviewDashboard;
|
||||
if (_.has(this.state, 'tutorial.artifacts.dashboards')) {
|
||||
overviewDashboard = this.state.tutorial.artifacts.dashboards.find(dashboard => {
|
||||
return dashboard.isOverview;
|
||||
});
|
||||
}
|
||||
let offset = 1;
|
||||
return instructions.instructionSets.map((instructionSet, index) => {
|
||||
const currentOffset = offset;
|
||||
|
@ -139,6 +145,7 @@ export class Tutorial extends React.Component {
|
|||
paramValues={this.state.paramValues}
|
||||
setParameter={this.setParameter}
|
||||
replaceTemplateStrings={this.props.replaceTemplateStrings}
|
||||
overviewDashboard={overviewDashboard}
|
||||
key={index}
|
||||
/>
|
||||
);
|
||||
|
@ -163,6 +170,11 @@ export class Tutorial extends React.Component {
|
|||
previewUrl = this.props.addBasePath(this.state.tutorial.previewImagePath);
|
||||
}
|
||||
|
||||
let exportedFieldsUrl;
|
||||
if (_.has(this.state, 'tutorial.artifacts.exportedFields')) {
|
||||
exportedFieldsUrl = this.props.replaceTemplateStrings(this.state.tutorial.artifacts.exportedFields.documentationUrl);
|
||||
}
|
||||
|
||||
const instructions = this.getInstructions();
|
||||
content = (
|
||||
<div>
|
||||
|
@ -170,6 +182,7 @@ export class Tutorial extends React.Component {
|
|||
title={this.state.tutorial.name}
|
||||
description={this.props.replaceTemplateStrings(this.state.tutorial.longDescription)}
|
||||
previewUrl={previewUrl}
|
||||
exportedFieldsUrl={exportedFieldsUrl}
|
||||
/>
|
||||
|
||||
<div className="text-center kuiVerticalRhythm">
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue