murano-dashboard/muranodashboard/templates/services/_wizard_create.html
Aleksey Nakoryakov 93d8a1e160 Show resource usages for application
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
2018-01-17 04:26:25 +00:00

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 %}