Implement Horizon UI patterns

On the app catalog index, remove the right-side control bar (search,
category, env) and replace with more "Horizon"-like UI elements at the
top of the page. Rename "Latest Apps" to "Recent Activity" and add info
text if no results. Add search query term to search field when showing
search results (UX).

Change-Id: I224dcd1946e846f198b909dd3020df2c09ec615b
Implements: blueprint murano-ui-horizon-patterns
This commit is contained in:
Brian Tully 2014-06-10 18:27:17 -04:00
parent a980dc2ad6
commit c2896b1487
3 changed files with 197 additions and 230 deletions

View File

@ -1,30 +1,83 @@
.table_header.catalog {
border-bottom: 2px solid #e5e5e5;
min-width: 780px;
}
.catalog .table_actions {
width: 100%;
}
h3.heading_switcher {
font-size: 18px;
}
h3.heading_switcher a.btn {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.catalog .table_search {
float: right;
}
.catalog .table_actions a, .catalog .table_actions button {
margin-left: 0;
}
.env_switcher {
margin-left: 25px;
}
.catalog .row_actions button, .catalog .row_actions a {
background: none;
float: none;
display: block;
padding: 5px 10px;
color: black;
text-align: left;
border-radius: 0;
border: 0 none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.catalog .dropdown-menu li > a:hover, .catalog .dropdown-menu .active > a, .catalog .dropdown-menu .active > a:hover {
color: black;
background-color: #CDCDCD;
}
.catalog .dropdown.open .dropdown-toggle {
color: black;
background: #e6e6e6;
}
.app-list .actions {
border-top:1px #ccc solid;
padding-top:15px;
margin-top:15px;
border-top:1px #ccc solid;
padding-top:15px;
margin-top:15px;
}
.app-description {
height: 100px;
height: 100px;
}
.btn-link {
padding: 5px 0;
padding: 5px 0;
}
.app-row {
overflow: hidden;
overflow: hidden;
}
.centering {
width: 100%;
text-align: center;
width: 100%;
text-align: center;
}
h3.link {
color: yellow;
opacity: 0.5;
color: yellow;
opacity: 0.5;
}
h3.link:hover {
opacity: 1;
opacity: 1;
}
h3.link .caret {
border-top: 4px solid yellow !important;
border-top: 4px solid yellow !important;
}
/*.well {*/
/*border: 1px solid #aaa;*/
@ -50,150 +103,97 @@ h3.link .caret {
/*transition: all .15s ease-out;*/
/*}*/
.row.app-list {
margin-top: 20px;
margin-bottom:20px;
margin-top: 20px;
margin-bottom:20px;
}
.app-list .app {
min-height:160px;
position:relative;
min-height:160px;
position:relative;
}
.app-list .app > div {
margin:0;
margin:0;
}
.app-list .app div.description {
padding-left:20px;
margin-left:0;
padding-left:20px;
margin-left:0;
}
.app-list .app h4 {;
margin-bottom:0.25em;
margin-bottom:0.25em;
}
.app-list .app .app-actions {
position:absolute;
bottom:15px;
right:15px;
position:absolute;
bottom:15px;
right:15px;
}
.app-actions div[class*='span'] {
margin-left:0;
margin-left:0;
}
.header.dropdown {
display:inline-block;
display:inline-block;
margin-left: 5px;
}
.header.dropdown ul {
font-size:14px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size:14px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
.nav-tabs {
margin-top:20px;
margin-top:20px;
}
.app-meta {
margin-top:30px;
margin-top:30px;
}
.app-icon {
line-height:0;
overflow:hidden;
margin-left:0;
line-height:0;
overflow:hidden;
margin-left:0;
}
.app-meta .app-icon {
margin-right:30px;
width:70px;
height:70px
margin-right:30px;
width:70px;
height:70px
}
.app-icon img {
width:100%;
height:70px;
margin:0px;
}
a.trigger.first {
top: 110px; right: 0;
}
a.trigger.second {
top: 165px; right: 0;
}
a.trigger.third {
top: 220px; right: 0;
width:100%;
height:70px;
margin:0px;
}
a.trigger{
position: absolute;
text-decoration: none;
font-size: 24px;
width:24px;
font-family: verdana, helvetica, arial, sans-serif;
color:#fff;
padding: 15px;
font-weight: 700;
background:#d93c27;
-moz-border-radius-topleft: 5px;
-webkit-border-top-left-radius: 5px;
-moz-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
display: block;
}
a.active.trigger {
background: #222222;
}
a.trigger:hover{
background:#ccc;
}
.murano-side-panel {
position: absolute;
top: 250px;
right: 0;
display: none;
background: #ffffff;
border:1px solid #ccc;
-moz-border-radius-topleft: 5px;
-webkit-border-top-left-radius: 5px;
-moz-border-radius-bottomleft: 5px;
-webkit-border-bottom-left-radius: 5px;
width: 330px;
height: auto;
padding: 30px 130px 30px 30px;
}
.murano-side-panel p{
margin: 0 0 15px 0;
padding: 0;
}
#environment_switcher {
border:1px solid #ccc;
padding:0 10px;
display: inline-block;
}
.panel-visible{
display: block;
display: block;
}
.columns{
clear: both;
width: 330px;
padding: 0 0 20px 0;
line-height: 22px;
clear: both;
width: 330px;
padding: 0 0 20px 0;
line-height: 22px;
}
.colleft{
float: left;
width: 150px;
line-height: 22px;
float: left;
width: 150px;
line-height: 22px;
}
.colright{
float: right;
width: 150px;
line-height: 22px;
float: right;
width: 150px;
line-height: 22px;
}
.server-stats {
margin: 10px 0;
margin: 10px 0;
}
.server-stats .label {
margin-right:12px;
margin-right:12px;
}
.server-stats meter {
margin-right:20px;
margin-right:20px;
}
.app-icon.server {
margin-right:20px;
margin-right:20px;
}
.no-results {

View File

@ -1,33 +1,25 @@
{% load i18n %}
{% load url from future %}
<div id="environment_switcher" class="dropdown switcher_bar" tabindex="1">
{% with num_of_envs=available_environments|length %}
{% if num_of_envs > 1 %}
<a class="dropdown-toggle" data-toggle="dropdown" href="#environment_switcher">
{% endif %}
<h3>
{% trans "Environment:" %}
{% if environment %}
{{ environment.name }}
{% else %}
<a href="{% url 'horizon:murano:environments:create_environment' %}?next={% url 'horizon:murano:catalog:index' %}" class="ajax-modal">{% trans "No Environments" %}</a>
{% endif %}
{% if num_of_envs > 1 %}
<span class="caret pull-right"></span>
{% endif %}
</h3>
{% if num_of_envs > 1 %}
</a>
<ul id="environment_list" class="dropdown-menu">
<li class='divider'></li>
{% for env in available_environments %}
{% if env.id != environment.id %}
<li><a href="{% url 'horizon:murano:catalog:switch_env' env.id %}?next={% url 'horizon:murano:catalog:index' %}">
{{ env.name }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</div>
<h3 class="heading_switcher env_switcher">{% trans "Environment:" %}
<div id="environment_switcher" class="header dropdown">
{% with num_of_envs=available_environments|length %}
{% if environment %}
<a href="#environment_switcher" class="btn btn-small dropdown-toggle" data-toggle="dropdown">{{ environment.name }} {% if num_of_envs > 1 %} <b class="caret"></b>{% endif %}</a>
{% else %}
<a href="{% url 'horizon:murano:environments:create_environment' %}?next={% url 'horizon:murano:catalog:index' %}" title="{% trans 'Click to create an environment' %}" class="btn btn-small btn-create ajax-modal">{% trans "Create Environment" %}</a>
{% endif %}
{% if num_of_envs > 1 %}
<ul id="environment_list" class="dropdown-menu row_actions clearfix">
{% for env in available_environments %}
{% if env.id != environment.id %}
<li class="clearfix"><a tabindex="-1" href="{% url 'horizon:murano:catalog:switch_env' env.id %}?next={% url 'horizon:murano:catalog:index' %}" class="btn btn-small">{{ env.name }}</a></li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</div>
</h3>

View File

@ -6,104 +6,79 @@
{% block title %}{% trans "Applications" %}{% endblock %}
{% block page_header %}
<link rel="stylesheet" href="{% static 'muranodashboard/css/catalog.css' %}">
<link rel="stylesheet" href="{% static 'muranodashboard/css/font-awesome.min.css' %}">
{% include "horizon/common/_page_header.html" with title=_("Applications") %}
<link rel="stylesheet" href="{% static 'muranodashboard/css/catalog.css' %}">
<link rel="stylesheet" href="{% static 'muranodashboard/css/font-awesome.min.css' %}">
{% include "horizon/common/_page_header.html" with title=_("Applications") %}
{% endblock page_header %}
{% block js %}
{% include "horizon/_scripts.html" %}
<script type="text/javascript">
var allPanelIds = ['#MuranoCategoriesPanel', '#MuranoSearchPanel',
'#MuranoDefaultEnvPanel'];
function bindPanelToggle(panelId) {
var toggler = $(panelId + 'Toggle'), panel = $(panelId);
toggler.click(function(event) {
panel.css('top', toggler.offset().top);
panel.toggleClass('panel-visible');
allPanelIds.forEach(function(panId) {
if ( panId != panelId ) {
$(panId).removeClass('panel-visible');
$(panId + 'Toggle').removeClass('active');
}
});
toggler.toggleClass('active');
})
}
$(function() {
bindPanelToggle('#MuranoCategoriesPanel');
bindPanelToggle('#MuranoSearchPanel');
bindPanelToggle('#MuranoDefaultEnvPanel');
})
</script>
{% endblock %}
{% block main %}
<div class="table_wrapper">
<h3 class="quota-heading">Latest Apps</h3>
{% if latest_list|length > 0 %}
<div class="app-row app-list row">
{% for app in latest_list %}
{% include 'catalog/app_tile.html' %}
{% endfor %}
<div class="table_wrapper">
<h3 class="quota-heading">Recent Activity</h3>
{% if latest_list|length > 0 %}
<div class="app-row app-list row">
{% for app in latest_list %}
{% include 'catalog/app_tile.html' %}
{% endfor %}
</div>
{% else %}
<div class="alert alert-block alert-info fade in">
<p>{% trans "No recent activity to report at this time." %}</p>
</div>
{% endif %}
<div class="table_header catalog">
<div class="table_actions clearfix">
<h3 class="heading_switcher">App Category: <div class="header dropdown">
<a href="#" class="btn btn-small dropdown-toggle" data-toggle="dropdown">
{{ current_category }} <b class="caret"></b></a>
<ul class="dropdown-menu row_actions clearfix">
{% for category in categories %}
<li class="clearfix"><a tabindex="-1" href="
{% url 'horizon:murano:catalog:index' %}?category={{ category|urlencode }}" class="btn btn-small">
{{ category }}</a></li>
{% endfor %}
</ul>
</h3>
{% include 'catalog/env_switcher.html' %}
<div class="table_search client">
<form class="search" method="GET" action="{% url 'horizon:murano:catalog:index' %}">
<input class="span3 example" value="{{ search }}" type="text" name="search" placeholder="Filter">
<button type="submit" class="btn btn-small btn-search" id="apps__action_filter">Filter</button>
</form>
</div>
</div>
</div>
{% if object_list|length > 0 %}
<div class="app-row app-list row">
{% for app in object_list %}
{% include 'catalog/app_tile.html' %}
{% endfor %}
</div>
{% else %}
<div class="alert alert-block alert-info fade in">
<p>{% trans "There are no applications matching your search criteria." %}</p>
</div>
{% endif %}
<div class="btn-toolbar centering">
<div class="btn-group">
{% if view.has_more_data %}
<a class="btn btn-default"
href="{% url 'horizon:murano:catalog:index' %}?category={{ current_category|urlencode }}&{{ view.get_pagination_string }}{% if search %}&search={{ search|urlencode }}{% endif %}">
More Apps</a>
{% endif %}
</div>
</div>
</div>
{% else %}
<p class="no-results">{% trans "There are no applications available at this time." %}</p>
{% endif %}
<h3 class="quota-heading">App Category: <div class="header dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
{{ current_category }}<b class="caret"></b></a>
<ul class="dropdown-menu">
{% for category in categories %}
<li><a tabindex="-1" href="
{% url 'horizon:murano:catalog:index' %}?category={{ category|urlencode }}">
{{ category }}</a></li>
{% endfor %}
</ul>
</div>
</h3>
{% if object_list|length > 0 %}
<div class="app-row app-list row">
{% for app in object_list %}
{% include 'catalog/app_tile.html' %}
{% endfor %}
</div>
{% else %}
<p class="no-results">{% trans "There are no applications matching your search criteria." %}</p>
{% endif %}
<div class="btn-toolbar centering">
<div class="btn-group">
{% if view.has_more_data %}
<a class="btn btn-default"
href="{% url 'horizon:murano:catalog:index' %}?category={{ current_category|urlencode }}&{{ view.get_pagination_string }}{% if search %}&search={{ search|urlencode }}{% endif %}">
More Apps</a>
{% endif %}
</div>
</div>
<div class="murano-side-panel" id="MuranoDefaultEnvPanel">
{% include 'catalog/env_switcher.html' %}
</div>
<a class="trigger third" href="#" id="MuranoDefaultEnvPanelToggle"><i class="fa fa-desktop"></i></a>
<div class="murano-side-panel" id="MuranoCategoriesPanel">
{% include 'catalog/categories.html' %}
</div>
<a class="trigger second" href="#" id="MuranoCategoriesPanelToggle"><i class="fa fa-th-list"></i></a>
<div class="murano-side-panel" id="MuranoSearchPanel">
<h3>Search</h3>
<form class="search" method="GET" action="{% url 'horizon:murano:catalog:index' %}">
<input name="search" class="text input-medium search-query"/>
<button class="btn_search btn">Go</button>
</form>
</div>
<a class="trigger first" href="#" id="MuranoSearchPanelToggle"><i class="fa fa-search"></i></a>
</div>
{% endblock %}