Skip to content

Commit

Permalink
Consolidate force hiding in chrome, add functional tests
Browse files Browse the repository at this point in the history
  • Loading branch information
eliperelman committed Nov 12, 2019
1 parent 638a804 commit 7d871ce
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/core/public/application/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export interface AppBase {

/**
* Hide the UI chrome when the application is mounted. Defaults to `false`.
* Takes precedence over chrome service visibility settings.
*/
chromeless?: boolean;
}
Expand Down
25 changes: 11 additions & 14 deletions src/core/public/chrome/chrome_service.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import React from 'react';
import { BehaviorSubject, Observable, ReplaySubject, combineLatest, of, merge } from 'rxjs';
import { map, takeUntil } from 'rxjs/operators';
import * as Url from 'url';
import { parse } from 'url';

import { i18n } from '@kbn/i18n';
import { IconType, Breadcrumb as EuiBreadcrumb } from '@elastic/eui';
Expand All @@ -41,11 +41,6 @@ export { ChromeNavControls, ChromeRecentlyAccessed, ChromeDocTitle };

const IS_COLLAPSED_KEY = 'core.chrome.isCollapsed';

function isEmbedParamInHash() {
const { query } = Url.parse(String(window.location.hash).slice(1), true);
return Boolean(query.embed);
}

/** @public */
export interface ChromeBadge {
text: string;
Expand Down Expand Up @@ -94,20 +89,22 @@ export class ChromeService {
injectedMetadata,
notifications,
}: StartDeps): Promise<InternalChromeStart> {
// Start off the chrome service hidden if "embed" is in the hash query string.
const isEmbedded = 'embed' in parse(location.hash.slice(1), true).query;

/**
* These observables allow consumers to toggle the chrome visibility via either:
* 1. Using setIsVisible() to trigger the next chromeHidden$
* 2. Setting `chromeless` when registering an application, which will
* reset the visibility whenever the next application is mounted
* 3. Having embed=true in the query string
* 3. Having "embed" in the query string
*/
const chromeHidden$ = new BehaviorSubject(false);
const forceHidden$ = of(isEmbedParamInHash());
const chromeHidden$ = new BehaviorSubject(isEmbedded);
const appHidden$ = merge(
// Default the app being hidden to the same value as forceHidden$ in case the
// application service has not emitted an app ID yet, since we want to trigger
// Default the app being hidden to the same value initial value as the chrome visibility
// in case the application service has not emitted an app ID yet, since we want to trigger
// combineLatest below regardless of having an application value yet.
forceHidden$,
of(isEmbedded),
application.currentAppId$.pipe(
map(
appId =>
Expand All @@ -117,8 +114,8 @@ export class ChromeService {
)
)
);
const isVisible$ = combineLatest(appHidden$, forceHidden$, chromeHidden$).pipe(
map(([appHidden, forceHidden, chromeHidden]) => !(appHidden || forceHidden || chromeHidden)),
const isVisible$ = combineLatest(appHidden$, chromeHidden$).pipe(
map(([appHidden, chromeHidden]) => !(appHidden || chromeHidden)),
takeUntil(this.stop$)
);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"id": "core_plugin_chromeless",
"version": "0.0.1",
"kibanaVersion": "kibana",
"configPath": ["core_plugin_chromeless"],
"server": false,
"ui": true
}
17 changes: 17 additions & 0 deletions test/plugin_functional/plugins/core_plugin_chromeless/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "core_plugin_chromeless",
"version": "1.0.0",
"main": "target/test/plugin_functional/plugins/core_plugin_chromeless",
"kibana": {
"version": "kibana",
"templateVersion": "1.0.0"
},
"license": "Apache-2.0",
"scripts": {
"kbn": "node ../../../../scripts/kbn.js",
"build": "rm -rf './target' && tsc"
},
"devDependencies": {
"typescript": "3.5.3"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { BrowserRouter as Router, Route } from 'react-router-dom';
import {
EuiPage,
EuiPageBody,
EuiPageContent,
EuiPageContentBody,
EuiPageContentHeader,
EuiPageContentHeaderSection,
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
} from '@elastic/eui';

import { AppMountContext, AppMountParameters } from 'kibana/public';

const Home = () => (
<EuiPageBody data-test-subj="chromelessAppHome">
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>Welcome to Chromeless!</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageContent>
<EuiPageContentHeader>
<EuiPageContentHeaderSection>
<EuiTitle>
<h2>Chromeless home page section title</h2>
</EuiTitle>
</EuiPageContentHeaderSection>
</EuiPageContentHeader>
<EuiPageContentBody>Where did all the chrome go?</EuiPageContentBody>
</EuiPageContent>
</EuiPageBody>
);

const ChromelessApp = ({ basename }: { basename: string; context: AppMountContext }) => (
<Router basename={basename}>
<EuiPage>
<Route path="/" component={Home} />
</EuiPage>
</Router>
);

export const renderApp = (
context: AppMountContext,
{ appBasePath, element }: AppMountParameters
) => {
render(<ChromelessApp basename={appBasePath} context={context} />, element);

return () => unmountComponentAtNode(element);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { PluginInitializer } from 'kibana/public';
import {
CorePluginChromelessPlugin,
CorePluginChromelessPluginSetup,
CorePluginChromelessPluginStart,
} from './plugin';

export const plugin: PluginInitializer<
CorePluginChromelessPluginSetup,
CorePluginChromelessPluginStart
> = () => new CorePluginChromelessPlugin();
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { Plugin, CoreSetup } from 'kibana/public';

export class CorePluginChromelessPlugin
implements Plugin<CorePluginChromelessPluginSetup, CorePluginChromelessPluginStart> {
public setup(core: CoreSetup, deps: {}) {
core.application.register({
id: 'chromeless',
title: 'Chromeless',
chromeless: true,
async mount(context, params) {
const { renderApp } = await import('./application');
return renderApp(context, params);
},
});

return {
getGreeting() {
return 'Hello from Plugin Chromeless!';
},
};
}

public start() {}
public stop() {}
}

export type CorePluginChromelessPluginSetup = ReturnType<CorePluginChromelessPlugin['setup']>;
export type CorePluginChromelessPluginStart = ReturnType<CorePluginChromelessPlugin['start']>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "../../../../tsconfig.json",
"compilerOptions": {
"outDir": "./target",
"skipLibCheck": true
},
"include": [
"index.ts",
"public/**/*.ts",
"public/**/*.tsx",
"../../../../typings/**/*",
],
"exclude": []
}
12 changes: 12 additions & 0 deletions test/plugin_functional/test_suites/core_plugins/applications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,18 @@ export default function({ getService, getPageObjects }: PluginFunctionalProvider
await testSubjects.existOrFail('fooAppPageA');
});

it('navigating to chromeless application hides chrome', async () => {
await appsMenu.clickLink('Chromeless');
await loadingScreenNotShown();
expect(await testSubjects.exists('headerGlobalNav')).to.be(false);
});

it('navigating away from chromeless application shows chrome', async () => {
await browser.goBack();
await loadingScreenNotShown();
expect(await testSubjects.exists('headerGlobalNav')).to.be(true);
});

it('can navigate from NP apps to legacy apps', async () => {
await appsMenu.clickLink('Management');
await loadingScreenShown();
Expand Down

0 comments on commit 7d871ce

Please sign in to comment.