Getting Started page (#11805)
* Getting Started page (#11673) * Initial code * Renaming files/folders * Notes and changes from HTML/CSS review * CSS changes * Fixing transform units * Fleshing out logo circle * Adding logos * Un-nesting styles * Adding kuiText class on <p> elements * Making shield icon 404 go away * Using trustAsHtml filter; using registry * Adding code for registry * Adding images * Hooking up the opt-out link * Fixing linter issues * Fix issue with refresh bringing back nav * Removing load_default module * Use GETTING_STARTED_ROUTE constant * Allow topMessage to be a directive * Adding kuiLink CSS class to anchor elements * Adding alt text to images * Replace getters with regular methods * Remove leftover comment * Removing unnecessary comment * Fixing typo in comment * Adding comments for message properties * Fixing typo in method name * Defining custom CSS class * Fixing method call * Creating custom CSS classes * Adding documentation links * Use a instead of button for demo link * Allow directives in manage and monitor messages * Refactoring shared code into single ui/public/getting_started folder * Adding README * Fixing whitespace in/around links * Trim messages before setting them * Decorate in-app links with opt-out attribute * Opt out of the Getting Started page if the user already has index patterns * Adding more commentary around expectations of setTopMessage use * Using ng-src and ng-href attributes where attr values are angular expressions * Importing the directive before using it * Using ui/registry for message registries * Renaming service => helpers to clarify intent * Adding explanatory comment * Adding "or" * Fixing div id * Breaks out the inject logic into another directive * Adding Getting Started page object for functional tests * Consolidate into one registry * Fixes incorrect classes * Changes how styles are applied to injected-items items * Modifying class name per CSS style guide * Adding getting started doc link * Removing unused import * Attempting to fix breaking build Apparently the Getting Started page is preventing access to Console (Dev Tools, really) so the functional tests for Console are failing. This commit opts the user out of the Getting Started page before attempting to navigate to Console. * Cleanup on aisle testbed! (#11765) * Navigate to getting started page so we can opt out of it
This commit is contained in:
parent
866bf5d520
commit
32eff371f2
8
src/core_plugins/getting_started/index.js
Normal file
8
src/core_plugins/getting_started/index.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
export default function (kibana) {
|
||||||
|
|
||||||
|
return new kibana.Plugin({
|
||||||
|
uiExports: {
|
||||||
|
managementSections: ['plugins/getting_started']
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
4
src/core_plugins/getting_started/package.json
Normal file
4
src/core_plugins/getting_started/package.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"name": "getting_started",
|
||||||
|
"version": "kibana"
|
||||||
|
}
|
|
@ -0,0 +1,179 @@
|
||||||
|
<div class="kuiViewContent gettingStartedContent">
|
||||||
|
|
||||||
|
<div
|
||||||
|
ng-if="!gettingStarted.hasOptedOut()"
|
||||||
|
class="kuiBar gettingStartedOptOutContent"
|
||||||
|
>
|
||||||
|
<div class="kuiBarSection">
|
||||||
|
<p class="kuiText kuiSubduedText">
|
||||||
|
<a
|
||||||
|
kbn-href="#/management"
|
||||||
|
class="kuiLink"
|
||||||
|
kbn-getting-started-opt-out
|
||||||
|
data-test-subj="lnkGettingStartedOptOut"
|
||||||
|
>I'm a pro, skip this stuff ></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiViewContentItem kuiVerticalRhythm gettingStartedWelcome">
|
||||||
|
<h1 class="kuiTitle gettingStartedTitle">
|
||||||
|
Welcome to Kibana
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiViewContentItem kuiVerticalRhythm gettingStartedLogo">
|
||||||
|
<img
|
||||||
|
ng-src="{{ gettingStarted.imageUrls.kibanaLogo }}"
|
||||||
|
alt="Kibana logo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiViewContentItem kuiVerticalRhythm">
|
||||||
|
<injected-items items="gettingStarted.topMessages"></injected-items>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiViewContentItem kuiVerticalRhythm">
|
||||||
|
<div class="kuiCardGroup kuiCardGroup">
|
||||||
|
<div class="kuiCard kuiCardGroup__card gettingStartedCard">
|
||||||
|
<div class="kuiCard__description">
|
||||||
|
<div class="kuiCard__descriptionTitle">
|
||||||
|
<h2 class="kuiSubTitle">
|
||||||
|
First, add your data
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard__descriptionText gettingStartedCard__descriptionText">
|
||||||
|
<div class="gettingStartedLogoRow">
|
||||||
|
<img
|
||||||
|
class="gettingStartedLogoRow__logo"
|
||||||
|
ng-src="{{ gettingStarted.imageUrls.beatsLogo }}"
|
||||||
|
alt="Beats logo"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
class="gettingStartedLogoRow__logo"
|
||||||
|
ng-src="{{ gettingStarted.imageUrls.logstashLogo }}"
|
||||||
|
alt="Logstash logo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard__footer">
|
||||||
|
<p class="kuiText">
|
||||||
|
Pull in data from the
|
||||||
|
<a
|
||||||
|
ng-href="{{ gettingStarted.documentationLinks.elasticsearch.docs }}"
|
||||||
|
class="kuiLink"
|
||||||
|
target="_blank"
|
||||||
|
>Elasticsearch API</a>,
|
||||||
|
<a
|
||||||
|
ng-href="{{ gettingStarted.documentationLinks.beats.docs }}"
|
||||||
|
class="kuiLink"
|
||||||
|
target="_blank"
|
||||||
|
>Beats</a>, or
|
||||||
|
<a
|
||||||
|
ng-href="{{ gettingStarted.documentationLinks.logstash.docs }}"
|
||||||
|
class="kuiLink"
|
||||||
|
target="_blank"
|
||||||
|
>Logstash</a>.
|
||||||
|
Not sure how to do that?
|
||||||
|
<a
|
||||||
|
ng-href="{{ gettingStarted.documentationLinks.gettingStarted }}"
|
||||||
|
class="kuiLink"
|
||||||
|
target="_blank"
|
||||||
|
>Read this introduction.</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard kuiCardGroup__card gettingStartedCard">
|
||||||
|
<div class="kuiCard__description">
|
||||||
|
<div class="kuiCard__descriptionTitle">
|
||||||
|
<h2 class="kuiSubTitle">
|
||||||
|
Visualize and explore
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard__descriptionText gettingStartedCard__descriptionText">
|
||||||
|
<div class="gettingStartedLogoRow">
|
||||||
|
<img
|
||||||
|
class="gettingStartedLogoRow__logo"
|
||||||
|
ng-src="{{ gettingStarted.imageUrls.dashboardIcon }}"
|
||||||
|
alt="Dashboard icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard__footer">
|
||||||
|
<p class="kuiText">Once you've added data, you'll need to
|
||||||
|
<a
|
||||||
|
href="#/management/kibana/index"
|
||||||
|
class="kuiLink"
|
||||||
|
kbn-getting-started-opt-out
|
||||||
|
>configure an index pattern</a>
|
||||||
|
for your data before using our Discover and Visualize applications.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="kuiCard kuiCardGroup__card gettingStartedCard"
|
||||||
|
ng-show="gettingStarted.hasManageAndMonitorMessages()"
|
||||||
|
>
|
||||||
|
<div class="kuiCard__description">
|
||||||
|
<div class="kuiCard__descriptionTitle">
|
||||||
|
<h2 class="kuiSubTitle">
|
||||||
|
Manage and monitor
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard__descriptionText gettingStartedCard__descriptionText">
|
||||||
|
<div class="gettingStartedLogoRow">
|
||||||
|
<img
|
||||||
|
class="gettingStartedLogoRow__logo"
|
||||||
|
ng-src="{{ gettingStarted.imageUrls.shieldIcon }}"
|
||||||
|
alt="Shield icon"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiCard__footer">
|
||||||
|
<injected-items items="gettingStarted.manageAndMonitorMessages"></injected-items>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiViewContentItem kuiVerticalRhythm">
|
||||||
|
<div class="kuiFieldGroup">
|
||||||
|
<div class="kuiFieldGroupSection">
|
||||||
|
<p class="kuiText">Just want to see what Kibana is capable of doing?</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiFieldGroupSection">
|
||||||
|
<a
|
||||||
|
class="kuiButton kuiButton--primary"
|
||||||
|
ng-href="{{ gettingStarted.documentationLinks.demoSite }}"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
<span class="kuiButton__inner">
|
||||||
|
<span>View the demo site</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="kuiViewContentItem kuiVerticalRhythm">
|
||||||
|
<p class="kuiText">
|
||||||
|
<a
|
||||||
|
ng-href="{{ gettingStarted.documentationLinks.kibana.docs }}"
|
||||||
|
class="kuiLink"
|
||||||
|
target="_blank"
|
||||||
|
>Kibana documentation</a>
|
||||||
|
is always available to help.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,65 @@
|
||||||
|
import { uiModules } from 'ui/modules';
|
||||||
|
import uiChrome from 'ui/chrome';
|
||||||
|
import 'ui/getting_started/opt_out_directive';
|
||||||
|
import { GettingStartedRegistryProvider } from 'ui/getting_started/registry';
|
||||||
|
import { GETTING_STARTED_REGISTRY_TYPES } from 'ui/getting_started/constants';
|
||||||
|
import { hasOptedOutOfGettingStarted } from 'ui/getting_started/opt_out_helpers';
|
||||||
|
import { documentationLinks } from 'ui/documentation_links';
|
||||||
|
|
||||||
|
import kibanaLogo from 'ui/images/logo-kibana-small.svg';
|
||||||
|
import beatsLogo from 'ui/images/logo-beats-small.svg';
|
||||||
|
import logstashLogo from 'ui/images/logo-logstash-small.svg';
|
||||||
|
import dashboardIcon from 'ui/images/icon-dashboard.svg';
|
||||||
|
import shieldIcon from 'ui/images/icon-shield.svg';
|
||||||
|
|
||||||
|
import template from './getting_started.html';
|
||||||
|
import './getting_started.less';
|
||||||
|
import '../injected_items';
|
||||||
|
|
||||||
|
const app = uiModules.get('kibana');
|
||||||
|
|
||||||
|
app.directive('gettingStarted', function ($injector) {
|
||||||
|
const Private = $injector.get('Private');
|
||||||
|
|
||||||
|
const registry = Private(GettingStartedRegistryProvider);
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
template: template,
|
||||||
|
scope: {
|
||||||
|
},
|
||||||
|
bindToController: true,
|
||||||
|
controllerAs: 'gettingStarted',
|
||||||
|
controller: class GettingStartedController {
|
||||||
|
constructor() {
|
||||||
|
if (this.hasOptedOut()) {
|
||||||
|
uiChrome.setVisible(true);
|
||||||
|
} else {
|
||||||
|
uiChrome.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
const registeredTopMessages = registry.byType[GETTING_STARTED_REGISTRY_TYPES.TOP_MESSAGE] || [];
|
||||||
|
this.topMessages = registeredTopMessages.map(item => item.template);
|
||||||
|
|
||||||
|
const registeredManageAndMonitorMessages = registry.byType[GETTING_STARTED_REGISTRY_TYPES.MANAGE_AND_MONITOR_MESSAGE] || [];
|
||||||
|
this.manageAndMonitorMessages = registeredManageAndMonitorMessages.map(item => item.template);
|
||||||
|
|
||||||
|
this.imageUrls = {
|
||||||
|
kibanaLogo,
|
||||||
|
beatsLogo,
|
||||||
|
logstashLogo,
|
||||||
|
dashboardIcon,
|
||||||
|
shieldIcon
|
||||||
|
};
|
||||||
|
|
||||||
|
this.documentationLinks = documentationLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasManageAndMonitorMessages = () => {
|
||||||
|
return this.manageAndMonitorMessages.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasOptedOut = hasOptedOutOfGettingStarted;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -0,0 +1,65 @@
|
||||||
|
.gettingStartedContent {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedOptOutContent {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px;
|
||||||
|
right: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedWelcome {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 200px;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedTitle {
|
||||||
|
transform: translateY(10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedLogo {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
border: 1px solid #D7DBDD;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
border-radius: 100%;
|
||||||
|
|
||||||
|
background-color: #ffffff;
|
||||||
|
|
||||||
|
transform: translateY(-60px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedLogoRow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedLogoRow__logo {
|
||||||
|
height: 80px;
|
||||||
|
|
||||||
|
& + & {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedCard__descriptionText {
|
||||||
|
margin-top: 32px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gettingStartedCard {
|
||||||
|
width: 340px;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
import './getting_started';
|
|
@ -0,0 +1 @@
|
||||||
|
import './injected_items';
|
|
@ -0,0 +1 @@
|
||||||
|
<div></div>
|
|
@ -0,0 +1,38 @@
|
||||||
|
import { isArray } from 'lodash';
|
||||||
|
import { uiModules } from 'ui/modules';
|
||||||
|
import angular from 'angular';
|
||||||
|
|
||||||
|
import template from './injected_items.html';
|
||||||
|
import './injected_items.less';
|
||||||
|
|
||||||
|
function makeAngularParseableExpression(item) {
|
||||||
|
return `<div class="injectedItems__item">${item} </div>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const app = uiModules.get('kibana');
|
||||||
|
|
||||||
|
app.directive('injectedItems', function ($injector) {
|
||||||
|
const $compile = $injector.get('$compile');
|
||||||
|
|
||||||
|
return {
|
||||||
|
restrict: 'E',
|
||||||
|
replace: true,
|
||||||
|
template: template,
|
||||||
|
scope: {
|
||||||
|
items: '='
|
||||||
|
},
|
||||||
|
link: ($scope, $el) => {
|
||||||
|
const items = $scope.items;
|
||||||
|
|
||||||
|
if (isArray(items) && items.length > 0) {
|
||||||
|
items.forEach(item => {
|
||||||
|
// Compile itemHtml with current $scope and append it into the container DOM element.
|
||||||
|
// We do this because we want to dynamically inject content (strings) into the DOM. This content
|
||||||
|
// may contain Angular directives so it must first be $compiled with the current $scope.
|
||||||
|
const itemHtml = $compile(makeAngularParseableExpression(item))($scope);
|
||||||
|
angular.element($el).append(itemHtml);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
|
@ -0,0 +1,3 @@
|
||||||
|
.injectedItems__item {
|
||||||
|
display: inline;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<getting-started></getting-started>
|
|
@ -0,0 +1,14 @@
|
||||||
|
import routes from 'ui/routes';
|
||||||
|
import template from './getting_started_route.html';
|
||||||
|
import './components/getting_started';
|
||||||
|
import { GETTING_STARTED_ROUTE } from './lib/constants';
|
||||||
|
|
||||||
|
routes
|
||||||
|
.when(GETTING_STARTED_ROUTE, {
|
||||||
|
template: template,
|
||||||
|
controllerAs: 'gettingStartedRoute',
|
||||||
|
controller: class GettingStartedRouteController {
|
||||||
|
constructor() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
3
src/core_plugins/getting_started/public/index.js
Normal file
3
src/core_plugins/getting_started/public/index.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import './lib/add_setup_work';
|
||||||
|
import './lib/register_management_section';
|
||||||
|
import './getting_started_route';
|
|
@ -0,0 +1,81 @@
|
||||||
|
import { get } from 'lodash';
|
||||||
|
import uiRoutes from 'ui/routes';
|
||||||
|
import uiChrome from 'ui/chrome';
|
||||||
|
import KbnUrlProvider from 'ui/url';
|
||||||
|
import { Notifier } from 'ui/notify/notifier';
|
||||||
|
import { IndexPatternsGetIdsProvider } from 'ui/index_patterns/_get_ids';
|
||||||
|
import { hasOptedOutOfGettingStarted, optOutOfGettingStarted } from 'ui/getting_started/opt_out_helpers';
|
||||||
|
|
||||||
|
import {
|
||||||
|
GETTING_STARTED_ROUTE,
|
||||||
|
CREATE_INDEX_PATTERN_ROUTE
|
||||||
|
} from './constants';
|
||||||
|
|
||||||
|
uiRoutes
|
||||||
|
.addSetupWork(function gettingStartedGateCheck(Private, $injector) {
|
||||||
|
const getIds = Private(IndexPatternsGetIdsProvider);
|
||||||
|
const kbnUrl = Private(KbnUrlProvider);
|
||||||
|
const config = $injector.get('config');
|
||||||
|
const $route = $injector.get('$route');
|
||||||
|
|
||||||
|
const currentRoute = get($route, 'current.$$route');
|
||||||
|
|
||||||
|
return getIds()
|
||||||
|
.then(indexPatterns => {
|
||||||
|
const indexPatternsExist = Array.isArray(indexPatterns) && indexPatterns.length > 0;
|
||||||
|
const isOnGettingStartedPage = get(currentRoute, 'originalPath') === GETTING_STARTED_ROUTE;
|
||||||
|
|
||||||
|
if (indexPatternsExist) {
|
||||||
|
|
||||||
|
// The user need not see the Getting Started page, so opt them out of it
|
||||||
|
optOutOfGettingStarted();
|
||||||
|
|
||||||
|
// Some routes require a default index pattern to be present. If we're
|
||||||
|
// NOT on such a route, there's nothing more to do; send the user on their way
|
||||||
|
if (!currentRoute.requireDefaultIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, check if we have a default index pattern
|
||||||
|
let defaultIndexPattern = config.get('defaultIndex');
|
||||||
|
|
||||||
|
// If we don't have an default index pattern, make the first index pattern the
|
||||||
|
// default one
|
||||||
|
if (!Boolean(defaultIndexPattern)) {
|
||||||
|
defaultIndexPattern = indexPatterns[0];
|
||||||
|
config.set('defaultIndex', defaultIndexPattern);
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, we have a default index pattern and are all set!
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point, no index patterns exist.
|
||||||
|
|
||||||
|
// If the user has explicitly opted out of the Getting Started page
|
||||||
|
if (hasOptedOutOfGettingStarted()) {
|
||||||
|
|
||||||
|
// Some routes require a default index pattern to be present. If we're
|
||||||
|
// NOT on such a route, there's nothing more to do; send the user on their way
|
||||||
|
if (!currentRoute.requireDefaultIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, redirect the user to the index pattern creation page with
|
||||||
|
// a notification about creating an index pattern
|
||||||
|
const notify = new Notifier({
|
||||||
|
location: 'Index Patterns'
|
||||||
|
});
|
||||||
|
notify.error('Please create a new index pattern');
|
||||||
|
kbnUrl.change(CREATE_INDEX_PATTERN_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect the user to the Getting Started page (unless they are on it already)
|
||||||
|
if (!isOnGettingStartedPage) {
|
||||||
|
uiChrome.setVisible(false);
|
||||||
|
kbnUrl.change(GETTING_STARTED_ROUTE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
2
src/core_plugins/getting_started/public/lib/constants.js
Normal file
2
src/core_plugins/getting_started/public/lib/constants.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export const GETTING_STARTED_ROUTE = '/management/kibana/getting_started';
|
||||||
|
export const CREATE_INDEX_PATTERN_ROUTE = '/management/kibana/index';
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { management } from 'ui/management';
|
||||||
|
import { GETTING_STARTED_ROUTE } from './constants';
|
||||||
|
|
||||||
|
management.getSection('kibana').register('getting_started', {
|
||||||
|
display: 'Getting Started',
|
||||||
|
order: 50,
|
||||||
|
url: `#${GETTING_STARTED_ROUTE}`
|
||||||
|
});
|
|
@ -19,10 +19,6 @@ uiRoutes
|
||||||
redirectTo: '/management'
|
redirectTo: '/management'
|
||||||
});
|
});
|
||||||
|
|
||||||
require('ui/index_patterns/route_setup/load_default')({
|
|
||||||
whenMissingRedirectTo: '/management/kibana/index'
|
|
||||||
});
|
|
||||||
|
|
||||||
uiModules
|
uiModules
|
||||||
.get('apps/management')
|
.get('apps/management')
|
||||||
.directive('kbnManagementApp', function (Private, $location, timefilter, buildNum, buildSha) {
|
.directive('kbnManagementApp', function (Private, $location, timefilter, buildNum, buildSha) {
|
||||||
|
|
|
@ -7,6 +7,18 @@ const urlVersion = `${major}.${minor}`;
|
||||||
const baseUrl = 'https://www.elastic.co/';
|
const baseUrl = 'https://www.elastic.co/';
|
||||||
|
|
||||||
export const documentationLinks = {
|
export const documentationLinks = {
|
||||||
|
elasticsearch: {
|
||||||
|
docs: `${baseUrl}guide/en/elasticsearch/reference/current`
|
||||||
|
},
|
||||||
|
beats: {
|
||||||
|
docs: `${baseUrl}guide/en/beats/libbeat/current`
|
||||||
|
},
|
||||||
|
logstash: {
|
||||||
|
docs: `${baseUrl}guide/en/logstash/current`
|
||||||
|
},
|
||||||
|
kibana: {
|
||||||
|
docs: `${baseUrl}guide/en/kibana/current`
|
||||||
|
},
|
||||||
filebeat: {
|
filebeat: {
|
||||||
installation: `${baseUrl}guide/en/beats/filebeat/${urlVersion}/filebeat-installation.html`,
|
installation: `${baseUrl}guide/en/beats/filebeat/${urlVersion}/filebeat-installation.html`,
|
||||||
configuration: `${baseUrl}guide/en/beats/filebeat/${urlVersion}/filebeat-configuration.html`,
|
configuration: `${baseUrl}guide/en/beats/filebeat/${urlVersion}/filebeat-configuration.html`,
|
||||||
|
@ -25,5 +37,7 @@ export const documentationLinks = {
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
luceneQuerySyntax: `${baseUrl}guide/en/elasticsearch/reference/${urlVersion}/query-dsl-query-string-query.html#query-string-syntax`
|
luceneQuerySyntax: `${baseUrl}guide/en/elasticsearch/reference/${urlVersion}/query-dsl-query-string-query.html#query-string-syntax`
|
||||||
}
|
},
|
||||||
|
demoSite: 'http://demo.elastic.co',
|
||||||
|
gettingStarted: `${baseUrl}products/kibana/getting-started-link`
|
||||||
};
|
};
|
||||||
|
|
6
src/ui/public/getting_started/constants.js
Normal file
6
src/ui/public/getting_started/constants.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export const GETTING_STARTED_OPT_OUT_FLAG = 'kibana.isGettingStartedOptedOut';
|
||||||
|
|
||||||
|
export const GETTING_STARTED_REGISTRY_TYPES = {
|
||||||
|
TOP_MESSAGE: 'topMessage',
|
||||||
|
MANAGE_AND_MONITOR_MESSAGE: 'monitorAndManageMessage'
|
||||||
|
};
|
14
src/ui/public/getting_started/opt_out_directive.js
Normal file
14
src/ui/public/getting_started/opt_out_directive.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { uiModules } from 'ui/modules';
|
||||||
|
import { optOutOfGettingStarted } from './opt_out_helpers';
|
||||||
|
|
||||||
|
const app = uiModules.get('kibana');
|
||||||
|
app.directive('kbnGettingStartedOptOut', () => {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: (scope, element) => {
|
||||||
|
element.on('click', () => {
|
||||||
|
optOutOfGettingStarted();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
11
src/ui/public/getting_started/opt_out_helpers.js
Normal file
11
src/ui/public/getting_started/opt_out_helpers.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import uiChrome from 'ui/chrome';
|
||||||
|
import { GETTING_STARTED_OPT_OUT_FLAG } from './constants';
|
||||||
|
|
||||||
|
export function hasOptedOutOfGettingStarted() {
|
||||||
|
return window.localStorage.getItem(GETTING_STARTED_OPT_OUT_FLAG) || false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function optOutOfGettingStarted() {
|
||||||
|
window.localStorage.setItem(GETTING_STARTED_OPT_OUT_FLAG, true);
|
||||||
|
uiChrome.setVisible(true);
|
||||||
|
}
|
18
src/ui/public/getting_started/registry.js
Normal file
18
src/ui/public/getting_started/registry.js
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import { uiRegistry } from 'ui/registry/_registry';
|
||||||
|
|
||||||
|
export const GettingStartedRegistryProvider = uiRegistry({
|
||||||
|
name: 'gettingStartedTopMessages',
|
||||||
|
group: [ 'type' ]
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* import { GettingStartedRegistryProvider } from 'ui/getting_started/registry';
|
||||||
|
* import { GETTING_STARTED_REGISTRY_TYPES } from 'ui/getting_started/constants';
|
||||||
|
*
|
||||||
|
* GettingStartedRegistryProvider.register(($injector, Private, someOtherService, ...) => ({
|
||||||
|
* type: GETTING_STARTED_REGISTRY_TYPES.TOP_MESSAGE,
|
||||||
|
* template: 'plain text | html markup | markup with directives'
|
||||||
|
* }));
|
||||||
|
*/
|
8
src/ui/public/images/icon-dashboard.svg
Normal file
8
src/ui/public/images/icon-dashboard.svg
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="67" height="67" viewBox="0 0 67 67">
|
||||||
|
<g fill="none" fill-rule="evenodd" transform="translate(.219 .219)">
|
||||||
|
<rect width="66.563" height="17.75" fill="#00A9E5" rx="2"/>
|
||||||
|
<rect width="28.844" height="17.75" y="24.406" fill="#00BFB3" rx="2"/>
|
||||||
|
<rect width="28.844" height="17.75" y="48.813" fill="#00A9E5" rx="2"/>
|
||||||
|
<rect width="31.063" height="42.156" x="35.5" y="24.406" fill="#00BFB3" rx="2"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 468 B |
14
src/ui/public/images/icon-shield.svg
Normal file
14
src/ui/public/images/icon-shield.svg
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="40px" height="50px" viewBox="0 0 40 50" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>icon-security-bb-edited</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs></defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="icon-security-bb-edited">
|
||||||
|
<path d="M0,25.9749 L0,26.2749 C0.8,36.6749 8.1,46.0759 19.3,49.8749 C19.7,49.9749 20.2,49.9749 20.6,49.8749 C32,46.0759 39.5,36.6749 40,26.2749 L40,25.9749 L0,25.9749 Z" id="Fill-1" fill="#00BFB3"></path>
|
||||||
|
<path d="M40,25.9749 L40,7.3749 C40,6.5749 39.4,5.7749 38.6,5.4749 L20.6,0.0749 C20.2,-0.0251 19.8,-0.0251 19.4,0.0749 L1.4,5.4749 C0.6,5.7749 0,6.4749 0,7.3749 L0,25.9749 L40,25.9749 Z" id="Fill-3" fill="#13A7DF"></path>
|
||||||
|
<polygon id="Fill-6" fill="#0078A0" points="0 25.975 40 25.975 40 19.975 0 19.975"></polygon>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
23
src/ui/public/images/logo-beats-small.svg
Normal file
23
src/ui/public/images/logo-beats-small.svg
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#07A5DE;}
|
||||||
|
.st1{fill:#3EBEB0;}
|
||||||
|
.st2{opacity:0.26;fill:#353535;enable-background:new ;}
|
||||||
|
.st3{fill:#353535;}
|
||||||
|
.st4{fill:none;}
|
||||||
|
</style>
|
||||||
|
<title>logo-menu</title>
|
||||||
|
<g id="ES_Hadoop_Gery">
|
||||||
|
<path class="st0" d="M5,0.5h14.2c6.3,0,11.4,5.1,11.4,11.4c0,0,0,0,0,0l0,0c0,6.3-5.1,11.4-11.4,11.4c0,0,0,0,0,0H5l0,0V0.5L5,0.5z
|
||||||
|
"/>
|
||||||
|
<path class="st1" d="M5,16.6h18.5C29.8,16.6,35,21.7,35,28c0,0,0,0,0,0.1l0,0c0,6.3-5.1,11.4-11.4,11.4c0,0,0,0-0.1,0H5l0,0V16.6
|
||||||
|
L5,16.6z"/>
|
||||||
|
<path class="st2" d="M32.2,20.6c-2.2-2.5-5.3-4-8.7-4H5v10.6h17.2C28.2,27.2,32.5,21,32.2,20.6z"/>
|
||||||
|
<path class="st3" d="M19.2,23.4c3.9,0,7.6-2,9.7-5.4c-0.3-0.1-0.5-0.3-0.8-0.4l-0.2-0.1c-0.3-0.1-0.6-0.2-0.8-0.3H27h-0.1
|
||||||
|
C26.6,17.1,26.3,17,26,17h-0.1h-0.2c-0.3,0-0.5-0.1-0.8-0.1h-0.2h-0.2c-0.3,0-0.6,0-0.9,0H5v6.8L19.2,23.4z"/>
|
||||||
|
</g>
|
||||||
|
<rect x="0" class="st4" width="40" height="40"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
20
src/ui/public/images/logo-kibana-small.svg
Normal file
20
src/ui/public/images/logo-kibana-small.svg
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#E9478B;}
|
||||||
|
.st1{fill:#3EBEB0;}
|
||||||
|
.st2{fill:#37A595;}
|
||||||
|
.st3{fill:#353535;}
|
||||||
|
.st4{fill:none;}
|
||||||
|
</style>
|
||||||
|
<title>logo-menu</title>
|
||||||
|
<g id="ES_Hadoop_Gery">
|
||||||
|
<path class="st0" d="M5.6,15.1c5,0,9.9,1.2,14.3,3.6L35,0.5H5v36.2l0,0V15.1L5.6,15.1z"/>
|
||||||
|
<path class="st1" d="M19.9,18.7L5,36.7v2.8h30C33.3,30.7,27.8,23,19.9,18.7z"/>
|
||||||
|
<path class="st2" d="M19.9,18.7L5,36.7v2.8h5.3l14.4-17.4c0,0-1-0.8-2.3-1.8C21.4,19.6,19.9,18.7,19.9,18.7z"/>
|
||||||
|
<path class="st3" d="M5.6,15.1H5v21.6l14.9-17.9C15.5,16.3,10.5,15.1,5.6,15.1z"/>
|
||||||
|
</g>
|
||||||
|
<rect x="0" class="st4" width="40" height="40"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 950 B |
20
src/ui/public/images/logo-logstash-small.svg
Normal file
20
src/ui/public/images/logo-logstash-small.svg
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 40 40" style="enable-background:new 0 0 40 40;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#F3BD19;}
|
||||||
|
.st1{fill:#231F20;}
|
||||||
|
.st2{fill:#3EBEB0;}
|
||||||
|
.st3{fill:#37A595;}
|
||||||
|
.st4{fill:none;}
|
||||||
|
</style>
|
||||||
|
<title>logo-menu</title>
|
||||||
|
<g id="ES_Hadoop_Gery">
|
||||||
|
<path class="st0" d="M2.7,0.5h5.5c7,0,12.6,5.7,12.6,12.6v8.2l0,0H2.7l0,0V0.5L2.7,0.5z"/>
|
||||||
|
<path class="st1" d="M2.7,21.4h18.1l0,0v18.1l0,0l0,0C10.8,39.5,2.7,31.4,2.7,21.4L2.7,21.4L2.7,21.4z"/>
|
||||||
|
<rect x="20.8" y="21.4" class="st2" width="16.5" height="18.1"/>
|
||||||
|
<rect x="20.8" y="21.4" class="st3" width="3.8" height="18.1"/>
|
||||||
|
</g>
|
||||||
|
<rect x="0" class="st4" width="40" height="40"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 915 B |
|
@ -1,58 +0,0 @@
|
||||||
import _ from 'lodash';
|
|
||||||
import { Notifier } from 'ui/notify/notifier';
|
|
||||||
import { NoDefaultIndexPattern } from 'ui/errors';
|
|
||||||
import { IndexPatternsGetIdsProvider } from '../_get_ids';
|
|
||||||
import uiRoutes from 'ui/routes';
|
|
||||||
const notify = new Notifier({
|
|
||||||
location: 'Index Patterns'
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = function (opts) {
|
|
||||||
opts = opts || {};
|
|
||||||
const whenMissingRedirectTo = opts.whenMissingRedirectTo || null;
|
|
||||||
let defaultRequiredToasts = null;
|
|
||||||
|
|
||||||
uiRoutes
|
|
||||||
.addSetupWork(function loadDefaultIndexPattern(Private, Promise, $route, config) {
|
|
||||||
const getIds = Private(IndexPatternsGetIdsProvider);
|
|
||||||
const route = _.get($route, 'current.$$route');
|
|
||||||
|
|
||||||
return getIds()
|
|
||||||
.then(function (patterns) {
|
|
||||||
let defaultId = config.get('defaultIndex');
|
|
||||||
let defined = !!defaultId;
|
|
||||||
const exists = _.contains(patterns, defaultId);
|
|
||||||
|
|
||||||
if (defined && !exists) {
|
|
||||||
config.remove('defaultIndex');
|
|
||||||
defaultId = defined = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!defined && route.requireDefaultIndex) {
|
|
||||||
// If there is only one index pattern, set it as default
|
|
||||||
if (patterns.length === 1) {
|
|
||||||
defaultId = patterns[0];
|
|
||||||
config.set('defaultIndex', defaultId);
|
|
||||||
} else {
|
|
||||||
throw new NoDefaultIndexPattern();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.afterWork(
|
|
||||||
// success
|
|
||||||
null,
|
|
||||||
|
|
||||||
// failure
|
|
||||||
function (err, kbnUrl) {
|
|
||||||
const hasDefault = !(err instanceof NoDefaultIndexPattern);
|
|
||||||
if (hasDefault || !whenMissingRedirectTo) throw err; // rethrow
|
|
||||||
|
|
||||||
kbnUrl.change(whenMissingRedirectTo);
|
|
||||||
if (!defaultRequiredToasts) defaultRequiredToasts = [];
|
|
||||||
else defaultRequiredToasts.push(notify.error(err));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
|
@ -15,11 +15,13 @@ export default function ({ getService, getPageObjects }) {
|
||||||
const retry = getService('retry');
|
const retry = getService('retry');
|
||||||
const log = getService('log');
|
const log = getService('log');
|
||||||
const screenshots = getService('screenshots');
|
const screenshots = getService('screenshots');
|
||||||
const PageObjects = getPageObjects(['common', 'console']);
|
const PageObjects = getPageObjects(['common', 'console', 'gettingStarted']);
|
||||||
|
|
||||||
describe('console app', function describeIndexTests() {
|
describe('console app', function describeIndexTests() {
|
||||||
before(function () {
|
before(async function () {
|
||||||
log.debug('navigateTo console');
|
log.debug('navigateTo console');
|
||||||
|
await PageObjects.common.navigateToUrl('settings', 'kibana/getting_started');
|
||||||
|
await PageObjects.gettingStarted.clickOptOutLink();
|
||||||
return PageObjects.common.navigateToApp('console');
|
return PageObjects.common.navigateToApp('console');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
SettingsPageProvider,
|
SettingsPageProvider,
|
||||||
MonitoringPageProvider,
|
MonitoringPageProvider,
|
||||||
PointSeriesPageProvider,
|
PointSeriesPageProvider,
|
||||||
|
GettingStartedPageProvider
|
||||||
} from './page_objects';
|
} from './page_objects';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
@ -52,6 +53,7 @@ export default function () {
|
||||||
settings: SettingsPageProvider,
|
settings: SettingsPageProvider,
|
||||||
monitoring: MonitoringPageProvider,
|
monitoring: MonitoringPageProvider,
|
||||||
pointSeries: PointSeriesPageProvider,
|
pointSeries: PointSeriesPageProvider,
|
||||||
|
gettingStarted: GettingStartedPageProvider,
|
||||||
},
|
},
|
||||||
services: {
|
services: {
|
||||||
kibanaServer: KibanaServerProvider,
|
kibanaServer: KibanaServerProvider,
|
||||||
|
|
|
@ -23,6 +23,10 @@ export function CommonPageProvider({ getService, getPageObjects }) {
|
||||||
return getUrl.baseUrl(config.get('servers.elasticsearch'));
|
return getUrl.baseUrl(config.get('servers.elasticsearch'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} appName As defined in the apps objects in test/server_config.js
|
||||||
|
* @param {string} subUrl The route after the hash (#)
|
||||||
|
*/
|
||||||
navigateToUrl(appName, subUrl) {
|
navigateToUrl(appName, subUrl) {
|
||||||
const appConfig = Object.assign({}, config.get(['apps', appName]), {
|
const appConfig = Object.assign({}, config.get(['apps', appName]), {
|
||||||
// Overwrite the default hash with the URL we really want.
|
// Overwrite the default hash with the URL we really want.
|
||||||
|
|
14
test/functional/page_objects/getting_started_page.js
Normal file
14
test/functional/page_objects/getting_started_page.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
export function GettingStartedPageProvider({ getService }) {
|
||||||
|
|
||||||
|
const log = getService('log');
|
||||||
|
const testSubjects = getService('testSubjects');
|
||||||
|
|
||||||
|
class GettingStartedPage {
|
||||||
|
async clickOptOutLink() {
|
||||||
|
log.debug('Clicking opt-out link');
|
||||||
|
await testSubjects.click('lnkGettingStartedOptOut');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new GettingStartedPage();
|
||||||
|
}
|
|
@ -9,3 +9,4 @@ export { VisualizePageProvider } from './visualize_page';
|
||||||
export { SettingsPageProvider } from './settings_page';
|
export { SettingsPageProvider } from './settings_page';
|
||||||
export { MonitoringPageProvider } from './monitoring_page';
|
export { MonitoringPageProvider } from './monitoring_page';
|
||||||
export { PointSeriesPageProvider } from './point_series_page';
|
export { PointSeriesPageProvider } from './point_series_page';
|
||||||
|
export { GettingStartedPageProvider } from './getting_started_page';
|
||||||
|
|
Loading…
Reference in a new issue