mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Merge pull request #7595 from cjcenizal/chore/remove-deprecated-tabs-nav
Remove deprecated nav UI and chrome tabs API.
This commit is contained in:
commit
b258ddc464
13 changed files with 16 additions and 631 deletions
|
@ -1,10 +1,6 @@
|
|||
require('ace');
|
||||
|
||||
require('ui/chrome')
|
||||
.setTabs([{
|
||||
id: '',
|
||||
title: 'Sense Tests'
|
||||
}])
|
||||
.setRootTemplate(require('./index.html'))
|
||||
.setRootController(function () {
|
||||
window.QUnit = require('qunit-1.10.0');
|
||||
|
|
|
@ -28,11 +28,6 @@ routes
|
|||
});
|
||||
|
||||
chrome
|
||||
.setTabDefaults({
|
||||
resetWhenActive: true,
|
||||
lastUrlStore: window.sessionStorage,
|
||||
activeIndicatorColor: '#656a76'
|
||||
})
|
||||
.setRootController('kibana', function ($scope, courier, config) {
|
||||
// wait for the application to finish loading
|
||||
$scope.$on('application.load', function () {
|
||||
|
|
|
@ -1,254 +0,0 @@
|
|||
import sinon from 'auto-release-sinon';
|
||||
|
||||
import Tab from '../tab';
|
||||
import expect from 'expect.js';
|
||||
import StubBrowserStorage from './fixtures/stub_browser_storage';
|
||||
|
||||
describe('Chrome Tab', function () {
|
||||
describe('construction', function () {
|
||||
it('accepts id, title, resetWhenActive, trackLastUrl, activeIndicatorColor, baseUrl', function () {
|
||||
const tab = new Tab({
|
||||
id: 'foo',
|
||||
title: 'Foo App',
|
||||
resetWhenActive: false,
|
||||
activeIndicatorColor: true,
|
||||
baseUrl: 'proto:host.domain:999'
|
||||
});
|
||||
|
||||
expect(tab.id).to.equal('foo');
|
||||
expect(tab.title).to.equal('Foo App');
|
||||
expect(tab.resetWhenActive).to.equal(false);
|
||||
expect(tab.activeIndicatorColor).to.equal(true);
|
||||
expect(tab.rootUrl).to.equal('proto:host.domain:999/foo');
|
||||
|
||||
const tab2 = new Tab({
|
||||
id: 'bar',
|
||||
title: 'Bar App',
|
||||
resetWhenActive: true,
|
||||
activeIndicatorColor: false,
|
||||
baseUrl: 'proto:host.domain:999/sub/#/'
|
||||
});
|
||||
|
||||
expect(tab2.id).to.equal('bar');
|
||||
expect(tab2.title).to.equal('Bar App');
|
||||
expect(tab2.resetWhenActive).to.equal(true);
|
||||
expect(tab2.activeIndicatorColor).to.equal(null);
|
||||
expect(tab2.rootUrl).to.equal('proto:host.domain:999/sub/#/bar');
|
||||
});
|
||||
|
||||
it('starts inactive', function () {
|
||||
const tab = new Tab();
|
||||
expect(tab.active).to.equal(false);
|
||||
});
|
||||
|
||||
it('uses the id to set the rootUrl', function () {
|
||||
const id = 'foo';
|
||||
const tab = new Tab({ id });
|
||||
expect(tab.id).to.equal(id);
|
||||
expect(tab.rootUrl).to.equal(`/${id}`);
|
||||
});
|
||||
|
||||
it('creates a regexp for matching the rootUrl', function () {
|
||||
const tab = new Tab({ id: 'foo' });
|
||||
|
||||
expect('/foo').to.match(tab.rootRegExp);
|
||||
expect('/foo/bar').to.match(tab.rootRegExp);
|
||||
expect('/foo/bar/max').to.match(tab.rootRegExp);
|
||||
expect('/foo?bar=baz').to.match(tab.rootRegExp);
|
||||
expect('/foo/?bar=baz').to.match(tab.rootRegExp);
|
||||
expect('/foo#?bar=baz').to.match(tab.rootRegExp);
|
||||
|
||||
expect('/foobar').to.not.match(tab.rootRegExp);
|
||||
expect('site.com/foo#?bar=baz').to.not.match(tab.rootRegExp);
|
||||
expect('http://site.com/foo#?bar=baz').to.not.match(tab.rootRegExp);
|
||||
});
|
||||
|
||||
it('includes the baseUrl in the rootRegExp if specified', function () {
|
||||
const tab = new Tab({
|
||||
id: 'foo',
|
||||
baseUrl: 'http://spiderman.com/kibana'
|
||||
});
|
||||
|
||||
expect('http://spiderman.com/kibana/foo/bar').to.match(tab.rootRegExp);
|
||||
|
||||
expect('/foo').to.not.match(tab.rootRegExp);
|
||||
expect('https://spiderman.com/kibana/foo/bar').to.not.match(tab.rootRegExp);
|
||||
});
|
||||
|
||||
it('accepts a function for activeIndicatorColor', function () {
|
||||
let i = 0;
|
||||
const tab = new Tab({
|
||||
activeIndicatorColor: function () {
|
||||
return i++;
|
||||
}
|
||||
});
|
||||
expect(tab.activeIndicatorColor).to.equal(0);
|
||||
expect(tab.activeIndicatorColor).to.equal(1);
|
||||
expect(tab.activeIndicatorColor).to.equal(2);
|
||||
expect(tab.activeIndicatorColor).to.equal(3);
|
||||
});
|
||||
|
||||
it('discovers the lastUrl', function () {
|
||||
const lastUrlStore = new StubBrowserStorage();
|
||||
const tab = new Tab({ id: 'foo', lastUrlStore });
|
||||
expect(tab.lastUrl).to.not.equal('/foo/bar');
|
||||
|
||||
tab.setLastUrl('/foo/bar');
|
||||
expect(tab.lastUrl).to.equal('/foo/bar');
|
||||
|
||||
const tab2 = new Tab({ id: 'foo', lastUrlStore });
|
||||
expect(tab2.lastUrl).to.equal('/foo/bar');
|
||||
});
|
||||
|
||||
it('logs a warning about last urls that do not match the rootUrl', function () {
|
||||
const lastUrlStore = new StubBrowserStorage();
|
||||
const tab = new Tab({ id: 'foo', baseUrl: '/bar', lastUrlStore });
|
||||
tab.setLastUrl('/bar/foo/1');
|
||||
|
||||
const stub = sinon.stub(console, 'log');
|
||||
const tab2 = new Tab({ id: 'foo', baseUrl: '/baz', lastUrlStore });
|
||||
sinon.assert.calledOnce(stub);
|
||||
expect(tab2.lastUrl).to.equal(null);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#setLastUrl()', function () {
|
||||
it('updates the lastUrl and storage value if passed a lastUrlStore', function () {
|
||||
const lastUrlStore = new StubBrowserStorage();
|
||||
const tab = new Tab({ id: 'foo', lastUrlStore });
|
||||
|
||||
expect(tab.lastUrl).to.not.equal('foo');
|
||||
tab.setLastUrl('foo');
|
||||
expect(tab.lastUrl).to.equal('foo');
|
||||
expect(lastUrlStore.getItem(tab.lastUrlStoreKey)).to.equal('foo');
|
||||
});
|
||||
|
||||
it('only updates lastUrl if no lastUrlStore', function () {
|
||||
const tab = new Tab({ id: 'foo' });
|
||||
|
||||
expect(tab.lastUrl).to.equal(null);
|
||||
tab.setLastUrl('foo');
|
||||
expect(tab.lastUrl).to.equal('foo');
|
||||
|
||||
const tab2 = new Tab({ id: 'foo' });
|
||||
expect(tab2.lastUrl).to.not.equal('foo');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('#href()', function () {
|
||||
it('returns the rootUrl/id be default', function () {
|
||||
const tab = new Tab({ id: 'foo' });
|
||||
expect(tab.href()).to.equal(tab.rootUrl);
|
||||
});
|
||||
|
||||
it('returns the lastUrl if tracking is on', function () {
|
||||
const tab = new Tab({ id: 'foo' });
|
||||
tab.setLastUrl('okay');
|
||||
expect(tab.href()).to.equal('okay');
|
||||
});
|
||||
|
||||
describe('when the tab is active', function () {
|
||||
it('returns the rootUrl when resetWhenActive: true', function () {
|
||||
const id = 'foo';
|
||||
const resetWhenActive = true;
|
||||
const tab = new Tab({ id, resetWhenActive });
|
||||
|
||||
tab.active = true;
|
||||
|
||||
expect(tab.href()).to.not.equal('butt');
|
||||
expect(tab.href()).to.equal(tab.rootUrl);
|
||||
});
|
||||
|
||||
it('or returns null when not', function () {
|
||||
const tab = new Tab({ id: 'foo', resetWhenActive: false });
|
||||
tab.active = true;
|
||||
|
||||
expect(tab.href()).to.not.equal('butt');
|
||||
expect(tab.href()).to.equal(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getLastPath()', function () {
|
||||
it('parses a path out of the lastUrl by removing the baseUrl', function () {
|
||||
const baseUrl = 'http://local:5601/app/visualize#';
|
||||
const tab = new Tab({ baseUrl });
|
||||
|
||||
tab.setLastUrl('http://local:5601/app/visualize#/index');
|
||||
expect(tab.getLastPath()).to.equal('/index');
|
||||
});
|
||||
|
||||
it('logs a warning if the lastUrl does not extend the root url', function () {
|
||||
const baseUrl = 'http://local:5601/app/visualize#';
|
||||
const tab = new Tab({ baseUrl });
|
||||
sinon.stub(console, 'log');
|
||||
|
||||
tab.setLastUrl('http://local:5601/');
|
||||
tab.getLastPath();
|
||||
sinon.assert.calledOnce(console.log);// eslint-disable-line no-console
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateLastUrlGlobalState', function () {
|
||||
const bases = [
|
||||
'http://local:5601',
|
||||
'',
|
||||
'weird.domain/with/subpath?path#',
|
||||
'weird.domain/with/#hashpath',
|
||||
];
|
||||
|
||||
context('with new state sets _g properly', function () {
|
||||
const paths = [
|
||||
[ '/', '/?_g=newState' ],
|
||||
[ '/?first', '/?first=&_g=newState' ],
|
||||
[ '/path?first=1&_g=afterHash', '/path?first=1&_g=newState' ],
|
||||
[ '/?first=1&_g=second', '/?first=1&_g=newState' ],
|
||||
[ '/?g=first', '/?g=first&_g=newState' ],
|
||||
[ '/a?first=1&_g=second', '/a?first=1&_g=newState' ],
|
||||
[ '/?first=1&_g=second', '/?first=1&_g=newState' ],
|
||||
[ '/?first&g=second', '/?first=&g=second&_g=newState' ],
|
||||
];
|
||||
|
||||
bases.forEach(baseUrl => {
|
||||
paths.forEach(([pathFrom, pathTo]) => {
|
||||
const fromUrl = `${baseUrl}${pathFrom}`;
|
||||
const toUrl = `${baseUrl}${pathTo}`;
|
||||
it(`${fromUrl} => ${toUrl}`, function () {
|
||||
const tab = new Tab({ baseUrl });
|
||||
tab.setLastUrl(fromUrl);
|
||||
tab.updateLastUrlGlobalState('newState');
|
||||
expect(tab.getLastUrl()).to.equal(toUrl);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('with new empty state removes _g', function () {
|
||||
const paths = [
|
||||
[ '/', '/' ],
|
||||
[ '/?first', '/?first=' ],
|
||||
[ '/path?first=1&_g=afterHash', '/path?first=1' ],
|
||||
[ '/?first=1&_g=second', '/?first=1' ],
|
||||
[ '/?g=first', '/?g=first' ],
|
||||
[ '/a?first=1&_g=second', '/a?first=1' ],
|
||||
[ '/?first=1&_g=second', '/?first=1' ],
|
||||
[ '/?first&g=second', '/?first=&g=second' ],
|
||||
];
|
||||
|
||||
bases.forEach(baseUrl => {
|
||||
paths.forEach(([pathFrom, pathTo]) => {
|
||||
const fromUrl = `${baseUrl}${pathFrom}`;
|
||||
const toUrl = `${baseUrl}${pathTo}`;
|
||||
it(`${fromUrl}`, function () {
|
||||
const tab = new Tab({ baseUrl });
|
||||
tab.setLastUrl(fromUrl);
|
||||
tab.updateLastUrlGlobalState();
|
||||
expect(tab.getLastUrl()).to.equal(toUrl);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,73 +0,0 @@
|
|||
import expect from 'expect.js';
|
||||
|
||||
import StubBrowserStorage from './fixtures/stub_browser_storage';
|
||||
import TabCollection from '../tab_collection';
|
||||
import Tab from '../tab';
|
||||
import { indexBy, random } from 'lodash';
|
||||
|
||||
describe('Chrome TabCollection', function () {
|
||||
describe('empty state', function () {
|
||||
it('has no tabs', function () {
|
||||
const tabs = new TabCollection();
|
||||
expect(tabs.get()).to.eql([]);
|
||||
});
|
||||
|
||||
it('has no active tab', function () {
|
||||
const tabs = new TabCollection();
|
||||
expect(!tabs.getActive()).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#set()', function () {
|
||||
it('consumes an ordered list of Tab specs', function () {
|
||||
const tabs = new TabCollection();
|
||||
tabs.set([
|
||||
{ id: 'foo' },
|
||||
{ id: 'bar' }
|
||||
]);
|
||||
|
||||
const ts = tabs.get();
|
||||
expect(ts.length).to.equal(2);
|
||||
expect(ts[0].id).to.equal('foo');
|
||||
expect(ts[1].id).to.equal('bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#setDefaults()', function () {
|
||||
it('applies the defaults used to create tabs', function () {
|
||||
const tabs = new TabCollection();
|
||||
tabs.setDefaults({ id: 'thing' });
|
||||
tabs.set([ {} ]);
|
||||
|
||||
expect(tabs.get()[0].id).to.equal('thing');
|
||||
});
|
||||
|
||||
it('recreates existing tabs with new defaults', function () {
|
||||
const tabs = new TabCollection();
|
||||
tabs.set([ {} ]);
|
||||
expect(!tabs.get()[0].id).to.equal(true);
|
||||
|
||||
tabs.setDefaults({ id: 'thing' });
|
||||
expect(tabs.get()[0].id).to.equal('thing');
|
||||
});
|
||||
});
|
||||
|
||||
describe('#consumeRouteUpdate()', function () {
|
||||
it('updates the active tab', function () {
|
||||
const store = new StubBrowserStorage();
|
||||
const baseUrl = `http://localhost:${random(1000, 9999)}`;
|
||||
const tabs = new TabCollection({ store, defaults: { baseUrl } });
|
||||
tabs.set([
|
||||
{ id: 'a' },
|
||||
{ id: 'b' }
|
||||
]);
|
||||
|
||||
tabs.consumeRouteUpdate(`${baseUrl}/a`);
|
||||
const {a, b} = indexBy(tabs.get(), 'id');
|
||||
expect(a.active).to.equal(true);
|
||||
expect(b.active).to.equal(false);
|
||||
expect(tabs.getActive()).to.equal(a);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -101,19 +101,13 @@ export default function (chrome, internals) {
|
|||
const { appId, globalState: newGlobalState } = decodeKibanaUrl(url);
|
||||
|
||||
for (const link of internals.nav) {
|
||||
const matchingTab = find(internals.tabs, { rootUrl: link.url });
|
||||
|
||||
link.active = startsWith(url, link.url);
|
||||
if (link.active) {
|
||||
setLastUrl(link, url);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (matchingTab) {
|
||||
setLastUrl(link, matchingTab.getLastUrl());
|
||||
} else {
|
||||
refreshLastUrl(link);
|
||||
}
|
||||
refreshLastUrl(link);
|
||||
|
||||
if (newGlobalState) {
|
||||
injectNewGlobalState(link, appId, newGlobalState);
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
import _ from 'lodash';
|
||||
import TabCollection from '../tab_collection';
|
||||
|
||||
module.exports = function (chrome, internals) {
|
||||
|
||||
internals.tabs = new TabCollection({
|
||||
defaults: {
|
||||
baseUrl: `${chrome.getAppUrl()}#/`
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* ui/chrome tabs API
|
||||
*
|
||||
* The navbar at the top of the page can be assigned links which will
|
||||
* pile up on the left. Each of these links has several properties that define
|
||||
* how it is rendered, how it looks when it's "active" and what happens when
|
||||
* it's clicked.
|
||||
*
|
||||
* To define a set of tabs, pass setTabs an array of TabSpec objects,
|
||||
* which are just plain objects with the following properties:
|
||||
*
|
||||
* id {string}
|
||||
* a unique value for this tab, should match the first path segment of
|
||||
* routes that are supposed to belong to this tab and is matched against the route
|
||||
* everytime it changes. When clicking the tab for the first time the user will be
|
||||
* sent to the '/${tab.id}' url which you can use to redirect to another url if needed
|
||||
*
|
||||
* title {string}
|
||||
* the text the tab should show
|
||||
*
|
||||
* resetWhenActive {boolean}
|
||||
* when the the tab is considered active, should clicking it
|
||||
* cause a redirect to just the id?
|
||||
*
|
||||
* trackLastUrl {boolean}
|
||||
* When this tab is active, should the current path be tracked
|
||||
* and persisted to session storage, then used as the tabs href attribute when the user navigates
|
||||
* away from the tab?
|
||||
*
|
||||
* activeIndicatorColor {string}
|
||||
* css color string that will be used to style the active
|
||||
* indicator applied to tabs which are currently active.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {TabSpec[]} tabSpecs
|
||||
* @return {chrome}
|
||||
*/
|
||||
chrome.setTabs = function (tabSpecs) {
|
||||
internals.tabs.set(tabSpecs);
|
||||
return chrome;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} defaults - defaults used for each tab
|
||||
* @return {chrome}
|
||||
*/
|
||||
chrome.setTabDefaults = function (defaults) {
|
||||
internals.tabs.setDefaults(defaults);
|
||||
return chrome;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {Tab[]}
|
||||
*/
|
||||
chrome.getTabs = function () {
|
||||
return internals.tabs.get();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {Tab}
|
||||
*/
|
||||
chrome.getActiveTab = function () {
|
||||
return internals.tabs.getActive();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {any} def - the default value if there isn't any active tab
|
||||
* @return {any}
|
||||
*/
|
||||
chrome.getActiveTabTitle = activeGetter('title');
|
||||
|
||||
// create a getter for properties of the active tab
|
||||
function activeGetter(prop) {
|
||||
return function (def) {
|
||||
let active = chrome.getActiveTab();
|
||||
return !active ? def : active[prop];
|
||||
};
|
||||
}
|
||||
|
||||
};
|
|
@ -1,71 +1,45 @@
|
|||
<div class="content" chrome-context >
|
||||
<!-- TODO: These config dropdowns shouldn't be hard coded -->
|
||||
<nav class="app-links-wrapper" ng-show="chrome.getVisible()">
|
||||
|
||||
<li
|
||||
ng-if="!chrome.getBrand('logo') && !chrome.getBrand('smallLogo')"
|
||||
ng-if="!chrome.getBrand('logo') && !chrome.getBrand('smallLogo')"
|
||||
aria-label="{{ chrome.getAppTitle() }} Logo"
|
||||
class="logo kibana"
|
||||
></li>
|
||||
></li>
|
||||
|
||||
<li
|
||||
ng-if="chrome.getBrand('logo')"
|
||||
ng-style="{ 'background': chrome.getBrand('logo') }"
|
||||
aria-label="{{ chrome.getAppTitle() }} Logo"
|
||||
class="logo hidden-sm"
|
||||
></li>
|
||||
></li>
|
||||
|
||||
<li
|
||||
ng-if="chrome.getBrand('smallLogo')"
|
||||
ng-style="{ 'background': chrome.getBrand('smallLogo') }"
|
||||
aria-label="{{ chrome.getAppTitle() }} Logo"
|
||||
class="logo-small visible-sm hidden-xs"
|
||||
></li>
|
||||
></li>
|
||||
|
||||
<app-switcher>
|
||||
</app-switcher>
|
||||
|
||||
<div class="bottom-apps">
|
||||
<div class="chrome-actions app-links" kbn-chrome-append-nav-controls></div>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
<div class="app-wrapper" ng-class="{ 'hidden-chrome': !chrome.getVisible() }">
|
||||
<div class="app-wrapper-panel">
|
||||
<kbn-notifications list="notifList"></kbn-notifications>
|
||||
<nav
|
||||
ng-style="::{ background: chrome.getNavBackground() }"
|
||||
ng-class="{ show: chrome.getTabs().length > 0 }"
|
||||
class="hide navbar navbar-inverse navbar-static-top">
|
||||
|
||||
<!-- Mobile navbar -->
|
||||
<div class="navbar-header">
|
||||
<button ng-click="showCollapsed = !showCollapsed" type="button" class="navbar-toggle">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<span class="visible-xs">
|
||||
<span ng-if="chrome.getBrand('title')" class="navbar-brand">{{ chrome.getBrand('title') }}</span>
|
||||
<span ng-if="chrome.getActiveTabTitle()" class="navbar-brand">{{ chrome.getActiveTabTitle() }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<!-- /Mobile navbar -->
|
||||
|
||||
<!-- Full navbar -->
|
||||
<div collapse="!showCollapsed" class="navbar-collapse" kbn-chrome-append-nav-controls>
|
||||
<div ng-if="chrome.getBrand('title')" class="navbar-brand">{{ chrome.getBrand('title') }}</div>
|
||||
<ul class="nav navbar-nav" role="navigation">
|
||||
|
||||
|
||||
<li ng-repeat="tab in chrome.getTabs()" ng-class="{ active: tab.active }">
|
||||
<a ng-href="{{ tab.href() }}" ng-style="{ 'border-bottom-color': tab.activeIndicatorColor }">
|
||||
{{ tab.title }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /Full navbar -->
|
||||
</nav>
|
||||
<kbn-loading-indicator></kbn-loading-indicator>
|
||||
<div class="application" ng-class="'tab-' + chrome.getFirstPathSegment() + ' ' + chrome.getApplicationClasses()" ng-view></div>
|
||||
<div
|
||||
class="application"
|
||||
ng-class="'tab-' + chrome.getFirstPathSegment() + ' ' + chrome.getApplicationClasses()"
|
||||
ng-view
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,6 +7,7 @@ import metadata from 'ui/metadata';
|
|||
import 'babel/polyfill';
|
||||
import $ from 'jquery';
|
||||
import 'ui/timefilter';
|
||||
import 'ui/notify';
|
||||
import 'ui/private';
|
||||
import 'ui/promises';
|
||||
import 'ui/directives/kbn_src';
|
||||
|
@ -37,7 +38,6 @@ require('./api/xsrf')(chrome, internals);
|
|||
require('./api/nav')(chrome, internals);
|
||||
require('./api/angular')(chrome, internals);
|
||||
require('./api/controls')(chrome, internals);
|
||||
require('./api/tabs')(chrome, internals);
|
||||
require('./api/template')(chrome, internals);
|
||||
require('./api/theme')(chrome, internals);
|
||||
|
||||
|
|
|
@ -33,8 +33,6 @@ export default function (chrome, internals) {
|
|||
// listen for route changes, propogate to tabs
|
||||
const onRouteChange = function () {
|
||||
let { href } = window.location;
|
||||
let persist = chrome.getVisible();
|
||||
internals.tabs.consumeRouteUpdate(href, persist);
|
||||
internals.trackPossibleSubUrl(href);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
import notify from 'ui/notify';
|
||||
import _ from 'lodash';
|
||||
import { escapeRegExp as reEsc } from 'lodash';
|
||||
import { parse, format } from 'url';
|
||||
|
||||
const urlJoin = (a, b) => {
|
||||
if (!b) return a;
|
||||
return `${a}${ a.endsWith('/') ? '' : '/' }${b}`;
|
||||
};
|
||||
|
||||
export default class Tab {
|
||||
constructor(spec = {}) {
|
||||
this.id = spec.id || '';
|
||||
this.title = spec.title || '';
|
||||
this.resetWhenActive = !!spec.resetWhenActive;
|
||||
this.activeIndicatorColor = spec.activeIndicatorColor || null;
|
||||
if (_.isFunction(this.activeIndicatorColor)) {
|
||||
// convert to a getter
|
||||
Object.defineProperty(this, 'activeIndicatorColor', {
|
||||
get: this.activeIndicatorColor
|
||||
});
|
||||
}
|
||||
|
||||
this.active = false;
|
||||
|
||||
this.baseUrl = spec.baseUrl || '/';
|
||||
this.rootUrl = urlJoin(this.baseUrl, this.id);
|
||||
this.rootRegExp = new RegExp(`^${reEsc(this.rootUrl)}(/|$|\\?|#)`);
|
||||
|
||||
this.lastUrlStoreKey = `lastUrl:${this.id}`;
|
||||
this.lastUrlStore = spec.lastUrlStore;
|
||||
|
||||
this.lastUrl = null;
|
||||
if (this.lastUrlStore) {
|
||||
this.lastUrl = this.lastUrlStore.getItem(this.lastUrlStoreKey);
|
||||
if (this.lastUrl && !this.lastUrl.startsWith(this.rootUrl)) {
|
||||
notify.log(`Found invalid lastUrl for tab with root url ${this.rootUrl}: "${this.lastUrl}"`);
|
||||
this.lastUrl = null;
|
||||
this.lastUrlStore.removeItem(this.lastUrlStoreKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
href() {
|
||||
if (this.active) {
|
||||
return this.resetWhenActive ? this.rootUrl : null;
|
||||
}
|
||||
return this.lastUrl || this.rootUrl;
|
||||
}
|
||||
|
||||
updateLastUrlGlobalState(globalState) {
|
||||
let lastPath = this.getLastPath();
|
||||
let { pathname, query, hash } = parse(lastPath, true);
|
||||
|
||||
query = query || {};
|
||||
if (!globalState) delete query._g;
|
||||
else query._g = globalState;
|
||||
|
||||
this.setLastUrl(`${this.rootUrl}${format({ pathname, query, hash })}`);
|
||||
}
|
||||
|
||||
getLastPath() {
|
||||
let { id, rootUrl } = this;
|
||||
let lastUrl = this.getLastUrl();
|
||||
|
||||
if (!lastUrl.startsWith(rootUrl)) {
|
||||
notify.log(`Tab "${id}" has invalid root "${rootUrl}" for last url "${lastUrl}"`);
|
||||
lastUrl = rootUrl;
|
||||
}
|
||||
|
||||
return lastUrl.slice(rootUrl.length);
|
||||
}
|
||||
|
||||
setLastUrl(url) {
|
||||
this.lastUrl = url;
|
||||
if (this.lastUrlStore) this.lastUrlStore.setItem(this.lastUrlStoreKey, this.lastUrl);
|
||||
}
|
||||
|
||||
getLastUrl() {
|
||||
return this.lastUrl || this.rootUrl;
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
import _ from 'lodash';
|
||||
import Tab from 'ui/chrome/tab';
|
||||
import { startsWith, get, set, omit, wrap, pick } from 'lodash';
|
||||
import { parse } from 'url';
|
||||
|
||||
function TabCollection(opts = {}) {
|
||||
let tabs = [];
|
||||
let specs = null;
|
||||
let defaults = opts.defaults || {};
|
||||
let activeTab = null;
|
||||
|
||||
this.set = function (_specs) {
|
||||
specs = _.cloneDeep([].concat(_specs || []));
|
||||
this._rebuildTabs();
|
||||
};
|
||||
|
||||
this.setDefaults = function () {
|
||||
defaults = _.defaults({}, arguments[0], defaults);
|
||||
this._rebuildTabs();
|
||||
};
|
||||
|
||||
this.get = function () {
|
||||
return [].concat(tabs || []);
|
||||
};
|
||||
|
||||
this._rebuildTabs = function () {
|
||||
_.invoke(this.get(), 'destroy');
|
||||
tabs = _.map(specs, function (spec) {
|
||||
return new Tab(_.defaults({}, spec, defaults));
|
||||
});
|
||||
};
|
||||
|
||||
this.getActive = function () {
|
||||
return activeTab;
|
||||
};
|
||||
|
||||
this.consumeRouteUpdate = function (href, persist) {
|
||||
tabs.forEach(function (tab) {
|
||||
tab.active = tab.rootRegExp.test(href);
|
||||
if (tab.active) {
|
||||
activeTab = tab;
|
||||
activeTab.setLastUrl(href);
|
||||
}
|
||||
});
|
||||
|
||||
if (!persist || !activeTab) return;
|
||||
|
||||
let globalState = get(parse(activeTab.getLastPath(), true), 'query._g');
|
||||
tabs.forEach(tab => tab.updateLastUrlGlobalState(globalState));
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = TabCollection;
|
|
@ -61,25 +61,12 @@ describe('docTitle Service', function () {
|
|||
});
|
||||
|
||||
describe('#change', function () {
|
||||
let getActiveTabStub;
|
||||
|
||||
beforeEach(function () {
|
||||
getActiveTabStub = sinon.stub(require('ui/chrome'), 'getActiveTab');
|
||||
});
|
||||
|
||||
it('writes the first param to as the first part of the doc name', function () {
|
||||
expect(document.title).to.be(MAIN_TITLE);
|
||||
docTitle.change('some secondary title');
|
||||
expect(document.title).to.be('some secondary title - ' + MAIN_TITLE);
|
||||
});
|
||||
|
||||
it('includes the title of the active tab if available', function () {
|
||||
expect(document.title).to.be(MAIN_TITLE);
|
||||
getActiveTabStub.returns({ title: 'fancy pants' });
|
||||
docTitle.change('some secondary title');
|
||||
expect(document.title).to.be('some secondary title - fancy pants - ' + MAIN_TITLE);
|
||||
});
|
||||
|
||||
it('will write just the first param if the second param is true', function () {
|
||||
expect(document.title).to.be(MAIN_TITLE);
|
||||
docTitle.change('entire name', true);
|
||||
|
|
|
@ -8,7 +8,6 @@ uiModules.get('kibana')
|
|||
$rootScope.$on('$routeChangeStart', docTitle.reset);
|
||||
$rootScope.$on('$routeChangeError', docTitle.update);
|
||||
$rootScope.$on('$routeChangeSuccess', docTitle.update);
|
||||
$rootScope.$watch(_.bindKey(chrome, 'getActiveTabTitle'), docTitle.update);
|
||||
})
|
||||
.service('docTitle', function ($rootScope) {
|
||||
let baseTitle = document.title;
|
||||
|
@ -20,9 +19,6 @@ uiModules.get('kibana')
|
|||
lastChange = lastChange || [];
|
||||
|
||||
let parts = [lastChange[0]];
|
||||
let activeTabTitle = chrome.getActiveTabTitle();
|
||||
|
||||
if (activeTabTitle) parts.push(activeTabTitle);
|
||||
|
||||
if (!lastChange[1]) parts.push(baseTitle);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue