ui/quota: implement a better quota UI plugin

Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
Rohit Yadav 2015-11-06 23:04:43 +05:30
parent 662b54b2e1
commit 84d5aeb7a5
1 changed files with 357 additions and 314 deletions

View File

@ -15,7 +15,6 @@
// specific language governing permissions and limitations
// under the License.
var g_quotaCurrency = '';
(function (cloudStack) {
cloudStack.plugins.quota = function(plugin) {
plugin.ui.addSection({
@ -25,344 +24,388 @@ var g_quotaCurrency = '';
preFilter: function(args) {
return true;
},
show: function() {
var $quotaView = $('<div class="quota-container detail-view ui-tabs ui-widget ui-widget-content ui-corner-all">');
var $toolbar = $('<div class="toolbar"><div class="section-switcher reduced-hide"><div class="section-select"><label>Quota Management</label></div></div></div>');
var $tabs = $('<ul class="ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all">');
var $tabViews = [];
var sections = [{'id': 'quota-statement',
'name': 'Statement',
'render': function ($node) {
var statementView = $('<div class="details quota-text" style="padding: 10px">');
var generatedStatement = $('<div class="quota-generated-statement">');
$.ajax({
url: createURL('quotaSummary'),
success: function(json) {
var quotaSummary = json.quotasummaryresponse.summary;
generatedStatement.empty();
$("<hr>").appendTo(generatedStatement);
if (quotaSummary.length < 1) {
return;
}
var statementTable = $('<table>');
statementTable.appendTo($('<div class="data-table">').appendTo(generatedStatement));
var statementTableHead = $('<tr>');
$('<th>').html(_l('label.name')).appendTo(statementTableHead);
$('<th>').html(_l('label.domain')).appendTo(statementTableHead);
$('<th>').html(_l('label.balance')).appendTo(statementTableHead);
$('<th>').html(_l('label.totalusage')).appendTo(statementTableHead);
$('<th>').html(_l('label.state')).appendTo(statementTableHead);
$('<th>').html(_l('label.quickview')).appendTo(statementTableHead);
statementTableHead.appendTo($('<thead>').appendTo(statementTable));
var statementTableBody = $('<tbody>');
for (var i = 0; i < quotaSummary.length; i++) {
var statementTableBodyRow = $('<tr>');
if (i % 2 == 0) {
statementTableBodyRow.addClass('even');
} else {
statementTableBodyRow.addClass('odd');
}
var g_quotaCurrency = quotaSummary[i].currency.trim() + ' ';
$('<td>').html(quotaSummary[i].account).appendTo(statementTableBodyRow);
$('<td>').html(quotaSummary[i].domain).appendTo(statementTableBodyRow);
$('<td>').html(g_quotaCurrency + quotaSummary[i].quota).appendTo(statementTableBodyRow);
$('<td>').html(g_quotaCurrency + quotaSummary[i].balance).appendTo(statementTableBodyRow);
$('<td>').html(quotaSummary[i].state).appendTo(statementTableBodyRow);
$('<td>').html(_l('label.quickview')).addClass('quick-view reduced-hide').appendTo(statementTableBodyRow);
statementTableBodyRow.appendTo(statementTableBody);
}
statementTableBody.appendTo(statementTable);
},
error: function(data) {
generatedStatement.empty();
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
generatedStatement.appendTo(statementView);
statementView.appendTo($node);
sectionSelect: {
label: 'label.select-view'
},
sections: {
statement: {
type: 'select',
title: 'label.quota.statement',
listView: {
label: 'label.quota.statement',
fields: {
account: {
label: 'label.account',
truncate: true
},
domain: {
label: 'label.domain'
},
balance: {
label: 'label.quota.balance',
},
quota: {
label: 'label.quota.totalusage',
editable: true,
truncate: true
},
state: {
label: 'label.quota.state',
indicator: {
'Enabled': 'on',
'Disabled': 'off',
}
},
{
'id': 'quota-tariff',
'name' : 'Tariff Plan',
'render': function($node) {
var tariffView = $('<div class="details quota-text" style="margin-top: -30px">');
var tariffViewList = $('<div class="view list-view">');
tariffViewList.appendTo(tariffView);
},
},
dataProvider: function(args) {
var data = {
page: args.page,
pagesize: pageSize
};
var renderDateForm = function(lastDate) {
var startDateInput = $('<input type="text" class="quota-input" id="quota-tariff-startdate">');
if (lastDate) {
startDateInput.val(lastDate);
// FIXME: add logic in mgmt server to filter by account
if (args.filterBy.search.value) {
data.account = args.filterBy.search.value;
}
$.ajax({
url: createURL('quotaSummary'),
data: data,
dataType: "json",
async: true,
success: function(json) {
var items = json.quotasummaryresponse.summary;
$.each(items, function(idx, item) {
items[idx].quota = items[idx].currency + ' ' + items[idx].quota;
items[idx].balance = items[idx].currency + ' ' + items[idx].balance;
// FIXME: state is boolean, this needs to be string?
if (items[idx].state) {
items[idx].state = 'Enabled';
} else {
items[idx].state = 'Disabled';
}
});
args.response.success({
data: items
});
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
},
detailView: {
actions: {
addCredits: {
label: 'label.quota.add.credits',
messages: {
notification: function(args) {
return 'label.quota.add.credits';
}
},
action: function(args) {
// FIX add code to show add credits form and fix css to show an icon
}
},
startDateInput.datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
onClose: function (selectedDate) {
if (!selectedDate) {
return;
}
tariffViewList.empty();
renderDateForm(selectedDate);
renderTariffTable(selectedDate);
}
});
startDateInput.appendTo($('<br><span class="quota-element quota-bold">').html('Effective Date ').appendTo(tariffViewList));
};
quotaStatementByDates: {
label: 'label.quota.statement.bydates',
messages: {
notification: function(args) {
return 'label.quota.statement.bydates';
}
},
action: function(args) {
// FIX add code to show form start/end date with datepicker injected, fix css
}
}
var renderTariffTable = function(startDate) {
var tariffTable = $('<table style="margin-top: 15px">');
tariffTable.appendTo(tariffViewList);
},
var tariffTableHead = $('<tr>');
$('<th>').html(_l('label.usage.type')).appendTo(tariffTableHead);
$('<th>').html(_l('label.usage.unit')).appendTo(tariffTableHead);
$('<th>').html(_l('label.quota.value')).appendTo(tariffTableHead);
$('<th>').html(_l('label.quota.description')).appendTo(tariffTableHead);
tariffTableHead.appendTo($('<thead>').appendTo(tariffTable));
tabs: {
details: {
title: 'label.details',
fields: [{
name: {
label: 'label.quota.statement.balance'
}
}, {
balance: {
label: 'label.quota.statement.balance',
},
startdate: {
label: 'label.quota.statement.date',
},
}],
dataProvider: function(args) {
console.log('staetment view');
console.log(args);
$.ajax({
url: createURL('quotaTariffList'),
data: {startdate: startDate },
success: function(json) {
var items = json.quotatarifflistresponse.quotatariff;
if (items.constructor === Array && items[0].currency) {
g_quotaCurrency = items[0].currency.trim() + ' ';
}
var tariffTableBody = $('<tbody>');
for (var i = 0; i < items.length; i++) {
var tariffTableBodyRow = $('<tr>');
if (i % 2 == 0) {
tariffTableBodyRow.addClass('even');
} else {
tariffTableBodyRow.addClass('odd');
}
$('<td>').html(items[i].usageName).appendTo(tariffTableBodyRow);
$('<td>').html(items[i].usageUnit).appendTo(tariffTableBodyRow);
if (isAdmin()) {
var valueCell = $('<td class="value actions">');
var value = $('<span class="quota-element">').html(g_quotaCurrency + items[i].tariffValue);
value.appendTo(valueCell);
valueCell.appendTo(tariffTableBodyRow);
var usageType = items[i].usageType;
var editButton = $('<div class="action edit quota-tariff-edit" alt="Change value" title="Change value"><span class="icon">&nbsp;</span></div>');
editButton.appendTo(valueCell);
editButton.attr('id', 'quota-tariff-edit-' + items[i].usageType);
editButton.click(function() {
var usageTypeId = $(this).context.id.replace('quota-tariff-edit-', '');
var updateTariffForm = cloudStack.dialog.createForm({
form: {
title: 'label.quota.configuration',
fields: {
quotaValue: {
label: 'label.quota.value',
validation: {
required: true
}
},
effectiveDate: {
label: 'Effective Date',
validation: {
required: true
}
},
}
},
after: function(args) {
$.ajax({
url: createURL('quotaTariffUpdate'),
data: {
usagetype: usageTypeId,
value: args.data.quotaValue,
startDate: args.data.effectiveDate
},
type: "POST",
success: function(json) {
$('#quota-tariff').click();
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
}
});
updateTariffForm.find('input[name=effectiveDate]').datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
});
});
} else {
$('<td>').html(g_quotaCurrency + items[i].tariffValue).appendTo(tariffTableBodyRow);
}
$('<td>').html(items[i].description).appendTo(tariffTableBodyRow);
tariffTableBodyRow.appendTo(tariffTableBody);
}
tariffTableBody.appendTo(tariffTable);
url: createURL('quotaBalance'),
data: {
domainid: args.context.statement[0].domainid,
account: args.context.statement[0].account
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
success: function(json) {
var item = json.quotabalanceresponse.balance;
item.name = args.context.statement[0].account;
item.balance = item.currency + ' ' + item.startquota;
args.response.success({
data: item
});
}
});
}
}
}
}
}
},
tariff: {
type: 'select',
title: 'label.quota.tariff',
listView: {
label: 'label.quota.tariff',
disableInfiniteScrolling: true,
actions: {
edit: {
label: 'label.change.value',
action: function(args) {
var data = {
usagetype: args.data.jsonObj.usageType,
value: args.data.tariffValue.split(' ')[1]
};
var updateTariffForm = cloudStack.dialog.createForm({
form: {
title: 'label.quota.configuration',
fields: {
quotaValue: {
label: 'label.quota.value',
validation: {
required: true
}
},
effectiveDate: {
label: 'Effective Date',
validation: {
required: true
}
},
}
},
after: function(argsLocal) {
data.startDate = argsLocal.data.effectiveDate;
$.ajax({
url: createURL('quotaTariffUpdate'),
data: data,
type: "POST",
success: function(json) {
args.response.success({
data: json.quotatariffupdateresponse.quotatariff
});
// Refresh listings on chosen date to reflect new tariff
$($.find('div.search-bar input')).val(data.startDate);
$('#basic_search').click();
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
}
});
updateTariffForm.find('input[name=quotaValue]').val(data.value);
updateTariffForm.find('input[name=effectiveDate]').datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
}).focus();
}
}
},
fields: {
usageName: {
label: 'label.usage.type',
id: true,
truncate: true
},
usageUnit: {
label: 'label.usage.unit'
},
tariffValue: {
label: 'label.quota.tariffvalue',
editable: true
},
description: {
label: 'label.quota.description',
truncate: true
}
},
dataProvider: function(args) {
var data = {};
if (args.filterBy.search.value) {
data.startdate = args.filterBy.search.value;
}
$.ajax({
url: createURL('quotaTariffList'),
data: data,
dataType: "json",
async: true,
success: function(json) {
var items = json.quotatarifflistresponse.quotatariff;
$.each(items, function(idx, item) {
items[idx].tariffValue = items[idx].currency + ' ' + items[idx].tariffValue;
});
args.response.success({
data: items
});
renderDateForm();
renderTariffTable();
tariffView.appendTo($node);
}
},
{'id': 'quota-email',
'name': 'Email Templates',
'render': function($node) {
var manageTemplatesView = $('<div class="details quota-text" style="padding: 10px">');
// Hook up date picker
var input = $($.find('div.search-bar input'));
input.datepicker({
defaultDate: new Date(),
changeMonth: true,
dateFormat: "yy-mm-dd",
});
input.parent().attr('title', _l('label.quota.effectivedate'));
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
}
}
},
var emailTemplateForm = $('<div class="quota-email-form">');
var templateDropdown = $('<div class="quota-template-dropdown">');
var templateOptions = $('<select class="quota-input" style="margin: 0px 0px 5px 11px"><option value="QUOTA_LOW">Template for accounts with low quota balance</option><option value="QUOTA_EMPTY">Template for accounts with no quota balance that will be locked</option><option value="QUOTA_UNLOCK_ACCOUNT">Template for accounts with enough credits getting unlocked</option><option value="QUOTA_STATEMENT">Template for quota statement</option><</select>');
$('<p class="quota-bold quota-element">').html('Email Template').appendTo(templateDropdown);
templateOptions.appendTo(templateDropdown);
// templateOptions.appendTo($('<p
// class="quota-bold quota-element">Email
// Template</p>').appendTo(templateDropdown));
emailTemplates: {
type: 'select',
title: 'label.quota.email.template',
listView: {
label: 'label.quota.email.template',
disableInfiniteScrolling: true,
fields: {
templatetype: {
label: 'label.quota.email.template',
},
templatesubject: {
label: 'label.quota.email.subject',
truncate: true
},
templatebody: {
label: 'label.quota.email.body',
truncate: true
},
last_updated: {
label: 'label.quota.email.lastupdated',
truncate: true
},
},
dataProvider: function(args) {
var data = {};
if (args.filterBy.search.value) {
data.templatetype = args.filterBy.search.value;
}
var templateSubjectTextArea = $('<textarea id="quota-template-subjectarea" class="quota-input" style="margin: 0px 0px 10px 12px; font-size: 12px">');
var templateBodyTextArea = $('<textarea id="quota-template-bodyarea" class="quota-input" style="height: 250px; margin: 0px 0px 10px 12px; font-size: 12px"></textarea>');
var saveTemplateButton = $('<button class="quota-button quota-element" id="quota-save-template-button">').html("Save Template");
$.ajax({
url: createURL('quotaEmailTemplateList'),
data: data,
dataType: "json",
async: true,
success: function(json) {
if (!json.hasOwnProperty('quotaemailtemplatelistresponse') || !json.quotaemailtemplatelistresponse.hasOwnProperty('quotaemailtemplate')) {
return;
}
var items = json.quotaemailtemplatelistresponse.quotaemailtemplate;
args.response.success({
data: items
});
},
error: function(data) {
cloudStack.dialog.notice({
message: parseXMLHttpResponse(data)
});
}
});
},
detailView: {
actions: {
edit: {
label: 'label.quota.email.edit',
messages: {
notification: function(args) {
return 'label.quota.email.edit';
}
},
action: function(args) {
console.log(args);
args.data.templatetype = args.context.emailTemplates[0].templatetype;
$.ajax({
url: createURL('quotaEmailTemplateUpdate'),
data: args.data,
success: function(json) {
args.response.success({
_custom: {
success: true
}
});
}
});
}
}
},
templateOptions.change(function() {
var templateName = $(this).find(':selected').val();
templateSubjectTextArea.val('');
templateBodyTextArea.val('');
tabs: {
details: {
title: 'label.details',
fields: [{
templatetype: {
label: 'label.quota.email.template'
}
}, {
templatesubject: {
label: 'label.quota.email.subject',
isEditable: true,
textArea: true
},
templatebody: {
label: 'label.quota.email.body',
isEditable: true,
textArea: true
},
last_updated: {
label: 'label.quota.email.lastupdated',
},
}],
dataProvider: function(args) {
$.ajax({
url: createURL('quotaEmailTemplateList'),
data: {
templatetype: templateName
templatetype: args.context.emailTemplates[0].templatetype
},
success: function(json) {
if (!json.hasOwnProperty('quotaemailtemplatelistresponse') || !json.quotaemailtemplatelistresponse.hasOwnProperty('quotaemailtemplate')) {
return;
}
var template = json.quotaemailtemplatelistresponse.quotaemailtemplate[0];
templateSubjectTextArea.val(template.templatesubject.replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/<br>/g, '\n'));
templateBodyTextArea.val(template.templatebody.replace(/\\n/g, '\n').replace(/\\"/g, '"').replace(/<br>/g, '\n'));
},
error: function(data) {
var item = json.quotaemailtemplatelistresponse.quotaemailtemplate[0];
args.response.success({
data: item
});
}
});
});
templateOptions.change();
}
}
}
}
}
}
saveTemplateButton.click(function() {
var templateName = templateOptions.find(':selected').val();
var templateSubject = templateSubjectTextArea.val().replace(/\n/g, '<br>');
var templateBody = templateBodyTextArea.val().replace(/\n/g, '<br>');
$.ajax({
url: createURL('quotaEmailTemplateUpdate'),
type: "POST",
data: {
templatetype: templateName,
templatesubject: templateSubject,
templatebody: unescape(templateBody),
},
success: function(json) {
templateOptions.change();
},
error: function(data) {
// handle error here
}
});
});
templateDropdown.appendTo(emailTemplateForm);
$('<p class="quota-bold quota-element">').html('Email Template Subject').appendTo(emailTemplateForm);
templateSubjectTextArea.appendTo(emailTemplateForm);
$('<p class="quota-bold quota-element">').html('Email Template Body').appendTo(emailTemplateForm);
templateBodyTextArea.appendTo(emailTemplateForm);
saveTemplateButton.appendTo(emailTemplateForm);
$('<hr>').appendTo(emailTemplateForm);
$('<p>').html("These options can be used in template as ${variable}: quotaBalance, quotaUsage, accountName, accountID, accountUsers, domainName, domainID").appendTo(emailTemplateForm);
emailTemplateForm.appendTo(manageTemplatesView);
manageTemplatesView.appendTo($node);
}
}];
if (isAdmin()) {
} else if (isDomainAdmin()) {
sections = $.grep(sections, function(item) {
return ['quota-credit', 'quota-email'].indexOf(item.id) < 0;
});
} else {
sections = $.grep(sections, function(item) {
return ['quota-credit', 'quota-email'].indexOf(item.id) < 0;
});
}
for (idx in sections) {
var tabLi = $('<li detail-view-tab="true" class="first ui-state-default ui-corner-top"><a href="#">' + sections[idx].name+ '</a></li>');
var tabView = $('<div class="detail-group ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide">');
tabLi.attr('id', sections[idx].id);
tabView.attr('id', 'details-tab-' + sections[idx].id);
tabLi.click(function() {
var tabIdx = 0;
for (sidx in sections) {
$('#' + sections[sidx].id).removeClass('ui-tabs-selected ui-state-active');
$('#details-tab-' + sections[sidx].id).addClass('ui-tabs-hide');
$('#details-tab-' + sections[sidx].id).empty();
if (sections[sidx].id === $(this).context.id) {
tabIdx = sidx;
}
}
$(this).addClass('ui-tabs-selected ui-state-active');
var tabDetails = $('#details-tab-' + $(this).context.id);
tabDetails.removeClass('ui-tabs-hide');
sections[tabIdx].render(tabDetails);
});
if (idx == 0) {
tabLi.addClass('ui-tabs-selected ui-state-active');
tabView.removeClass('ui-tabs-hide');
sections[idx].render(tabView);
}
tabLi.appendTo($tabs);
$tabViews.push(tabView);
}
$toolbar.appendTo($quotaView);
$tabs.appendTo($quotaView);
for (idx in $tabViews) {
$tabViews[idx].appendTo($quotaView);
}
return $quotaView;
}
});
});
};
}(cloudStack));