Skip to content

Commit

Permalink
Merge pull request #1942 from spenceralger/doc-title
Browse files Browse the repository at this point in the history
Doc title
  • Loading branch information
rashidkpc committed Nov 19, 2014
2 parents bf009a3 + a0eab7a commit b8a068a
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 14 deletions.
51 changes: 51 additions & 0 deletions src/kibana/components/doc_title/doc_title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
define(function (require) {

require('modules').get('kibana')
.run(function ($rootScope, docTitle) {
// always bind to the route events
$rootScope.$on('$routeChangeStart', docTitle.reset);
$rootScope.$on('$routeChangeError', docTitle.update);
$rootScope.$on('$routeChangeSuccess', docTitle.update);
$rootScope.$watch('activeApp', docTitle.update);
})
.service('docTitle', function ($rootScope) {
var baseTitle = document.title;
var self = this;

var lastChange;

function render() {
lastChange = lastChange || [];

var parts = [lastChange[0]];

if ($rootScope.activeApp) {
parts.push($rootScope.activeApp.name);
}

if (!lastChange[1]) {
parts.push(baseTitle);
}

return parts.filter(Boolean).join(' - ');
}

self.change = function (title, complete) {
lastChange = [title, complete];
self.update();
};

self.reset = function () {
lastChange = null;
};

self.update = function () {
document.title = render();
};
});

// return a "private module" so that it can be used both ways
return function DoctitleProvider(docTitle) {
return docTitle;
};
});
6 changes: 2 additions & 4 deletions src/kibana/controllers/kibana.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ define(function (require) {
require('components/state_management/app_state');
require('components/storage/storage');
require('components/url/url');
require('components/doc_title/doc_title');
require('directives/click_focus');
require('directives/info');
require('directives/tooltip');
Expand Down Expand Up @@ -131,15 +132,12 @@ define(function (require) {

function onRouteChange() {
var route = $location.path().split(/\//);
var app = _.find($scope.apps, {id: route[1]});
var app = $rootScope.activeApp = _.find($scope.apps, {id: route[1]});

if (!app) return;

// Record the last URL w/ state of the app, use for tab.
lastPathFor(app, globalState.removeFromUrl($location.url()));

// Set class of container to application-<appId>
$scope.activeApp = route ? route[1] : null;
}

$rootScope.$on('$routeChangeSuccess', onRouteChange);
Expand Down
6 changes: 3 additions & 3 deletions src/kibana/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
require(['kibana'], function (kibana) { kibana.init(); });
</script>
</head>
<body ng-controller="kibana" ng-class="'application-'+activeApp">
<body ng-controller="kibana" ng-class="'application-' + activeApp.id">
<kbn-notifications list="notifList"></kbn-notifications>
<div class="content" style="display: none;">
<nav ng-hide="appEmbedded" bindonce class="navbar navbar-inverse navbar-static-top">
Expand All @@ -38,7 +38,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="navbar-brand visible-xs">{{activeApp}}
<span class="navbar-brand visible-xs">{{ activeApp.name }}
<span ng-show="httpActive.length" class="spinner">
</span>
</span>
Expand All @@ -48,7 +48,7 @@
<!-- Full navbar -->
<div collapse="!showCollapsed" class="navbar-collapse" id="kibana-primary-navbar">
<ul class="nav navbar-nav">
<li ng-repeat="app in apps.inOrder" ng-class="{active: activeApp == app.id}">
<li ng-repeat="app in apps.inOrder" ng-class="{active: activeApp === app}">
<a ng-href="#{{app.lastPath}}" bo-text="app.name"></a>
</li>
</ul>
Expand Down
2 changes: 1 addition & 1 deletion src/kibana/plugins/dashboard/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div dashboard-app class="app-container dashboard-container">
<nav ng-show="!appEmbedded" class="navbar navbar-default navbar-static-top">
<navbar>
<span class="name">
<span class="name" ng-if="dash.id">
{{dash.title}}
</span>

Expand Down
12 changes: 10 additions & 2 deletions src/kibana/plugins/dashboard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ define(function (require) {

app.directive('dashboardApp', function (Notifier, courier, savedVisualizations, AppState, timefilter, kbnUrl) {
return {
controller: function ($scope, $route, $routeParams, $location, configFile) {
controller: function ($scope, $route, $routeParams, $location, configFile, Private) {
var notify = new Notifier({
location: 'Dashboard'
});
Expand Down Expand Up @@ -85,7 +85,15 @@ define(function (require) {

function init() {
updateQueryOnRootSource();
$scope.$broadcast('application.load');

var docTitle = Private(require('components/doc_title/doc_title'));
$scope.$watch('dash.title', function (title) {
if (dash.id) {
docTitle.change(title);
}
});

$scope.$emit('application.load');
}

function updateQueryOnRootSource() {
Expand Down
6 changes: 5 additions & 1 deletion src/kibana/plugins/discover/controllers/discover.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ define(function (require) {
app.controller('discover', function ($scope, config, courier, $route, $window, Notifier, AppState, timefilter, Promise, Private, kbnUrl) {

var Vis = Private(require('components/vis/vis'));
var docTitle = Private(require('components/doc_title/doc_title'));
var SegmentedFetch = Private(require('plugins/discover/_segmented_fetch'));

var HitSortFn = Private(require('plugins/discover/_hit_sort_fn'));
Expand Down Expand Up @@ -78,8 +79,11 @@ define(function (require) {
// Manage state & url state
var initialQuery = $scope.searchSource.get('query');

var defaultFormat = courier.indexPatterns.fieldFormats.defaultByType.string;
if (savedSearch.id) {
docTitle.change(savedSearch.title);
}

var defaultFormat = courier.indexPatterns.fieldFormats.defaultByType.string;

var stateDefaults = {
query: initialQuery || '',
Expand Down
2 changes: 1 addition & 1 deletion src/kibana/plugins/visualize/editor/editor.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
</vis-editor-sidebar>

<div class="vis-editor-canvas">
<p class="vis-editor-canvas-title" ng-if="savedVis.title" ng-bind="savedVis.title"></p>
<h3 class="vis-editor-canvas-title" ng-if="savedVis.id" ng-bind="savedVis.title"></h3>
<visualize vis="vis" editable-vis="editableVis" search-source="savedVis.searchSource"></visualize>
</div>
</div>
Expand Down
8 changes: 7 additions & 1 deletion src/kibana/plugins/visualize/editor/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ define(function (require) {
'kibana/notify',
'kibana/courier'
])
.controller('VisEditor', function ($scope, $route, timefilter, AppState, $location, kbnUrl, $timeout, courier) {
.controller('VisEditor', function ($scope, $route, timefilter, AppState, $location, kbnUrl, $timeout, courier, Private) {

var _ = require('lodash');
var angular = require('angular');
var ConfigTemplate = require('utils/config_template');
var Notifier = require('components/notify/_notifier');
var docTitle = Private(require('components/doc_title/doc_title'));

var notify = new Notifier({
location: 'Visualization Editor'
Expand All @@ -67,6 +69,10 @@ define(function (require) {
share: require('text!plugins/visualize/editor/panels/share.html'),
});

if (savedVis.id) {
docTitle.change(savedVis.title);
}

var $state = (function initState() {
var savedVisState = vis.getState();
var stateDefaults = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ define(function (require) {
},

defaults: {
title: '',
title: 'New Visualization',
visState: (function () {
if (!opts.type) return null;
var def = {};
Expand Down
87 changes: 87 additions & 0 deletions test/unit/specs/components/doc_title/doc_title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
define(function (require) {
describe('docTitle Service', function () {
var _ = require('lodash');
var sinon = require('test_utils/auto_release_sinon');
var initialDocTitle;
var MAIN_TITLE = 'Kibana 4';
var fakeApp = { name: 'fancy pants' };

var docTitle;
var $rootScope;

beforeEach(function () {
initialDocTitle = document.title;
document.title = MAIN_TITLE;
});
afterEach(function () {
document.title = initialDocTitle;
});

beforeEach(module('kibana', function ($provide) {
$provide.decorator('docTitle', sinon.decorateWithSpy('update'));
$provide.decorator('$rootScope', sinon.decorateWithSpy('$on'));
}));

beforeEach(inject(function ($injector, Private) {
if (_.random(0, 1)) {
docTitle = $injector.get('docTitle');
} else {
docTitle = Private(require('components/doc_title/doc_title'));
}

$rootScope = $injector.get('$rootScope');
}));

describe('setup', function () {
it('resets the title when a route change begins', function () {
var call;
var spy = $rootScope.$on;
for (var i = 0; i < spy.callCount; i++) {
if (spy.args[i][0] === '$routeChangeStart') {
call = spy.getCall(i);
break;
}
}

if (!call) throw new Error('$rootScope.$on not called');

expect(call.args[0]).to.be('$routeChangeStart');
expect(call.args[1]).to.be(docTitle.reset);
});
});

describe('#reset', function () {
it('clears the internal state, next update() will write the default', function () {
docTitle.change('some title');
docTitle.update();
expect(document.title).to.be('some title - ' + MAIN_TITLE);

docTitle.reset();
docTitle.update();
expect(document.title).to.be(MAIN_TITLE);
});
});

describe('#change', function () {
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 name of the active app if available', function () {
expect(document.title).to.be(MAIN_TITLE);
$rootScope.activeApp = fakeApp;
docTitle.change('some secondary title');
expect(document.title).to.be('some secondary title - ' + fakeApp.name + ' - ' + 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);
expect(document.title).to.be('entire name');
});
});

});
});
13 changes: 13 additions & 0 deletions test/utils/auto_release_sinon.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ define(function (require) {
});
});

// helper
sinon.decorateWithSpy = function (/* prop... */) {
var props = _.rest(arguments, 0);

return function ($delegate) {
props.forEach(function (prop) {
sinon.spy($delegate, prop);
});

return $delegate;
};
};

afterEach(function () {
if (!toRestore.length) return;

Expand Down

0 comments on commit b8a068a

Please sign in to comment.