Skip to content

Commit

Permalink
Merge pull request elastic#7711 from cjcenizal/7467/pin-sidebar
Browse files Browse the repository at this point in the history
Refactor app-switcher links components.

Former-commit-id: 16ecfc2
  • Loading branch information
cjcenizal authored Jul 27, 2016
2 parents f87f2de + e14de3b commit 4fb5035
Show file tree
Hide file tree
Showing 10 changed files with 372 additions and 106 deletions.
2 changes: 1 addition & 1 deletion src/ui/public/chrome/chrome.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</app-switcher>

<div class="bottom-apps">
<div class="chrome-actions app-links" kbn-chrome-append-nav-controls></div>
<div class="chrome-actions" kbn-chrome-append-nav-controls></div>
</div>

</nav>
Expand Down
35 changes: 10 additions & 25 deletions src/ui/public/chrome/directives/app_switcher/app_switcher.html
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
<div class="app-links">
<div
class="app-link"
ng-repeat="link in switcher.shownNavLinks"
ng-class="{ active: link.active, 'is-app-switcher-app-link-disabled': !switcher.isNavLinkEnabled(link) }"
tooltip="{{link.tooltip}}"
tooltip-placement="right"
tooltip-popup-delay="400"
tooltip-append-to-body="1"
>

<a
ng-click="switcher.ensureNavigation($event, link)"
ng-href="{{ link.active ? link.url : (link.lastSubUrl || link.url) }}"
data-test-subj="appLink"
ng-class="{ 'app-link__anchor': !switcher.isNavLinkEnabled(link) }"
title="{{ link.title }}"
>

<div ng-if="link.icon" class="app-icon"><img kbn-src="{{'/' + link.icon}}"></div>
<div ng-if="!link.icon" class="app-icon-missing">{{ link.title[0] }}</div>

<div class="app-title">{{ link.title }}</div>
</a>
</div>
</div>
<app-switcher-link
ng-repeat="link in switcher.shownNavLinks"
app-switcher-link-is-active="link.active"
app-switcher-link-is-disabled="!switcher.isNavLinkEnabled(link)"
app-switcher-link-tooltip="link.tooltip"
app-switcher-link-on-click="switcher.ensureNavigation($event, link)"
app-switcher-link-href="link.active ? link.url : (link.lastSubUrl || link.url)"
app-switcher-link-icon="link.icon"
app-switcher-link-title="link.title"
></app-switcher-link>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import DomLocationProvider from 'ui/dom_location';
import { parse } from 'url';
import { bindKey } from 'lodash';
import '../app_switcher/app_switcher.less';
import './app_switcher.less';
import uiModules from 'ui/modules';
import appSwitcherTemplate from './app_switcher.html';

Expand Down
78 changes: 0 additions & 78 deletions src/ui/public/chrome/directives/app_switcher/app_switcher.less
Original file line number Diff line number Diff line change
Expand Up @@ -70,81 +70,3 @@ body { overflow-x: hidden; }
.flex-parent(@shrink: 0);
box-shadow: -4px 0px 3px rgba(0,0,0,0.2);
}

.app-links {
text-align: justify;

.app-link {
width: @as-open-width;
height: @app-icon-height;
line-height: @app-line-height;

> a {
display: block;
height: 100%;
color: #ebf7fa;
}

&.is-app-switcher-app-link-disabled {
opacity: 0.5;

.app-link__anchor {
cursor: default;
}
}

.app-icon {
float: left;
font-weight: bold;
text-align: center;
font-size: 1.7em;
display: inline-block;
height: @app-icon-height;
width: @as-closed-width;

> img {
height: 18px;
margin-top: 8px;
filter: invert(100%);
}
> i {
color: #fff;
line-height: @app-icon-height
}
}

.app-icon-missing {
float: left;
text-align: center;
font-size: 1.7em;
display: inline-block;
height: @app-icon-height;
line-height: @app-icon-height;
width: @as-closed-width;
background-position: center;
background-size: contain;
background-repeat: no-repeat;
}

.app-title {
width: calc(@as-open-width - @as-closed-width);
display: inline-block;
float: right;
font-size: 0.9em;
text-align: left;
padding-left: 3px;
line-height: @app-icon-height;
white-space: nowrap;
}

&:hover,
&.active {
background-color: @app-links-active-background;
> a {
color: @white;
text-decoration: none;
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import sinon from 'auto-release-sinon';
import ngMock from 'ng_mock';
import expect from 'expect.js';

import '../app_switcher_link';

describe('appSwitcherLink directive', () => {
let scope;
let $compile;

beforeEach(ngMock.module('kibana'));

beforeEach(() => {
ngMock.inject(($rootScope, _$compile_) => {
scope = $rootScope.$new();
$compile = _$compile_;
});
});

function create(attrs) {
const template = `
<app-switcher-link
app-switcher-link-is-active="appSwitcherLinkIsActive"
app-switcher-link-is-disabled="appSwitcherLinkIsDisabled"
app-switcher-link-tooltip="appSwitcherLinkTooltip"
app-switcher-link-on-click="appSwitcherLinkOnClick()"
app-switcher-link-href="appSwitcherLinkHref"
app-switcher-link-kbn-route="appSwitcherLinkKbnRoute"
app-switcher-link-icon="appSwitcherLinkIcon"
app-switcher-link-title="appSwitcherLinkTitle"
/>
`;

const element = $compile(template)(scope);

scope.$apply(() => {
Object.assign(scope, attrs);
});

return element;
}

describe('interface', () => {

describe('appSwitcherLinkIsActive attribute', () => {
it(`doesn't apply the active class when false`, () => {
const element = create({
appSwitcherLinkIsActive: false,
});
expect(element.hasClass('active')).to.be(false);
});

it('applies the active class when true', () => {
const element = create({
appSwitcherLinkIsActive: true,
});
expect(element.hasClass('active')).to.be(true);
});
});

describe('appSwitcherLinkIsDisabled attribute', () => {
it(`doesn't apply the is-app-switcher-link-disabled class when false`, () => {
const element = create({
appSwitcherLinkIsDisabled: false,
});
expect(element.hasClass('is-app-switcher-link-disabled')).to.be(false);
});

it('applies the is-app-switcher-link-disabled class when true', () => {
const element = create({
appSwitcherLinkIsDisabled: true,
});
expect(element.hasClass('is-app-switcher-link-disabled')).to.be(true);
});
});

describe('appSwitcherLinkTooltip attribute', () => {
it('is applied to the tooltip directive', () => {
const attrs = {
appSwitcherLinkTooltip: 'hello i am a tooltip',
};
const element = create(attrs);
expect(element.attr('tooltip')).to.be(attrs.appSwitcherLinkTooltip);
});
});

describe('appSwitcherLinkOnClick attribute', () => {
it('is called when the link is clicked', () => {
const attrs = {
appSwitcherLinkOnClick: sinon.spy(),
};
const element = create(attrs);
element.find('[data-test-subj=appLink]').click();
sinon.assert.called(attrs.appSwitcherLinkOnClick);
});
});

describe('appSwitcherLinkHref attribute', () => {
it('is applied to the link', () => {
const attrs = {
appSwitcherLinkHref: 'link to a website',
};
const element = create(attrs);
const link = element.find('[data-test-subj=appLink]');
expect(link.attr('href')).to.be(attrs.appSwitcherLinkHref);
});
});

describe('appSwitcherLinkKbnRoute attribute', () => {
it(`is applied to the link when href isn't defined`, () => {
const attrs = {
appSwitcherLinkKbnRoute: '#test',
};
const element = create(attrs);
const link = element.find('[data-test-subj=appLink]');
expect(link.attr('href')).to.be(attrs.appSwitcherLinkKbnRoute);
});

it(`isn't applied to the link when href is defined`, () => {
const attrs = {
appSwitcherLinkHref: 'link to a website',
appSwitcherLinkKbnRoute: '#test',
};
const element = create(attrs);
const link = element.find('[data-test-subj=appLink]');
expect(link.attr('href')).not.to.be(attrs.appSwitcherLinkKbnRoute);
});
});

describe('appSwitcherLinkIcon attribute', () => {
describe('when present', () => {
it('displays the img element', () => {
const attrs = {
appSwitcherLinkIcon: 'icon url',
};
const element = create(attrs);
const img = element.find('img');
expect(img.length).to.be(1);
});

it('hides the placeholder', () => {
const attrs = {
appSwitcherLinkIcon: 'icon url',
};
const element = create(attrs);
const placeholder = element.find('[data-test-subj=appLinkIconPlaceholder]');
expect(placeholder.length).to.be(0);
});

it(`is set as the img src`, () => {
const attrs = {
appSwitcherLinkIcon: 'icon url',
};
const element = create(attrs);
const img = element.find('img');
expect(img.attr('src')).to.contain(encodeURI(attrs.appSwitcherLinkIcon));
});
});

describe('when not present', () => {
it('hides the img element', () => {
const attrs = {
appSwitcherLinkIcon: undefined,
};
const element = create(attrs);
const img = element.find('img');
expect(img.length).to.be(0);
});

it('displays the placeholder', () => {
const attrs = {
appSwitcherLinkIcon: undefined,
};
const element = create(attrs);
const placeholder = element.find('[data-test-subj=appLinkIconPlaceholder]');
expect(placeholder.length).to.be(1);
});

it(`uses the title's first letter as the placeholder`, () => {
const attrs = {
appSwitcherLinkIcon: undefined,
appSwitcherLinkTitle: 'Xyz',
};
const element = create(attrs);
const placeholder = element.find('[data-test-subj=appLinkIconPlaceholder]');
expect(placeholder.text()).to.contain(attrs.appSwitcherLinkTitle[0]);
});
});
});

describe('appSwitcherLinkTitle attribute', () => {
it('is displayed', () => {
const attrs = {
appSwitcherLinkTitle: 'demo title',
};
const element = create(attrs);
const title = element.find('.app-switcher-link__title');
expect(title.text().trim()).to.be(attrs.appSwitcherLinkTitle);
});

it('is set as a title attribute on the anchor tag', () => {
const attrs = {
appSwitcherLinkTitle: 'demo title',
};
const element = create(attrs);
const link = element.find('[data-test-subj=appLink]');
expect(link.attr('title')).to.be(attrs.appSwitcherLinkTitle);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<div
class="app-switcher-link"
ng-class="{ active: isActive, 'is-app-switcher-link-disabled': isDisabled }"
tooltip="{{ tooltip }}"
tooltip-placement="right"
tooltip-popup-delay="400"
tooltip-append-to-body="1"
>
<a
class="app-switcher-link__anchor"
href="{{ getHref() }}"
ng-click="onClick({ $event: $event })"
data-test-subj="appLink"
title="{{ title }}"
>
<div class="app-switcher-link__icon">
<img
ng-if="icon"
class="app-switcher-link__icon-image"
kbn-src="{{ '/' + icon }}"
>

<span
ng-if="!icon"
class="app-switcher-link__icon-placeholder"
data-test-subj="appLinkIconPlaceholder"
>
{{ title[0] }}
</span>
</div>

<div class="app-switcher-link__title">
{{ title }}
</div>
</a>
</div>
Loading

0 comments on commit 4fb5035

Please sign in to comment.