From: Imre Farkas <ifarkas(a)redhat.com>
Rebased it once again.
Note: it depends on my previous patchset "BZ781482: feedback for image build/push
failures".
https://bugzilla.redhat.com/show_bug.cgi?id=773034
---
src/app/controllers/images_controller.rb | 53 ++++++++++++++
src/app/models/provider_account.rb | 6 ++
src/app/views/images/show.html.haml | 105 ++++++++++++++++++++++++++++
src/public/javascripts/application.js | 32 +++++++++
src/public/javascripts/backbone/models.js | 8 ++
src/public/javascripts/backbone/routers.js | 19 +++++
src/public/javascripts/backbone/views.js | 45 ++++++------
7 files changed, 245 insertions(+), 23 deletions(-)
diff --git a/src/app/controllers/images_controller.rb
b/src/app/controllers/images_controller.rb
index 41c48a5..997ab6a 100644
--- a/src/app/controllers/images_controller.rb
+++ b/src/app/controllers/images_controller.rb
@@ -60,6 +60,59 @@ class ImagesController < ApplicationController
load_builds
load_target_images(@build)
flash[:error] = t("images.flash.error.no_provider_accounts") if
@account_groups.size == 0
+
+ respond_to do |format|
+ format.html
+ format.json do
+ active_builds = @account_groups.keys.inject({}) do |result, driver|
+ result[driver] = @builder.find_active_build((a)build.id, driver) if @build
+ result
+ end
+
+ active_pushes = @account_groups.inject({}) do |result, (driver, group)|
+ timg = @target_images_by_target[driver]
+ group[:accounts].each do |account|
+ result[account.id] = @builder.find_active_push(timg.id,
account.provider.name, account.credentials_hash['username'])
+ end if timg.present?
+
+ result
+ end
+
+ provider_images = @account_groups.inject({}) do |result, (driver, group)|
+ timg = @target_images_by_target[driver]
+ group[:accounts].each do |account|
+ result[account.id] =
timg.find_provider_image_by_provider_and_account(account.provider.name,
account.credentials_hash['username']).first
+ end if timg.present?
+
+ result
+ end
+
+ failed_build_counts = @account_groups.keys.inject({}) do |result, driver|
+ result[driver] = @builder.failed_build_count((a)build.id, driver) if @build
+ result
+ end
+
+ failed_push_counts = @account_groups.inject({}) do |result, (driver, group)|
+ timg = @target_images_by_target[driver]
+ group[:accounts].each do |account|
+ result[account.id] = @builder.failed_push_count(timg.id,
account.provider.name, account.credentials_hash['username'])
+ end if timg.present?
+
+ result
+ end
+
+ render :json => { :image => @image,
+ :build => @build,
+ :account_groups => @account_groups,
+ :provider_images => provider_images,
+ :target_images_by_target => @target_images_by_target,
+ :active_builds => active_builds,
+ :active_pushes => active_pushes,
+ :failed_build_counts => failed_build_counts,
+ :failed_push_counts => failed_push_counts,
+ :latest_build_id => @latest_build }
+ end
+ end
end
def rebuild_all
diff --git a/src/app/models/provider_account.rb b/src/app/models/provider_account.rb
index e772f52..153a910 100644
--- a/src/app/models/provider_account.rb
+++ b/src/app/models/provider_account.rb
@@ -150,6 +150,12 @@ class ProviderAccount < ActiveRecord::Base
label.blank? ? credentials_hash['username'] : label
end
+ def as_json(options={})
+ super(options).merge({
+ :provider_name => provider.name
+ })
+ end
+
def populate_profiles_and_validate
begin
populate_hardware_profiles
diff --git a/src/app/views/images/show.html.haml b/src/app/views/images/show.html.haml
index 0667aa9..3f47973 100644
--- a/src/app/views/images/show.html.haml
+++ b/src/app/views/images/show.html.haml
@@ -91,3 +91,108 @@
$("#seletect_build_button").click();
});
});
+
+%script#imageBuildsTemplate{ :type => 'text/x-jquery-tmpl' }
+ :plain
+ {{each(driver, groups) account_groups}}
+ <li>
+ <dl>
+ <dt>
+ <h3>${groups['type']['name']}</h3>
+ {{if build && active_builds[driver]}}
+ <label>${active_builds[driver]['status']}</label>
+ {{else target_images_by_target[driver]}}
+ #{path = image_target_image_path('replace_image_id',
'replace_target_image_id')
+ path = path.sub('replace_image_id',
'${image[\'uuid\']}')
+ path = path.sub('replace_target_image_id',
'${target_images_by_target[driver][\'uuid\']}')
+ button_to(t('images.show.delete'), path, :method => :delete)}
+ {{else build && build['uuid'] == latest_build_id}}
+ #{path = image_target_images_path('replace_image_id', :target =>
'replace_driver', :build_id => 'replace_build_id')
+ path = path.sub('replace_image_id',
'${image[\'uuid\']}')
+ path = path.sub('replace_driver', '${driver}')
+ path = path.sub('replace_build_id',
'${build[\'uuid\']}')
+ button_to(t('images.show.build'), path, :method => :post)}
+ {{if failed_build_counts[driver] > 1}}
+ <div class="light">
+ #{t('images.show.failed_build_attemts', :count =>
'${failed_build_counts[driver]}' )}
+ </div>
+ {{else failed_build_counts[driver] == 1}}
+ <div class="light">
+ #{t('images.show.failed_build_attemts', :count => 1 )}
+ </div>
+ {{/if}}
+ {{else}}
+
+ {{/if}}
+ </dt>
+ <dd>
+ <table class="light_table">
+ <thead>
+ <tr>
+ <th>
+ <strong>#{t'images.show.account'}</strong>
+ </th>
+ <th>
+ #{t'images.show.provider'}
+ </th>
+ <th>
+ #{t'images.show.image_uuid'}
+ </th>
+ <th>
+ #{t'images.show.image_uri'}
+ </th>
+ <th class="image_controls"></th>
+ </tr></thead>
+
+ <tbody>
+ {{each(index, account) groups['accounts']}}
+ <tr>
+ <td>
+ <strong>${account['label']}</strong>
+ </td>
+ <td class="light">
+ ${account['provider_name']}
+ </td>
+ <td class="light">
+ {{if provider_images[account['id']]}}
+
${provider_images[account['id']]['target_identifier']}
+ {{/if}}
+ </td>
+ <td class="light">
+ {{if provider_images[account['id']]}}
+ ${provider_images[account['id']]['uuid']}
+ {{/if}}
+ </td>
+ <td class="image_controls light">
+ {{if target_images_by_target[driver] &&
active_pushes[account['id']]}}
+
<label>${active_pushes[account['id']]['status']}</label>
+ {{else target_images_by_target[driver] &&
!provider_images[account['id']] && build && build['uuid']
== latest_build_id}}
+ #{path = image_provider_images_path('replace_image_id',
:build_id => 'replace_build_id', :target_image_id =>
'replace_target_image_id', :account_id => 'replace_account_id')
+ path = path.sub('replace_image_id',
'${image[\'uuid\']}')
+ path = path.sub('replace_build_id',
'${build[\'uuid\']}')
+ path = path.sub('replace_target_image_id',
'${target_images_by_target[driver][\'uuid\']}')
+ path = path.sub('replace_account_id',
'${account[\'id\']}')
+ button_to(t('images.show.upload'), path, :method =>
:post, :class => 'upload_image')}
+ {{if failed_push_counts[account['id']] > 1}}
+ #{t('images.show.failed_push_attemts', :count =>
'${failed_push_counts[account[\'id\']]}' )}
+ {{else failed_push_counts[account['id']] == 1}}
+ #{t('images.show.failed_push_attemts', :count => 1
)}
+ {{/if}}
+ {{else provider_images[account['id']]}}
+ #{path = image_provider_image_path('replace_image_id',
'replace_provider_image_id')
+ path = path.sub('replace_image_id',
'${image[\'uuid\']}')
+ path = path.sub('replace_provider_image_id',
'${provider_images[account[\'id\']][\'uuid\']}')
+ button_to("", path, :method => :delete, :class
=> 'delete_image')}
+ {{else}}
+
+ {{/if}}
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+ </dd>
+ </dl>
+ <div class="clear"></div>
+ </li>
+ {{/each}}
diff --git a/src/public/javascripts/application.js
b/src/public/javascripts/application.js
index e9c0ca3..a3dd4a7 100644
--- a/src/public/javascripts/application.js
+++ b/src/public/javascripts/application.js
@@ -164,6 +164,34 @@ $.extend(Conductor, {
});
},
+ urlParams: function() {
+ var paramsData = window.location.search.slice(1).split('&');
+ var params = {};
+ $.each(paramsData, function(index, value){
+ var eqSign = value.search('=');
+ if(eqSign != -1) {
+ params[value.substring(0, eqSign)] = value.substring(eqSign+1);
+ }
+ });
+
+ return params;
+ },
+
+ extractQueryParams: function(paramsToInclude) {
+ var result = {};
+ var urlParams = Conductor.urlParams();
+
+ $.each(paramsToInclude, function(paramIndex, paramValue) {
+ for (var urlParamName in urlParams) {
+ if (urlParamName == paramValue) {
+ result[urlParamName] = urlParams[urlParamName];
+ break;
+ }
+ };
+ });
+
+ return result;
+ },
prefixedPath: function(path) {
var prefix = this.PATH_PREFIX;
@@ -205,6 +233,10 @@ $.extend(Conductor, {
return parseInt(urlFragment.split('?')[0]);
},
+ uuidFromURLFragment: function(urlFragment) {
+ return urlFragment.split('?')[0];
+ },
+
saveCheckboxes: function(checkboxSelector, $scope) {
if(!$scope) $scope = $;
diff --git a/src/public/javascripts/backbone/models.js
b/src/public/javascripts/backbone/models.js
index a89cb6b..15ebf7c 100644
--- a/src/public/javascripts/backbone/models.js
+++ b/src/public/javascripts/backbone/models.js
@@ -45,3 +45,11 @@ Conductor.Models.Deployments = Backbone.Collection.extend({
return Conductor.parameterizedPath(path, this.queryParams);
}
});
+
+Conductor.Models.Image = Backbone.Model.extend({
+ queryParams: {},
+ url: function() {
+ var path = Conductor.prefixedPath('/images/' + this.id);
+ return Conductor.parameterizedPath(path, this.queryParams);
+ }
+});
diff --git a/src/public/javascripts/backbone/routers.js
b/src/public/javascripts/backbone/routers.js
index ed896d6..d2f0123 100644
--- a/src/public/javascripts/backbone/routers.js
+++ b/src/public/javascripts/backbone/routers.js
@@ -85,3 +85,22 @@ Conductor.Routers.Deployments = Backbone.Router.extend({
}, Conductor.AJAX_REFRESH_INTERVAL);
}
});
+
+Conductor.Routers.Images = Backbone.Router.extend({
+ routes: {
+ 'images/:id': 'show'
+ },
+
+ show: function(id) {
+ id = Conductor.uuidFromURLFragment(id);
+
+ setInterval(function() {
+ var image = new Conductor.Models.Image({ id: id });
+
+ var view = new Conductor.Views.ImagesShow({ model: image });
+ view.model.queryParams = view.queryParams();
+
+ image.fetch({ success: function() { view.render(); } })
+ }, Conductor.AJAX_REFRESH_INTERVAL);
+ }
+});
diff --git a/src/public/javascripts/backbone/views.js
b/src/public/javascripts/backbone/views.js
index 97f678d..ec558e9 100644
--- a/src/public/javascripts/backbone/views.js
+++ b/src/public/javascripts/backbone/views.js
@@ -38,32 +38,10 @@ Conductor.Views.PoolsIndex = Backbone.View.extend({
}
},
- urlParams: function() {
- var paramsData = window.location.search.slice(1).split('&');
- var params = {};
- $.each(paramsData, function(index, value){
- var eqSign = value.search('=');
- if(eqSign != -1) {
- params[value.substring(0, eqSign)] = value.substring(eqSign+1);
- }
- });
-
- return params;
- },
-
queryParams: function() {
- var result = {};
var paramsToInclude = [this.currentTab() + '_preset_filter',
this.currentTab() + '_search'];
- var urlParams = this.urlParams();
+ var result = Conductor.extractQueryParams(paramsToInclude);
- $.each(paramsToInclude, function(paramIndex, paramValue) {
- for (var urlParamName in urlParams) {
- if (urlParamName == paramValue) {
- result[urlParamName] = urlParams[urlParamName];
- break;
- }
- };
- });
// If there is no URL param for the preset filter, we still need to merge in the
preset filter
var filter = this.currentTab() + '_preset_filter';
if(result[filter] == undefined) {
@@ -179,3 +157,24 @@ Conductor.Views.DeploymentsShow = Backbone.View.extend({
}
});
+
+
+Conductor.Views.ImagesShow = Backbone.View.extend({
+ el: '#content',
+
+ queryParams: function() {
+ var paramsToInclude = ['build'];
+ var result = Conductor.extractQueryParams(paramsToInclude);
+
+ return result;
+ },
+
+ render: function() {
+ var $builds = this.$('ul.image_builds');
+ if($builds.length === 0) return;
+
+ $builds.empty();
+
+ $('#imageBuildsTemplate').tmpl(this.model.toJSON()).appendTo($builds);
+ }
+});
--
1.7.6.5