Bootstrap 3 and SCSS

Since Horizon has moved to SCSS and Bootstrap 3,
we have to update our styles to match them.

Change-Id: I1f34f35c24ed7b9e73006343a7ae13d87e4f3d8d
This commit is contained in:
Radomir Dopieralski 2014-07-29 10:08:50 +02:00
parent 651158dfea
commit 37b1bb1cbe
35 changed files with 301 additions and 607 deletions

View File

@ -7,8 +7,8 @@
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
<h4>{% trans "Hardware Info" %}</h4>
<dl class="clearfix">
<dt>{% trans "Architecture" %}</dt>

View File

@ -8,8 +8,8 @@
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
{{ tab_group.render }}
</div>
</div>

View File

@ -42,7 +42,7 @@ class NodeForm(django.forms.Form):
choices=DRIVER_CHOICES,
required=True,
widget=django.forms.Select(attrs={
'class': 'input input-medium switchable',
'class': 'form-control switchable',
'data-slug': 'driver',
}),
)
@ -51,7 +51,7 @@ class NodeForm(django.forms.Form):
label=_("IPMI Address"),
required=False,
widget=django.forms.TextInput(attrs={
'class': 'switched',
'class': 'form-control switched',
'data-switch-on': 'driver',
'data-driver-ipmi': 'ipmi',
}),
@ -60,7 +60,7 @@ class NodeForm(django.forms.Form):
label=_("IPMI User"),
required=False,
widget=django.forms.TextInput(attrs={
'class': 'input input-medium switched',
'class': 'form-control switched',
'data-switch-on': 'driver',
'data-driver-ipmi': 'ipmi',
}),
@ -69,7 +69,7 @@ class NodeForm(django.forms.Form):
label=_("IPMI Password"),
required=False,
widget=django.forms.PasswordInput(render_value=False, attrs={
'class': 'input input-medium switched',
'class': 'form-control switched',
'data-switch-on': 'driver',
'data-driver-ipmi': 'ipmi',
}),
@ -77,7 +77,7 @@ class NodeForm(django.forms.Form):
mac_addresses = tuskar_ui.forms.MultiMACField(
label=_("NIC MAC Addresses"),
widget=django.forms.Textarea(attrs={
'class': 'input input-medium',
'class': 'form-control',
'rows': '2',
}),
)
@ -87,7 +87,7 @@ class NodeForm(django.forms.Form):
required=True,
choices=ARCHITECTURE_CHOICES,
widget=django.forms.Select(
attrs={'class': 'input input-medium'}),
attrs={'class': 'form-control'}),
)
cpus = django.forms.IntegerField(
label=_("CPUs"),
@ -95,7 +95,7 @@ class NodeForm(django.forms.Form):
min_value=1,
initial=1,
widget=tuskar_ui.forms.NumberInput(
attrs={'class': 'input input-medium'}),
attrs={'class': 'form-control'}),
)
memory_mb = django.forms.IntegerField(
label=_("Memory"),
@ -103,7 +103,7 @@ class NodeForm(django.forms.Form):
min_value=1,
initial=1,
widget=tuskar_ui.forms.NumberInput(
attrs={'class': 'input input-medium'}),
attrs={'class': 'form-control'}),
)
local_gb = django.forms.IntegerField(
label=_("Local Disk"),
@ -111,7 +111,7 @@ class NodeForm(django.forms.Form):
min_value=1,
initial=1,
widget=tuskar_ui.forms.NumberInput(
attrs={'class': 'input input-medium'}),
attrs={'class': 'form-control'}),
)
def get_name(self):

View File

@ -1,10 +1,12 @@
<div class="row-fluid form-field control-group{% if field.errors %} error{% endif %}{% if required or field.required %} required{% endif %}">
<label class="span4 control-label">{{ field.label }}</label>
<div class="span6">{{ field }}</div>
<div class="span2 muted">{{ extra_text|default:'' }}</div>
{% load form_helpers %}
<div class="row form-field control-group{% if field.errors %} error{% endif %}{% if required or field.required %} required{% endif %}">
<label class="col-xs-4 control-label">{{ field.label }}</label>
<div class="col-xs-6">{{ field|add_bootstrap_class }}</div>
<div class="col-xs-2 muted">{{ extra_text|default:'' }}</div>
</div>
{% if field.errors %}
<div class="row-fluid form-field control-group error">
<div class="row form-field control-group error">
{% for error in field.errors %}
<span class="help-inline">{{ error }}</span>
{% endfor %}

View File

@ -1,30 +1,30 @@
<div class="well well-small tab-pane{% if active %} active{% endif %}"
<div class="well tab-pane{% if active %} active{% endif %}"
id="tab-{{ form.prefix }}">
<div class="form form-inline"><fieldset>
<div class="row-fluid">
<div class="row">
<h4>Node Detail</h4>
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.node_tags %}
</div>
<div class="row-fluid">
<div class="row">
<h5>Power Management</h5>
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.driver required=True %}
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_address %}
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_username %}
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.ipmi_password %}
</div>
<div class="row-fluid">
<div class="row">
<h5>Networking</h5>
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.mac_addresses required=True %}
</div>
<div class="row-fluid">
<div class="span4">
<div class="row">
<div class="col-xs-4">
<h5>Hardware</h5>
</div>
<label class="span6 checkbox checkbox-inline">
<label class="col-xs-6 checkbox checkbox-inline">
{{ form.introspect_hardware }}<small> {{ form.introspect_hardware.label }}</small>
</label>
</div>
<div class="row-fluid" id="register-hardware-fields">
<div class="row" id="register-hardware-fields">
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.architecture required=True %}
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.cpus extra_text=_('units') required=True %}
{% include 'infrastructure/nodes/_nodes_formset_field.html' with field=form.memory_mb extra_text=_('MB') required=True %}

View File

@ -2,8 +2,8 @@
{% load url from future%}
<div class="nodes">
<div class="span4">
<div class="nodes row">
<div class="col-xs-4">
<div class="widget">
<h3>{% trans 'Hardware Inventory' %}</h3>
<table class="table">
@ -21,7 +21,7 @@
</table>
</div>
</div>
<div class="span4">
<div class="col-xs-4">
<div class="widget">
<h3>{% trans 'Free Nodes' %}</h3>
<div class="d3_pie_chart_distribution" data-used="Deployed={{ deployed_nodes|length }}|Free={{ free_nodes|length }}"></div>
@ -39,7 +39,7 @@
</div>
</div>
</div>
<div class="span4">
<div class="col-xs-4">
<div class="widget">
<h2>{% trans 'Power Status' %}</h2>
<div class="d3_pie_chart_distribution" data-used="Running={{ total_nodes_up|length }}|Stopped={{ total_nodes_down|length }}"></div>

View File

@ -89,7 +89,7 @@
<select data-line-chart-command="select_box_change"
id="date_options"
name="date_options"
class="span2">
class="col-xs-2">
<option value="0.041666">{% trans "Last hour" %}</option>
<option value="0.25">{% trans "Last 6 hours" %}</option>
<option value="0.5">{% trans "Last 12 hours" %}</option>
@ -110,7 +110,7 @@
type="text"
id="date_from"
name="date_from"
class="span2 example"/>
class="col-xs-2 example"/>
</div>
</div>
<div class="control-group" id="date_to">
@ -119,7 +119,7 @@
<input data-line-chart-command="date_picker_change"
type="text"
name="date_to"
class="span2 example"/>
class="col-xs-2 example"/>
</div>
</div>
</form>
@ -155,7 +155,7 @@
<div id="node-charts" class="clearfix">
{% for meter_label, url_part, y_max in meter_conf %}
<div class="span3">
<div class="col-xs-3">
{% include "infrastructure/_performance_chart.html" with label=meter_label y_max=y_max url=node_perf_url|add:"?"|add:url_part only %}
</div>
{% endfor %}

View File

@ -8,8 +8,8 @@
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
<div class="actions pull-right">
<a href="{% url 'horizon:infrastructure:nodes:register' %}" class="btn ajax-modal">
{% trans 'Register Nodes' %}

View File

@ -4,8 +4,8 @@
{% if stack.is_deploying or stack.is_failed %}
{% if stack.is_deploying %}
<div class="alert alert-info">
<div class="row-fluid">
<div class="span2">
<div class="row">
<div class="col-xs-2">
<strong>Deploying...</strong>
<div class="progress progress-striped active progress-info">
<div class="bar bar-info" style="width:{{ progress }}%"></div>
@ -13,15 +13,15 @@
</div>
{% else %}
<div class="alert alert-error">
<div class="row-fluid">
<div class="span2">
<div class="row">
<div class="col-xs-2">
<strong>Deployment failed</strong>
<div class="progress progress-striped progress-danger">
<div class="bar bar-info" style="width:{{ progress }}%"></div>
</div>
</div>
{% endif %}
<div class="span10">
<div class="col-xs-10">
{% if last_failed_events %}
<strong>{% trans "Last failed events:" %}</strong>
{% for event in last_failed_events %}
@ -46,8 +46,8 @@
{% endif %}
{% if not dashboard_urls and not stack.is_deploying and not stack.is_failed %}
<div class="row-fluid">
<div class="span8">
<div class="row">
<div class="col-xs-8">
{% blocktrans %}
Your cloud is now deployed; however, it needs to be initialized. To do so, copy the appropriate script into a file, make it executable, and run it.
{% endblocktrans %}
@ -183,8 +183,8 @@ nova flavor-create m1.tiny 1 512 2 1
</div>
{% endif %}
<div class="row-fluid">
<div class="span8">
<div class="row">
<div class="col-xs-8">
<h2>{% trans "Deployment Roles" %}</h2>
<div class="widget">
<table class="table">
@ -228,9 +228,9 @@ nova flavor-create m1.tiny 1 512 2 1
</td>
<td>
{% if role.capacity %}
<div class="row-fluid">
<div class="span6"><p>{{ role.capacity }}%</p></div>
<div class="span6">
<div class="row">
<div class="col-xs-6"><p>{{ role.capacity }}%</p></div>
<div class="col-xs-6">
<div class="progress active progress-info">
<div class="bar bar-info" style="width:{{ role.capacity }}%"></div>
</div>
@ -243,7 +243,7 @@ nova flavor-create m1.tiny 1 512 2 1
</table>
</div>
</div>
<div class="span4">
<div class="col-xs-4">
<div class="widget">
<h2>{% trans "Deployment Role Distribution" %}</h2>
<div class="d3_pie_chart_distribution" data-used='{% for role in roles %}{{ role.name }}={{ role.deployed_node_count|default:"0" }}{% if not forloop.last %}|{% endif %}{% endfor %}'></div>

View File

@ -1,13 +1,13 @@
{% load i18n %}
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
<div class="actions pull-right">
</div>
{% if stack.is_deleting %}
<div class="alert alert-error">
<div class="row-fluid">
<div class="span2">
<div class="row">
<div class="col-xs-2">
<strong>Undeploying...</strong>
<div class="progress progress-striped progress-danger">
<div class="bar bar-info" style="width:{{ progress }}%"></div>
@ -15,15 +15,15 @@
</div>
{% else %}
<div class="alert alert-error">
<div class="row-fluid">
<div class="span2">
<div class="row">
<div class="col-xs-2">
<strong>Undeploying failed</strong>
<div class="progress progress-striped progress-danger">
<div class="bar bar-info" style="width:{{ progress }}%"></div>
</div>
</div>
{% endif %}
<div class="span10">
<div class="col-xs-10">
{% if last_failed_events %}
<strong>{% trans "Last failed events:" %}</strong>
{% for event in last_failed_events %}

View File

@ -16,9 +16,9 @@
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
<div class="actions pull-right">
<div class="row">
<div class="col-xs-12">
<div class="actions page-actions pull-right">
<a href="{% url 'horizon:infrastructure:overcloud:undeploy_confirmation' stack.id %}"
class="btn btn-danger ajax-modal
{% if not stack.is_deployed and not stack.is_failed %}disabled{% endif %}">

View File

@ -8,8 +8,8 @@
{% endblock page_header %}
{% block main %}
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
<p><strong>{% blocktrans count counter=nodes|length %}{{ counter }} instance{% plural %}{{ counter }} instances{% endblocktrans %}</strong></p>
<dl>
<dt>{% trans 'Flavor' %}</dt>

View File

@ -2,8 +2,8 @@
<noscript><h3>{{ step }}</h3></noscript>
<p>{{ step.get_help_text }}</p>
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
{% include 'horizon/common/_form_fields.html' with form=form %}
</div>
</div>

View File

@ -4,8 +4,8 @@
<noscript><h3>{{ step }}</h3></noscript>
<div class="widget muted">{{ step.get_help_text }}</div>
<div class="row-fluid">
<div class="span8">
<div class="row">
<div class="col-xs-8">
<h2>{% trans "Roles" %}</h2>
<div class="widget">
<td class="actions">

View File

@ -32,7 +32,7 @@ tuskar.menu_formset = (function () {
function add_delete_link($nav_item) {
var $form = $content.find($nav_item.find('a').attr('href'));
$nav_item.prepend('<span class="btn-small pull-right delete-icon"><i class="icon-trash icon-white"></i></span>');
$nav_item.prepend('<span class="btn-small pull-right delete-icon"><i class="glyphicon glyphicon-trash"></i></span>');
$nav_item.find('span.delete-icon:first').click(function () {
var count;
$form.remove();

View File

@ -1,36 +0,0 @@
/* Bootstrap buttons overrides/additions */
// Make a button look and behave like a link - available in later
// bootstrap versions
.btn {
&.btn-link,
&.btn-link:active,
&.btn-link[disabled],
&.btn-link:not(.btn-danger) {
background-color: transparent;
background-image: none;
.box-shadow(none); // mixin override does not work
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
&.btn-link {
border-color: transparent;
cursor: pointer;
color: @linkColor;
.border-radius(0);
}
&.btn-link:hover,
&.btn-link:focus,
&.btn-link:hover:not(.btn-danger),
&.btn-link:focus:not(.btn-danger) {
color: @linkColorHover;
text-decoration: underline;
background-color: transparent;
}
&.btn-link[disabled]:hover,
&.btn-link[disabled]:focus {
color: @linkColor;
text-decoration: none;
}
}

View File

@ -1,228 +0,0 @@
// general
h2 {
font-weight: 200;
font-size: 24px;
color: rgb(80, 80, 80);
line-height: 130%;
}
h3 {
font-weight: lighter;
font-size: 20px;
color: rgb(80,80,80);
margin-bottom: 3px;
margin: 0 0 3px 0;
}
h4 {
font-weight: lighter;
font-size: 18px;
color: rgb(120,120,120);
margin-bottom: 3px;
}
h5 {
font-weight: lighter;
font-size: 16px;
color: rgb(120,120,120);
margin-bottom: 3px;
}
// topbar
.topbar {
background: rgb(239, 239, 239);
padding: 0.5em 2em;
font-size: 90%;
height: 24px;
border-bottom: 1px solid rgb(220, 220, 220);
}
h1.brand a {
height: 24px;
width: 107px;
margin: 0 1em 0 0;
background-size: auto 24px;
}
.topbar .switcher_bar h3 {
line-height: 18px;
font-size: 11px !important;
}
#tenant_switcher {
display: none;
}
#user_info {
margin: 0;
padding: 0;
line-height: 24px;
font-size: 11px !important;
& > a {
font-size: 11px !important;
}
}
// sidebar
.sidebar {
margin: 2.5em 2em;
border: 0 none;
background: none;
}
.nav_accordion {
background: none;
// dashboards
dt {
font-size: 90%;
color: rgb(170, 170, 170);
background-color: transparent;
border: 0 none;
border-bottom: 3px solid rgb(230, 230, 230);
padding: 0.2em 2em 0.2em 0;
&:not(:first-child) {
margin-top: 1em;
}
&.active {
color: rgb(120, 120, 120);
border-bottom: 3px solid rgb(130, 130, 130);
}
div {
font-size: inherit;
color: inherit;
font-weight: normal;
margin: 0;
}
}
// panel groups
dd {
margin: 0;
h4 {
margin: 0;
border: 1px solid rgb(210, 210, 210);
background-color: rgb(240, 240, 240);
color: rgb(140, 140, 140);
max-width: none;
div {
margin: 0 0 0 14px;
}
&.active {
border: 1px solid rgb(210, 210, 210);
background-color: rgb(230, 230, 230);
color: rgb(90, 90, 90);
}
}
// items
ul {
width: auto;
margin: 0 0 0 14px;
li a {
width: auto;
margin: 0;
border-bottom: 1px solid rgb(190, 190, 190);
border-left: 5px solid rgb(230, 230, 230);
color: rgb(90, 90, 90);
opacity: 0.8;
&:last-child {
margin: 0;
}
&.active {
color: rgb(215, 65, 50);
border-top: 0 none;
border-left: 5px solid rgb(215, 65, 50);
background-color: rgb(245, 245, 245);
margin: 0;
border-radius: 0;
opacity: 1;
}
&:hover {
background-color: rgb(245, 245, 245);
opacity: 1;
}
}
}
}
}
// content body
#content_body {
padding-left: 300px;
padding-right: 35px;
padding-top: 2em;
padding-bottom: 3.5em;
}
.page-header {
margin-bottom: 0;
padding: 0;
}
// content nav
#main_content {
.nav-tabs {
margin: 0 0 30px;
border: 0 none;
li a {
font-weight: 500;
position: relative;
top: -1px;
padding: 10px 15px;
border-radius: 0 0 4px 4px;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
border-top-width: 0;
border-color: transparent;
color: #43A1D6;
}
li.active a {
border: 1px solid rgb(220, 220, 220);
background: #43A1D6;
color: white;
text-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
&:after {
color: inherit;
}
}
li:not(.active) a:hover {
border: 1px solid rgb(240, 240, 240);
border-top-width: 0;
background: rgb(244, 244, 244);
}
}
.tab-content {
padding: 0;
border: 0 none;
}
// content area
#content_body > .row-fluid {
margin: 0;
}
.widget:not(:last-child) {
margin: 0 0 2em 0;
}
}
// general
a[data-target] {
cursor: pointer;
}

View File

@ -1,84 +0,0 @@
#nodes-formset-datatable .datatable tbody {
input {
padding: 2px 1px;
}
input.number_input_slim {
width: 3em;
}
td {
padding: 2px;
text-align: center;
a.close {
margin-right: 4px;
}
}
}
// Register nodes formset
.register-nodes-formset {
a.add-node-link {
display: block;
}
.nav-tabs > .active > a {
color: @white;
background-color: @linkColor;
}
ul.nav-tabs > li span.delete-icon {
display: none;
}
ul.nav-tabs > li.active span.delete-icon {
display: block;
margin: 4px 19px 4px 0;
cursor: pointer;
}
ul.nav-tabs > li {
position: relative;
}
ul.nav-tabs > li.active {
width: 107%;
}
ul.nav-tabs > li.active:after {
display: block;
content: '';
position: absolute;
top: 1px;
right: -7px;
border-top: 16px solid transparent;
border-bottom: 16px solid transparent;
border-left: 8px solid @linkColor;
}
.register-nav-head {
margin-top: 19px;
margin-bottom: 5px;
}
.form h5 {
margin: 0.5em 0 0.75em 0;
}
.form label.checkbox {
font-weight: normal;
}
fieldset .form-field {
input, textarea, select {
width: 150px;
margin-left: 5px;
}
}
}
#detail__overview {
ul {
list-style: disc;
margin: 0 0 9px 25px;
}
}

View File

@ -1,96 +0,0 @@
/* Additional CSS for infrastructure. */
@import "../../bootstrap/less/variables.less";
@import "numberpicker.less";
@import "bootstrap.less";
@import "breadcrumbs.less";
@import "buttons.less";
@import "capacities.less";
@import "flavor_usages.less";
@import "formsets.less";
@import "index_pages.less";
@import "individual_pages.less";
@import "tables.less";
@import "horizon_upgrades.less";
// disable text select on element
.unselectable {
user-select: none;
-o-user-select:none;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
}
.actions {
// not nice, but actions should be placed above the line
// will fix the style for now, better solution needed
margin: -33px 0 0 0;
}
// hide the project switcher from the top bar
#tenant_switcher {
visibility: hidden;
}
// Node detail view
.node-details {
.powerstate {
background-image: url(../images/power.png);
background-repeat: no-repeat;
height: 20px;
padding: 4px 30px;
}
.node-detail {
width: 50%;
}
.node-deployment {
float: right;
width: 50%;
}
.dropdown-menu li {
margin: 5px 10px;
}
.node h4 {
margin-top: 8px;
margin-bottom: 5px;
}
#node-charts {
margin-left: -20px;
}
.chart svg {
height: 120px;
width: 144px;
path.undefined {
stroke-width: 1px;
stroke: #ff7f0e;
}
.y_ticks text {
display: none;
}
}
}
// Node overview
.nodes {
.widget-info {
span {
font-size: 200%;
}
}
.d3_pie_chart_distribution {
.legend {
position: fixed;
}
}
}

View File

@ -1,69 +0,0 @@
// tables
table.table {
th.table_header {
padding: 10px 0;
background: none;
}
th {
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
}
tfoot {
color: rgb(180,180,180);
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
tr td {
padding: 7px 12px;
height: auto;
}
}
.table_actions {
width: 100%;
text-align: right;
}
.table_title {
display: none;
}
.table_search {
float: left;
}
tr td {
padding: 0px 10px;
line-height: 1;
height: 53px;
vertical-align: middle;
&.anchor {
padding: 0;
a {
padding: 4px 10px;
}
}
}
.table_search input {
padding-left: 10px;
}
.table-bordered tr.table_caption + tr th:first-child {
border-top-left-radius: 2px;
}
.table-bordered tr.table_caption + tr th:last-child {
border-top-right-radius: 2px;
}
.table-bordered tfoot tr td:first-child {
border-bottom-left-radius: 2px;
}
.table-bordered tfoot tr td:last-child {
border-bottom-right-radius: 2px;
}
}

View File

@ -15,11 +15,11 @@
}
th span.required:after {
// Copied from horizon.less, because there is no way to reuse their class.
// Copied from horizon, because there is no way to reuse their class.
content: "*";
font-weight: bold;
line-height: 0;
padding-left: 4px;
color: #3290c0;
color: #428bca;
}
}

View File

@ -0,0 +1,158 @@
#nodes-formset-datatable .datatable tbody {
input {
padding: 2px 1px;
}
input.number_input_slim {
width: 3em;
}
td {
padding: 2px;
text-align: center;
a.close {
margin-right: 4px;
}
}
}
$link-color: #428bca;
// Register nodes formset
.register-nodes-formset {
a.add-node-link {
display: block;
float: right;
}
.nav-pills > .active > a {
color: #fff;
background-color: $link-color;
}
ul.nav-pills > li span.delete-icon {
display: none;
}
ul.nav-pills > li.active span.delete-icon {
display: block;
cursor: default;
color: #fff;
z-index: 1000;
position: absolute;
right: 16px;
top: 10px;
}
ul.nav-pills > li {
position: relative;
}
ul.nav-pills > li.active {
width: 107%;
}
ul.nav-pills > li.active:after {
display: block;
content: '';
position: absolute;
top: 1px;
right: -7px;
border-top: 18px solid transparent;
border-bottom: 18px solid transparent;
border-left: 8px solid $link-color;
}
.register-nav-head {
margin-top: 19px;
margin-bottom: 5px;
h4 {
margin: 0;
}
}
.form h5 {
margin: 0.5em 0 0.75em 0;
}
.form label.checkbox {
font-weight: normal;
}
fieldset .form-field {
input, textarea, select {
width: 150px;
margin-left: 5px;
}
}
}
#detail__overview {
ul {
list-style: disc;
margin: 0 0 9px 25px;
}
}
// Node detail view
.node-details {
.powerstate {
background-image: url(../images/power.png);
background-repeat: no-repeat;
height: 20px;
padding: 4px 30px;
}
.node-detail {
width: 50%;
}
.node-deployment {
float: right;
width: 50%;
}
.dropdown-menu li {
margin: 5px 10px;
}
.node h4 {
margin-top: 8px;
margin-bottom: 5px;
}
#node-charts {
margin-left: -20px;
}
.chart svg {
height: 120px;
width: 144px;
path.undefined {
stroke-width: 1px;
stroke: #ff7f0e;
}
.y_ticks text {
display: none;
}
}
}
// Node overview
.nodes {
.widget-info {
span {
font-size: 200%;
}
}
.d3_pie_chart_distribution {
.legend {
position: fixed;
}
}
}

View File

@ -0,0 +1,16 @@
/* Additional CSS for infrastructure. */
@import "/horizon/scss/_variables";
@import "_numberpicker";
@import "_breadcrumbs";
@import "_buttons";
@import "_capacities";
@import "_flavor_usages";
@import "_formsets";
@import "_index_pages";
@import "_individual_pages";
// hide the project switcher from the top bar
#tenant_switcher {
visibility: hidden;
}

View File

@ -3,14 +3,15 @@
{% for error in formset.non_form_errors %}
<div class="alert alert-error error">{{ error }}</div>
{% endfor %}
<div class="row-fluid register-nodes-formset" id="formset-{{ formset.prefix }}">
<div class="span5">
<div class="row register-nodes-formset" id="formset-{{ formset.prefix }}">
<div class="col-xs-5">
<div class="clearfix register-nav-head">
<a class="pull-right add-node-link"
href="#"><i class="icon-plus"></i> {% trans "Add Node" %}</a>
<a class="add-node-link" href="#">
<i class="glyphicon glyphicon-plus"></i> {% trans "Add Node" %}
</a>
<h4>Nodes to register</h4>
</div>
<ul class="nav nav-tabs nav-stacked">
<ul class="nav nav-pills nav-stacked">
{% for form in formset %}
<li {% if forloop.first %}class="active"{% endif %}>
<a href="#tab-{{ form.prefix }}" data-toggle="tab">
@ -20,7 +21,7 @@
{% endfor %}
</ul>
</div>
<div class="span7">
<div class="col-xs-7">
<div class="tab-content">
{% for form in formset %}
{% include form_template with form=form active=forloop.first %}

View File

@ -1,12 +1,2 @@
<div class="control-group form-field clearfix{% if field.errors %} error{% endif %} {{ field.css_classes }}">
{{ field.label_tag }}
{% if field.errors %}
{% for error in field.errors %}
<span class="help-inline">{{ error }}</span>
{% endfor %}
{% endif %}
<span class="help-block">{{ field.help_text }}</span>
<div class="input">
{{ field }}
</div>
</div>
{% load bootstrap_form_field %}
{{ field|bootstrap_form_field }}

View File

@ -1,7 +1,9 @@
{% load form_helpers %}
<div class="control-group{% if field.errors %} error{% endif %} {{ field.css_classes }}">
<label class="control-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
<div class="controls">
{{ field }}
{{ field|add_bootstrap_class }}
{% for error in field.errors %}
<span class="help-inline text-error">{{ error }}</span>
{% empty %}

View File

@ -1,7 +1,7 @@
{% load i18n %}
{% with workflow.get_entry_point as entry_point %}
<div class="row-fluid">
<form class="form form-horizontal span12" {{ workflow.attr_string|safe }} action="{{ workflow.get_absolute_url }}" {% if add_to_field %}data-add-to-field="{{ add_to_field }}"{% endif %} method="POST"{% if workflow.multipart %} enctype="multipart/form-data"{% endif %}>
<div class="row">
<form class="form form-horizontal col-xs-12" {{ workflow.attr_string|safe }} action="{{ workflow.get_absolute_url }}" {% if add_to_field %}data-add-to-field="{{ add_to_field }}"{% endif %} method="POST"{% if workflow.multipart %} enctype="multipart/form-data"{% endif %}>
{% csrf_token %}
{% if REDIRECT_URL %}<input type="hidden" name="{{ workflow.redirect_param_name }}" value="{{ REDIRECT_URL }}"/>{% endif %}
<div class="fullscreen-workflow-body">

View File

@ -5,7 +5,7 @@
{% load compress %}
{% compress css %}
<link href='{{ STATIC_URL }}infrastructure/less/infrastructure.less' type='text/less' media='screen' rel='stylesheet' />
<link href='{{ STATIC_URL }}infrastructure/scss/infrastructure.scss' type='text/scss' media='screen' rel='stylesheet' />
{% endcompress %}
{% endblock %}

View File

@ -2,8 +2,8 @@
{% block main %}
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
{% block breadcrumbs %}{% endblock %}
<div class="pull-right btn-toolbar">
@ -14,8 +14,8 @@
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div class="row">
<div class="col-xs-12">
<div class="pull-right">
{% block overall_usage %}{% endblock %}
</div>

View File

@ -0,0 +1,38 @@
# -*- coding: utf8 -*-
#
# 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.
import django.forms
import django.template
register = django.template.Library()
@register.filter
def add_bootstrap_class(field):
"""Add a "form-control" CSS class to the field's widget.
This is so that Bootstrap styles it properly.
"""
if not isinstance(field, (
django.forms.CheckboxInput,
django.forms.CheckboxSelectMultiple,
django.forms.RadioSelect,
django.forms.FileInput,
str,
)):
field_classes = set(field.field.widget.attrs.get('class', '').split())
field_classes.add('form-control')
field.field.widget.attrs['class'] = ' '.join(field_classes)
return field