2016-12-02 17:06:04 +07:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2012-06-23 13:58:35 -07:00
|
|
|
/*
|
2013-05-06 16:53:11 -07:00
|
|
|
Used for animating and displaying quota information on forms using
|
|
|
|
D3js progress bars. Also used for displaying flavor details on modal-
|
2012-06-23 13:58:35 -07:00
|
|
|
dialogs.
|
|
|
|
|
|
|
|
Usage:
|
|
|
|
In order to have progress bars that work with this, you need to have a
|
|
|
|
DOM structure like this in your Django template:
|
|
|
|
|
|
|
|
<div id="your_progress_bar_id" class="quota_bar">
|
|
|
|
</div>
|
|
|
|
|
|
|
|
With this progress bar, you then need to add some data- HTML attributes
|
|
|
|
to the div #your_progress_bar_id. The available data- attributes are:
|
|
|
|
|
|
|
|
data-quota-used="integer" REQUIRED
|
2013-12-27 14:48:59 +01:00
|
|
|
Integer representing the total number used by the user.
|
2012-06-23 13:58:35 -07:00
|
|
|
|
|
|
|
data-quota-limit="integer" REQUIRED
|
2013-12-27 14:48:59 +01:00
|
|
|
Integer representing the total quota limit the user has. Note this IS
|
|
|
|
NOT the amount remaining they can use, but the total original quota.
|
2012-06-23 13:58:35 -07:00
|
|
|
|
|
|
|
ONE OF THE THREE ATTRIBUTES BELOW IS REQUIRED:
|
|
|
|
|
|
|
|
data-progress-indicator-step-by="integer" OPTIONAL
|
2013-12-27 14:48:59 +01:00
|
|
|
Indicates the numeric unit the quota JavaScript should automatically
|
|
|
|
animate this progress bar by on load. Can be used with the other
|
|
|
|
data- attributes.
|
2012-06-23 13:58:35 -07:00
|
|
|
|
2013-12-27 14:48:59 +01:00
|
|
|
A good use-case here is when you have a modal dialog to create ONE
|
|
|
|
volume, and you have a progress bar for volumes, but there are no
|
|
|
|
form elements that represent that number (as it is not settable by
|
|
|
|
the user.)
|
2012-06-23 13:58:35 -07:00
|
|
|
|
|
|
|
data-progress-indicator-for="html_id_of_form_input"
|
2013-12-27 14:48:59 +01:00
|
|
|
Tells the quota JavaScript which form element on this page is tied to
|
|
|
|
this progress indicator. If this form element is an input, it will
|
|
|
|
automatically fire on "keyup" in that form field, and change this
|
|
|
|
progress bar to denote the numeric change.
|
2012-06-23 13:58:35 -07:00
|
|
|
|
|
|
|
data-progress-indicator-flavor
|
2013-12-27 14:48:59 +01:00
|
|
|
This attribute is used to tell this quota JavaScript that this
|
|
|
|
progress bar is controller by an instance flavor select form element.
|
|
|
|
This attribute takes no value, but is used and configured
|
2014-02-07 15:14:40 +08:00
|
|
|
automatically by this script to update when a new flavor is chosen
|
2013-12-27 14:48:59 +01:00
|
|
|
by the end-user.
|
2012-06-23 13:58:35 -07:00
|
|
|
*/
|
|
|
|
horizon.Quota = {
|
|
|
|
is_flavor_quota: false, // Is this a flavor-based quota display?
|
|
|
|
user_value_progress_bars: [], // Progress bars triggered by user-changeable form elements.
|
|
|
|
auto_value_progress_bars: [], // Progress bars that should be automatically changed.
|
|
|
|
flavor_progress_bars: [], // Progress bars that relate to flavor details.
|
|
|
|
user_value_form_inputs: [], // The actual form inputs that trigger progress changes.
|
|
|
|
selected_flavor: null, // The flavor object of the current selected flavor on the form.
|
|
|
|
flavors: [], // The flavor objects the form represents, passed to us in initWithFlavors.
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Determines the progress bars and form elements to be used for quota
|
|
|
|
display. Also attaches handlers to the form elements as well as performing
|
|
|
|
the animations when the progress bars first load.
|
|
|
|
*/
|
2012-06-23 13:58:35 -07:00
|
|
|
init: function() {
|
|
|
|
this.user_value_progress_bars = $('div[data-progress-indicator-for]');
|
|
|
|
this.auto_value_progress_bars = $('div[data-progress-indicator-step-by]');
|
|
|
|
this.user_value_form_inputs = $($.map(this.user_value_progress_bars, function(elm) {
|
|
|
|
return ('#' + $(elm).attr('data-progress-indicator-for'));
|
|
|
|
}));
|
|
|
|
|
|
|
|
this._attachInputHandlers();
|
|
|
|
},
|
|
|
|
|
2013-05-30 13:48:49 -04:00
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Confirm that the specified attribute 'actual' meets
|
|
|
|
or exceeds the specified value 'minimum'.
|
|
|
|
*/
|
2013-05-30 13:48:49 -04:00
|
|
|
belowMinimum: function(minimum, actual) {
|
2013-12-27 14:48:59 +01:00
|
|
|
return parseInt(minimum, 10) > parseInt(actual, 10);
|
2013-05-30 13:48:49 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Determines if the selected image meets the requirements of
|
|
|
|
the selected flavor.
|
|
|
|
*/
|
2013-05-30 13:48:49 -04:00
|
|
|
imageFitsFlavor: function(image, flavor) {
|
2013-11-26 15:17:02 +01:00
|
|
|
if (image === undefined) {
|
2013-12-27 14:48:59 +01:00
|
|
|
/*
|
|
|
|
If we don't actually have an image, we don't need to
|
|
|
|
limit our flavors, so we return true in this case.
|
|
|
|
*/
|
|
|
|
return true;
|
2013-05-30 13:48:49 -04:00
|
|
|
} else {
|
2015-04-22 16:04:56 -07:00
|
|
|
var overDisk = horizon.Quota.belowMinimum(image.min_disk, flavor.disk);
|
|
|
|
var overRAM = horizon.Quota.belowMinimum(image.min_ram, flavor.ram);
|
2013-12-27 14:48:59 +01:00
|
|
|
return !(overDisk || overRAM);
|
2013-05-30 13:48:49 -04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Note to the user that some flavors have been disabled.
|
|
|
|
*/
|
2013-05-30 13:48:49 -04:00
|
|
|
noteDisabledFlavors: function(allDisabled) {
|
2013-11-26 15:17:02 +01:00
|
|
|
if ($('#some_flavors_disabled').length === 0) {
|
2016-02-19 10:41:34 +01:00
|
|
|
var message = allDisabled ? horizon.Quota.allFlavorsDisabledMessage
|
|
|
|
: horizon.Quota.disabledFlavorMessage;
|
2013-05-30 13:48:49 -04:00
|
|
|
$('#id_flavor').parent().append("<span id='some_flavors_disabled'>" +
|
2013-12-27 14:48:59 +01:00
|
|
|
message + '</span>');
|
2013-05-30 13:48:49 -04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Re-enables all flavors that may have been disabled, and
|
|
|
|
clear the message displayed about them being disabled.
|
|
|
|
*/
|
2013-05-30 13:48:49 -04:00
|
|
|
resetFlavors: function() {
|
|
|
|
if ($('#some_flavors_disabled')) {
|
2013-12-27 14:48:59 +01:00
|
|
|
$('#some_flavors_disabled').remove();
|
|
|
|
$('#id_flavor option').each(function() {
|
|
|
|
$(this).attr('disabled', false);
|
|
|
|
});
|
2013-05-30 13:48:49 -04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
A convenience method to find an image object by its id.
|
|
|
|
*/
|
2013-05-30 13:48:49 -04:00
|
|
|
findImageById: function(id) {
|
2015-04-22 16:04:56 -07:00
|
|
|
var _image;
|
2013-05-30 13:48:49 -04:00
|
|
|
$.each(horizon.Quota.images, function(i, image){
|
2014-01-02 15:58:43 +01:00
|
|
|
if(image.id === id) {
|
2013-12-27 14:48:59 +01:00
|
|
|
_image = image;
|
|
|
|
}
|
2013-05-30 13:48:49 -04:00
|
|
|
});
|
|
|
|
return _image;
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2015-12-14 17:56:25 +01:00
|
|
|
Return an image/snapshot Object based on which image/snapshot ID is selected
|
2013-12-27 14:48:59 +01:00
|
|
|
*/
|
2015-12-14 17:56:25 +01:00
|
|
|
getSelectedImageOrSnapshot: function(source_type) {
|
|
|
|
var selected = $('#id_' + source_type + '_id option:selected').val();
|
2013-05-30 13:48:49 -04:00
|
|
|
return horizon.Quota.findImageById(selected);
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2015-12-14 17:56:25 +01:00
|
|
|
Disable any flavors for a given image/snapshot that do not meet
|
2013-12-27 14:48:59 +01:00
|
|
|
its minimum RAM or disk requirements.
|
|
|
|
*/
|
2015-12-14 17:56:25 +01:00
|
|
|
disableFlavorsForImage: function(source_type) {
|
|
|
|
var source = horizon.Quota.getSelectedImageOrSnapshot(source_type);
|
2015-04-22 16:04:56 -07:00
|
|
|
var to_disable = []; // an array of flavor names to disable
|
2013-05-30 13:48:49 -04:00
|
|
|
|
|
|
|
horizon.Quota.resetFlavors(); // clear any previous messages
|
|
|
|
|
|
|
|
$.each(horizon.Quota.flavors, function(i, flavor) {
|
2015-12-14 17:56:25 +01:00
|
|
|
if (!horizon.Quota.imageFitsFlavor(source, flavor)) {
|
2013-12-27 14:48:59 +01:00
|
|
|
to_disable.push(flavor.name);
|
|
|
|
}
|
2013-05-30 13:48:49 -04:00
|
|
|
});
|
|
|
|
|
2015-04-22 16:04:56 -07:00
|
|
|
var flavors = $('#id_flavor option');
|
2013-05-30 13:48:49 -04:00
|
|
|
// Now, disable anything from above:
|
|
|
|
$.each(to_disable, function(i, flavor_name) {
|
2013-12-27 14:48:59 +01:00
|
|
|
flavors.each(function(){
|
2014-01-02 15:58:43 +01:00
|
|
|
if ($(this).text() === flavor_name) {
|
2013-12-27 14:48:59 +01:00
|
|
|
$(this).attr('disabled', 'disabled');
|
|
|
|
}
|
|
|
|
});
|
2013-05-30 13:48:49 -04:00
|
|
|
});
|
|
|
|
|
|
|
|
// And then, finally, clean up:
|
|
|
|
if (to_disable.length > 0) {
|
2015-04-22 16:04:56 -07:00
|
|
|
var selected = ($('#id_flavor option').filter(':selected'))[0];
|
2013-12-27 14:48:59 +01:00
|
|
|
if (to_disable.length < flavors.length && selected.disabled) {
|
|
|
|
// we need to find a new flavor to select
|
|
|
|
flavors.each(function(index, element) {
|
|
|
|
if (!element.disabled) {
|
|
|
|
$('#id_flavor').val(element.value);
|
|
|
|
$('#id_flavor').change(); // force elements to update
|
|
|
|
return false; // break
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2014-01-02 15:58:43 +01:00
|
|
|
horizon.Quota.noteDisabledFlavors(to_disable.length === flavors.length);
|
2013-05-30 13:48:49 -04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Store an array of image objects
|
|
|
|
*/
|
2013-05-30 13:48:49 -04:00
|
|
|
initWithImages: function(images, disabledMessage, allDisabledMessage) {
|
|
|
|
this.images = images;
|
|
|
|
this.disabledFlavorMessage = disabledMessage;
|
|
|
|
this.allFlavorsDisabledMessage = allDisabledMessage;
|
|
|
|
// Check if the image is pre-selected
|
2015-12-14 17:56:25 +01:00
|
|
|
horizon.Quota.disableFlavorsForImage('image');
|
2013-05-30 13:48:49 -04:00
|
|
|
},
|
|
|
|
|
2012-06-23 13:58:35 -07:00
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Sets up the quota to be used with flavor form selectors, which requires
|
|
|
|
some different handling of the forms. Also calls init() so that all of the
|
|
|
|
other animations and handlers are taken care of as well when initializing
|
|
|
|
with this method.
|
|
|
|
*/
|
2012-06-23 13:58:35 -07:00
|
|
|
initWithFlavors: function(flavors) {
|
|
|
|
this.is_flavor_quota = true;
|
|
|
|
this.flavor_progress_bars = $('div[data-progress-indicator-flavor]');
|
|
|
|
this.flavors = flavors;
|
|
|
|
|
|
|
|
this.init();
|
|
|
|
|
|
|
|
this.showFlavorDetails();
|
|
|
|
this.updateFlavorUsage();
|
|
|
|
},
|
|
|
|
|
|
|
|
// Returns the flavor object for the selected flavor in the form.
|
2014-08-26 16:08:35 -07:00
|
|
|
// also find out if there is old_flavor
|
2012-06-23 13:58:35 -07:00
|
|
|
getSelectedFlavor: function() {
|
|
|
|
if(this.is_flavor_quota) {
|
2013-12-05 15:31:19 +01:00
|
|
|
this.selected_flavor = $.grep(this.flavors, function(flavor) {
|
2014-01-02 15:58:43 +01:00
|
|
|
return flavor.id === $("#id_flavor").children(":selected").val();
|
2013-12-05 15:31:19 +01:00
|
|
|
})[0];
|
2014-08-26 16:08:35 -07:00
|
|
|
|
|
|
|
this.old_flavor = $.grep(this.flavors, function(flavor) {
|
|
|
|
return flavor.name === $('#id_old_flavor_name').val();
|
|
|
|
})[0];
|
2012-06-23 13:58:35 -07:00
|
|
|
} else {
|
2014-08-26 16:08:35 -07:00
|
|
|
this.old_flavor = null;
|
2012-06-23 13:58:35 -07:00
|
|
|
this.selected_flavor = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.selected_flavor;
|
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Populates the flavor details table with the flavor attributes of the
|
|
|
|
selected flavor on the form select element.
|
|
|
|
*/
|
2012-06-23 13:58:35 -07:00
|
|
|
showFlavorDetails: function() {
|
|
|
|
this.getSelectedFlavor();
|
|
|
|
|
2012-06-28 17:36:21 -07:00
|
|
|
if (this.selected_flavor) {
|
2015-10-05 09:44:51 -07:00
|
|
|
var vcpus = horizon.Quota.humanizeNumbers(this.selected_flavor.vcpus);
|
|
|
|
var disk = horizon.Quota.humanizeNumbers(this.selected_flavor.disk);
|
|
|
|
var ephemeral = horizon.Quota.humanizeNumbers(this.selected_flavor["OS-FLV-EXT-DATA:ephemeral"]);
|
2012-06-28 17:36:21 -07:00
|
|
|
var disk_total = this.selected_flavor.disk + this.selected_flavor["OS-FLV-EXT-DATA:ephemeral"];
|
2015-10-05 09:44:51 -07:00
|
|
|
var disk_total_display = horizon.Quota.humanizeNumbers(disk_total);
|
|
|
|
var ram = horizon.Quota.humanizeNumbers(this.selected_flavor.ram);
|
2012-06-28 17:36:21 -07:00
|
|
|
|
2015-09-02 11:33:42 -07:00
|
|
|
$("#flavor_name").text(this.selected_flavor.name);
|
2012-06-28 17:36:21 -07:00
|
|
|
$("#flavor_vcpus").text(vcpus);
|
|
|
|
$("#flavor_disk").text(disk);
|
|
|
|
$("#flavor_ephemeral").text(ephemeral);
|
|
|
|
$("#flavor_disk_total").text(disk_total_display);
|
|
|
|
$("#flavor_ram").text(ram);
|
|
|
|
}
|
2014-08-26 16:08:35 -07:00
|
|
|
else {//if change to nothing selected
|
|
|
|
$("#flavor_name").html('');
|
|
|
|
$("#flavor_vcpus").text('');
|
|
|
|
$("#flavor_disk").text('');
|
|
|
|
$("#flavor_ephemeral").text('');
|
|
|
|
$("#flavor_disk_total").text('');
|
|
|
|
$("#flavor_ram").text('');
|
|
|
|
}
|
2012-06-23 13:58:35 -07:00
|
|
|
},
|
|
|
|
|
2015-10-05 09:44:51 -07:00
|
|
|
/*
|
|
|
|
* Adds commas to any integer or numbers within a string for human display.
|
2016-10-20 15:31:23 +08:00
|
|
|
* The number formatting depends on what language the user choose in Horizon
|
|
|
|
* settings.
|
2015-10-05 09:44:51 -07:00
|
|
|
*
|
|
|
|
* Example:
|
2016-10-20 15:31:23 +08:00
|
|
|
* Default:
|
|
|
|
* horizon.Quota.humanizeNumbers(1234); -> "1,234"
|
|
|
|
* horizon.Quota.humanizeNumbers("My Total: 1234"); -> "My Total: 1,234"
|
|
|
|
*
|
|
|
|
* If the user change the language to "Deutsch (de)":
|
|
|
|
* horizon.Quota.humanizeNumbers(1234); -> "1.234"
|
|
|
|
* horizon.Quota.humanizeNumbers("My Total: 1234"); -> "My Total: 1.234"
|
|
|
|
*
|
|
|
|
* If the user change the language to "Français (fr)":
|
|
|
|
* horizon.Quota.humanizeNumbers(1234); -> "1 234"
|
|
|
|
* horizon.Quota.humanizeNumbers("My Total: 1234"); -> "My Total: 1 234"
|
2015-10-05 09:44:51 -07:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
humanizeNumbers: function (number) {
|
2016-10-20 15:31:23 +08:00
|
|
|
return number.toString().replace(/\d+(?:\.\d+)?/g, function(match) {
|
|
|
|
var lang = horizon.cookies.get('horizon_language');
|
|
|
|
try {
|
|
|
|
return new Intl.NumberFormat(lang).format(match);
|
|
|
|
} catch(e) {
|
|
|
|
return match;
|
|
|
|
}
|
|
|
|
});
|
2015-10-05 09:44:51 -07:00
|
|
|
},
|
|
|
|
|
2012-06-23 13:58:35 -07:00
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
When a new flavor is selected, this takes care of updating the relevant
|
|
|
|
progress bars associated with the flavor quota usage.
|
|
|
|
*/
|
2012-06-23 13:58:35 -07:00
|
|
|
updateFlavorUsage: function() {
|
2014-08-26 16:08:35 -07:00
|
|
|
if (!this.is_flavor_quota) { return; }
|
2012-06-23 13:58:35 -07:00
|
|
|
|
|
|
|
var scope = this;
|
|
|
|
var instance_count = (parseInt($("#id_count").val(), 10) || 1);
|
|
|
|
var update_amount = 0;
|
|
|
|
|
|
|
|
this.getSelectedFlavor();
|
|
|
|
|
|
|
|
$(this.flavor_progress_bars).each(function(index, element) {
|
|
|
|
var element_id = $(element).attr('id');
|
|
|
|
var progress_stat = element_id.match(/^quota_(.+)/)[1];
|
2016-10-24 14:30:14 -07:00
|
|
|
var sourceType = $("#id_source_type").val();
|
|
|
|
var createVolume = (sourceType === "volume_snapshot_id" || sourceType === "volume_image_id");
|
2012-06-23 13:58:35 -07:00
|
|
|
|
2014-08-26 16:08:35 -07:00
|
|
|
if (!progress_stat) {
|
2012-06-23 13:58:35 -07:00
|
|
|
return;
|
2014-08-26 16:08:35 -07:00
|
|
|
} else if (progress_stat === 'resize_instance') {
|
|
|
|
// There is no instance added for resize.
|
|
|
|
update_amount = 0;
|
|
|
|
} else if (progress_stat === 'instances') {
|
|
|
|
update_amount = instance_count;
|
|
|
|
} else if (progress_stat === 'vcpus' &&
|
|
|
|
scope.old_flavor &&
|
|
|
|
scope.selected_flavor) {
|
|
|
|
// Dealing with resizing instance where update_amount should be the
|
|
|
|
// difference of old and new vcpus.
|
|
|
|
var old_vcpus = scope.old_flavor.vcpus;
|
|
|
|
var new_vcpus = scope.selected_flavor.vcpus;
|
|
|
|
// If the user changes to a smaller flavor, it will not make any change
|
|
|
|
// in the progress bar.
|
|
|
|
// The default kvm doesn't seem to support downgrading to a smaller
|
|
|
|
// flavor. Same comments apply to changing ram.
|
|
|
|
update_amount =
|
|
|
|
(new_vcpus - old_vcpus < 0) ? 0 : (new_vcpus - old_vcpus);
|
|
|
|
} else if (progress_stat === 'ram' &&
|
|
|
|
scope.old_flavor &&
|
|
|
|
scope.selected_flavor) {
|
|
|
|
// Dealing with resizing instance where update_amount should be the
|
|
|
|
// difference of old and new ram.
|
2015-04-22 16:04:56 -07:00
|
|
|
var old_ram = scope.old_flavor.ram;
|
|
|
|
var new_ram = scope.selected_flavor.ram;
|
2014-08-26 16:08:35 -07:00
|
|
|
update_amount = (new_ram - old_ram < 0) ? 0 : (new_ram - old_ram);
|
2016-10-24 14:30:14 -07:00
|
|
|
} else if (progress_stat === "volume") {
|
|
|
|
update_amount = createVolume ? instance_count : 0;
|
|
|
|
} else if (progress_stat === "volume_storage") {
|
|
|
|
var volumeSize = 0;
|
|
|
|
|
|
|
|
if (sourceType === "volume_snapshot_id") {
|
|
|
|
// get volume size from the selected snapshot
|
|
|
|
var volumeSizeMatches = $("#id_volume_snapshot_id").children(":selected").html().match(/\s(\d+)\s/g);
|
|
|
|
volumeSize = horizon.Quota.getSelectedFlavor().disk; // set volume size as the minimum flavor size
|
|
|
|
if(volumeSizeMatches) {
|
|
|
|
volumeSize = Math.max(volumeSize, volumeSizeMatches[volumeSizeMatches.length - 1]);
|
|
|
|
}
|
|
|
|
} else if (sourceType === "volume_image_id") {
|
|
|
|
volumeSize = $("#id_volume_size").val();
|
|
|
|
}
|
|
|
|
|
|
|
|
update_amount = volumeSize * instance_count;
|
2012-06-28 17:36:21 -07:00
|
|
|
} else if (scope.selected_flavor) {
|
2012-06-23 13:58:35 -07:00
|
|
|
update_amount = (scope.selected_flavor[progress_stat] * instance_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
scope.updateUsageFor(element, update_amount);
|
|
|
|
});
|
|
|
|
},
|
|
|
|
|
|
|
|
// Does the math to calculate what percentage to update a progress bar by.
|
|
|
|
updateUsageFor: function(progress_element, increment_by) {
|
2015-11-13 13:42:45 -07:00
|
|
|
var $progress_element = $(progress_element);
|
2012-06-23 13:58:35 -07:00
|
|
|
|
2013-05-06 16:53:11 -07:00
|
|
|
//var update_indicator = progress_element.find('.progress_bar_selected');
|
2015-11-13 13:42:45 -07:00
|
|
|
var quota_limit = parseInt($progress_element.attr('data-quota-limit'), 10);
|
2012-06-23 13:58:35 -07:00
|
|
|
var percentage_to_update = ((increment_by / quota_limit) * 100);
|
|
|
|
|
2015-11-13 13:42:45 -07:00
|
|
|
this.update($progress_element.attr('id'), percentage_to_update);
|
2013-05-06 16:53:11 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
// Update the progress Bar
|
|
|
|
update: function(element, value) {
|
|
|
|
|
2015-11-13 13:42:45 -07:00
|
|
|
// Find Progress Bars, we'll need both of them
|
|
|
|
var bars = $('#' + element).find('.progress-bar');
|
|
|
|
|
|
|
|
// Determine how much is already used -> this is the first bar
|
|
|
|
// Also, convert it to an int ;)
|
|
|
|
var used_val = +$(bars[0]).attr('aria-valuenow');
|
|
|
|
|
|
|
|
// Calculate new total
|
|
|
|
var total = used_val + value;
|
|
|
|
|
|
|
|
// Make sure to normalize the value to 100 or less
|
|
|
|
if (total > 100) {
|
|
|
|
value = 100 - used_val;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn percentage into a proper percentage string for style
|
|
|
|
var percent_str = value + '%';
|
|
|
|
|
|
|
|
// jQuery construct it and then cache it, we need it more than once
|
|
|
|
var $bar = $(bars[1]);
|
|
|
|
|
|
|
|
// Update the second progress bar
|
|
|
|
$bar.css('width', percent_str)
|
|
|
|
.attr('aria-valuenow', value)
|
|
|
|
.find('.sr-only')
|
|
|
|
.html(percent_str);
|
|
|
|
|
|
|
|
// If the value is going to set total to 100+, set danger class
|
|
|
|
if (total > 99) {
|
|
|
|
$bar.removeClass('progress-bar-warning').addClass('progress-bar-danger');
|
|
|
|
} else {
|
|
|
|
$bar.removeClass('progress-bar-danger');
|
|
|
|
|
|
|
|
/*eslint-disable */
|
|
|
|
total > 89 ?
|
|
|
|
$bar.addClass('progress-bar-warning') :
|
|
|
|
$bar.removeClass('progress-bar-warning');
|
|
|
|
/*eslint-enable */
|
|
|
|
}
|
2012-06-23 13:58:35 -07:00
|
|
|
},
|
|
|
|
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Attaches event handlers for the form elements associated with the
|
|
|
|
progress bars.
|
|
|
|
*/
|
2012-06-23 13:58:35 -07:00
|
|
|
_attachInputHandlers: function() {
|
|
|
|
var scope = this;
|
|
|
|
|
|
|
|
if(this.is_flavor_quota) {
|
2015-04-22 16:04:56 -07:00
|
|
|
var eventCallback = function() {
|
2012-06-23 13:58:35 -07:00
|
|
|
scope.showFlavorDetails();
|
|
|
|
scope.updateFlavorUsage();
|
|
|
|
};
|
|
|
|
|
2015-04-22 16:04:56 -07:00
|
|
|
var imageChangeCallback = function() {
|
2015-12-14 17:56:25 +01:00
|
|
|
scope.disableFlavorsForImage('image');
|
|
|
|
};
|
|
|
|
|
|
|
|
var snapshotChangeCallback = function() {
|
|
|
|
scope.disableFlavorsForImage('instance_snapshot');
|
2013-05-30 13:48:49 -04:00
|
|
|
};
|
|
|
|
|
2016-10-24 14:30:14 -07:00
|
|
|
var volumeChangeCallback = function() {
|
|
|
|
scope.updateFlavorUsage();
|
|
|
|
};
|
|
|
|
|
2014-11-14 07:17:20 -08:00
|
|
|
$('#id_flavor').on('keyup change', eventCallback);
|
2014-09-15 16:28:56 +01:00
|
|
|
$('#id_count').on('input', eventCallback);
|
2013-05-30 13:48:49 -04:00
|
|
|
$('#id_image_id').on('change', imageChangeCallback);
|
2015-12-14 17:56:25 +01:00
|
|
|
$('#id_instance_snapshot_id').on('change', snapshotChangeCallback);
|
2016-10-24 14:30:14 -07:00
|
|
|
$('#id_source_type').on('change', volumeChangeCallback);
|
|
|
|
$('#id_volume_snapshot_id').on('change', volumeChangeCallback);
|
|
|
|
$('#id_image_id').on('change', volumeChangeCallback);
|
|
|
|
$('#id_volume_size').on('keyup change', volumeChangeCallback);
|
2012-06-23 13:58:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
$(this.user_value_form_inputs).each(function(index, element) {
|
2015-11-13 13:42:45 -07:00
|
|
|
$(element).on('input', function() {
|
|
|
|
var $this = $(this);
|
|
|
|
var $progress_element = $('div[data-progress-indicator-for=' + $this.attr('id') + ']');
|
|
|
|
var integers_in_input = $this.val().match(/\d+/g);
|
2012-06-23 13:58:35 -07:00
|
|
|
var user_integer;
|
|
|
|
|
|
|
|
if(integers_in_input === null) {
|
|
|
|
user_integer = 0;
|
|
|
|
} else if(integers_in_input.length > 1) {
|
|
|
|
/*
|
2013-12-27 14:48:59 +01:00
|
|
|
Join all the numbers together that have been typed in. This takes
|
|
|
|
care of junk input like "dd8d72n3k" and uses just the digits in
|
|
|
|
that input, resulting in "8723".
|
|
|
|
*/
|
2012-06-23 13:58:35 -07:00
|
|
|
user_integer = integers_in_input.join('');
|
2014-01-02 15:58:43 +01:00
|
|
|
} else if(integers_in_input.length === 1) {
|
2012-06-23 13:58:35 -07:00
|
|
|
user_integer = integers_in_input[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
var progress_amount = parseInt(user_integer, 10);
|
|
|
|
|
2015-11-13 13:42:45 -07:00
|
|
|
scope.updateUsageFor($progress_element, progress_amount);
|
2012-06-23 13:58:35 -07:00
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|