93d8a1e160
Show them in the description section right under the Flavor field title (as quota usages + predicted increment progress bar). Co-Authored-By: Timur Sufiev <tsufiev@gmail.com> Co-Authored-By: Artem Tiumentcev <darland.maik@gmail.com> Change-Id: I842cbce209ea90ab715d2e50824296a19c202a76
302 lines
12 KiB
HTML
302 lines
12 KiB
HTML
{% extends "horizon/common/_modal_form.html" %}
|
|
{% load i18n horizon humanize bootstrap %}
|
|
{% block form_action %}
|
|
{% url 'horizon:app-catalog:catalog:add' app_id environment_id do_redirect drop_wm_form %}
|
|
{% endblock %}
|
|
{% block form_id %}form_{{ app_id }}{% endblock %}
|
|
{% block modal_id %}modal_{{ app_id }}{% endblock %}
|
|
{% block modal-header %}
|
|
<span class="wizard_title">
|
|
<img src="{% url 'horizon:app-catalog:catalog:images' app_id %}" height="25" width="25"/>
|
|
{% trans "Configure Application" %}: {{ service_name }}
|
|
</span>
|
|
{% endblock %}
|
|
{% block steps-list %}
|
|
<div class="steps_list_container">
|
|
<ul class="steps_list list-inline">
|
|
{% with steps=wizard.steps %}
|
|
{% for step in steps.all %}
|
|
{% with counter0=forloop.counter0 %}
|
|
<li class="{% if counter0 == steps.step0 %}active {% elif counter0 < steps.step0 %}done{% endif %}">
|
|
{{ step }}
|
|
</li>
|
|
{% endwith %}
|
|
{% endfor %}
|
|
{% endwith %}
|
|
</ul>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block modal-body %}
|
|
{% for ext_description in extended_descriptions %}
|
|
<p>{{ ext_description }}</p>
|
|
{% endfor %}
|
|
<div class="left">
|
|
{{ wizard.management_form }}
|
|
{% if wizard.form.forms %}
|
|
{{ wizard.form.management_form }}
|
|
{% for form in wizard.form.forms %}
|
|
{{ form }}
|
|
{% endfor %}
|
|
{% else %}
|
|
<fieldset>
|
|
{% with form=wizard.form %}
|
|
{% include "horizon/common/_form_fields.html" %}
|
|
{% endwith %}
|
|
</fieldset>
|
|
{% endif %}
|
|
</div>
|
|
<div class="right">
|
|
{% for name, title, description in field_descriptions %}
|
|
<p>
|
|
{% if title %}
|
|
<strong data-field-name="{{ wizard.steps.step0 }}-{{ name }}">
|
|
{{ title }}:
|
|
</strong>
|
|
{% endif %}
|
|
<div class="more_dynamicui_description">
|
|
{{ description|linebreaksbr }}
|
|
</div>
|
|
</p>
|
|
{% endfor %}
|
|
</div>
|
|
{% if usages %}
|
|
<script type="text/html" id="quota_bars">
|
|
<div class="quota_title">
|
|
<strong class="pull-left">{% trans "Number of Instances" %}</strong>
|
|
<span class="pull-right">
|
|
{% blocktrans with used=usages.totalInstancesUsed|intcomma other_used=other_usages.totalInstancesUsed|intcomma quota=usages.maxTotalInstances|intcomma|quotainf %}
|
|
{{ used }} + {{ other_used }} of {{ quota }} used
|
|
{% endblocktrans %}
|
|
</span>
|
|
</div>
|
|
<div id="quota_instances"
|
|
class="quota_bar"
|
|
data-progress-indicator-flavor
|
|
data-quota-limit="{{ usages.maxTotalInstances }}"
|
|
data-quota-used="{{ usages.totalInstancesUsed }}">
|
|
{% widthratio usages.totalInstancesUsed usages.maxTotalInstances 100 as instance_percent %}
|
|
{% widthratio other_usages.totalInstancesUsed usages.maxTotalInstances 100 as instance_other_percent %}
|
|
{% bs_progress_bar instance_percent instance_other_percent 0 contexts=contexts %}
|
|
</div>
|
|
|
|
<div class="quota_title">
|
|
<strong class="pull-left">{% trans "Number of VCPUs" %}</strong>
|
|
<span class="pull-right">
|
|
{% blocktrans with used=usages.totalCoresUsed|intcomma other_used=other_usages.totalCoresUsed|intcomma quota=usages.maxTotalCores|intcomma|quotainf %}
|
|
{{ used }} + {{ other_used }} of {{ quota }} used
|
|
{% endblocktrans %}
|
|
</span>
|
|
</div>
|
|
<div id="quota_vcpus"
|
|
class="quota_bar"
|
|
data-progress-indicator-flavor
|
|
data-quota-limit="{{ usages.maxTotalCores }}"
|
|
data-quota-used="{{ usages.totalCoresUsed }}">
|
|
{% widthratio usages.totalCoresUsed usages.maxTotalCores 100 as vcpu_percent %}
|
|
{% widthratio other_usages.totalCoresUsed usages.maxTotalCores 100 as vcpu_other_percent %}
|
|
{% bs_progress_bar vcpu_percent vcpu_other_percent 0 contexts=contexts %}
|
|
</div>
|
|
|
|
<div class="quota_title">
|
|
<strong class="pull-left">{% trans "Total RAM" %}</strong>
|
|
<span class="pull-right">
|
|
{% blocktrans with used=usages.totalRAMUsed|intcomma other_used=other_usages.totalRAMUsed|intcomma quota=usages.maxTotalRAMSize|intcomma|quotainf %}
|
|
{{ used }} + {{ other_used }} of {{ quota }} MB used
|
|
{% endblocktrans %}
|
|
</span>
|
|
</div>
|
|
<div id="quota_ram"
|
|
class="quota_bar"
|
|
data-progress-indicator-flavor
|
|
data-quota-limit="{{ usages.maxTotalRAMSize }}"
|
|
data-quota-used="{{ usages.totalRAMUsed }}">
|
|
{% widthratio usages.totalRAMUsed usages.maxTotalRAMSize 100 as ram_percent %}
|
|
{% widthratio other_usages.totalRAMUsed usages.maxTotalRAMSize 100 as ram_other_percent %}
|
|
{% bs_progress_bar ram_percent ram_other_percent 0 contexts=contexts %}
|
|
</div>
|
|
</script>
|
|
{% endif %}
|
|
{% endblock %}
|
|
|
|
{% block modal-footer %}
|
|
<script type="text/javascript">
|
|
{# TODO(efedorova): extract to a separate file #}
|
|
$(function() {
|
|
"use strict";
|
|
{# Make element ids unique per-wizard to avoid interference #}
|
|
{# upon pressing 'Back' button while creating one application #}
|
|
{# from another #}
|
|
var btn_id = '#{{ prefix }}_btn',
|
|
val_id = '#{{ prefix }}_val',
|
|
current_step = {{ wizard.steps.index }},
|
|
form_data = {},
|
|
wizard_id = '{{ wizard_id }}',
|
|
session_data = sessionStorage.getItem(wizard_id + current_step),
|
|
form = $('#form_' + '{{ prefix }}'.split("_")[1]),
|
|
fields = '.form-group input, .form-group select, .form-group textarea';
|
|
if (current_step > 0) {
|
|
// Update form with saved data
|
|
if (session_data) {
|
|
setFormData(JSON.parse(session_data));
|
|
}
|
|
// Collect loaded form data
|
|
form_data = rearrangeKeys(getFormData());
|
|
}
|
|
$(btn_id).click(function() {
|
|
var current_data = JSON.stringify(rearrangeKeys(getFormData()));
|
|
// Check if there any changes in the form
|
|
if (current_data != JSON.stringify(form_data)) {
|
|
// Save current data into session storage
|
|
sessionStorage.setItem(wizard_id + current_step, current_data);
|
|
}
|
|
$(val_id).val('{{ wizard.steps.prev }}')
|
|
});
|
|
$('input[type="submit"]').click(function() {
|
|
clearSession(current_step);
|
|
return true;
|
|
});
|
|
$('a.close').click(function() {
|
|
var step = 1;
|
|
for (; step < {{ wizard.steps.count }}; step++) {
|
|
clearSession(step);
|
|
}
|
|
return true;
|
|
});
|
|
$('#modal_wrapper').on('new_modal', function(evt, modal) {
|
|
var $modal = $(modal);
|
|
$modal.find('.form-group input, select').each(function(index, elem) {
|
|
var $elem = $(elem),
|
|
name = $elem.attr('name'),
|
|
$descEntry = $modal.find('strong[data-field-name*="'+name+'"]'),
|
|
$button = elem.tagName == 'SELECT' && $elem.next().find('a'),
|
|
bindHandler = function($el) {
|
|
$el.blur(function() {
|
|
$descEntry.children('i').remove();
|
|
$descEntry.removeClass('selected-field');
|
|
}).focus(function() {
|
|
// remove <i> if previous form without submit
|
|
$descEntry.children('i').remove();
|
|
$descEntry.addClass('selected-field');
|
|
$descEntry.prepend(
|
|
"<i class='fa fa-chevron-circle-right'></i>");
|
|
})
|
|
};
|
|
bindHandler($elem);
|
|
// track both parts of add-select widget
|
|
if ( $button && $button.length ) {
|
|
bindHandler($button);
|
|
}
|
|
}).filter(':first').trigger('focus');
|
|
|
|
// Update flavor specs in a description area
|
|
var $flavorElem = $modal.find('.form-group select.flavor');
|
|
if ($flavorElem.length) {
|
|
var name = $flavorElem.attr('name'),
|
|
$flavorTitle = $modal.find('strong[data-field-name*="'+name+'"]').closest('p'),
|
|
$flavorSpecs = $flavorTitle.find('.flavor-specs');
|
|
|
|
if ($flavorSpecs.length == 0) {
|
|
$flavorTitle.append('<div class="flavor-specs"></div>');
|
|
$flavorSpecs = $flavorTitle.find('.flavor-specs');
|
|
}
|
|
var flavors = {{ flavors|safe|default:"{}" }};
|
|
if (!$flavorSpecs.find('.progress').length && flavors.length) {
|
|
$flavorSpecs.append($('#quota_bars').html());
|
|
horizon.Quota.initWithFlavors(flavors);
|
|
}
|
|
|
|
// Update quota titles according to the selected flavor
|
|
var updateQuotaTitles = function() {
|
|
var appendVal = function(elem, value) {
|
|
var origTitle = elem.data('orig-title');
|
|
if (!origTitle) {
|
|
elem.data('orig-title', origTitle = elem.text());
|
|
}
|
|
elem.text(value + ' + ' + origTitle);
|
|
};
|
|
var selFlavor = $.grep(flavors, function(flavor) {
|
|
return flavor.id === $flavorElem.val();
|
|
})[0];
|
|
$flavorSpecs.find('.quota_title span').each(function(idx) {
|
|
switch (idx) {
|
|
// instance count title case
|
|
case 0:
|
|
appendVal($(this), 1);
|
|
break;
|
|
// VCPU count title case
|
|
case 1:
|
|
appendVal($(this), selFlavor.vcpus);
|
|
break;
|
|
// RAM amount title case
|
|
case 2:
|
|
appendVal($(this), selFlavor.ram);
|
|
break;
|
|
}
|
|
});
|
|
};
|
|
updateQuotaTitles();
|
|
$flavorElem.on('change', updateQuotaTitles);
|
|
}
|
|
});
|
|
// show full name on text overflow
|
|
$('.modal-dialog h3').each(function () {
|
|
$(this).bind('mouseenter', function () {
|
|
var $this = $(this);
|
|
|
|
if (this.offsetWidth < this.scrollWidth && !$this.attr('title')) {
|
|
$this.attr('title', $this.text());
|
|
}
|
|
});
|
|
});
|
|
function getFormData() {
|
|
var inputs = {};
|
|
form.find(fields).each(function() {
|
|
inputs[this.id] = [$(this).val(), $(this).is(':checked')];
|
|
});
|
|
return inputs;
|
|
}
|
|
function setFormData(data) {
|
|
form.find(fields).each(function() {
|
|
var field = $(this);
|
|
if (field.is('select')) {
|
|
field.find('option:selected').removeAttr('selected');
|
|
}
|
|
if (data[this.id][1]) {
|
|
field.prop('checked', true);
|
|
}
|
|
field.val(data[this.id][0]);
|
|
});
|
|
}
|
|
function clearSession(step) {
|
|
sessionStorage.removeItem(wizard_id + step);
|
|
}
|
|
function rearrangeKeys(obj) {
|
|
return Object.keys(obj).sort().reduce(function assemble(acc, key) {
|
|
acc[key] = obj[key];
|
|
return acc;
|
|
}, {});
|
|
}
|
|
});
|
|
</script>
|
|
{{ wizard.form.media }}
|
|
|
|
<input type="hidden" name="wizard_id" value="{{ wizard_id }}"/>
|
|
<input type="hidden" name="wizard_goto_step" id="{{ prefix }}_val"/>
|
|
<input type="hidden" name="do_redirect" value="{{ do_redirect }}"/>
|
|
<input type="hidden" name="drop_wm_form" value="{{ drop_wm_form }}"/>
|
|
{% if wizard.steps.next %}
|
|
{% trans "Next" as next %}
|
|
{% else %}
|
|
{% trans "Create" as next %}
|
|
{% endif %}
|
|
{% if wizard.steps.index > 0 %}
|
|
<input type="submit" class="btn btn-primary pull-right" value="{{ next }}"/>
|
|
<button name="wizard_goto_step" type="submit" class="btn btn-small wizard_cancel"
|
|
id="{{ prefix }}_btn">{% trans "Back" %}</button>
|
|
{% else %}
|
|
<button name="wizard_goto_step" type="submit" class="btn btn-small">
|
|
{{ next }}</button>
|
|
{% endif %}
|
|
{% endblock %}
|