mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
parent
a0e3a1f0ef
commit
72f71ef468
78 changed files with 608 additions and 611 deletions
|
@ -11,6 +11,13 @@
|
|||
@import './doc_viewer/index';
|
||||
@import './inspector/index';
|
||||
@import './markdown/index';
|
||||
@import './accessibility/index';
|
||||
@import './chrome/index';
|
||||
@import './error_allow_explicit_index/index';
|
||||
@import './error_auto_create_index/index';
|
||||
@import './error_url_overflow/index';
|
||||
@import './field_editor/index';
|
||||
@import './notify/index';
|
||||
@import './query_bar/index';
|
||||
|
||||
// The following are prefixed with "vis"
|
||||
|
|
|
@ -29,17 +29,19 @@ describe('kbnUiAceKeyboardMode directive', () => {
|
|||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
|
||||
beforeEach(ngMock.inject(($compile, $rootScope) => {
|
||||
element = $compile(`<div ui-ace kbn-ui-ace-keyboard-mode></div>`)($rootScope.$new());
|
||||
}));
|
||||
beforeEach(
|
||||
ngMock.inject(($compile, $rootScope) => {
|
||||
element = $compile(`<div ui-ace kbn-ui-ace-keyboard-mode></div>`)($rootScope.$new());
|
||||
})
|
||||
);
|
||||
|
||||
it('should add the hint element', () => {
|
||||
expect(element.find('.uiAceKeyboardHint').length).to.be(1);
|
||||
expect(element.find('.kbnUiAceKeyboardHint').length).to.be(1);
|
||||
});
|
||||
|
||||
describe('hint element', () => {
|
||||
it('should be tabable', () => {
|
||||
expect(element.find('.uiAceKeyboardHint').attr('tabindex')).to.be('0');
|
||||
expect(element.find('.kbnUiAceKeyboardHint').attr('tabindex')).to.be('0');
|
||||
});
|
||||
|
||||
it('should move focus to textbox and be inactive if pressed enter on it', () => {
|
||||
|
@ -47,20 +49,22 @@ describe('kbnUiAceKeyboardMode directive', () => {
|
|||
sinon.spy(textarea[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ENTER;
|
||||
element.find('.uiAceKeyboardHint').trigger(ev);
|
||||
element.find('.kbnUiAceKeyboardHint').trigger(ev);
|
||||
expect(textarea[0].focus.called).to.be(true);
|
||||
expect(element.find('.uiAceKeyboardHint').hasClass('uiAceKeyboardHint-isInactive')).to.be(true);
|
||||
expect(
|
||||
element.find('.kbnUiAceKeyboardHint').hasClass('kbnUiAceKeyboardHint-isInactive')
|
||||
).to.be(true);
|
||||
});
|
||||
|
||||
it('should be shown again, when pressing Escape in ace editor', () => {
|
||||
const textarea = element.find('textarea');
|
||||
const hint = element.find('.uiAceKeyboardHint');
|
||||
const hint = element.find('.kbnUiAceKeyboardHint');
|
||||
sinon.spy(hint[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ESCAPE;
|
||||
textarea.trigger(ev);
|
||||
expect(hint[0].focus.called).to.be(true);
|
||||
expect(hint.hasClass('uiAceKeyboardHint-isInactive')).to.be(false);
|
||||
expect(hint.hasClass('kbnUiAceKeyboardHint-isInactive')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -69,7 +73,6 @@ describe('kbnUiAceKeyboardMode directive', () => {
|
|||
expect(element.find('textarea').attr('tabindex')).to.be('-1');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('kbnUiAceKeyboardModeService', () => {
|
||||
|
@ -77,19 +80,21 @@ describe('kbnUiAceKeyboardModeService', () => {
|
|||
|
||||
beforeEach(ngMock.module('kibana'));
|
||||
|
||||
beforeEach(ngMock.inject(($compile, $rootScope, kbnUiAceKeyboardModeService) => {
|
||||
const scope = $rootScope.$new();
|
||||
element = $compile(`<div ui-ace></div>`)(scope);
|
||||
kbnUiAceKeyboardModeService.initialize(scope, element);
|
||||
}));
|
||||
beforeEach(
|
||||
ngMock.inject(($compile, $rootScope, kbnUiAceKeyboardModeService) => {
|
||||
const scope = $rootScope.$new();
|
||||
element = $compile(`<div ui-ace></div>`)(scope);
|
||||
kbnUiAceKeyboardModeService.initialize(scope, element);
|
||||
})
|
||||
);
|
||||
|
||||
it('should add the hint element', () => {
|
||||
expect(element.find('.uiAceKeyboardHint').length).to.be(1);
|
||||
expect(element.find('.kbnUiAceKeyboardHint').length).to.be(1);
|
||||
});
|
||||
|
||||
describe('hint element', () => {
|
||||
it('should be tabable', () => {
|
||||
expect(element.find('.uiAceKeyboardHint').attr('tabindex')).to.be('0');
|
||||
expect(element.find('.kbnUiAceKeyboardHint').attr('tabindex')).to.be('0');
|
||||
});
|
||||
|
||||
it('should move focus to textbox and be inactive if pressed enter on it', () => {
|
||||
|
@ -97,20 +102,22 @@ describe('kbnUiAceKeyboardModeService', () => {
|
|||
sinon.spy(textarea[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ENTER;
|
||||
element.find('.uiAceKeyboardHint').trigger(ev);
|
||||
element.find('.kbnUiAceKeyboardHint').trigger(ev);
|
||||
expect(textarea[0].focus.called).to.be(true);
|
||||
expect(element.find('.uiAceKeyboardHint').hasClass('uiAceKeyboardHint-isInactive')).to.be(true);
|
||||
expect(
|
||||
element.find('.kbnUiAceKeyboardHint').hasClass('kbnUiAceKeyboardHint-isInactive')
|
||||
).to.be(true);
|
||||
});
|
||||
|
||||
it('should be shown again, when pressing Escape in ace editor', () => {
|
||||
const textarea = element.find('textarea');
|
||||
const hint = element.find('.uiAceKeyboardHint');
|
||||
const hint = element.find('.kbnUiAceKeyboardHint');
|
||||
sinon.spy(hint[0], 'focus');
|
||||
const ev = angular.element.Event('keydown'); // eslint-disable-line new-cap
|
||||
ev.keyCode = keyCodes.ESCAPE;
|
||||
textarea.trigger(ev);
|
||||
expect(hint[0].focus.called).to.be(true);
|
||||
expect(hint.hasClass('uiAceKeyboardHint-isInactive')).to.be(false);
|
||||
expect(hint.hasClass('kbnUiAceKeyboardHint-isInactive')).to.be(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -119,5 +126,4 @@ describe('kbnUiAceKeyboardModeService', () => {
|
|||
expect(element.find('textarea').attr('tabindex')).to.be('-1');
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
|
1
src/ui/public/accessibility/_index.scss
Normal file
1
src/ui/public/accessibility/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './kbn_ui_ace_keyboard_mode';
|
|
@ -1,12 +1,10 @@
|
|||
@import (reference) "~ui/styles/variables";
|
||||
|
||||
.uiAceKeyboardHint {
|
||||
.kbnUiAceKeyboardHint {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
background: transparentize($euiColorEmptyShade, 0.3);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
@ -16,11 +14,11 @@
|
|||
|
||||
&:focus {
|
||||
opacity: 1;
|
||||
border: 2px solid @globalColorBlue;
|
||||
border: 2px solid $euiColorPrimary;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
&.uiAceKeyboardHint-isInactive {
|
||||
&.kbnUiAceKeyboardHint-isInactive {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -33,19 +33,19 @@
|
|||
|
||||
import angular from 'angular';
|
||||
import { uiModules } from '../modules';
|
||||
import './kbn_ui_ace_keyboard_mode.less';
|
||||
import { keyCodes } from '@elastic/eui';
|
||||
|
||||
let aceKeyboardModeId = 0;
|
||||
|
||||
uiModules.get('kibana')
|
||||
uiModules
|
||||
.get('kibana')
|
||||
.factory('kbnUiAceKeyboardModeService', () => ({
|
||||
initialize(scope, element) {
|
||||
const uniqueId = `uiAceKeyboardHint-${scope.$id}-${aceKeyboardModeId++}`;
|
||||
const uniqueId = `kbnUiAceKeyboardHint-${scope.$id}-${aceKeyboardModeId++}`;
|
||||
|
||||
const hint = angular.element(
|
||||
`<div
|
||||
class="uiAceKeyboardHint"
|
||||
class="kbnUiAceKeyboardHint"
|
||||
id="${uniqueId}"
|
||||
tabindex="0"
|
||||
role="application"
|
||||
|
@ -63,15 +63,15 @@ uiModules.get('kibana')
|
|||
|
||||
function startEditing() {
|
||||
// We are not using ng-class in the element, so that we won't need to $compile it
|
||||
hint.addClass('uiAceKeyboardHint-isInactive');
|
||||
hint.addClass('kbnUiAceKeyboardHint-isInactive');
|
||||
uiAceTextbox.focus();
|
||||
}
|
||||
|
||||
function enableOverlay() {
|
||||
hint.removeClass('uiAceKeyboardHint-isInactive');
|
||||
hint.removeClass('kbnUiAceKeyboardHint-isInactive');
|
||||
}
|
||||
|
||||
hint.keydown((ev) => {
|
||||
hint.keydown(ev => {
|
||||
if (ev.keyCode === keyCodes.ENTER) {
|
||||
ev.preventDefault();
|
||||
startEditing();
|
||||
|
@ -86,19 +86,23 @@ uiModules.get('kibana')
|
|||
|
||||
// We have to capture this event on the 'capture' phase, otherwise Ace will have already
|
||||
// dismissed the autocompleter when the user hits ESC.
|
||||
document.addEventListener('keydown', () => {
|
||||
const autoCompleter = document.querySelector('.ace_autocomplete');
|
||||
document.addEventListener(
|
||||
'keydown',
|
||||
() => {
|
||||
const autoCompleter = document.querySelector('.ace_autocomplete');
|
||||
|
||||
if (!autoCompleter) {
|
||||
isAutoCompleterOpen = false;
|
||||
return;
|
||||
}
|
||||
if (!autoCompleter) {
|
||||
isAutoCompleterOpen = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// The autoComplete is just hidden when it's closed, not removed from the DOM.
|
||||
isAutoCompleterOpen = autoCompleter.style.display !== 'none';
|
||||
}, { capture: true });
|
||||
// The autoComplete is just hidden when it's closed, not removed from the DOM.
|
||||
isAutoCompleterOpen = autoCompleter.style.display !== 'none';
|
||||
},
|
||||
{ capture: true }
|
||||
);
|
||||
|
||||
uiAceTextbox.keydown((ev) => {
|
||||
uiAceTextbox.keydown(ev => {
|
||||
if (ev.keyCode === keyCodes.ESCAPE) {
|
||||
// If the autocompletion context menu is open then we want to let ESC close it but
|
||||
// **not** exit out of editing mode.
|
||||
|
@ -115,11 +119,11 @@ uiModules.get('kibana')
|
|||
// Prevent tabbing into the ACE textarea, we now handle all focusing for it
|
||||
uiAceTextbox.attr('tabindex', '-1');
|
||||
element.prepend(hint);
|
||||
}
|
||||
},
|
||||
}))
|
||||
.directive('kbnUiAceKeyboardMode', (kbnUiAceKeyboardModeService) => ({
|
||||
.directive('kbnUiAceKeyboardMode', kbnUiAceKeyboardModeService => ({
|
||||
restrict: 'A',
|
||||
link(scope, element) {
|
||||
kbnUiAceKeyboardModeService.initialize(scope, element);
|
||||
}
|
||||
},
|
||||
}));
|
||||
|
|
3
src/ui/public/chrome/_index.scss
Normal file
3
src/ui/public/chrome/_index.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
@import './variables';
|
||||
|
||||
@import './directives/index';
|
11
src/ui/public/chrome/_variables.scss
Normal file
11
src/ui/public/chrome/_variables.scss
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
$kbnChromeGlobalNavBackground: shade($euiColorPrimary, 30%);
|
||||
|
||||
$kbnGlobalNavClosedWidth: 53px;
|
||||
$kbnGlobalNavOpenWidth: 180px;
|
||||
$kbnGlobalNavLogoHeight: 70px;
|
||||
$kbnGlobalNavAppIconHeight: 38px;
|
||||
|
||||
$kbnLoadingIndicatorBackgroundSize: $euiSizeXXL * 10;
|
||||
$kbnLoadingIndicatorColor1: tint($euiColorAccent, 15%);
|
||||
$kbnLoadingIndicatorColor2: tint($euiColorAccent, 60%);
|
|
@ -2,22 +2,22 @@
|
|||
|
||||
exports[`kbnLoadingIndicator is hidden by default 1`] = `
|
||||
<div
|
||||
className="loadingIndicator hidden"
|
||||
className="kbnLoadingIndicator hidden"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
>
|
||||
<div
|
||||
className="loadingIndicator__bar essentialAnimation"
|
||||
className="kbnLoadingIndicator__bar essentialAnimation"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`kbnLoadingIndicator is visible when loadingCount is > 0 1`] = `
|
||||
<div
|
||||
className="loadingIndicator"
|
||||
className="kbnLoadingIndicator"
|
||||
data-test-subj="globalLoadingIndicator"
|
||||
>
|
||||
<div
|
||||
className="loadingIndicator__bar essentialAnimation"
|
||||
className="kbnLoadingIndicator__bar essentialAnimation"
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
|
5
src/ui/public/chrome/directives/_index.scss
Normal file
5
src/ui/public/chrome/directives/_index.scss
Normal file
|
@ -0,0 +1,5 @@
|
|||
@import './kbn_chrome';
|
||||
@import './loading_indicator';
|
||||
|
||||
@import './global_nav/index';
|
||||
@import './header_global_nav/index';
|
|
@ -1,12 +1,9 @@
|
|||
|
||||
@import (reference) "~ui/styles/mixins";
|
||||
@import (reference) "~ui/styles/variables";
|
||||
|
||||
/**
|
||||
* stretch the root element of the Kibana application to set the base-size that
|
||||
* flexed children should keep. Only works when paired with root styles applied
|
||||
* by core service from new platform
|
||||
*/
|
||||
// SASSTODO: Naming here is too embedded and high up that changing them could cause major breaks
|
||||
#kibana-body {
|
||||
overflow-x: hidden;
|
||||
min-height: 100%;
|
||||
|
@ -16,16 +13,16 @@
|
|||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
position: absolute;
|
||||
left: @global-nav-closed-width;
|
||||
left: $kbnGlobalNavClosedWidth;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 5;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
background-color: $euiColorEmptyShade;
|
||||
|
||||
/**
|
||||
* 1. Dirty, but we need to override the .is-global-nav-open state
|
||||
* 1. Dirty, but we need to override the .kbnGlobalNav-isOpen state
|
||||
* when we're looking at the log-in screen.
|
||||
*/
|
||||
&.hidden-chrome {
|
46
src/ui/public/chrome/directives/_loading_indicator.scss
Normal file
46
src/ui/public/chrome/directives/_loading_indicator.scss
Normal file
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* 1. Position this loader on top of the content.
|
||||
* 2. Make sure indicator isn't wider than the screen.
|
||||
*/
|
||||
.kbnLoadingIndicator {
|
||||
position: fixed; // 1
|
||||
top: 0; // 1
|
||||
left: 0; // 1
|
||||
right: 0; // 1
|
||||
z-index: $euiZLevel1; // 1
|
||||
overflow: hidden; // 2
|
||||
height: $euiSizeXS / 2;
|
||||
|
||||
&.hidden {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition-delay: 0.25s;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnLoadingIndicator__bar {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
z-index: $euiZLevel1 + 1;
|
||||
visibility: visible;
|
||||
display: block;
|
||||
animation: kbn-animate-loading-indicator 2s linear infinite;
|
||||
background-color: $kbnLoadingIndicatorColor2;
|
||||
background-image: linear-gradient(to right,
|
||||
$kbnLoadingIndicatorColor1 0%,
|
||||
$kbnLoadingIndicatorColor1 50%,
|
||||
$kbnLoadingIndicatorColor2 50%,
|
||||
$kbnLoadingIndicatorColor2 100%
|
||||
);
|
||||
background-repeat: repeat-x;
|
||||
background-size: $kbnLoadingIndicatorBackgroundSize $kbnLoadingIndicatorBackgroundSize;
|
||||
width: 200%;
|
||||
}
|
||||
|
||||
@keyframes kbn-animate-loading-indicator {
|
||||
from { transform: translateX(0); }
|
||||
to { transform: translateX(-$kbnLoadingIndicatorBackgroundSize); }
|
||||
}
|
70
src/ui/public/chrome/directives/global_nav/_global_nav.scss
Normal file
70
src/ui/public/chrome/directives/global_nav/_global_nav.scss
Normal file
|
@ -0,0 +1,70 @@
|
|||
.kbnGlobalNav {
|
||||
width: $kbnGlobalNavClosedWidth;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
background-color: $kbnChromeGlobalNavBackground;
|
||||
overflow: hidden;
|
||||
|
||||
&.kbnGlobalNav-isOpen {
|
||||
width: $kbnGlobalNavOpenWidth;
|
||||
|
||||
+ .app-wrapper {
|
||||
left: $kbnGlobalNavOpenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnGlobalNav__smallLogoBrand,
|
||||
.kbnGlobalNav__logoBrand {
|
||||
height: $kbnGlobalNavLogoHeight;
|
||||
width: $kbnGlobalNavOpenWidth;
|
||||
list-style-type: none;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Push main apps to the top and bottom buttons to the bottom.
|
||||
* 2. Fill height of global nav, but respect the height of the logo.
|
||||
* 3. Allow user to scroll to see clipped nav items when the nav is too short.
|
||||
* 4. Style the scrollbar to look good in Chrome and Safari.
|
||||
*/
|
||||
.kbnGlobalNav__links {
|
||||
@include euiScrollBar; /* 4 */
|
||||
|
||||
display: flex; /* 1 */
|
||||
flex-direction: column; /* 1 */
|
||||
justify-content: space-between; /* 1 */
|
||||
height: calc(100% - #{$kbnGlobalNavLogoHeight}); /* 2 */
|
||||
overflow-x: hidden; /* 3 */
|
||||
overflow-y: auto; /* 3 */
|
||||
|
||||
&::-webkit-scrollbar { /* 4 */
|
||||
@include size($euiSizeS);
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb { /* 4 */
|
||||
background-color: tint($kbnChromeGlobalNavBackground, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent the top and bottom links from collapsing when the browser window is too short.
|
||||
* This problem is specific to Safari.
|
||||
*/
|
||||
.kbnGlobalNav__linksSection {
|
||||
flex: 0 0 auto; /* 1 */
|
||||
}
|
||||
|
||||
.kbnGlobalNav__logoLink {
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
background-color: darken($euiColorPrimary, 15%);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $euiColorPrimary;
|
||||
}
|
||||
}
|
2
src/ui/public/chrome/directives/global_nav/_index.scss
Normal file
2
src/ui/public/chrome/directives/global_nav/_index.scss
Normal file
|
@ -0,0 +1,2 @@
|
|||
@import './global_nav';
|
||||
@import './global_nav_link/index';
|
|
@ -1,14 +1,13 @@
|
|||
<nav
|
||||
class="global-nav"
|
||||
ng-class="{'is-global-nav-open': isGlobalNavOpen}"
|
||||
class="kbnGlobalNav"
|
||||
ng-class="{'kbnGlobalNav-isOpen': isGlobalNavOpen}"
|
||||
ng-show="isVisible"
|
||||
data-test-subj="globalNav"
|
||||
>
|
||||
|
||||
<!-- Logo -->
|
||||
<div class="global-nav__logo">
|
||||
<div class="kbnGlobalNav__logo">
|
||||
<a
|
||||
class="global_nav_logo"
|
||||
class="kbnGlobalNav__logoLink"
|
||||
ng-class="{ active: isHomeActive() }"
|
||||
href="{{ getHref('/app/kibana#/home') }}"
|
||||
data-test-subj="kibanaLogo"
|
||||
|
@ -17,37 +16,33 @@
|
|||
<li
|
||||
ng-if="!logoBrand && !smallLogoBrand"
|
||||
aria-label="{{ appTitle }} home"
|
||||
class="logo kibana"
|
||||
class="kbnGlobalNav__logoBrand kibana"
|
||||
></li>
|
||||
|
||||
<li
|
||||
ng-if="logoBrand"
|
||||
ng-style="{ 'background': logoBrand }"
|
||||
aria-label="{{ appTitle }} home"
|
||||
class="logo hidden-sm"
|
||||
class="kbnGlobalNav__logoBrand hidden-sm"
|
||||
></li>
|
||||
|
||||
<li
|
||||
ng-if="smallLogoBrand"
|
||||
ng-style="{ 'background': smallLogoBrand }"
|
||||
aria-label="{{ appTitle }} home"
|
||||
class="logo-small visible-sm hidden-xs"
|
||||
class="kbnGlobalNav__smallLogoBrand visible-sm hidden-xs"
|
||||
></li>
|
||||
</ul>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Links -->
|
||||
<div class="global-nav__links">
|
||||
<div class="kbnGlobalNav__links">
|
||||
<!-- Main apps -->
|
||||
<div class="global-nav__links-section">
|
||||
<app-switcher
|
||||
chrome="chrome"
|
||||
></app-switcher>
|
||||
</div>
|
||||
<div class="kbnGlobalNav__linksSection"><app-switcher chrome="chrome"></app-switcher></div>
|
||||
|
||||
<!-- Bottom button -->
|
||||
<div class="global-nav__links-section">
|
||||
<div class="kbnGlobalNav__linksSection">
|
||||
<div class="chrome-actions" kbn-chrome-append-nav-controls></div>
|
||||
|
||||
<!-- Open/close sidebar -->
|
||||
|
@ -60,5 +55,4 @@
|
|||
></global-nav-link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
import './app_switcher';
|
||||
import './global_nav_link';
|
||||
import 'ui/i18n';
|
||||
|
@ -46,13 +45,21 @@ module.directive('globalNav', (globalNavState, chrome, i18n) => {
|
|||
const isOpen = globalNavState.isOpen();
|
||||
scope.isGlobalNavOpen = isOpen;
|
||||
scope.globalNavToggleButton = {
|
||||
classes: isOpen ? 'global-nav-link--close' : undefined,
|
||||
title: isOpen ?
|
||||
i18n('common.ui.chrome.globalNav.navToggleButtonCollapseTitle', { defaultMessage: 'Collapse' })
|
||||
: i18n('common.ui.chrome.globalNav.navToggleButtonExpandTitle', { defaultMessage: 'Expand' }),
|
||||
tooltipContent: isOpen ?
|
||||
i18n('common.ui.chrome.globalNav.navToggleButtonCollapseTooltip', { defaultMessage: 'Collapse side bar' })
|
||||
: i18n('common.ui.chrome.globalNav.navToggleButtonExpandTooltip', { defaultMessage: 'Expand side bar' }),
|
||||
classes: isOpen ? 'kbnGlobalNavLink--close' : undefined,
|
||||
title: isOpen
|
||||
? i18n('common.ui.chrome.globalNav.navToggleButtonCollapseTitle', {
|
||||
defaultMessage: 'Collapse',
|
||||
})
|
||||
: i18n('common.ui.chrome.globalNav.navToggleButtonExpandTitle', {
|
||||
defaultMessage: 'Expand',
|
||||
}),
|
||||
tooltipContent: isOpen
|
||||
? i18n('common.ui.chrome.globalNav.navToggleButtonCollapseTooltip', {
|
||||
defaultMessage: 'Collapse side bar',
|
||||
})
|
||||
: i18n('common.ui.chrome.globalNav.navToggleButtonExpandTooltip', {
|
||||
defaultMessage: 'Expand side bar',
|
||||
}),
|
||||
};
|
||||
|
||||
// Notify visualizations, e.g. the dashboard, that they should re-render.
|
||||
|
@ -77,6 +84,6 @@ module.directive('globalNav', (globalNavState, chrome, i18n) => {
|
|||
scope.isHomeActive = () => {
|
||||
return window.location.hash.indexOf('#/home') === 0;
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,36 +1,7 @@
|
|||
|
||||
@import (reference) "~ui/styles/mixins";
|
||||
@import (reference) "~ui/styles/variables";
|
||||
|
||||
@global-nav-logo-height: 70px;
|
||||
|
||||
.global-nav {
|
||||
width: @global-nav-closed-width;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
z-index: 0;
|
||||
background-color: #005571;
|
||||
overflow: hidden;
|
||||
|
||||
&.is-global-nav-open {
|
||||
width: @global-nav-open-width;
|
||||
|
||||
.app-title {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
+ .app-wrapper {
|
||||
left: @global-nav-open-width;
|
||||
}
|
||||
}
|
||||
|
||||
.logo-small,
|
||||
.logo {
|
||||
height: @global-nav-logo-height;
|
||||
width: @global-nav-open-width;
|
||||
list-style-type: none;
|
||||
// SASSTODO: Move to sass when image paths work
|
||||
.kbnGlobalNav {
|
||||
.kbnGlobalNav__smallLogoBrand,
|
||||
.kbnGlobalNav__logoBrand {
|
||||
&.kibana {
|
||||
background-image: url("~ui/images/kibana.svg");
|
||||
background-position: 10px 14px;
|
||||
|
@ -39,41 +10,3 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Push main apps to the top and bottom buttons to the bottom.
|
||||
* 2. Fill height of global nav, but respect the height of the logo.
|
||||
* 3. Allow user to scroll to see clipped nav items when the nav is too short.
|
||||
* 4. Style the scrollbar to look good in Chrome and Safari.
|
||||
*/
|
||||
.global-nav__links {
|
||||
display: flex; /* 1 */
|
||||
flex-direction: column; /* 1 */
|
||||
justify-content: space-between; /* 1 */
|
||||
height: ~"calc(100% - @{global-nav-logo-height})"; /* 2 */
|
||||
overflow-x: hidden; /* 3 */
|
||||
overflow-y: auto; /* 3 */
|
||||
|
||||
&::-webkit-scrollbar { /* 4 */
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-thumb { /* 4 */
|
||||
background-color: #2f99c1;
|
||||
border: 6px solid transparent;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
&::-webkit-scrollbar-track { /* 4 */
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Prevent the top and bottom links from collapsing when the browser window is too short.
|
||||
* This problem is specific to Safari.
|
||||
*/
|
||||
.global-nav__links-section {
|
||||
flex: 0 0 auto; /* 1 */
|
||||
}
|
||||
|
|
|
@ -60,7 +60,6 @@ describe('globalNavLink directive', () => {
|
|||
}
|
||||
|
||||
describe('interface', () => {
|
||||
|
||||
describe('isActive attribute', () => {
|
||||
it(`doesn't apply the active class when false`, () => {
|
||||
const element = create({
|
||||
|
@ -78,18 +77,18 @@ describe('globalNavLink directive', () => {
|
|||
});
|
||||
|
||||
describe('isDisabled attribute', () => {
|
||||
it(`doesn't apply the is-global-nav-link-disabled class when false`, () => {
|
||||
it(`doesn't apply the kbnGlobalNavLink-isDisabled class when false`, () => {
|
||||
const element = create({
|
||||
isDisabled: false,
|
||||
});
|
||||
expect(element.hasClass('is-global-nav-link-disabled')).to.be(false);
|
||||
expect(element.hasClass('kbnGlobalNavLink-isDisabled')).to.be(false);
|
||||
});
|
||||
|
||||
it('applies the is-global-nav-link-disabled class when true', () => {
|
||||
it('applies the kbnGlobalNavLink-isDisabled class when true', () => {
|
||||
const element = create({
|
||||
isDisabled: true,
|
||||
});
|
||||
expect(element.hasClass('is-global-nav-link-disabled')).to.be(true);
|
||||
expect(element.hasClass('kbnGlobalNavLink-isDisabled')).to.be(true);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
.kbnGlobalNavLink {
|
||||
&:hover {
|
||||
background-color: shade($euiColorPrimary, 15%);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $euiColorPrimary;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnGlobalNavLink {
|
||||
position: relative;
|
||||
width: $kbnGlobalNavClosedWidth;
|
||||
height: $kbnGlobalNavAppIconHeight;
|
||||
line-height: $euiSizeL;
|
||||
|
||||
&.kbnGlobalNavLink-isDisabled {
|
||||
opacity: 0.5;
|
||||
|
||||
.kbnGlobalNavLink__anchor {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
.kbnGlobalNavLink__anchor {
|
||||
color: $euiColorEmptyShade;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kbnGlobalNav-isOpen {
|
||||
.kbnGlobalNavLink {
|
||||
width: $kbnGlobalNavOpenWidth;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnGlobalNavLink__anchor {
|
||||
display: block;
|
||||
height: 100%;
|
||||
color: $euiColorEmptyShade;
|
||||
width: 100%;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.kbnGlobalNavLink__icon {
|
||||
display: inline-block;
|
||||
width: $kbnGlobalNavClosedWidth;
|
||||
height: $kbnGlobalNavAppIconHeight;
|
||||
float: left;
|
||||
text-align: center;
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
/**
|
||||
* This image is used to display the icon.
|
||||
*/
|
||||
.kbnGlobalNavLink__iconImage {
|
||||
height: 18px;
|
||||
margin-top: $euiSizeS;
|
||||
}
|
||||
|
||||
/**
|
||||
* This placeholder text gets shown if there is no specified icon.
|
||||
*/
|
||||
.kbnGlobalNavLink__iconPlaceholder {
|
||||
line-height: $kbnGlobalNavAppIconHeight;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.kbnGlobalNavLink__title {
|
||||
@include euiTextTruncate;
|
||||
display: none;
|
||||
width: $kbnGlobalNavOpenWidth - $kbnGlobalNavClosedWidth - 3px;
|
||||
float: right;
|
||||
font-size: 0.9em;
|
||||
text-align: left;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
line-height: $kbnGlobalNavAppIconHeight;
|
||||
|
||||
.kbnGlobalNav-isOpen & {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnGlobalNavLink--close {
|
||||
/**
|
||||
* 1. Translation accounts for the icon image being slightly off-center.
|
||||
*/
|
||||
.kbnGlobalNavLink__icon {
|
||||
transform: translateX(1px) scaleX(-1); /* 1 */
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
@import './global_nav_link';
|
|
@ -1,37 +1,35 @@
|
|||
<div
|
||||
class="global-nav-link {{classes}}"
|
||||
ng-class="{ active: isActive, 'is-global-nav-link-disabled': isDisabled }"
|
||||
class="kbnGlobalNavLink {{classes}}"
|
||||
ng-class="{ active: isActive, 'kbnGlobalNavLink-isDisabled': isDisabled }"
|
||||
tooltip="{{ tooltipContent }}"
|
||||
tooltip-placement="right"
|
||||
tooltip-popup-delay="0"
|
||||
tooltip-append-to-body="1"
|
||||
>
|
||||
<a
|
||||
class="global-nav-link__anchor"
|
||||
class="kbnGlobalNavLink__anchor"
|
||||
href="{{ getHref() }}"
|
||||
ng-click="onClick({ $event: $event })"
|
||||
data-test-subj="appLink"
|
||||
aria-label="{{::label}}"
|
||||
>
|
||||
<div class="global-nav-link__icon">
|
||||
<div class="kbnGlobalNavLink__icon">
|
||||
<img
|
||||
ng-if="icon"
|
||||
class="global-nav-link__icon-image"
|
||||
class="kbnGlobalNavLink__iconImage"
|
||||
kbn-src="{{ '/' + icon }}"
|
||||
aria-hidden="true"
|
||||
>
|
||||
/>
|
||||
|
||||
<span
|
||||
ng-if="!icon"
|
||||
class="global-nav-link__icon-placeholder"
|
||||
class="kbnGlobalNavLink__iconPlaceholder"
|
||||
data-test-subj="appLinkIconPlaceholder"
|
||||
>
|
||||
{{ label[0] }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="global-nav-link__title">
|
||||
{{ label }}
|
||||
</div>
|
||||
<div class="kbnGlobalNavLink__title">{{ label }}</div>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
|
||||
|
||||
import globalNavLinkTemplate from './global_nav_link.html';
|
||||
import './global_nav_link.less';
|
||||
import { uiModules } from '../../../../modules';
|
||||
|
||||
const module = uiModules.get('kibana');
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
@import (reference) "~ui/styles/variables";
|
||||
|
||||
.global_nav_logo {
|
||||
display: inline-block;
|
||||
|
||||
&:hover {
|
||||
background-color: darken(@globalColorBlue, 15%);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: @globalColorBlue;
|
||||
}
|
||||
}
|
||||
|
||||
.global-nav-link {
|
||||
position: relative;
|
||||
width: @global-nav-closed-width;
|
||||
height: @app-icon-height;
|
||||
line-height: @app-line-height;
|
||||
|
||||
&.is-global-nav-link-disabled {
|
||||
opacity: 0.5;
|
||||
|
||||
.global-nav-link__anchor {
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: darken(@globalColorBlue, 15%);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: @globalColorBlue;
|
||||
|
||||
.global-nav-link__anchor {
|
||||
color: @white;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.is-global-nav-open {
|
||||
.global-nav-link {
|
||||
width: @global-nav-open-width;
|
||||
}
|
||||
}
|
||||
|
||||
.global-nav-link__anchor {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
line-height: inherit;
|
||||
color: @globalColorWhite;
|
||||
|
||||
&:focus, &:hover {
|
||||
color: @globalColorWhite;
|
||||
}
|
||||
}
|
||||
|
||||
.global-nav-link__icon {
|
||||
display: inline-block;
|
||||
width: @global-nav-closed-width;
|
||||
height: @app-icon-height;
|
||||
float: left;
|
||||
text-align: center;
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
/**
|
||||
* This image is used to display the icon.
|
||||
*/
|
||||
.global-nav-link__icon-image {
|
||||
height: 18px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/**
|
||||
* This placeholder text gets shown if there is no specified icon.
|
||||
*/
|
||||
.global-nav-link__icon-placeholder {
|
||||
line-height: @app-icon-height;
|
||||
background-position: center;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.global-nav-link__title {
|
||||
display: none;
|
||||
width: calc(@global-nav-open-width - @global-nav-closed-width - 3px);
|
||||
float: right;
|
||||
font-size: 0.9em;
|
||||
text-align: left;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
line-height: @app-icon-height;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
.is-global-nav-open & {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.global-nav-link--close {
|
||||
/**
|
||||
* 1. Translation accounts for the icon image being slightly off-center.
|
||||
*/
|
||||
.global-nav-link__icon {
|
||||
transform: translateX(1px) scaleX(-1); /* 1 */
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
@import './header_global_nav';
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
import { uiModules } from '../../../modules';
|
||||
import { Header } from './components/header';
|
||||
import './header_global_nav.less';
|
||||
import { chromeHeaderNavControlsRegistry } from 'ui/registry/chrome_header_nav_controls';
|
||||
import { injectI18nProvider } from '@kbn/i18n/react';
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import React from 'react';
|
|||
import ReactDOM from 'react-dom';
|
||||
import $ from 'jquery';
|
||||
|
||||
import './kbn_chrome.less';
|
||||
import { uiModules } from '../../modules';
|
||||
import {
|
||||
getUnhashableStatesProvider,
|
||||
|
|
|
@ -24,17 +24,15 @@ import classNames from 'classnames';
|
|||
import { uiModules } from 'ui/modules';
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
import './loading_indicator.less';
|
||||
|
||||
export class LoadingIndicator extends React.Component {
|
||||
state = {
|
||||
visible: false,
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._unsub = chrome.loadingCount.subscribe((count) => {
|
||||
this._unsub = chrome.loadingCount.subscribe(count => {
|
||||
this.setState({
|
||||
visible: count > 0
|
||||
visible: count > 0,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -45,10 +43,7 @@ export class LoadingIndicator extends React.Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const className = classNames(
|
||||
'loadingIndicator',
|
||||
this.state.visible ? null : 'hidden'
|
||||
);
|
||||
const className = classNames('kbnLoadingIndicator', this.state.visible ? null : 'hidden');
|
||||
|
||||
const testSubj = this.state.visible
|
||||
? 'globalLoadingIndicator'
|
||||
|
@ -56,7 +51,7 @@ export class LoadingIndicator extends React.Component {
|
|||
|
||||
return (
|
||||
<div className={className} data-test-subj={testSubj}>
|
||||
<div className="loadingIndicator__bar essentialAnimation" />
|
||||
<div className="kbnLoadingIndicator__bar essentialAnimation" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
@import "~ui/styles/variables";
|
||||
|
||||
@loadingIndicatorBackgroundSize: 400px;
|
||||
@loadingIndicatorHeight: 2px;
|
||||
@loadingIndicatorColor1: @kibanaPink1;
|
||||
@loadingIndicatorColor2: @kibanaPink2;
|
||||
|
||||
/**
|
||||
* 1. Position this loader on top of the content.
|
||||
* 2. Make sure indicator isn't wider than the screen.
|
||||
*/
|
||||
.loadingIndicator {
|
||||
position: fixed; // 1
|
||||
top: 0; // 1
|
||||
left: 0; // 1
|
||||
right: 0; // 1
|
||||
z-index: 20; // 1
|
||||
overflow: hidden; // 2
|
||||
height: @loadingIndicatorHeight;
|
||||
|
||||
&.hidden {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition-delay: 0.25s;
|
||||
}
|
||||
}
|
||||
|
||||
.loadingIndicator__bar {
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
position: absolute;
|
||||
z-index: 21;
|
||||
visibility: visible;
|
||||
display: block;
|
||||
animation: animate-loading-indicator 2s linear infinite;
|
||||
background-color: @kibanaPink2;
|
||||
background-image: linear-gradient(to right,
|
||||
@loadingIndicatorColor1 0%,
|
||||
@loadingIndicatorColor1 50%,
|
||||
@loadingIndicatorColor2 50%,
|
||||
@loadingIndicatorColor2 100%
|
||||
);
|
||||
background-repeat: repeat-x;
|
||||
background-size: @loadingIndicatorBackgroundSize @loadingIndicatorBackgroundSize;
|
||||
width: 200%;
|
||||
}
|
||||
|
||||
@keyframes animate-loading-indicator {
|
||||
from { transform: translateX(0); }
|
||||
to { transform: translateX(-@loadingIndicatorBackgroundSize); }
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.kbnError--multi-allow-explicit-index {
|
||||
padding: $euiSizeL;
|
||||
}
|
1
src/ui/public/error_allow_explicit_index/_index.scss
Normal file
1
src/ui/public/error_allow_explicit_index/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './error_allow_explicit_index';
|
|
@ -1,18 +1,25 @@
|
|||
<div class="app-container error-multi-allow-explicit-index">
|
||||
<h3>
|
||||
<i aria-hidden="true" class="fa fa-warning text-danger"></i> Oh no!
|
||||
</h3>
|
||||
<div class="app-container kbnError--multi-allow-explicit-index euiText">
|
||||
<h3><icon aria-hidden="true" type="'alert'" color="'danger'"></icon> Oh no!</h3>
|
||||
|
||||
<p>
|
||||
It looks like your Elasticsearch cluster has the <code>rest.action.multi.allow_explicit_index</code> setting set to <code>false</code>, which prevents Kibana from making search requests. We use this ability to send a single request to Elasticsearch that searches multiple indexes so that when there are many panels on a dashboard they will load quickly and uniformly.
|
||||
It looks like your Elasticsearch cluster has the
|
||||
<code>rest.action.multi.allow_explicit_index</code> setting set to <code>false</code>, which
|
||||
prevents Kibana from making search requests. We use this ability to send a single request to
|
||||
Elasticsearch that searches multiple indexes so that when there are many panels on a dashboard
|
||||
they will load quickly and uniformly.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Unfortunately, until this issue is fixed you won't be able to use certain apps in Kibana, like Discover, Visualize and Dashboard.
|
||||
Unfortunately, until this issue is fixed you won't be able to use certain apps in Kibana, like
|
||||
Discover, Visualize and Dashboard.
|
||||
</p>
|
||||
|
||||
<h3>Ok, how do I fix this?</h3>
|
||||
<ol>
|
||||
<li>Remove <code>rest.action.multi.allow_explicit_index: false</code> from your Elasticsearch config file.</li>
|
||||
<li>
|
||||
Remove <code>rest.action.multi.allow_explicit_index: false</code> from your Elasticsearch
|
||||
config file.
|
||||
</li>
|
||||
<li>Restart Elasticsearch.</li>
|
||||
<li>Use the browser's back button to return to what you were doing.</li>
|
||||
</ol>
|
||||
|
|
|
@ -22,7 +22,6 @@ import { get } from 'lodash';
|
|||
import uiRoutes from '../routes';
|
||||
import { KbnUrlProvider } from '../url';
|
||||
|
||||
import './error_allow_explicit_index.less';
|
||||
import template from './error_allow_explicit_index.html';
|
||||
|
||||
uiRoutes
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.error-multi-allow-explicit-index {
|
||||
padding: 25px;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.kbnError--auto-create-index {
|
||||
padding: $euiSizeL;
|
||||
}
|
1
src/ui/public/error_auto_create_index/_index.scss
Normal file
1
src/ui/public/error_auto_create_index/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './error_auto_create_index'
|
|
@ -1,22 +1,21 @@
|
|||
<div class="app-container error-auto-create-index">
|
||||
<h3 class="kuiVerticalRhythm">
|
||||
<i aria-hidden="true" class="fa fa-warning text-danger"></i> Oh no!
|
||||
</h3>
|
||||
<div class="app-container kbnError--auto-create-index euiText">
|
||||
<h3><icon aria-hidden="true" type="'alert'" color="'danger'"></icon> Oh no!</h3>
|
||||
|
||||
<p class="kuiVerticalRhythm">
|
||||
It looks like your Elasticsearch cluster's <code>action.auto_create_index</code> setting is preventing Kibana from automatically creating an index to store saved objects. Kibana uses this Elasticsearch feature because it is the best way to make sure that the saved object index uses the correct mappings/schema, and it allows Kibana to poll Elasticsearch less often.
|
||||
<p>
|
||||
It looks like your Elasticsearch cluster's <code>action.auto_create_index</code> setting is
|
||||
preventing Kibana from automatically creating an index to store saved objects. Kibana uses this
|
||||
Elasticsearch feature because it is the best way to make sure that the saved object index uses
|
||||
the correct mappings/schema, and it allows Kibana to poll Elasticsearch less often.
|
||||
</p>
|
||||
|
||||
<p class="kuiVerticalRhythm">
|
||||
Unfortunately, until this issue is fixed you won't be able to save anything in Kibana.
|
||||
</p>
|
||||
<p>Unfortunately, until this issue is fixed you won't be able to save anything in Kibana.</p>
|
||||
|
||||
<h3 class="kuiVerticalRhythm">
|
||||
Ok, how do I fix this?
|
||||
</h3>
|
||||
<h3>Ok, how do I fix this?</h3>
|
||||
|
||||
<ol class="kuiVerticalRhythm">
|
||||
<li>Remove <code>action.auto_create_index: false</code> from your Elasticsearch configuration file</li>
|
||||
<ol>
|
||||
<li>
|
||||
Remove <code>action.auto_create_index: false</code> from your Elasticsearch configuration file
|
||||
</li>
|
||||
<li>Restart elasticsearch.</li>
|
||||
<li>Use the browser's back button to return to what you were doing.</li>
|
||||
</ol>
|
||||
|
@ -28,14 +27,15 @@
|
|||
aria-label="Info"
|
||||
role="img"
|
||||
></span>
|
||||
<span class="kuiInfoPanelHeader__title">
|
||||
Note:
|
||||
</span>
|
||||
<span class="kuiInfoPanelHeader__title"> Note: </span>
|
||||
</div>
|
||||
|
||||
<div class="kuiInfoPanelBody">
|
||||
<div class="kuiInfoPanelBody__message">
|
||||
The <code>action.auto_create_index</code> can also define a whitelist of patterns where this feature should be enabled. We don't discuss how to use the setting that way here because it requires knowing all of the other plugins/interactions that rely on the feature for the same reasons that Kibana does.
|
||||
The <code>action.auto_create_index</code> can also define a whitelist of patterns where this
|
||||
feature should be enabled. We don't discuss how to use the setting that way here because it
|
||||
requires knowing all of the other plugins/interactions that rely on the feature for the same
|
||||
reasons that Kibana does.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,6 @@ import { get } from 'lodash';
|
|||
|
||||
import uiRoutes from '../routes';
|
||||
|
||||
import './error_auto_create_index.less';
|
||||
import template from './error_auto_create_index.html';
|
||||
|
||||
uiRoutes
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
.error-auto-create-index {
|
||||
padding: 25px;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.kbnError--url-overflow-app {
|
||||
padding: $euiSizeL;
|
||||
}
|
1
src/ui/public/error_url_overflow/_index.scss
Normal file
1
src/ui/public/error_url_overflow/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './error_url_overflow';
|
|
@ -1,19 +1,32 @@
|
|||
<div class="app-container error-url-overflow-app">
|
||||
<h3>
|
||||
<i aria-hidden="true" class="fa fa-warning text-danger"></i> Woah there!
|
||||
</h3>
|
||||
<div class="app-container kbnError--url-overflow-app euiText">
|
||||
<h3><icon aria-hidden="true" type="'alert'" color="'danger'"></icon> Woah there!</h3>
|
||||
<p>
|
||||
That's a big URL you have there. I have some unfortunate news: Your browser doesn't play nice with Kibana's bacon-double-cheese-burger-with-extra-fries sized URL. To keep you from running into problems Kibana limits URLs in your browser to {{controller.limit}} characters for your safety.
|
||||
That's a big URL you have there. I have some unfortunate news: Your browser doesn't play nice
|
||||
with Kibana's bacon-double-cheese-burger-with-extra-fries sized URL. To keep you from running
|
||||
into problems Kibana limits URLs in your browser to {{ controller.limit }} characters for your
|
||||
safety.
|
||||
</p>
|
||||
|
||||
<h3>Ok, how do I fix this?</h3>
|
||||
<p>This usually only happens with big, complex dashboards, so you have some options:</p>
|
||||
<ol>
|
||||
<li>Enable the <code>state:storeInSessionStorage</code> option in the <a href="#/management/kibana/settings">advanced settings</a>. This will prevent the URLs from getting long, but makes them a bit less portable.</li>
|
||||
<li>Remove some stuff from your dashboard. This will reduce the length of the URL and keep IE in a good place.</li>
|
||||
<li>
|
||||
Enable the <code>state:storeInSessionStorage</code> option in the
|
||||
<a href="#/management/kibana/settings">advanced settings</a>. This will prevent the URLs from
|
||||
getting long, but makes them a bit less portable.
|
||||
</li>
|
||||
<li>
|
||||
Remove some stuff from your dashboard. This will reduce the length of the URL and keep IE in a
|
||||
good place.
|
||||
</li>
|
||||
<li>Don't use IE. Every other supported browser we know of doesn't have this limit.</li>
|
||||
</ol>
|
||||
<br>
|
||||
<br>
|
||||
<p><small>Foot note: Party size candy bars are tiny. Party size sub sandwiches are massive. Really makes you think.</small></p>
|
||||
<br />
|
||||
<br />
|
||||
<p>
|
||||
<small
|
||||
>Foot note: Party size candy bars are tiny. Party size sub sandwiches are massive. Really
|
||||
makes you think.</small
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
import uiRoutes from '../routes';
|
||||
import { KbnUrlProvider } from '../url';
|
||||
|
||||
import './error_url_overflow.less';
|
||||
import template from './error_url_overflow.html';
|
||||
import { UrlOverflowServiceProvider } from './url_overflow_service';
|
||||
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
.error-url-overflow-app {
|
||||
padding: 25px;
|
||||
|
||||
pre {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
1
src/ui/public/field_editor/_index.scss
Normal file
1
src/ui/public/field_editor/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './components/field_format_editor/samples/index';
|
|
@ -14,7 +14,7 @@ exports[`FormatEditorSamples should render normally 1`] = `
|
|||
}
|
||||
>
|
||||
<EuiBasicTable
|
||||
className="fieldFormatEditor__samples"
|
||||
className="kbnFieldFormatEditor__samples"
|
||||
columns={
|
||||
Array [
|
||||
Object {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
@import './samples';
|
|
@ -1,4 +1,4 @@
|
|||
.fieldFormatEditor__samples {
|
||||
.kbnFieldFormatEditor__samples {
|
||||
audio {
|
||||
max-width: 100%;
|
||||
}
|
|
@ -20,21 +20,18 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import {
|
||||
EuiBasicTable,
|
||||
EuiFormRow,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import './samples.less';
|
||||
import { EuiBasicTable, EuiFormRow } from '@elastic/eui';
|
||||
|
||||
import { injectI18n, FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
export class FormatEditorSamplesComponent extends PureComponent {
|
||||
static propTypes = {
|
||||
samples: PropTypes.arrayOf(PropTypes.shape({
|
||||
input: PropTypes.any.isRequired,
|
||||
output: PropTypes.any.isRequired,
|
||||
})).isRequired,
|
||||
samples: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
input: PropTypes.any.isRequired,
|
||||
output: PropTypes.any.isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
|
@ -43,15 +40,21 @@ export class FormatEditorSamplesComponent extends PureComponent {
|
|||
const columns = [
|
||||
{
|
||||
field: 'input',
|
||||
name: intl.formatMessage({ id: 'common.ui.fieldEditor.samples.inputHeader', defaultMessage: 'Input' }),
|
||||
render: (input) => {
|
||||
name: intl.formatMessage({
|
||||
id: 'common.ui.fieldEditor.samples.inputHeader',
|
||||
defaultMessage: 'Input',
|
||||
}),
|
||||
render: input => {
|
||||
return typeof input === 'object' ? JSON.stringify(input) : input;
|
||||
},
|
||||
},
|
||||
{
|
||||
field: 'output',
|
||||
name: intl.formatMessage({ id: 'common.ui.fieldEditor.samples.outputHeader', defaultMessage: 'Output' }),
|
||||
render: (output) => {
|
||||
name: intl.formatMessage({
|
||||
id: 'common.ui.fieldEditor.samples.outputHeader',
|
||||
defaultMessage: 'Output',
|
||||
}),
|
||||
render: output => {
|
||||
return (
|
||||
<div
|
||||
/*
|
||||
|
@ -62,16 +65,17 @@ export class FormatEditorSamplesComponent extends PureComponent {
|
|||
/>
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
return samples.length ? (
|
||||
<EuiFormRow
|
||||
label={<FormattedMessage id="common.ui.fieldEditor.samplesHeader" defaultMessage="Samples" />}
|
||||
label={
|
||||
<FormattedMessage id="common.ui.fieldEditor.samplesHeader" defaultMessage="Samples" />
|
||||
}
|
||||
>
|
||||
<EuiBasicTable
|
||||
className="fieldFormatEditor__samples"
|
||||
className="kbnFieldFormatEditor__samples"
|
||||
compressed={true}
|
||||
items={samples}
|
||||
columns={columns}
|
||||
|
|
|
@ -132,10 +132,10 @@ describe('Notifier', function () {
|
|||
it('has css class helper functions', function () {
|
||||
expect(notify('error').getIconClass()).to.equal('fa fa-warning');
|
||||
expect(notify('error').getButtonClass()).to.equal('kuiButton--danger');
|
||||
expect(notify('error').getAlertClassStack()).to.equal('toast-stack alert alert-danger');
|
||||
expect(notify('error').getAlertClass()).to.equal('toast alert alert-danger');
|
||||
expect(notify('error').getButtonGroupClass()).to.equal('toast-controls');
|
||||
expect(notify('error').getToastMessageClass()).to.equal('toast-message');
|
||||
expect(notify('error').getAlertClassStack()).to.equal('kbnToast__stack alert alert-danger');
|
||||
expect(notify('error').getAlertClass()).to.equal('kbnToast alert alert-danger');
|
||||
expect(notify('error').getButtonGroupClass()).to.equal('kbnToast__controls');
|
||||
expect(notify('error').getToastMessageClass()).to.equal('kbnToast__message');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
2
src/ui/public/notify/_index.scss
Normal file
2
src/ui/public/notify/_index.scss
Normal file
|
@ -0,0 +1,2 @@
|
|||
@import './banners/index';
|
||||
@import './partials/index';
|
|
@ -4,16 +4,16 @@ exports[`GlobalBannerList is rendered 1`] = `null`;
|
|||
|
||||
exports[`GlobalBannerList props banners is rendered 1`] = `
|
||||
<div
|
||||
class="globalBanner__list"
|
||||
class="kbnGlobalBannerList"
|
||||
>
|
||||
<div
|
||||
class="globalBanner__item"
|
||||
class="kbnGlobalBannerList__item"
|
||||
data-test-priority="1"
|
||||
>
|
||||
a component
|
||||
</div>
|
||||
<div
|
||||
class="globalBanner__item"
|
||||
class="kbnGlobalBannerList__item"
|
||||
data-test-subj="b"
|
||||
>
|
||||
b good
|
||||
|
|
7
src/ui/public/notify/banners/_global_banner_list.scss
Normal file
7
src/ui/public/notify/banners/_global_banner_list.scss
Normal file
|
@ -0,0 +1,7 @@
|
|||
.kbnGlobalBannerList {
|
||||
padding: $euiSize;
|
||||
}
|
||||
|
||||
.kbnGlobalBannerList__item + .kbnGlobalBannerList__item {
|
||||
margin-top: $euiSize;
|
||||
}
|
1
src/ui/public/notify/banners/_index.scss
Normal file
1
src/ui/public/notify/banners/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './global_banner_list';
|
|
@ -20,8 +20,6 @@
|
|||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import './global_banner_list.less';
|
||||
|
||||
/**
|
||||
* GlobalBannerList is a list of "banners". A banner something that is displayed at the top of Kibana that may or may not disappear.
|
||||
*
|
||||
|
@ -33,7 +31,6 @@ import './global_banner_list.less';
|
|||
* @param {Array} banners The array of banners represented by objects in the form of { id, component }.
|
||||
*/
|
||||
export class GlobalBannerList extends Component {
|
||||
|
||||
static propTypes = {
|
||||
banners: PropTypes.array,
|
||||
subscribe: PropTypes.func,
|
||||
|
@ -57,29 +54,15 @@ export class GlobalBannerList extends Component {
|
|||
}
|
||||
|
||||
const flexBanners = this.props.banners.map(banner => {
|
||||
const {
|
||||
id,
|
||||
component,
|
||||
priority,
|
||||
...rest
|
||||
} = banner;
|
||||
const { id, component, priority, ...rest } = banner;
|
||||
|
||||
return (
|
||||
<div
|
||||
key={id}
|
||||
data-test-priority={priority}
|
||||
className="globalBanner__item"
|
||||
{...rest}
|
||||
>
|
||||
{ component }
|
||||
<div key={id} data-test-priority={priority} className="kbnGlobalBannerList__item" {...rest}>
|
||||
{component}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="globalBanner__list">
|
||||
{flexBanners}
|
||||
</div>
|
||||
);
|
||||
return <div className="kbnGlobalBannerList">{flexBanners}</div>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
.globalBanner__list {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.globalBanner__item + .globalBanner__item {
|
||||
margin-top: 16px;
|
||||
}
|
|
@ -25,10 +25,7 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
const notifs = [];
|
||||
|
||||
const {
|
||||
version,
|
||||
buildNum,
|
||||
} = metadata;
|
||||
const { version, buildNum } = metadata;
|
||||
|
||||
function closeNotif(notif, cb = _.noop, key) {
|
||||
return function () {
|
||||
|
@ -68,13 +65,17 @@ function startNotifTimer(notif, cb) {
|
|||
|
||||
notif.timeRemaining = Math.floor(notif.lifetime / interval);
|
||||
|
||||
notif.timerId = Notifier.config.setInterval(function () {
|
||||
notif.timeRemaining -= 1;
|
||||
notif.timerId = Notifier.config.setInterval(
|
||||
function () {
|
||||
notif.timeRemaining -= 1;
|
||||
|
||||
if (notif.timeRemaining <= 0) {
|
||||
closeNotif(notif, cb, 'ignore')();
|
||||
}
|
||||
}, interval, notif.timeRemaining);
|
||||
if (notif.timeRemaining <= 0) {
|
||||
closeNotif(notif, cb, 'ignore')();
|
||||
}
|
||||
},
|
||||
interval,
|
||||
notif.timeRemaining
|
||||
);
|
||||
|
||||
notif.cancelTimer = timerCanceler(notif, cb);
|
||||
}
|
||||
|
@ -88,7 +89,7 @@ const typeToButtonClassMap = {
|
|||
danger: 'kuiButton--danger', // NOTE: `error` type is internally named as `danger`
|
||||
info: 'kuiButton--primary',
|
||||
};
|
||||
const buttonHierarchyClass = (index) => {
|
||||
const buttonHierarchyClass = index => {
|
||||
if (index === 0) {
|
||||
// first action: primary className
|
||||
return 'kuiButton--primary';
|
||||
|
@ -121,7 +122,7 @@ function add(notif, cb) {
|
|||
getButtonClass() {
|
||||
const buttonTypeClass = typeToButtonClassMap[notif.type];
|
||||
return `${buttonHierarchyClass(index)} ${buttonTypeClass}`;
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -134,11 +135,11 @@ function add(notif, cb) {
|
|||
|
||||
// decorate the notification with helper functions for the template
|
||||
notif.getButtonClass = () => typeToButtonClassMap[notif.type];
|
||||
notif.getAlertClassStack = () => `toast-stack alert ${typeToAlertClassMap[notif.type]}`;
|
||||
notif.getAlertClassStack = () => `kbnToast__stack alert ${typeToAlertClassMap[notif.type]}`;
|
||||
notif.getIconClass = () => `fa fa-${notif.icon}`;
|
||||
notif.getToastMessageClass = () => 'toast-message';
|
||||
notif.getAlertClass = () => `toast alert ${typeToAlertClassMap[notif.type]}`;
|
||||
notif.getButtonGroupClass = () => 'toast-controls';
|
||||
notif.getToastMessageClass = () => 'kbnToast__message';
|
||||
notif.getAlertClass = () => `kbnToast alert ${typeToAlertClassMap[notif.type]}`;
|
||||
notif.getButtonGroupClass = () => 'kbnToast__controls';
|
||||
|
||||
let dup = null;
|
||||
if (notif.content) {
|
||||
|
@ -175,9 +176,7 @@ export function Notifier(opts) {
|
|||
// label type thing to say where notifications came from
|
||||
self.from = opts.location;
|
||||
|
||||
const notificationLevels = [
|
||||
'error',
|
||||
];
|
||||
const notificationLevels = ['error'];
|
||||
|
||||
notificationLevels.forEach(function (m) {
|
||||
self[m] = _.bind(self[m], self);
|
||||
|
@ -189,7 +188,7 @@ Notifier.config = {
|
|||
errorLifetime: 300000,
|
||||
infoLifetime: 5000,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
clearInterval: window.clearInterval,
|
||||
};
|
||||
|
||||
Notifier.applyConfig = function (config) {
|
||||
|
@ -223,5 +222,6 @@ Notifier.prototype.error = function (err, opts, cb) {
|
|||
actions: ['report', 'accept'],
|
||||
stack: formatStack(err)
|
||||
}, _.pick(opts, overridableOptions));
|
||||
|
||||
return add(config, cb);
|
||||
};
|
||||
|
|
|
@ -25,7 +25,6 @@ import { fatalError } from './fatal_error';
|
|||
import { banners } from './banners';
|
||||
import { Notifier } from './notifier';
|
||||
import template from './partials/toaster.html';
|
||||
import './notify.less';
|
||||
import '../filters/markdown';
|
||||
import '../directives/truncated';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
@import "~ui/styles/mixins";
|
||||
|
||||
.toaster-container {
|
||||
visibility: visible;
|
||||
width: 100%;
|
||||
|
||||
.toaster {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Shouldn't look like a button.
|
||||
*/
|
||||
.toaster-countdown {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: 5px 15px;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.toast {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
&:not(:last-child) {
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toast-message {
|
||||
flex: 1 1 auto;
|
||||
.ellipsis();
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
.toast-stack {
|
||||
padding-bottom: 10px;
|
||||
|
||||
pre {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin: 10px 0;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.toast-controls {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.alert-info .badge {
|
||||
background: darken(@alert-info-bg, 25%);
|
||||
}
|
||||
.alert-warning .badge {
|
||||
background: darken(@alert-warning-bg, 25%);
|
||||
}
|
||||
.alert-danger .badge {
|
||||
background: darken(@alert-danger-bg, 25%);
|
||||
}
|
||||
|
||||
.toast-message {
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
// toast message class for banner needs to be display:block because banner does
|
||||
// not have a flex layout, and the styled element could be any kind of element
|
||||
.toast-message-banner {
|
||||
display: block;
|
||||
}
|
1
src/ui/public/notify/partials/_index.scss
Normal file
1
src/ui/public/notify/partials/_index.scss
Normal file
|
@ -0,0 +1 @@
|
|||
@import './toaster';
|
63
src/ui/public/notify/partials/_toaster.scss
Normal file
63
src/ui/public/notify/partials/_toaster.scss
Normal file
|
@ -0,0 +1,63 @@
|
|||
.kbnToaster__container {
|
||||
visibility: visible;
|
||||
width: 100%;
|
||||
|
||||
.kbnToaster {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Shouldn't look like a button.
|
||||
*/
|
||||
.kbnToaster__countdown {
|
||||
appearance: none;
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.alert {
|
||||
padding: $euiSizeXS $euiSize;
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.kbnToast {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
> * {
|
||||
flex: 0 0 auto;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-right: $euiSizeXS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.kbnToast__message {
|
||||
text-overflow: ellipsis;
|
||||
flex: 1 1 auto;
|
||||
line-height: normal;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.kbnToast__stack {
|
||||
padding-bottom: $euiSizeS;
|
||||
|
||||
pre {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
margin: $euiSizeS 0;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.kbnToast__controls {
|
||||
display: flex;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
<div class="toaster-container">
|
||||
<ul class="toaster">
|
||||
<div class="kbnToaster__container">
|
||||
<ul class="kbnToaster">
|
||||
<li ng-repeat="notif in list" kbn-toast notif="notif">
|
||||
<div ng-class="notif.getAlertClass()">
|
||||
|
||||
<span ng-show="notif.count > 1" class="euiBadge euiBadge--default">
|
||||
<span class="euiBadge__content">
|
||||
<span class="euiBadge__text">{{ notif.count }}</span>
|
||||
|
@ -84,14 +83,12 @@
|
|||
class="euiBadge euiBadge--default"
|
||||
type="button"
|
||||
ng-if="notif.isTimed()"
|
||||
class="toaster-countdown"
|
||||
class="kbnToaster__countdown"
|
||||
ng-click="notif.cancelTimer()"
|
||||
title="Stop"
|
||||
>
|
||||
<span class="euiBadge__content">
|
||||
<span>
|
||||
{{notif.timeRemaining}}s
|
||||
</span>
|
||||
<span> {{ notif.timeRemaining }}s </span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
@ -99,7 +96,6 @@
|
|||
<div ng-if="notif.stack && notif.showStack" ng-class="notif.getAlertClassStack()">
|
||||
<pre ng-repeat="stack in notif.stacks" ng-bind="stack"></pre>
|
||||
</div>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -121,6 +121,15 @@
|
|||
.alert-warning { .alert-styles(@alert-warning-bg); }
|
||||
.alert-danger { .alert-styles(@alert-danger-bg); }
|
||||
|
||||
.alert-info .badge {
|
||||
background: darken(@alert-info-bg, 25%);
|
||||
}
|
||||
.alert-warning .badge {
|
||||
background: darken(@alert-warning-bg, 25%);
|
||||
}
|
||||
.alert-danger .badge {
|
||||
background: darken(@alert-danger-bg, 25%);
|
||||
}
|
||||
|
||||
//
|
||||
// Progress bars
|
||||
|
|
|
@ -31,13 +31,13 @@
|
|||
}
|
||||
|
||||
.navbar-inverse {
|
||||
.logo {
|
||||
.kbnGlobalNav__logoBrand {
|
||||
height: @navbar-height;
|
||||
width: 252px;
|
||||
background-color: @navbar-inverse-brand-bg;
|
||||
}
|
||||
|
||||
.logo-small {
|
||||
.kbnGlobalNav__smallLogoBrand {
|
||||
height: @navbar-height;
|
||||
width: 45px;
|
||||
background-color: @navbar-inverse-brand-bg;
|
||||
|
|
|
@ -27,26 +27,23 @@ export default function ({ getService, getPageObjects }) {
|
|||
before(function () {
|
||||
log.debug('check for X-Pack welcome, opt-out, and dismiss it');
|
||||
|
||||
// find class toaster and see if there's any list items in it?
|
||||
return PageObjects.settings.navigateTo()
|
||||
// find class kbnToaster and see if there's any list items in it?
|
||||
return PageObjects.settings
|
||||
.navigateTo()
|
||||
.then(() => {
|
||||
return PageObjects.monitoring.getToasterContents();
|
||||
})
|
||||
.then((contents) => {
|
||||
// Welcome to X-Pack!
|
||||
// Sharing your cluster statistics with us helps us improve. Your data is never shared with anyone. Not interested? Opt out here.
|
||||
// Dismiss
|
||||
.then(contents => {
|
||||
// Welcome to X-Pack!
|
||||
// Sharing your cluster statistics with us helps us improve. Your data is never shared with anyone. Not interested? Opt out here.
|
||||
// Dismiss
|
||||
log.debug('Toast banner contents = ' + contents);
|
||||
if (contents.includes('X-Pack')) {
|
||||
return PageObjects.monitoring.clickOptOut()
|
||||
.then(() => {
|
||||
return PageObjects.monitoring.dismissWelcome();
|
||||
});
|
||||
return PageObjects.monitoring.clickOptOut().then(() => {
|
||||
return PageObjects.monitoring.dismissWelcome();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
const defaultFindTimeout = config.get('timeouts.find');
|
||||
|
||||
class HeaderPage {
|
||||
|
||||
async clickSelector(selector) {
|
||||
log.debug(`clickSelector(${selector})`);
|
||||
await find.clickByCssSelector(selector);
|
||||
|
@ -198,7 +197,7 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
// check if the auto refresh state is active and to pause it
|
||||
async pauseAutoRefresh() {
|
||||
let result = false;
|
||||
if (await this.getAutoRefreshState() === 'active') {
|
||||
if ((await this.getAutoRefreshState()) === 'active') {
|
||||
await testSubjects.click('globalTimepickerAutoRefreshButton');
|
||||
result = true;
|
||||
}
|
||||
|
@ -208,7 +207,7 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
// check if the auto refresh state is inactive and to resume it
|
||||
async resumeAutoRefresh() {
|
||||
let result = false;
|
||||
if (await this.getAutoRefreshState() === 'inactive') {
|
||||
if ((await this.getAutoRefreshState()) === 'inactive') {
|
||||
await testSubjects.click('globalTimepickerAutoRefreshButton');
|
||||
result = true;
|
||||
}
|
||||
|
@ -216,8 +215,10 @@ export function HeaderPageProvider({ getService, getPageObjects }) {
|
|||
}
|
||||
|
||||
async getToastMessage(findTimeout = defaultFindTimeout) {
|
||||
const toastMessage =
|
||||
await find.displayedByCssSelector('kbn-truncated.toast-message', findTimeout);
|
||||
const toastMessage = await find.displayedByCssSelector(
|
||||
'kbn-truncated.kbnToast__message',
|
||||
findTimeout
|
||||
);
|
||||
const messageText = await toastMessage.getVisibleText();
|
||||
log.debug(`getToastMessage: ${messageText}`);
|
||||
return messageText;
|
||||
|
|
|
@ -32,14 +32,13 @@ export function MonitoringPageProvider({ getService }) {
|
|||
}
|
||||
|
||||
async getToasterContents() {
|
||||
const el = await find.byCssSelector('div.toaster-container');
|
||||
const el = await find.byCssSelector('div.kbnToaster__container');
|
||||
return await el.getVisibleText();
|
||||
}
|
||||
|
||||
async clickOptOut() {
|
||||
return find.clickByLinkText('Opt out here');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return new MonitoringPage();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
body.canvas-isFullscreen {
|
||||
// this is a hack that overwrites Kibana's core chrome
|
||||
.global-nav.is-global-nav-open + .app-wrapper,
|
||||
.kbnGlobalNav.kbnGlobalNav-isOpen + .app-wrapper,
|
||||
.app-wrapper {
|
||||
left: 0;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ body.canvas-isFullscreen {
|
|||
}
|
||||
|
||||
// hide all the interface parts
|
||||
nav.global-nav, // K6 global side nav
|
||||
nav.kbnGlobalNav, // K6 global side nav
|
||||
.header-global-wrapper, // K7 global top nav
|
||||
.canvasLayout__stageHeader,
|
||||
.canvasLayout__sidebar,
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
@import 'ui/public/chrome/variables';
|
||||
|
||||
@mixin gphSvgText() {
|
||||
font-family: $euiFontFamily;
|
||||
font-size: $euiSizeS;
|
||||
|
@ -14,11 +16,11 @@
|
|||
.gphGraph__container {
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
width: calc(100% - 53px); /* 1 */
|
||||
width: calc(100% - #{$kbnGlobalNavClosedWidth}); /* 1 */
|
||||
}
|
||||
|
||||
.global-nav.is-global-nav-open + .app-wrapper .gphGraph__container {
|
||||
width: calc(100% - 180px); /* 1 */
|
||||
.kbnGlobalNav.kbnGlobalNav-isOpen + .app-wrapper .gphGraph__container {
|
||||
width: calc(100% - #{$kbnGlobalNavOpenWidth}); /* 1 */
|
||||
}
|
||||
|
||||
.gphGraph {
|
||||
|
@ -49,7 +51,7 @@
|
|||
|
||||
.gphNode__label {
|
||||
@include gphSvgText;
|
||||
cursor:pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.gphNode__label--html {
|
||||
|
|
|
@ -32,7 +32,7 @@ mlChartTooltipService.show = function (contents, target, offset = { x: 0, y: 0 }
|
|||
this.element.html(contents);
|
||||
|
||||
// side bar width
|
||||
const navOffset = $('.global-nav').width();
|
||||
const navOffset = $('.kbnGlobalNav').width();
|
||||
const contentWidth = $('body').width() - navOffset - 10;
|
||||
const tooltipWidth = this.element.width();
|
||||
const scrollTop = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
|
||||
|
|
|
@ -252,6 +252,6 @@ ml-multi-metric-job-chart {
|
|||
|
||||
// hide the default es loading indicator bar as it can't be switched off
|
||||
// for standard es searches using the http header.
|
||||
.loadingIndicator__bar {
|
||||
.kbnLoadingIndicator__bar {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -288,6 +288,6 @@ ml-population-job-chart {
|
|||
|
||||
// hide the default es loading indicator bar as it can't be switched off
|
||||
// for standard es searches using the http header.
|
||||
.loadingIndicator__bar {
|
||||
.kbnLoadingIndicator__bar {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -188,6 +188,6 @@
|
|||
|
||||
// hide the default es loading indicator bar as it can't be switched off
|
||||
// for standard es searches using the http header.
|
||||
.loadingIndicator__bar {
|
||||
.kbnLoadingIndicator__bar {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -205,6 +205,6 @@
|
|||
|
||||
// hide the default es loading indicator bar as it can't be switched off
|
||||
// for standard es searches using the http header.
|
||||
.loadingIndicator__bar {
|
||||
.kbnLoadingIndicator__bar {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
}
|
||||
|
||||
/* hide unusable controls */
|
||||
.global-nav,
|
||||
.kbnGlobalNav,
|
||||
kbn-top-nav,
|
||||
.toaster-container,
|
||||
.kbnToaster__container,
|
||||
filter-bar,
|
||||
::-webkit-scrollbar {
|
||||
display: none !important;
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
}
|
||||
|
||||
/* hide unusable controls */
|
||||
.global-nav,
|
||||
.kbnGlobalNav,
|
||||
kbn-top-nav,
|
||||
.toaster-container,
|
||||
.kbnToaster__container,
|
||||
filter-bar,
|
||||
::-webkit-scrollbar {
|
||||
display: none !important;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
.global-nav-link__icon .spaceNavGraphic {
|
||||
.kbnGlobalNavLink__icon .spaceNavGraphic {
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
|
|
|
@ -10,10 +10,10 @@ import { ButtonProps } from '../types';
|
|||
export class SpacesGlobalNavButton extends Component<ButtonProps> {
|
||||
public render() {
|
||||
return (
|
||||
<div className="global-nav-link">
|
||||
<button className="global-nav-link__anchor" onClick={this.props.toggleSpaceSelector}>
|
||||
<div className="global-nav-link__icon"> {this.props.linkIcon} </div>
|
||||
<div className="global-nav-link__title"> {this.props.linkTitle} </div>
|
||||
<div className="kbnGlobalNavLink">
|
||||
<button className="kbnGlobalNavLink__anchor" onClick={this.props.toggleSpaceSelector}>
|
||||
<span className="kbnGlobalNavLink__icon"> {this.props.linkIcon} </span>
|
||||
<span className="kbnGlobalNavLink__title"> {this.props.linkTitle} </span>
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -123,7 +123,7 @@ export default function ({ getService, getPageObjects }) {
|
|||
const collapseLinkExists = await find.existsByLinkText('Collapse');
|
||||
expect(collapseLinkExists).to.be(true);
|
||||
|
||||
const navLinks = await find.allByCssSelector('.global-nav-link');
|
||||
const navLinks = await find.allByCssSelector('.kbnGlobalNavLink');
|
||||
expect(navLinks.length).to.equal(5);
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue