Even moar 'ui/public' LESS to SASS (#26435) (#27221)

also Fixes #26597
This commit is contained in:
Caroline Horn 2018-12-14 12:48:59 -05:00 committed by GitHub
parent a0e3a1f0ef
commit 72f71ef468
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
78 changed files with 608 additions and 611 deletions

View file

@ -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"

View file

@ -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');
});
});
});

View file

@ -0,0 +1 @@
@import './kbn_ui_ace_keyboard_mode';

View file

@ -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;
}
}

View file

@ -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);
}
},
}));

View file

@ -0,0 +1,3 @@
@import './variables';
@import './directives/index';

View 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%);

View file

@ -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>
`;

View file

@ -0,0 +1,5 @@
@import './kbn_chrome';
@import './loading_indicator';
@import './global_nav/index';
@import './header_global_nav/index';

View file

@ -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 {

View 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); }
}

View 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;
}
}

View file

@ -0,0 +1,2 @@
@import './global_nav';
@import './global_nav_link/index';

View file

@ -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>

View file

@ -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;
};
}
},
};
});

View file

@ -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 */
}

View file

@ -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);
});
});

View file

@ -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 */
}
}

View file

@ -0,0 +1 @@
@import './global_nav_link';

View file

@ -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>

View file

@ -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');

View file

@ -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 */
}
}

View file

@ -0,0 +1 @@
@import './header_global_nav';

View file

@ -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';

View file

@ -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,

View file

@ -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>
);
}

View file

@ -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); }
}

View file

@ -0,0 +1,3 @@
.kbnError--multi-allow-explicit-index {
padding: $euiSizeL;
}

View file

@ -0,0 +1 @@
@import './error_allow_explicit_index';

View file

@ -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>

View file

@ -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

View file

@ -1,3 +0,0 @@
.error-multi-allow-explicit-index {
padding: 25px;
}

View file

@ -0,0 +1,3 @@
.kbnError--auto-create-index {
padding: $euiSizeL;
}

View file

@ -0,0 +1 @@
@import './error_auto_create_index'

View file

@ -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>

View file

@ -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

View file

@ -1,3 +0,0 @@
.error-auto-create-index {
padding: 25px;
}

View file

@ -0,0 +1,3 @@
.kbnError--url-overflow-app {
padding: $euiSizeL;
}

View file

@ -0,0 +1 @@
@import './error_url_overflow';

View file

@ -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>

View file

@ -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';

View file

@ -1,7 +0,0 @@
.error-url-overflow-app {
padding: 25px;
pre {
white-space: pre-wrap;
}
}

View file

@ -0,0 +1 @@
@import './components/field_format_editor/samples/index';

View file

@ -14,7 +14,7 @@ exports[`FormatEditorSamples should render normally 1`] = `
}
>
<EuiBasicTable
className="fieldFormatEditor__samples"
className="kbnFieldFormatEditor__samples"
columns={
Array [
Object {

View file

@ -0,0 +1 @@
@import './samples';

View file

@ -1,4 +1,4 @@
.fieldFormatEditor__samples {
.kbnFieldFormatEditor__samples {
audio {
max-width: 100%;
}

View file

@ -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}

View file

@ -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');
});
});

View file

@ -0,0 +1,2 @@
@import './banners/index';
@import './partials/index';

View file

@ -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

View file

@ -0,0 +1,7 @@
.kbnGlobalBannerList {
padding: $euiSize;
}
.kbnGlobalBannerList__item + .kbnGlobalBannerList__item {
margin-top: $euiSize;
}

View file

@ -0,0 +1 @@
@import './global_banner_list';

View file

@ -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>;
}
}

View file

@ -1,7 +0,0 @@
.globalBanner__list {
padding: 16px;
}
.globalBanner__item + .globalBanner__item {
margin-top: 16px;
}

View file

@ -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);
};

View file

@ -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';

View file

@ -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;
}

View file

@ -0,0 +1 @@
@import './toaster';

View 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;
}
}

View file

@ -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>

View file

@ -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

View file

@ -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;

View file

@ -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();
});
}
});
});
});
}

View file

@ -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;

View file

@ -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();

View file

@ -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,

View file

@ -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 {

View file

@ -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);

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -15,9 +15,9 @@
}
/* hide unusable controls */
.global-nav,
.kbnGlobalNav,
kbn-top-nav,
.toaster-container,
.kbnToaster__container,
filter-bar,
::-webkit-scrollbar {
display: none !important;

View file

@ -15,9 +15,9 @@
}
/* hide unusable controls */
.global-nav,
.kbnGlobalNav,
kbn-top-nav,
.toaster-container,
.kbnToaster__container,
filter-bar,
::-webkit-scrollbar {
display: none !important;

View file

@ -1,3 +1,3 @@
.global-nav-link__icon .spaceNavGraphic {
.kbnGlobalNavLink__icon .spaceNavGraphic {
margin-top: 0.5em;
}

View file

@ -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>
);

View file

@ -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);
});