Merge "Introduce gr-dropdown element"
This commit is contained in:
commit
d9ed432e47
@ -17,21 +17,12 @@ limitations under the License.
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-dropdown/gr-dropdown.html">
|
||||
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
|
||||
<dom-module id="gr-account-dropdown">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
.dropdown-trigger {
|
||||
text-decoration: none;
|
||||
}
|
||||
.dropdown-content {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
|
||||
}
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
@ -43,51 +34,15 @@ limitations under the License.
|
||||
width: 2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
ul .accountName {
|
||||
font-weight: bold;
|
||||
}
|
||||
li .accountInfo,
|
||||
li a {
|
||||
display: block;
|
||||
padding: .85em 1em;
|
||||
}
|
||||
li a:link,
|
||||
li a:visited {
|
||||
color: #00e;
|
||||
text-decoration: none;
|
||||
}
|
||||
li a:hover {
|
||||
background-color: #6B82D6;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<gr-button link class="dropdown-trigger" id="trigger"
|
||||
on-tap="_showDropdownTapHandler">
|
||||
<span hidden$="[[_hasAvatars]]" hidden>[[account.name]]</span>
|
||||
<gr-avatar account="[[account]]" hidden$="[[!_hasAvatars]]" hidden
|
||||
image-size="56"></gr-avatar>
|
||||
</gr-button>
|
||||
<iron-dropdown id="dropdown"
|
||||
vertical-align="top"
|
||||
vertical-offset="25"
|
||||
<gr-dropdown items=[[links]] top-content=[[topContent]]
|
||||
horizontal-align="right">
|
||||
<div class="dropdown-content">
|
||||
<ul>
|
||||
<li>
|
||||
<div class="accountInfo">
|
||||
<div class="accountName">[[account.name]]</div>
|
||||
<div>[[account.email]]</div>
|
||||
</div>
|
||||
</li>
|
||||
<li><a href$="[[_computeRelativeURL('/settings')]]">Settings</a></li>
|
||||
<li><a href$="[[_computeRelativeURL('/switch-account')]]">Switch account</a></li>
|
||||
<li><a href$="[[_computeRelativeURL('/logout')]]">Sign out</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</iron-dropdown>
|
||||
<gr-button link class="dropdown-trigger" id="trigger">
|
||||
<span hidden$="[[_hasAvatars]]" hidden>[[account.name]]</span>
|
||||
<gr-avatar account="[[account]]" hidden$="[[!_hasAvatars]]" hidden
|
||||
image-size="56"></gr-avatar>
|
||||
</gr-button>
|
||||
</gr-dropdown>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
</template>
|
||||
<script src="gr-account-dropdown.js"></script>
|
||||
|
@ -20,26 +20,31 @@
|
||||
properties: {
|
||||
account: Object,
|
||||
_hasAvatars: Boolean,
|
||||
links: {
|
||||
type: Array,
|
||||
value: [
|
||||
{name: 'Settings', url: '/settings'},
|
||||
{name: 'Switch account', url: '/switch-account'},
|
||||
{name: 'Sign out', url: '/logout'},
|
||||
],
|
||||
},
|
||||
topContent: {
|
||||
type: Array,
|
||||
computed: '_getTopContent(account)',
|
||||
},
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
this.$.restAPI.getConfig().then(function(cfg) {
|
||||
this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
|
||||
}.bind(this));
|
||||
|
||||
this.listen(this.$.dropdown, 'tap', '_handleDropdownTap');
|
||||
},
|
||||
|
||||
_handleDropdownTap: function(e) {
|
||||
this.$.dropdown.close();
|
||||
},
|
||||
|
||||
_showDropdownTapHandler: function(e) {
|
||||
this.$.dropdown.open();
|
||||
},
|
||||
|
||||
_computeRelativeURL: function(path) {
|
||||
return '//' + window.location.host + path;
|
||||
_getTopContent: function(account) {
|
||||
return [
|
||||
{text: account.name, bold: true},
|
||||
{text: account.email},
|
||||
];
|
||||
},
|
||||
});
|
||||
})();
|
||||
|
@ -41,11 +41,10 @@ limitations under the License.
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('tap on trigger opens menu', function() {
|
||||
assert.isFalse(element.$.dropdown.opened);
|
||||
MockInteractions.tap(element.$.trigger);
|
||||
assert.isTrue(element.$.dropdown.opened);
|
||||
test('account information', function() {
|
||||
element.account = {name: 'John Doe', email: 'john@doe.com'};
|
||||
assert.deepEqual(element.topContent,
|
||||
[{text: 'John Doe', bold: true}, {text: 'john@doe.com'}]);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
112
polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
Normal file
112
polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.html
Normal file
@ -0,0 +1,112 @@
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed 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.
|
||||
-->
|
||||
|
||||
<link rel="import" href="../../../bower_components/polymer/polymer.html">
|
||||
<link rel="import" href="../../../bower_components/iron-dropdown/iron-dropdown.html">
|
||||
<link rel="import" href="../../shared/gr-button/gr-button.html">
|
||||
<link rel="import" href="../../shared/gr-rest-api-interface/gr-rest-api-interface.html">
|
||||
|
||||
<dom-module id="gr-dropdown">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
.dropdown-trigger {
|
||||
text-decoration: none;
|
||||
}
|
||||
.dropdown-content {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
|
||||
}
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
font: inherit;
|
||||
padding: .3em 0;
|
||||
}
|
||||
gr-avatar {
|
||||
height: 2em;
|
||||
width: 2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
ul {
|
||||
list-style: none;
|
||||
}
|
||||
ul .accountName {
|
||||
font-weight: bold;
|
||||
}
|
||||
li .accountInfo,
|
||||
li a {
|
||||
display: block;
|
||||
padding: .85em 1em;
|
||||
}
|
||||
li a:link,
|
||||
li a:visited {
|
||||
color: #00e;
|
||||
text-decoration: none;
|
||||
}
|
||||
li a:hover {
|
||||
background-color: #6B82D6;
|
||||
color: #fff;
|
||||
}
|
||||
.topContent {
|
||||
display: block;
|
||||
padding: .85em 1em;
|
||||
}
|
||||
.bold-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<gr-button link class="dropdown-trigger" id="trigger"
|
||||
on-tap="_showDropdownTapHandler">
|
||||
<content></content>
|
||||
</gr-button>
|
||||
<iron-dropdown id="dropdown"
|
||||
vertical-align="top"
|
||||
vertical-offset="25"
|
||||
horizontal-align="[[horizontalAlign]]"
|
||||
on-tap="_handleDropdownTap">
|
||||
<div class="dropdown-content">
|
||||
<ul>
|
||||
<template is="dom-if" if="[[topContent]]">
|
||||
<div class="topContent">
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[topContent]]"
|
||||
as="item"
|
||||
initial-count="75">
|
||||
<div class$="[[_getClassIfBold(item.bold)]] top-item">
|
||||
[[item.text]]
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template
|
||||
is="dom-repeat"
|
||||
items="[[items]]"
|
||||
as="link"
|
||||
initial-count="75">
|
||||
<li><a href$="[[_computeRelativeURL(link.url)]]">[[link.name]]</a>
|
||||
</li>
|
||||
</template>
|
||||
</ul>
|
||||
</div>
|
||||
</iron-dropdown>
|
||||
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
|
||||
</template>
|
||||
<script src="gr-dropdown.js"></script>
|
||||
</dom-module>
|
57
polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
Normal file
57
polygerrit-ui/app/elements/shared/gr-dropdown/gr-dropdown.js
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed 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.
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
Polymer({
|
||||
is: 'gr-dropdown',
|
||||
|
||||
properties: {
|
||||
items: Array,
|
||||
topContent: Object,
|
||||
horizontalAlign: {
|
||||
type: String,
|
||||
value: 'left',
|
||||
},
|
||||
_hasAvatars: String,
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
this.$.restAPI.getConfig().then(function(cfg) {
|
||||
this._hasAvatars = !!(cfg && cfg.plugin && cfg.plugin.has_avatars);
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
_handleDropdownTap: function(e) {
|
||||
this.$.dropdown.close();
|
||||
},
|
||||
|
||||
_showDropdownTapHandler: function(e) {
|
||||
this.$.dropdown.open();
|
||||
},
|
||||
|
||||
_getClassIfBold: function(bold) {
|
||||
return bold ? 'bold-text' : '';
|
||||
},
|
||||
|
||||
_computeURLHelper: function(host, path) {
|
||||
return '//' + host + path;
|
||||
},
|
||||
|
||||
_computeRelativeURL: function(path) {
|
||||
var host = window.location.host;
|
||||
return this._computeURLHelper(host, path);
|
||||
},
|
||||
});
|
||||
})();
|
@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html>
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source Project
|
||||
|
||||
Licensed 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.
|
||||
-->
|
||||
|
||||
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
|
||||
<title>gr-dropdown</title>
|
||||
|
||||
<script src="../../../bower_components/webcomponentsjs/webcomponents.min.js"></script>
|
||||
<script src="../../../bower_components/web-component-tester/browser.js"></script>
|
||||
|
||||
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">
|
||||
<link rel="import" href="gr-dropdown.html">
|
||||
|
||||
<test-fixture id="basic">
|
||||
<template>
|
||||
<gr-dropdown></gr-dropdown>
|
||||
</template>
|
||||
</test-fixture>
|
||||
|
||||
<script>
|
||||
suite('gr-dropdown tests', function() {
|
||||
var element;
|
||||
|
||||
setup(function() {
|
||||
stub('gr-rest-api-interface', {
|
||||
getConfig: function() { return Promise.resolve({}); },
|
||||
});
|
||||
element = fixture('basic');
|
||||
});
|
||||
|
||||
test('tap on trigger opens menu', function() {
|
||||
assert.isFalse(element.$.dropdown.opened);
|
||||
MockInteractions.tap(element.$.trigger);
|
||||
assert.isTrue(element.$.dropdown.opened);
|
||||
});
|
||||
|
||||
test('_computeRelativeURL', function() {
|
||||
var path = '/test';
|
||||
var host = 'http://www.testsite.com';
|
||||
var computedPath = element._computeURLHelper(host, path);
|
||||
assert.equal(computedPath, '//http://www.testsite.com/test');
|
||||
});
|
||||
|
||||
test('_getClassIfBold', function() {
|
||||
var bold = true;
|
||||
assert.equal(element._getClassIfBold(bold), 'bold-text');
|
||||
|
||||
bold = false;
|
||||
assert.equal(element._getClassIfBold(bold), '');
|
||||
});
|
||||
|
||||
test('Top text exists and is bolded correctly', function() {
|
||||
element.topContent = [{text: 'User', bold: true}, {text: 'email'}];
|
||||
flushAsynchronousOperations();
|
||||
var topItems = Polymer.dom(element.root).querySelectorAll('.top-item');
|
||||
assert.equal(topItems.length, 2);
|
||||
assert.isTrue(topItems[0].classList.contains('bold-text'));
|
||||
assert.isFalse(topItems[1].classList.contains('bold-text'));
|
||||
});
|
||||
});
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user