diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index ffa0aebbf51..573afe9daf9 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -1641,6 +1641,12 @@ div.details div.detail-group td.value input[type=text] { width: 93%; } +div.details .main-groups label.error { + position: absolute; + right: 10%; + top: 6px; +} + /*** Actions*/ div.detail-group.actions { padding: 0; @@ -2831,6 +2837,7 @@ Dialogs*/ -webkit-box-shadow: 0px -4px 15px #4C4A4A; -o-box-shadow: 0px -4px 15px #4C4A4A; box-shadow: 0px -4px 15px #4C4A4A; + position:absolute; } .ui-dialog .ui-widget-content { diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js index eafe5c5f271..6f30963e242 100644 --- a/ui/scripts/accounts.js +++ b/ui/scripts/accounts.js @@ -514,7 +514,8 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { @@ -816,16 +817,16 @@ label: 'label.new.password', isPassword: true, validation: { required: true }, - id: 'newPassword' + id: 'newPassword' }, - 'password-confirm': { - label: 'label.confirm.password', - validation: { - required: true, - equalTo: '#newPassword' - }, - isPassword: true - } + 'password-confirm': { + label: 'label.confirm.password', + validation: { + required: true, + equalTo: '#newPassword' + }, + isPassword: true + } } }, action: function(args) { @@ -979,7 +980,8 @@ { username: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { @@ -997,15 +999,18 @@ domain: { label: 'label.domain' }, email: { label: 'label.email', - isEditable: true + isEditable: true, + validation: { required: true, email: true } }, firstname: { label: 'label.first.name', - isEditable: true + isEditable: true, + validation: { required: true } }, lastname: { label: 'label.last.name', - isEditable: true + isEditable: true, + validation: { required: true } }, timezone: { label: 'label.timezone', diff --git a/ui/scripts/configuration.js b/ui/scripts/configuration.js index 4a8f9586d90..766dcf32f7b 100644 --- a/ui/scripts/configuration.js +++ b/ui/scripts/configuration.js @@ -285,14 +285,16 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { id: { label: 'label.id' }, displaytext: { label: 'label.description', - isEditable: true + isEditable: true, + validation: { required: true } }, storagetype: { label: 'label.storage.type' }, cpunumber: { label: 'label.num.cpu.cores' }, @@ -615,14 +617,16 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { id: { label: 'label.id' }, displaytext: { label: 'label.description', - isEditable: true + isEditable: true, + validation: { required: true } }, systemvmtype: { label: 'label.system.vm.type', @@ -911,14 +915,16 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { id: { label: 'label.id' }, displaytext: { label: 'label.description', - isEditable: true + isEditable: true, + validation: { required: true } }, iscustomized: { label: 'label.custom.disk.size', @@ -1701,14 +1707,16 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { id: { label: 'label.id' }, displaytext: { label: 'label.description', - isEditable: true + isEditable: true, + validation: { required: true } }, state: { label: 'label.state' }, guestiptype: { diff --git a/ui/scripts/templates.js b/ui/scripts/templates.js index bf34f925fb7..811a27a7c66 100644 --- a/ui/scripts/templates.js +++ b/ui/scripts/templates.js @@ -579,7 +579,8 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { @@ -588,7 +589,8 @@ zoneid: { label: 'label.zone.id' }, displaytext: { label: 'label.description', - isEditable: true + isEditable: true, + validation: { required: true } }, hypervisor: { label: 'label.hypervisor' }, templatetype: { label: 'label.type' }, @@ -1114,7 +1116,8 @@ { name: { label: 'label.name', - isEditable: true + isEditable: true, + validation: { required: true } } }, { @@ -1123,7 +1126,8 @@ zoneid: { label: 'label.zone.id' }, displaytext: { label: 'label.description', - isEditable: true + isEditable: true, + validation: { required: true } }, isready: { label: 'state.Ready', converter:cloudStack.converters.toBooleanText }, status: { label: 'label.status' }, diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index 80e99f6e372..1ac609f2745 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -326,6 +326,18 @@ } }); }; + + var removeEditForm = function() { + // Remove Edit form + var $form = $detailView.find('form'); + if ($form.size()) { + var $mainGroups = $form.find('div.main-groups').detach(); + $form.parent('div').append($mainGroups); + $form.remove(); + } + //Remove required labels + $detailView.find('span.field-required').remove(); + } // Put in original values var cancelEdits = function($inputs, $editButton) { @@ -340,6 +352,8 @@ $editButton.fadeOut('fast', function() { $editButton.remove(); }); + + removeEditForm(); }; var applyEdits = function($inputs, $editButton) { @@ -381,6 +395,7 @@ notificationArgs, function() {}, [] ); replaceListViewItem($detailView, data); + removeEditForm(); } else { $loading.appendTo($detailView); cloudStack.ui.notifications.add( @@ -389,6 +404,7 @@ replaceListViewItem($detailView, data); convertInputs($inputs); + removeEditForm(); $loading.remove(); }, [], function() { @@ -407,17 +423,24 @@ } }; - $editButton.click(function() { - var $inputs = $detailView.find('input, select'); + $editButton.click(function() { + var $inputs = $detailView.find('input, select'), + $form = $detailView.find('form'); if ($(this).hasClass('done')) { - applyEdits($inputs, $editButton); + if (!$form.valid()) { + // Ignore hidden field validation + if ($form.find('input.error:visible, select.error:visible').size()) { + return false; + } + } + applyEdits($inputs, $editButton); } else { // Cancel cancelEdits($inputs, $editButton); } }); - - $detailView.find('td.value span').each(function() { + + $detailView.find('td.value span').each(function() { var name = $(this).closest('tr').data('detail-view-field'); var $value = $(this); if (!$value.data('detail-view-is-editable')) return true; @@ -426,6 +449,7 @@ var selectData = $value.data('detail-view-editable-select'); var isBoolean = $value.data('detail-view-editable-boolean'); var data = !isBoolean ? cloudStack.sanitizeReverse($value.html()) : $value.data('detail-view-boolean-value'); + var rules = $value.data('validation-rules') ? $value.data('validation-rules') : {}; $value.html(''); @@ -467,13 +491,36 @@ name: name, type: 'text', value: data - }).data('original-value', data) + }).data('original-value', data) ); } + + if (rules && rules.required) { + var $required = $('').addClass('field-required').text(' *'); + $value.parent('td.value').prev('td.name').append($required); + } return true; }); + if ($detailView.find('td.value span:data(detail-view-is-editable)').size()) { + var $detailsEdit = $detailView.find('div.main-groups').detach(), + $detailsEditForm = $('
').append($detailsEdit); + + $detailView.find('div.details').append($detailsEditForm); + } + + // Setup form validation + $detailView.find('form').validate(); + $detailView.find('form').find('input, select').each(function() { + var data = $(this).parent('span').data('validation-rules'); + if (data) { + $(this).rules('add', data); + } else { + $(this).rules('add', {}); + } + }); + return $detailView; } }; @@ -689,23 +736,26 @@ //??? /* - if("pollAgainIfValueIsIn" in value) { - if ((content in value.pollAgainIfValueIsIn) && (value.pollAgainFn != null)) { - //poll again - var intervalKey = setInterval(function() { - var toClearInterval = value.pollAgainFn(context); - if(toClearInterval == true) { - clearInterval(intervalKey); - $('.detail-view .toolbar .button.refresh').click(); //click Refresh button to refresh detailView - } - }, 2000); - } - } - */ - + if("pollAgainIfValueIsIn" in value) { + if ((content in value.pollAgainIfValueIsIn) && (value.pollAgainFn != null)) { + //poll again + var intervalKey = setInterval(function() { + var toClearInterval = value.pollAgainFn(context); + if(toClearInterval == true) { + clearInterval(intervalKey); + $('.detail-view .toolbar .button.refresh').click(); //click Refresh button to refresh detailView + } + }, 2000); + } + } + */ + $name.html(_l(value.label)); $value.html(_s(content)); + // Set up validation metadata + $value.data('validation-rules', value.validation); + // Set up editable metadata if(typeof(value.isEditable) == 'function') $value.data('detail-view-is-editable', value.isEditable()); diff --git a/ui/scripts/ui/widgets/overlay.js b/ui/scripts/ui/widgets/overlay.js index 296b58a1a3d..ecf12e6aedd 100644 --- a/ui/scripts/ui/widgets/overlay.js +++ b/ui/scripts/ui/widgets/overlay.js @@ -43,4 +43,8 @@ return this; }; + + $(window).bind('resize scroll', function() { + $('.overlay').css( 'top', $(window).scrollTop()); + }); })(window.jQuery);