diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css index 5f104eb5970..6b981c74170 100644 --- a/ui/css/cloudstack3.css +++ b/ui/css/cloudstack3.css @@ -122,6 +122,14 @@ table tbody td.actions { vertical-align: middle; } +table tbody td.actions input { + /*+placement:shift 10px -6px;*/ + position: relative; + left: 10px; + top: -6px; + margin: 11px 0 0px; +} + table tbody tr { border-left: 1px solid #C4C5C5; border-right: 1px solid #C4C5C5; @@ -796,7 +804,8 @@ div.notification-box .button.close:hover { /*** Corner alert*/ div.notification.corner-alert { background: #EBE8E8; - width: 260px; + display: inline-block; + min-width: 260px; height: 70px; position: absolute; text-indent: 10px; @@ -1013,14 +1022,6 @@ div.list-view td.state.off { top: 2px; } -.project-view .ui-tabs ul { - /*+placement:shift 0px 0px;*/ - position: relative; - left: 0px; - top: 0px; - height: 39px; -} - .ui-tabs .info { background: #EFEFEF; width: 91%; @@ -1209,6 +1210,41 @@ div.list-view td.state.off { padding: 20px 0px 17px; } +.detail-view .button.done { + display: inline-block; + color: #FFFFFF; + font-size: 12px; + font-weight: bold; + /*+border-radius:10px;*/ + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -khtml-border-radius: 10px; + border-radius: 10px 10px 10px 10px; + /*+text-shadow:0px -1px 2px #000000;*/ + -moz-text-shadow: 0px -1px 2px #000000; + -webkit-text-shadow: 0px -1px 2px #000000; + -o-text-shadow: 0px -1px 2px #000000; + text-shadow: 0px -1px 2px #000000; + /*+box-shadow:0px 1px 4px #ADADAD;*/ + -moz-box-shadow: 0px 1px 4px #ADADAD; + -webkit-box-shadow: 0px 1px 4px #ADADAD; + -o-box-shadow: 0px 1px 4px #ADADAD; + box-shadow: 0px 1px 4px #ADADAD; + cursor: pointer; + margin: 0 0 0 12px; + padding: 9px 20px; + background: url(../images/bg-gradients.png) 0px -221px; +} + +.detail-view .button.done:hover { + background-position: 0px -950px; + /*+box-shadow:inset 0px 1px 3px #000000;*/ + -moz-box-shadow: inset 0px 1px 3px #000000; + -webkit-box-shadow: inset 0px 1px 3px #000000; + -o-box-shadow: inset 0px 1px 3px #000000; + box-shadow: inset 0px 1px 3px #000000; +} + div.group-multiple div.detail-group table { margin-top: -12px; } @@ -1778,7 +1814,7 @@ div.detail-group.actions td { } .project-view .ui-tabs div.ui-tabs-panel { - background: #DBDDDF; + background: #C7C7C7 0px 9px; } #browser div.panel .shadow { @@ -5109,6 +5145,7 @@ div.panel.ui-dialog div.list-view div.fixed-header { border: none; width: 100%; margin: 0; + text-indent: 37px; } .multi-edit .data .data-body .data-item .expandable-listing tr.odd td { diff --git a/ui/images/bg-gradients.png b/ui/images/bg-gradients.png index 23e8a81ad98..977bced185c 100644 Binary files a/ui/images/bg-gradients.png and b/ui/images/bg-gradients.png differ diff --git a/ui/index-test.html b/ui/index-test.html index bb2c84c61b2..c90975d02ba 100644 --- a/ui/index-test.html +++ b/ui/index-test.html @@ -374,7 +374,7 @@
diff --git a/ui/index.jsp b/ui/index.jsp index 8f682175d2c..e2fb02d51bb 100644 --- a/ui/index.jsp +++ b/ui/index.jsp @@ -374,7 +374,7 @@
    -
  • 1Zone Type
  • +
  • 1Select Type
  • 2Setup Zone
diff --git a/ui/scripts-test/domains.js b/ui/scripts-test/domains.js index fc0cdc257de..722efc57b83 100644 --- a/ui/scripts-test/domains.js +++ b/ui/scripts-test/domains.js @@ -61,7 +61,7 @@ messages: { notification: function(args) { - return 'Created domain' + return 'Created domain'; } }, @@ -78,10 +78,6 @@ validation: { required: true } } } - }, - - notification: { - poll: testData.notifications.testPoll } } }, diff --git a/ui/scripts-test/storage.js b/ui/scripts-test/storage.js index 4ffb07bf8ef..d3fc8691109 100644 --- a/ui/scripts-test/storage.js +++ b/ui/scripts-test/storage.js @@ -403,10 +403,9 @@ edit: { label: 'Edit volume details', action: function(args) { - args.response.success(); - }, - notification: { - poll: testData.notifications.testPoll + setTimeout(function() { + args.response.success(); + }, 500); } }, snapshot: { diff --git a/ui/scripts/ui-custom/enableStaticNAT.js b/ui/scripts/ui-custom/enableStaticNAT.js index 4b52d4d5d20..03e060743b7 100644 --- a/ui/scripts/ui-custom/enableStaticNAT.js +++ b/ui/scripts/ui-custom/enableStaticNAT.js @@ -53,7 +53,7 @@ title: 'Select VM for Static NAT', buttons: [ { - text: 'Done', + text: 'Apply', 'class': 'ok', click: function() { var complete = args.complete; diff --git a/ui/scripts/ui/multiEdit.js b/ui/scripts/ui/multiEdit.js index 5af4e9cd8e7..005325f4db9 100644 --- a/ui/scripts/ui/multiEdit.js +++ b/ui/scripts/ui/multiEdit.js @@ -535,7 +535,7 @@ title: args.add.label, buttons: [ { - text: 'Done', + text: 'Apply', 'class': 'ok', click: function() { $dataList.fadeOut(function() { diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js index c7737858ee8..a95fdec34c1 100644 --- a/ui/scripts/ui/widgets/detailView.js +++ b/ui/scripts/ui/widgets/detailView.js @@ -60,7 +60,8 @@ */ standard: function($detailView, args, additional) { var action = args.actions[args.actionName]; - var notification = action.notification; + var notification = action.notification ? + action.notification : {}; var messages = action.messages; var messageArgs = { name: $detailView.find('tr.name td.value').html() }; var id = args.id; @@ -98,6 +99,10 @@ var $form = options.$form; + // Set loading appearance + var $loading = $('
').addClass('loading-overlay'); + $detailView.prepend($loading); + action.action({ data: data, _custom: _custom, @@ -109,11 +114,6 @@ args = args ? args : {}; notification._custom = args._custom; - // Set loading appearance - $detailView.prepend( - $('
').addClass('loading-overlay') - ); - if (additional && additional.success) additional.success(args); // Setup notification @@ -121,12 +121,15 @@ notification, function(args) { if ($detailView.is(':visible')) { - $detailView.find('.loading-overlay').remove(); + $loading.remove(); // Refresh actions loadTabContent( $detailView.find('.detail-group:visible'), - $detailView.data('view-args') + $detailView.data('view-args'), + { + newData: args.data + } ); } @@ -203,70 +206,102 @@ * @param callback */ edit: function($detailView, args) { + if ($detailView.find('.button.done').size()) return false; + // Convert value TDs var $inputs = $detailView.find('input[type=text], select'); + var action = args.actions[args.actionName]; + var id = $detailView.data('view-args').id; + var $editButton = $('
').addClass('button done').html('Apply') + .hide() + .appendTo( + $detailView.find('.ui-tabs-panel:visible') + ) + .fadeIn('fast'); - if ($inputs.size()) { - $inputs.animate({ opacity: 0.5 }, 500); - - var data = {}; + var convertInputs = function($inputs) { + // Save and turn back into labels $inputs.each(function() { - data[$(this).attr('name')] = $(this).val(); - }); + var $input = $(this); + var $value = $input.closest('td.value'); - args.actions[args.actionName].action({ - data: data, - _custom: $detailView.data('_custom'), - context: $detailView.data('view-args').context, - response: { + if ($input.is('input[type=text]')) + $value.html( + $input.attr('value') + ); + else if ($input.is('select')) { + $value.html( + $input.find('option:selected').html() + ); + $value.data('detail-view-selected-option', $input.find('option:selected').val()); + } + }); + }; + + var applyEdits = function($inputs, $editButton) { + if ($inputs.size()) { + $inputs.animate({ opacity: 0.5 }, 500); + + var data = {}; + $inputs.each(function() { + data[$(this).attr('name')] = $(this).val(); + }); + + $editButton.fadeOut('fast', function() { + $editButton.remove(); + }); + + var $loading = $('
').addClass('loading-overlay'); + + action.action({ data: data, - success: function(data) { - // Save and turn back into labels - $inputs.each(function() { - var $input = $(this); - var $value = $input.closest('td.value'); - - if ($input.is('input[type=text]')) - $value.html( - $input.attr('value') - ); - else if ($input.is('select')) { - $value.html( - $input.find('option:selected').html() - ); - $value.data('detail-view-selected-option', $input.find('option:selected').val()); - } - }); - - var id = $detailView.data('view-args').id - - addNotification( - { + _custom: $detailView.data('_custom'), + context: $detailView.data('view-args').context, + response: { + data: data, + success: function(data) { + var notificationArgs = { section: id, desc: 'Changed item properties' - }, - function(data) { - }, - [] - ); - }, - error: function(args) { - // Put in original values on error - $inputs.each(function() { - var $input = $(this); - var $value = $input.closest('td.value'); - var originalValue = $input.data('original-value'); + }; - $value.html(originalValue); - }); + if (!action.notification) { + convertInputs($inputs); + addNotification( + notificationArgs, function(data) {}, [] + ); + } else { + $loading.appendTo($detailView); + addNotification( + $.extend(true, {}, action.notification, notificationArgs), + function(args) { + convertInputs($inputs); + $loading.remove(); + }, [] + ); + } + }, + error: function(args) { + // Put in original values on error + $inputs.each(function() { + var $input = $(this); + var $value = $input.closest('td.value'); + var originalValue = $input.data('original-value'); - if (args.message) cloudStack.dialog.notice({ message: args.message }); + $value.html(originalValue); + }); + + if (args.message) cloudStack.dialog.notice({ message: args.message }); + } } - } - }); + }); + } + }; - return $detailView; - } + $editButton.click(function() { + var $inputs = $detailView.find('input[type=text], select'); + applyEdits($inputs, $editButton); + }); $detailView.find('td.value').each(function() { var name = $(this).closest('tr').data('detail-view-field'); @@ -587,8 +622,10 @@ * * @param $tabContent {jQuery} tab div to load content into * @param args {object} Detail view data + * @param options {object} Additional options */ - var loadTabContent = function($tabContent, args) { + var loadTabContent = function($tabContent, args, options) { + if (!options) options = {}; $tabContent.html(''); var targetTabID = $tabContent.data('detail-view-tab-id'); @@ -622,10 +659,14 @@ return dataProvider({ tab: targetTabID, id: args.id, - jsonObj: args.jsonObj, + jsonObj: options.newData ? $.extend(true, {}, args.jsonObj, options.newData) : args.jsonObj, context: args.context, response: { success: function(args) { + if (options.newData) { + $.extend(args.data, options.newData); + } + if (args._custom) { $detailView.data('_custom', args._custom); }