* Reducing wrapping divs from RenderingService * Applying more styles to .kbnAppWrapper Some being temporary and will need a better solution when introducing the page layout component * Almost fixing tests for rendering service Can’t figure out how to have a optional Observable `Received: "kbnAppWrapper class-name”` * Adding some comments * [Dashboard] Using the APP_WRAPPER_CLASS * fix test & ts types * Fixin a few more tests that were using `.app-wrapper` * Creating docs for new var and cleaning up some selectors * Fixing reporting * Fixing banner position and truncation * Fixed CSS error in loading screen and jump in animation * Fixing selectors in Canvas * Remove unused var * Added `APP_WRAPPER_CLASS` export from `server` and updated reporting to use it * Fix monitoring icon clicks * move APP_WRAPPER_CLASS definition to src/core/common * Fixing Monitoring snapshots and wrapper class * Moved `APP_WRAPPER_CLASS` utils but exported from `public` and `server` * Remove old folder * Fix dashboard test by only showing HR in edit mode Co-authored-by: pgayvallet Co-authored-by: tsullivan
This commit is contained in:
parent
041d6cbbc5
commit
203061bfcb
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [APP\_WRAPPER\_CLASS](./kibana-plugin-core-public.app_wrapper_class.md)
|
||||
|
||||
## APP\_WRAPPER\_CLASS variable
|
||||
|
||||
The class name for top level \*and\* nested application wrappers to ensure proper layout
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
APP_WRAPPER_CLASS = "kbnAppWrapper"
|
||||
```
|
|
@ -138,6 +138,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
|
||||
| Variable | Description |
|
||||
| --- | --- |
|
||||
| [APP\_WRAPPER\_CLASS](./kibana-plugin-core-public.app_wrapper_class.md) | The class name for top level \*and\* nested application wrappers to ensure proper layout |
|
||||
| [URL\_MAX\_LENGTH](./kibana-plugin-core-public.url_max_length.md) | The max URL length allowed by the current browser. Should be used to display warnings to users when query parameters cause URL to exceed this limit. |
|
||||
|
||||
## Type Aliases
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||
|
||||
[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [APP\_WRAPPER\_CLASS](./kibana-plugin-core-server.app_wrapper_class.md)
|
||||
|
||||
## APP\_WRAPPER\_CLASS variable
|
||||
|
||||
The class name for top level \*and\* nested application wrappers to ensure proper layout
|
||||
|
||||
<b>Signature:</b>
|
||||
|
||||
```typescript
|
||||
APP_WRAPPER_CLASS = "kbnAppWrapper"
|
||||
```
|
|
@ -230,6 +230,7 @@ The plugin integrates with the core system via lifecycle events: `setup`<!-- -->
|
|||
|
||||
| Variable | Description |
|
||||
| --- | --- |
|
||||
| [APP\_WRAPPER\_CLASS](./kibana-plugin-core-server.app_wrapper_class.md) | The class name for top level \*and\* nested application wrappers to ensure proper layout |
|
||||
| [kibanaResponseFactory](./kibana-plugin-core-server.kibanaresponsefactory.md) | Set of helpers used to create <code>KibanaResponse</code> to form HTTP response on an incoming request. Should be returned as a result of [RequestHandler](./kibana-plugin-core-server.requesthandler.md) execution. |
|
||||
| [ServiceStatusLevels](./kibana-plugin-core-server.servicestatuslevels.md) | The current "level" of availability of a service. |
|
||||
| [validBodyOutput](./kibana-plugin-core-server.validbodyoutput.md) | The set of valid body.output |
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.header__topBanner {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: $kbnHeaderBannerHeight;
|
||||
width: 100%;
|
||||
z-index: $euiZHeader;
|
||||
|
|
|
@ -199,7 +199,7 @@ describe('#start()', () => {
|
|||
root.innerHTML = '<p>foo bar</p>';
|
||||
await startCore(root);
|
||||
expect(root.innerHTML).toMatchInlineSnapshot(
|
||||
`"<div id=\\"kibana-body\\"></div><div></div><div></div>"`
|
||||
`"<div id=\\"kibana-body\\" data-test-subj=\\"kibanaChrome\\"></div><div></div><div></div>"`
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -176,6 +176,7 @@ export class CoreSystem {
|
|||
|
||||
const coreUiTargetDomElement = document.createElement('div');
|
||||
coreUiTargetDomElement.id = 'kibana-body';
|
||||
coreUiTargetDomElement.dataset.testSubj = 'kibanaChrome';
|
||||
const notificationsTargetDomElement = document.createElement('div');
|
||||
const overlayTargetDomElement = document.createElement('div');
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ export type {
|
|||
DomainDeprecationDetails,
|
||||
} from '../server/types';
|
||||
export type { CoreContext, CoreSystem } from './core_system';
|
||||
export { DEFAULT_APP_CATEGORIES } from '../utils';
|
||||
export { DEFAULT_APP_CATEGORIES, APP_WRAPPER_CLASS } from '../utils';
|
||||
export type {
|
||||
AppCategory,
|
||||
UiSettingsParams,
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
.kbnGlobalBannerList {
|
||||
padding: $euiSize;
|
||||
}
|
||||
|
||||
.kbnGlobalBannerList__item + .kbnGlobalBannerList__item {
|
||||
margin-top: $euiSizeS;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ export interface App<HistoryLocationState = unknown> {
|
|||
updater$?: Observable<AppUpdater>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export const APP_WRAPPER_CLASS = "kbnAppWrapper";
|
||||
|
||||
// @public
|
||||
export interface AppCategory {
|
||||
ariaLabel?: string;
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
@import '../mixins';
|
||||
|
||||
/**
|
||||
* stretch the root element of the Kibana application to set the base-size that
|
||||
* 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;
|
||||
// DO NOT ADD ANY OVERFLOW BEHAVIORS HERE
|
||||
// It will break the sticky navigation
|
||||
min-height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
// Affixes a div to restrict the position of charts tooltip to the visible viewport minus the header
|
||||
#app-fixed-viewport {
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
|
@ -21,26 +25,17 @@
|
|||
left: 0;
|
||||
}
|
||||
|
||||
.app-wrapper {
|
||||
.kbnAppWrapper {
|
||||
// DO NOT ADD ANY OTHER STYLES TO THIS SELECTOR
|
||||
// This a very nested dependency happnening in "all" apps
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
margin: 0 auto;
|
||||
|
||||
@include kibanaFullBodyMinHeight();
|
||||
}
|
||||
|
||||
.app-wrapper-panel {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
flex-direction: column;
|
||||
|
||||
> * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
z-index: 0; // This effectively puts every high z-index inside the scope of this wrapper to it doesn't interfere with the header and/or overlay mask
|
||||
position: relative; // This is temporary for apps that relied on this being present on `.application`
|
||||
}
|
||||
|
||||
// TODO: This is problematic because it doesn't stay in line with EUI:
|
||||
// adapted from euiHeaderAffordForFixed as we need to handle the top banner
|
||||
@mixin kbnAffordForHeader($headerHeight) {
|
||||
padding-top: $headerHeight;
|
||||
|
|
|
@ -6,21 +6,25 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, of } from 'rxjs';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { mount } from 'enzyme';
|
||||
import React from 'react';
|
||||
|
||||
import { AppWrapper, AppContainer } from './app_containers';
|
||||
import { AppWrapper } from './app_containers';
|
||||
|
||||
describe('AppWrapper', () => {
|
||||
it('toggles the `hidden-chrome` class depending on the chrome visibility state', () => {
|
||||
const chromeVisible$ = new BehaviorSubject<boolean>(true);
|
||||
|
||||
const component = mount(<AppWrapper chromeVisible$={chromeVisible$}>app-content</AppWrapper>);
|
||||
const component = mount(
|
||||
<AppWrapper chromeVisible$={chromeVisible$} classes$={of([])}>
|
||||
app-content
|
||||
</AppWrapper>
|
||||
);
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="app-wrapper"
|
||||
class="kbnAppWrapper"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
|
@ -30,7 +34,7 @@ describe('AppWrapper', () => {
|
|||
component.update();
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="app-wrapper hidden-chrome"
|
||||
class="kbnAppWrapper kbnAppWrapper--hiddenChrome"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
|
@ -40,22 +44,25 @@ describe('AppWrapper', () => {
|
|||
component.update();
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="app-wrapper"
|
||||
class="kbnAppWrapper"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('AppContainer', () => {
|
||||
it('adds classes supplied by chrome', () => {
|
||||
const chromeVisible$ = new BehaviorSubject<boolean>(true);
|
||||
const appClasses$ = new BehaviorSubject<string[]>([]);
|
||||
|
||||
const component = mount(<AppContainer classes$={appClasses$}>app-content</AppContainer>);
|
||||
const component = mount(
|
||||
<AppWrapper chromeVisible$={chromeVisible$} classes$={appClasses$}>
|
||||
app-content
|
||||
</AppWrapper>
|
||||
);
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="application"
|
||||
class="kbnAppWrapper"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
|
@ -65,7 +72,7 @@ describe('AppContainer', () => {
|
|||
component.update();
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="application classA classB"
|
||||
class="kbnAppWrapper classA classB"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
|
@ -75,7 +82,7 @@ describe('AppContainer', () => {
|
|||
component.update();
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="application classC"
|
||||
class="kbnAppWrapper classC"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
|
@ -85,7 +92,7 @@ describe('AppContainer', () => {
|
|||
component.update();
|
||||
expect(component.getDOMNode()).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="application"
|
||||
class="kbnAppWrapper"
|
||||
>
|
||||
app-content
|
||||
</div>
|
||||
|
|
|
@ -10,17 +10,23 @@ import React from 'react';
|
|||
import { Observable } from 'rxjs';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import classNames from 'classnames';
|
||||
import { APP_WRAPPER_CLASS } from '../../utils';
|
||||
|
||||
export const AppWrapper: React.FunctionComponent<{
|
||||
chromeVisible$: Observable<boolean>;
|
||||
}> = ({ chromeVisible$, children }) => {
|
||||
const visible = useObservable(chromeVisible$);
|
||||
return <div className={classNames('app-wrapper', { 'hidden-chrome': !visible })}>{children}</div>;
|
||||
};
|
||||
|
||||
export const AppContainer: React.FunctionComponent<{
|
||||
classes$: Observable<string[]>;
|
||||
}> = ({ classes$, children }) => {
|
||||
const classes = useObservable(classes$);
|
||||
return <div className={classNames('application', classes)}>{children}</div>;
|
||||
}> = ({ chromeVisible$, classes$, children }) => {
|
||||
const visible = useObservable(chromeVisible$);
|
||||
const classes = useObservable(classes$, ['']);
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
APP_WRAPPER_CLASS,
|
||||
{ 'kbnAppWrapper--hiddenChrome': !visible },
|
||||
classes
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,7 @@ import { RenderingService } from './rendering_service';
|
|||
import { applicationServiceMock } from '../application/application_service.mock';
|
||||
import { chromeServiceMock } from '../chrome/chrome_service.mock';
|
||||
import { overlayServiceMock } from '../overlays/overlay_service.mock';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, of } from 'rxjs';
|
||||
|
||||
describe('RenderingService#start', () => {
|
||||
let application: ReturnType<typeof applicationServiceMock.createInternalStartContract>;
|
||||
|
@ -28,6 +28,7 @@ describe('RenderingService#start', () => {
|
|||
|
||||
chrome = chromeServiceMock.createStartContract();
|
||||
chrome.getHeaderComponent.mockReturnValue(<div>Hello chrome!</div>);
|
||||
chrome.getApplicationClasses$.mockReturnValue(of([]));
|
||||
|
||||
overlays = overlayServiceMock.createStartContract();
|
||||
overlays.banners.getComponent.mockReturnValue(<div>I'm a banner!</div>);
|
||||
|
@ -48,54 +49,58 @@ describe('RenderingService#start', () => {
|
|||
|
||||
it('renders application service into provided DOM element', () => {
|
||||
startService();
|
||||
expect(targetDomElement.querySelector('div.application')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="application class-name"
|
||||
>
|
||||
<div>
|
||||
Hello application!
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
expect(targetDomElement.querySelector('div.kbnAppWrapper')).toMatchInlineSnapshot(`
|
||||
<div
|
||||
class="kbnAppWrapper kbnAppWrapper--hiddenChrome"
|
||||
>
|
||||
<div
|
||||
id="app-fixed-viewport"
|
||||
/>
|
||||
<div>
|
||||
Hello application!
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
|
||||
it('adds the `chrome-hidden` class to the AppWrapper when chrome is hidden', () => {
|
||||
it('adds the `kbnAppWrapper--hiddenChrome` class to the AppWrapper when chrome is hidden', () => {
|
||||
const isVisible$ = new BehaviorSubject(true);
|
||||
chrome.getIsVisible$.mockReturnValue(isVisible$);
|
||||
startService();
|
||||
|
||||
const appWrapper = targetDomElement.querySelector('div.app-wrapper')!;
|
||||
expect(appWrapper.className).toEqual('app-wrapper');
|
||||
const appWrapper = targetDomElement.querySelector('div.kbnAppWrapper')!;
|
||||
expect(appWrapper.className).toEqual('kbnAppWrapper');
|
||||
|
||||
act(() => isVisible$.next(false));
|
||||
expect(appWrapper.className).toEqual('app-wrapper hidden-chrome');
|
||||
expect(appWrapper.className).toEqual('kbnAppWrapper kbnAppWrapper--hiddenChrome');
|
||||
|
||||
act(() => isVisible$.next(true));
|
||||
expect(appWrapper.className).toEqual('app-wrapper');
|
||||
expect(appWrapper.className).toEqual('kbnAppWrapper');
|
||||
});
|
||||
|
||||
it('adds the application classes to the AppContainer', () => {
|
||||
it('adds the application classes to the AppWrapper', () => {
|
||||
const applicationClasses$ = new BehaviorSubject<string[]>([]);
|
||||
const isVisible$ = new BehaviorSubject(true);
|
||||
chrome.getIsVisible$.mockReturnValue(isVisible$);
|
||||
chrome.getApplicationClasses$.mockReturnValue(applicationClasses$);
|
||||
startService();
|
||||
|
||||
const appContainer = targetDomElement.querySelector('div.application')!;
|
||||
expect(appContainer.className).toEqual('application');
|
||||
const appContainer = targetDomElement.querySelector('div.kbnAppWrapper')!;
|
||||
expect(appContainer.className).toEqual('kbnAppWrapper');
|
||||
|
||||
act(() => applicationClasses$.next(['classA', 'classB']));
|
||||
expect(appContainer.className).toEqual('application classA classB');
|
||||
expect(appContainer.className).toEqual('kbnAppWrapper classA classB');
|
||||
|
||||
act(() => applicationClasses$.next(['classC']));
|
||||
expect(appContainer.className).toEqual('application classC');
|
||||
expect(appContainer.className).toEqual('kbnAppWrapper classC');
|
||||
|
||||
act(() => applicationClasses$.next([]));
|
||||
expect(appContainer.className).toEqual('application');
|
||||
expect(appContainer.className).toEqual('kbnAppWrapper');
|
||||
});
|
||||
|
||||
it('contains wrapper divs', () => {
|
||||
startService();
|
||||
expect(targetDomElement.querySelector('div.app-wrapper')).toBeDefined();
|
||||
expect(targetDomElement.querySelector('div.app-wrapper-pannel')).toBeDefined();
|
||||
expect(targetDomElement.querySelector('div.kbnAppWrapper')).toBeDefined();
|
||||
});
|
||||
|
||||
it('renders the banner UI', () => {
|
||||
|
|
|
@ -14,7 +14,7 @@ import { pairwise, startWith } from 'rxjs/operators';
|
|||
import { InternalChromeStart } from '../chrome';
|
||||
import { InternalApplicationStart } from '../application';
|
||||
import { OverlayStart } from '../overlays';
|
||||
import { AppWrapper, AppContainer } from './app_containers';
|
||||
import { AppWrapper } from './app_containers';
|
||||
|
||||
interface StartDeps {
|
||||
application: InternalApplicationStart;
|
||||
|
@ -48,16 +48,25 @@ export class RenderingService {
|
|||
|
||||
ReactDOM.render(
|
||||
<I18nProvider>
|
||||
<div className="content" data-test-subj="kibanaChrome">
|
||||
<>
|
||||
{/* Fixed headers */}
|
||||
{chromeHeader}
|
||||
<AppWrapper chromeVisible$={chrome.getIsVisible$()}>
|
||||
<div className="app-wrapper-panel">
|
||||
<div id="app-fixed-viewport" />
|
||||
<div id="globalBannerList">{bannerComponent}</div>
|
||||
<AppContainer classes$={chrome.getApplicationClasses$()}>{appComponent}</AppContainer>
|
||||
</div>
|
||||
|
||||
{/* banners$.subscribe() for things like the No data banner */}
|
||||
<div id="globalBannerList">{bannerComponent}</div>
|
||||
|
||||
{/* The App Wrapper outside of the fixed headers that accepts custom class names from apps */}
|
||||
<AppWrapper
|
||||
chromeVisible$={chrome.getIsVisible$()}
|
||||
classes$={chrome.getApplicationClasses$()}
|
||||
>
|
||||
{/* Affixes a div to restrict the position of charts tooltip to the visible viewport minus the header */}
|
||||
<div id="app-fixed-viewport" />
|
||||
|
||||
{/* The actual plugin/app */}
|
||||
{appComponent}
|
||||
</AppWrapper>
|
||||
</div>
|
||||
</>
|
||||
</I18nProvider>,
|
||||
targetDomElement
|
||||
);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
// In order to override the TM (Textmate) theme of Ace/Brace, everywhere,
|
||||
// it is being scoped by a known outer selector
|
||||
.application {
|
||||
.kbnBody {
|
||||
.ace-tm {
|
||||
$aceBackground: tintOrShade($euiColorLightShade, 50%, 0);
|
||||
|
||||
|
|
|
@ -5,29 +5,6 @@
|
|||
// Grab some nav-specific EUI vars
|
||||
@import '@elastic/eui/src/components/collapsible_nav/variables';
|
||||
|
||||
// Application Layout
|
||||
|
||||
.application,
|
||||
.app-container {
|
||||
> * {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.application {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
flex-basis: auto;
|
||||
flex-direction: column;
|
||||
|
||||
> * {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// We apply brute force focus states to anything not coming from Eui
|
||||
// which has focus states designed at the component level.
|
||||
// You can also use "kbn-resetFocusState" to not apply the default focus
|
||||
|
|
|
@ -397,7 +397,7 @@ export type {
|
|||
} from './deprecations';
|
||||
|
||||
export type { AppCategory } from '../types';
|
||||
export { DEFAULT_APP_CATEGORIES } from '../utils';
|
||||
export { DEFAULT_APP_CATEGORIES, APP_WRAPPER_CLASS } from '../utils';
|
||||
|
||||
export type {
|
||||
SavedObject,
|
||||
|
|
|
@ -89,8 +89,7 @@ const InlineStyles: FC<{ darkMode: boolean }> = ({ darkMode }) => {
|
|||
}
|
||||
|
||||
.kbnWelcomeText {
|
||||
font-family:
|
||||
display: inline-block;
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
font-family: sans-serif;
|
||||
line-height: 40px !important;
|
||||
|
@ -103,7 +102,7 @@ const InlineStyles: FC<{ darkMode: boolean }> = ({ darkMode }) => {
|
|||
text-align: center;
|
||||
line-height: 1;
|
||||
text-align: center;
|
||||
font-faimily: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial !important;
|
||||
font-family: sans-serif;
|
||||
letter-spacing: -.005em;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
|
|
|
@ -175,6 +175,9 @@ import { URL } from 'url';
|
|||
|
||||
export { AddConfigDeprecation }
|
||||
|
||||
// @public
|
||||
export const APP_WRAPPER_CLASS = "kbnAppWrapper";
|
||||
|
||||
// @public
|
||||
export interface AppCategory {
|
||||
ariaLabel?: string;
|
||||
|
|
13
src/core/utils/app_wrapper_class.ts
Normal file
13
src/core/utils/app_wrapper_class.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except
|
||||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The class name for top level *and* nested application wrappers to ensure proper layout
|
||||
* @public
|
||||
*/
|
||||
export const APP_WRAPPER_CLASS = 'kbnAppWrapper';
|
|
@ -7,3 +7,4 @@
|
|||
*/
|
||||
|
||||
export { DEFAULT_APP_CATEGORIES } from './default_app_categories';
|
||||
export { APP_WRAPPER_CLASS } from './app_wrapper_class';
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
.dshAppContainer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.dashboardViewport {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
|
|
|
@ -303,7 +303,7 @@ export function DashboardApp({
|
|||
}, [data.search.session]);
|
||||
|
||||
return (
|
||||
<div className="app-container dshAppContainer">
|
||||
<>
|
||||
{savedDashboard && dashboardStateManager && dashboardContainer && viewMode && (
|
||||
<>
|
||||
<DashboardTopNav
|
||||
|
@ -334,6 +334,6 @@ export function DashboardApp({
|
|||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -620,36 +620,38 @@ export function DashboardTopNav({
|
|||
return (
|
||||
<>
|
||||
<TopNavMenu {...getNavBarProps()} />
|
||||
<EuiHorizontalRule margin="none" />
|
||||
{viewMode !== ViewMode.VIEW ? (
|
||||
<SolutionToolbar isDarkModeEnabled={IS_DARK_THEME}>
|
||||
{{
|
||||
primaryActionButton: (
|
||||
<PrimaryActionButton
|
||||
isDarkModeEnabled={IS_DARK_THEME}
|
||||
label={i18n.translate('dashboard.solutionToolbar.addPanelButtonLabel', {
|
||||
defaultMessage: 'Create visualization',
|
||||
})}
|
||||
onClick={createNewVisType(lensAlias)}
|
||||
iconType="lensApp"
|
||||
data-test-subj="dashboardAddNewPanelButton"
|
||||
/>
|
||||
),
|
||||
quickButtonGroup: <QuickButtonGroup buttons={quickButtons} />,
|
||||
addFromLibraryButton: (
|
||||
<AddFromLibraryButton
|
||||
onClick={addFromLibrary}
|
||||
data-test-subj="dashboardAddPanelButton"
|
||||
/>
|
||||
),
|
||||
extraButtons: [
|
||||
<EditorMenu
|
||||
createNewVisType={createNewVisType}
|
||||
dashboardContainer={dashboardContainer}
|
||||
/>,
|
||||
],
|
||||
}}
|
||||
</SolutionToolbar>
|
||||
<>
|
||||
<EuiHorizontalRule margin="none" />
|
||||
<SolutionToolbar isDarkModeEnabled={IS_DARK_THEME}>
|
||||
{{
|
||||
primaryActionButton: (
|
||||
<PrimaryActionButton
|
||||
isDarkModeEnabled={IS_DARK_THEME}
|
||||
label={i18n.translate('dashboard.solutionToolbar.addPanelButtonLabel', {
|
||||
defaultMessage: 'Create visualization',
|
||||
})}
|
||||
onClick={createNewVisType(lensAlias)}
|
||||
iconType="lensApp"
|
||||
data-test-subj="dashboardAddNewPanelButton"
|
||||
/>
|
||||
),
|
||||
quickButtonGroup: <QuickButtonGroup buttons={quickButtons} />,
|
||||
addFromLibraryButton: (
|
||||
<AddFromLibraryButton
|
||||
onClick={addFromLibrary}
|
||||
data-test-subj="dashboardAddPanelButton"
|
||||
/>
|
||||
),
|
||||
extraButtons: [
|
||||
<EditorMenu
|
||||
createNewVisType={createNewVisType}
|
||||
dashboardContainer={dashboardContainer}
|
||||
/>,
|
||||
],
|
||||
}}
|
||||
</SolutionToolbar>
|
||||
</>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -12,6 +12,7 @@ import { filter, map } from 'rxjs/operators';
|
|||
|
||||
import { Start as InspectorStartContract } from 'src/plugins/inspector/public';
|
||||
import { UrlForwardingSetup, UrlForwardingStart } from 'src/plugins/url_forwarding/public';
|
||||
import { APP_WRAPPER_CLASS } from '../../../core/public';
|
||||
import {
|
||||
App,
|
||||
Plugin,
|
||||
|
@ -292,7 +293,7 @@ export class DashboardPlugin
|
|||
category: DEFAULT_APP_CATEGORIES.kibana,
|
||||
mount: async (params: AppMountParameters) => {
|
||||
this.currentHistory = params.history;
|
||||
params.element.classList.add('dshAppContainer');
|
||||
params.element.classList.add(APP_WRAPPER_CLASS);
|
||||
const { mountApp } = await import('./application/dashboard_router');
|
||||
appMounted();
|
||||
return mountApp({
|
||||
|
|
|
@ -25,7 +25,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
|
|||
expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false);
|
||||
|
||||
const getAppWrapperHeight = async () => {
|
||||
const wrapper = await find.byClassName('app-wrapper');
|
||||
const wrapper = await find.byClassName('kbnAppWrapper');
|
||||
return (await wrapper.getSize()).height;
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export const Banner: FC<BannerProps> = ({ bannerConfig }) => {
|
|||
color: textColor,
|
||||
}}
|
||||
>
|
||||
<div data-test-subj="bannerInnerWrapper">
|
||||
<div className="eui-textTruncate" data-test-subj="bannerInnerWrapper">
|
||||
<Markdown markdown={textContent} openLinksInNewTab={true} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,10 +5,6 @@ body.canvas-isFullscreen {
|
|||
padding-top: 0;
|
||||
}
|
||||
|
||||
.headerWrapper ~ .app-wrapper {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
// following rule is for docked navigation
|
||||
&.euiBody--collapsibleNavIsDocked {
|
||||
padding-left: 0 !important; // sass-lint:disable-line no-important
|
||||
|
|
|
@ -86,7 +86,7 @@ export class Popover extends Component<Props, State> {
|
|||
return button(handleClick);
|
||||
};
|
||||
|
||||
const appWrapper = document.querySelector('.app-wrapper');
|
||||
const appWrapper = document.querySelector('.kbnAppWrapper');
|
||||
const EuiPopoverAny = (EuiPopover as any) as React.FC<any>;
|
||||
|
||||
return (
|
||||
|
|
|
@ -10,10 +10,10 @@ import { uiRoutes } from './helpers/routes';
|
|||
import { Legacy } from '../legacy_shims';
|
||||
import { configureAppAngularModule } from '../../../../../src/plugins/kibana_legacy/public';
|
||||
import { localAppModule, appModuleName } from './app_modules';
|
||||
import { APP_WRAPPER_CLASS } from '../../../../../src/core/public';
|
||||
|
||||
import { MonitoringStartPluginDependencies } from '../types';
|
||||
|
||||
const APP_WRAPPER_CLASS = 'monApplicationWrapper';
|
||||
export class AngularApp {
|
||||
private injector?: angular.auto.IInjectorService;
|
||||
|
||||
|
|
|
@ -31,13 +31,19 @@ exports[`Node Listing Metric Cell should format a non-percentage metric 1`] = `
|
|||
<div
|
||||
class="euiPopover__anchor"
|
||||
>
|
||||
<span
|
||||
data-euiicon-type="arrowDown"
|
||||
<button
|
||||
aria-label="More information about this metric"
|
||||
class="euiButtonIcon euiButtonIcon--text euiButtonIcon--empty euiButtonIcon--xSmall"
|
||||
data-test-subj="monitoringCellIcon-testCell2"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
title="More information about this metric"
|
||||
/>
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="euiButtonIcon__icon"
|
||||
data-euiicon-type="sortDown"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -78,13 +84,19 @@ exports[`Node Listing Metric Cell should format a percentage metric 1`] = `
|
|||
<div
|
||||
class="euiPopover__anchor"
|
||||
>
|
||||
<span
|
||||
data-euiicon-type="arrowDown"
|
||||
<button
|
||||
aria-label="More information about this metric"
|
||||
class="euiButtonIcon euiButtonIcon--text euiButtonIcon--empty euiButtonIcon--xSmall"
|
||||
data-test-subj="monitoringCellIcon-testCell"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
title="More information about this metric"
|
||||
/>
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="euiButtonIcon__icon"
|
||||
data-euiicon-type="sortDown"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -11,10 +11,9 @@ import { formatMetric } from '../../../lib/format_number';
|
|||
import {
|
||||
EuiText,
|
||||
EuiPopover,
|
||||
EuiIcon,
|
||||
EuiButtonIcon,
|
||||
EuiDescriptionList,
|
||||
EuiSpacer,
|
||||
EuiKeyboardAccessible,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
|
@ -40,7 +39,7 @@ const getDirection = (slope) => {
|
|||
|
||||
const getIcon = (slope) => {
|
||||
if (slope || slope === 0) {
|
||||
return slope > 0 ? 'arrowUp' : 'arrowDown';
|
||||
return slope > 0 ? 'sortUp' : 'sortDown';
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
@ -83,17 +82,22 @@ function MetricCell({ isOnline, metric = {}, isPercent, ...props }) {
|
|||
},
|
||||
];
|
||||
|
||||
const iconLabel = i18n.translate(
|
||||
'xpack.monitoring.elasticsearch.node.cells.tooltip.iconLabel',
|
||||
{
|
||||
defaultMessage: 'More information about this metric',
|
||||
}
|
||||
);
|
||||
|
||||
const button = (
|
||||
<EuiKeyboardAccessible>
|
||||
<EuiIcon
|
||||
onClick={onButtonClick}
|
||||
type={getIcon(slope)}
|
||||
data-test-subj={`monitoringCellIcon-${props['data-test-subj']}`}
|
||||
title={i18n.translate('xpack.monitoring.elasticsearch.node.cells.tooltip.iconLabel', {
|
||||
defaultMessage: 'More information about this metric',
|
||||
})}
|
||||
/>
|
||||
</EuiKeyboardAccessible>
|
||||
<EuiButtonIcon
|
||||
color="text"
|
||||
onClick={onButtonClick}
|
||||
iconType={getIcon(slope)}
|
||||
data-test-subj={`monitoringCellIcon-${props['data-test-subj']}`}
|
||||
title={iconLabel}
|
||||
aria-label={iconLabel}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
|
|
|
@ -6,9 +6,3 @@
|
|||
// monChart__legend
|
||||
// monChart__legend--small
|
||||
// monChart__legend-isLoading
|
||||
|
||||
.monApplicationWrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
|
|
@ -23,11 +23,6 @@ filter-bar,
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
/* override open/closed positioning of the app wrapper/nav */
|
||||
.app-wrapper {
|
||||
left: 0px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover Tweaks
|
||||
*/
|
||||
|
|
|
@ -23,11 +23,6 @@ filter-bar,
|
|||
display: none !important;
|
||||
}
|
||||
|
||||
/* override open/closed positioning of the app wrapper/nav */
|
||||
.app-wrapper {
|
||||
left: 0px !important;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover Tweaks
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export const DEFAULT_PAGELOAD_SELECTOR = '.application';
|
||||
import { APP_WRAPPER_CLASS } from '../../../../../../src/core/server';
|
||||
export const DEFAULT_PAGELOAD_SELECTOR = `.${APP_WRAPPER_CLASS}`;
|
||||
|
||||
export const CONTEXT_GETNUMBEROFITEMS = 'GetNumberOfItems';
|
||||
export const CONTEXT_GETBROWSERDIMENSIONS = 'GetBrowserDimensions';
|
||||
|
|
|
@ -204,7 +204,7 @@ describe('Screenshot Observable Pipeline', () => {
|
|||
expect(mockOpen.mock.calls.length).toBe(2);
|
||||
|
||||
const firstSelector = mockOpen.mock.calls[0][1].waitForSelector;
|
||||
expect(firstSelector).toBe('.application');
|
||||
expect(firstSelector).toBe('.kbnAppWrapper');
|
||||
|
||||
const secondSelector = mockOpen.mock.calls[1][1].waitForSelector;
|
||||
expect(secondSelector).toBe('[data-shared-page="2"]');
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ReportingCore } from '../..';
|
||||
import { APP_WRAPPER_CLASS } from '../../../../../../src/core/server';
|
||||
import { API_DIAGNOSE_URL } from '../../../common/constants';
|
||||
import { omitBlockedHeaders } from '../../export_types/common';
|
||||
import { getAbsoluteUrlFactory } from '../../export_types/common/get_absolute_url';
|
||||
|
@ -47,8 +48,8 @@ export const registerDiagnoseScreenshot = (reporting: ReportingCore, logger: Log
|
|||
height: 2024,
|
||||
},
|
||||
selectors: {
|
||||
screenshot: '.application',
|
||||
renderComplete: '.application',
|
||||
screenshot: `.${APP_WRAPPER_CLASS}`,
|
||||
renderComplete: `.${APP_WRAPPER_CLASS}`,
|
||||
itemsCountAttribute: 'data-test-subj="kibanaChrome"',
|
||||
timefilterDurationAttribute: 'data-test-subj="kibanaChrome"',
|
||||
},
|
||||
|
|
|
@ -32,7 +32,7 @@ export const AppGlobalStyle = createGlobalStyle<{ theme: { eui: { euiColorPrimar
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
div.app-wrapper {
|
||||
div.kbnAppWrapper {
|
||||
background-color: rgba(0,0,0,0);
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ const Application = (props: UptimeAppProps) => {
|
|||
<UptimeSettingsContextProvider {...props}>
|
||||
<UptimeThemeContextProvider darkMode={darkMode}>
|
||||
<UptimeStartupPluginsContextProvider {...startPlugins}>
|
||||
<EuiPage className="app-wrapper-panel " data-test-subj="uptimeApp">
|
||||
<EuiPage data-test-subj="uptimeApp">
|
||||
<RedirectAppLinks application={core.application}>
|
||||
<main>
|
||||
<UptimeAlertsFlyoutWrapper />
|
||||
|
|
|
@ -108,7 +108,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider
|
|||
|
||||
if (expectedResult === 'chrome') {
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj="kibanaChrome"] .app-wrapper:not(.hidden-chrome)',
|
||||
'[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
|
||||
20000
|
||||
);
|
||||
log.debug(`Finished login process currentUrl = ${await browser.getCurrentUrl()}`);
|
||||
|
|
|
@ -43,7 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj="kibanaChrome"] .app-wrapper:not(.hidden-chrome)',
|
||||
'[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
|
||||
20000
|
||||
);
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
);
|
||||
|
||||
await find.byCssSelector(
|
||||
'[data-test-subj="kibanaChrome"] .app-wrapper:not(.hidden-chrome)',
|
||||
'[data-test-subj="kibanaChrome"] .kbnAppWrapper:not(.kbnAppWrapper--hiddenChrome)',
|
||||
20000
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue