[PATCH] BZ810919 mustach-ify pretty-view pool header so that instance/deployment counts are automatically updated

Imre Farkas ifarkas at redhat.com
Tue May 22 10:12:40 UTC 2012


On 05/22/2012 08:44 AM, Tzu-Mainn Chen wrote:
> ---
>   src/app/controllers/pools_controller.rb            |    7 ++-
>   src/app/helpers/mustache_helper.rb                 |   22 ++++++++++-
>   src/app/views/pools/_header_index.html.haml        |    5 ++-
>   src/app/views/pools/_pretty_list.html.haml         |   24 ++---------
>   .../views/pools/_pretty_list_header.html.mustache  |   24 +++++++++++
>   src/app/views/pools/_scoreboard_index.html.haml    |   29 --------------
>   .../views/pools/_scoreboard_index.html.mustache    |   41 ++++++++++++++++++++
>   src/public/javascripts/backbone/models.js          |    5 ++
>   src/public/javascripts/backbone/routers.js         |    8 +---
>   src/public/javascripts/backbone/views.js           |   36 ++++++++---------
>   10 files changed, 122 insertions(+), 79 deletions(-)
>   create mode 100644 src/app/views/pools/_pretty_list_header.html.mustache
>   delete mode 100644 src/app/views/pools/_scoreboard_index.html.haml
>   create mode 100644 src/app/views/pools/_scoreboard_index.html.mustache
>
> diff --git a/src/app/controllers/pools_controller.rb b/src/app/controllers/pools_controller.rb
> index 6eaa6f1..d53fd3f 100644
> --- a/src/app/controllers/pools_controller.rb
> +++ b/src/app/controllers/pools_controller.rb
> @@ -83,12 +83,13 @@ class PoolsController<  ApplicationController
>         format.json do
>           case @details_tab[:id]
>           when 'pools'
> -          render :json =>  @pools.map{ |pool| view_context.pool_for_mustache(pool) }
> +          json = @pools.map{ |pool| view_context.pool_for_mustache(pool) }
>           when 'instances'
> -          render :json =>  @instances.map{ |instance| view_context.instance_for_mustache(instance) }
> +          json = @instances.map{ |instance| view_context.instance_for_mustache(instance) }
>           when 'deployments'
> -          render :json =>  @deployments.map{ |deployment| view_context.deployment_for_mustache(deployment) }
> +          json = @deployments.map{ |deployment| view_context.deployment_for_mustache(deployment) }
>           end
> +        render :json =>  { :collection =>  json, :user_info =>  view_context.user_info_for_mustache() }
You don't need the parentheses here...

>         end
>       end
>     end
> diff --git a/src/app/helpers/mustache_helper.rb b/src/app/helpers/mustache_helper.rb
> index cc3670a..1c10d10 100644
> --- a/src/app/helpers/mustache_helper.rb
> +++ b/src/app/helpers/mustache_helper.rb
> @@ -19,6 +19,23 @@
>
>   module MustacheHelper
>
> +  def user_info_for_mustache()
...and neither here

> +    user_pools = Pool.list_for_user(current_user, Privilege::CREATE, Deployment);
> +    user_instances = current_user.owned_instances
> +    user_available_quota = current_user.quota.maximum_running_instances
> +    {
> +      :user_pools_count  =>  user_pools.count,
> +      :pools_in_use      =>  user_pools.select { |pool| pool.instances.pending_or_deployed.count>  0 }.count,
> +      :deployments_count =>  current_user.deployments.count,
> +      :instances_count   =>  user_instances.count,
> +      :instances_pending_count =>  user_instances.select {|instance| instance.state == Instance::STATE_NEW || instance.state == Instance::STATE_PENDING}.count,
You can also use the scopes defined on instance like:
:instances_pending_count =>  user_instances.pending.count

> +      :instances_failed_count  =>  user_instances.failed.count,
> +      :percentage_quota        =>  number_to_percentage(current_user.quota.percentage_used, :precision =>  0),
> +      :user_running_instances  =>  current_user.quota.running_instances,
> +      :user_available_quota    =>  user_available_quota.nil? ? raw('&infin;') : user_available_quota
> +    }
> +  end
> +
>     def instance_for_mustache(instance)
>       available_actions = instance.get_action_list
>
> @@ -76,6 +93,7 @@ module MustacheHelper
>       {
>         :id               =>  pool.id,
>         :name             =>  pool.name,
> +      :view_path =>  pool_path(pool),
>         :filter_view_path =>  pool_path(pool, :view =>  :filter),
>         :failed_instances_present =>  pool_statistics[:instances_failed_count]>  0,
>         :deployments_count        =>  pool.deployments.count,
> @@ -91,7 +109,9 @@ module MustacheHelper
>         :pool_family =>  {
>           :name =>  pool.pool_family.name,
>           :path =>  user_can_access_pool_family ? pool_family_path(pool.pool_family) : nil
> -      }
> +      },
> +
> +      :user_deployments =>  paginate_collection(pool.deployments.list_for_user(current_user, Privilege::VIEW).ascending_by_name, params[:page], PER_PAGE)
>       }
>     end
>
> diff --git a/src/app/views/pools/_header_index.html.haml b/src/app/views/pools/_header_index.html.haml
> index 5735208..aab67c3 100644
> --- a/src/app/views/pools/_header_index.html.haml
> +++ b/src/app/views/pools/_header_index.html.haml
> @@ -7,4 +7,7 @@
>           = link_to t('pools.new_pool'), new_pool_path, { :class =>  'button primary', :id =>  'new_pool_button' }
>     %h1.section-index= t 'pools.index.overview'
>
> -= render :partial =>  'scoreboard_index'
> \ No newline at end of file
> += render :partial =>  'scoreboard_index', :mustache =>  user_info_for_mustache()
You don't need the parentheses here too

> +
> +%script#poolScoreboardIndexTemplate{ :type =>  'text/html' }
> +  = render :partial =>  'scoreboard_index'
> diff --git a/src/app/views/pools/_pretty_list.html.haml b/src/app/views/pools/_pretty_list.html.haml
> index 041d092..7061af6 100644
> --- a/src/app/views/pools/_pretty_list.html.haml
> +++ b/src/app/views/pools/_pretty_list.html.haml
> @@ -4,25 +4,8 @@
>   .content#pools-list
>     - @pools.each do |pool|
>       %div.pool.overview{:id =>  ['pool', pool.id], :class =>  ('collapsed' unless pool.deployments.size>  0)}
> -      %header
> -        %h3.name
> -          = link_to pool.name, pool
> -        %dl.statistics
> -          %ul.groups
> -            %li
> -              %dt=t 'deployments.deployments'
> -              %dd.count.deployment= pool.deployments.size
> -            %li
> -              %dt=t 'instances.instances.other'
> -              %dd.count.instance= pool.instances.size
> -              %dd.count.instance.pending= pool.instances.select {|i| i.state == Instance::STATE_PENDING }.length
> -              %dd.count.instance.failure= pool.instances.select {|i| i.state == Instance::STATE_ERROR || i.state == Instance::STATE_CREATE_FAILED }.length
> -            %li
> -              %dt=t'quota_used'
> -              %dd.percentage.quota
> -                = number_to_percentage(pool.quota.percentage_used, :precision =>  0)
> -        %a.control{:href =>  '#'}
> -          %span Expand/Collapse
> +      %header{:class =>  "pool-header-#{pool.id}"}
> +        = render :partial =>  'pretty_list_header', :mustache =>  pool_for_mustache(pool)
>         %div.content
>           - deployments = paginate_collection(pool.deployments.includes(:owner, :pool, :instances, :events).list_for_user(current_user, Privilege::VIEW).ascending_by_name, params[:page], PER_PAGE)
>           = render :partial =>  'deployments', :locals =>  {:pool =>  pool, :deployments =>  deployments}
> @@ -48,3 +31,6 @@
>         });
>       })
>     });
> +
> +%script#poolPrettyListHeaderTemplate{ :type =>  'text/html' }
> +  = render :partial =>  'pretty_list_header'
> diff --git a/src/app/views/pools/_pretty_list_header.html.mustache b/src/app/views/pools/_pretty_list_header.html.mustache
> new file mode 100644
> index 0000000..140cd67
> --- /dev/null
> +++ b/src/app/views/pools/_pretty_list_header.html.mustache
> @@ -0,0 +1,24 @@
> +<h3 class="name">
> +<%= link_to('{{name}}', '{{view_path}}') %>
> +</h3>
> +<dl class="statistics">
> +<ul class="groups">
> +<li>
> +<dt><%= t('deployments.deployments')%></dt>
> +<dd class="count deployment">{{deployments_count}}</dd>
> +</li>
> +<li>
> +<dt><%= t('instances.instances.other')%></dt>
> +<dd class="count instance">{{statistics.total_instances}}</dd>
> +<dd class="count instance pending">{{statistics.instances_pending}}</dd>
> +<dd class="count instance failure">{{statistics.instances_failed_count}}</dd>
> +</li>
> +<li>
> +<dt><%= t('quota_used')%></dt>
> +<dd class="percentage_quota">{{statistics.quota_percent}}</dd>
> +</li>
> +</ul>
> +</dl>
> +<a class="control" href="#">
> +<span>Expand/Collapse</span>
> +</a>
> diff --git a/src/app/views/pools/_scoreboard_index.html.haml b/src/app/views/pools/_scoreboard_index.html.haml
> deleted file mode 100644
> index 24a6689..0000000
> --- a/src/app/views/pools/_scoreboard_index.html.haml
> +++ /dev/null
> @@ -1,29 +0,0 @@
> -#scoreboard
> -  %dl.statistics
> -    %ul.groups
> -      %li
> -        %dt= t("pools.pools")
> -        %dd.count.pool= @user_pools.count
> -        %dd.count.pool.partial= @statistics[:pools_in_use]
> -      %li
> -        %dt= t("deployments.deployments")
> -        %dd.count.deployment= @statistics[:deployments]
> -      %li
> -        %dt= t("instances.instances.other")
> -        %dd.count.instance= @statistics[:instances]
> -        %dd.count.instance.pending= @statistics[:instances_pending]
> -        %dd.count.instance.failure= @statistics[:instances_failed_count]
> -      %li
> -        %ul.subgroup
> -          %li
> -            %dt= t("alerts_label")
> -            %dd.count.alert= @statistics[:instances_failed_count]
> -      %li
> -        %dt
> -          = t("user")
> -          = t("quota_used")
> -        %dd.percentage.quota= number_to_percentage(@statistics[:user_used_percentage], :precision =>  0)
> -        %dd.fraction.instance
> -          %span.part= @statistics[:user_running_instances]
> -          %span.divider.label.small.caps of
> -          %span.total= @statistics[:user_available_quota].nil? ? raw('&infin;') : @statistics[:user_available_quota]
> diff --git a/src/app/views/pools/_scoreboard_index.html.mustache b/src/app/views/pools/_scoreboard_index.html.mustache
> new file mode 100644
> index 0000000..c45f265
> --- /dev/null
> +++ b/src/app/views/pools/_scoreboard_index.html.mustache
> @@ -0,0 +1,41 @@
> +<div id="scoreboard" class="scoreboard">
> +<dl class="statistics">
> +<ul class="groups">
> +<li>
> +<dt><%= t('pools.pools')%></dt>
> +<dd class="count pool">{{user_pools_count}}</dd>
> +<dd class="count pool partial">{{pools_in_use}}</dd>
> +</li>
> +<li>
> +<dt><%= t('deployments.deployments')%></dt>
> +<dd class="count deployment">{{deployments_count}}</dd>
> +</li>
> +<li>
> +<dt><%= t('instances.instances.other')%></dt>
> +<dd class="count instance">{{instances_count}}</dd>
> +<dd class="count instance pending">{{instances_pending_count}}</dd>
> +<dd class="count instance failure">{{instances_failed_count}}</dd>
> +</li>
> +<li>
> +<ul class="subgroup">
> +<li>
> +<dt><%= t('alerts_label')%></dt>
> +<dd class="count alert">{{instances_failed_count}}</dd>
> +</li>
> +</ul>
> +</li>
> +<li>
> +<dt>
> +<%= t('user')%>
> +<%= t('quota_used')%>
> +</dt>
> +<dd class="percentage quota">{{percentage_quota}}</dd>
> +<dd class="fraction instance">
> +<span class="part">{{user_running_instances}}</span>
> +<span class="divider label small caps">of</span>
> +<span class="total"><%= @statistics[:user_available_quota].nil? ? raw('&infin;') : @statistics[:user_available_quota] %></span>
> +</dd>
> +</li>
> +</ul>
> +</dl>
> +</div>
> diff --git a/src/public/javascripts/backbone/models.js b/src/public/javascripts/backbone/models.js
> index 8c40572..4c3084d 100644
> --- a/src/public/javascripts/backbone/models.js
> +++ b/src/public/javascripts/backbone/models.js
> @@ -1,5 +1,6 @@
>   Conductor.Models = Conductor.Models || {}
>
> +Conductor.Models.UserInfo = Backbone.Model.extend({});
>
>   Conductor.Models.Pool = Backbone.Model.extend({
>     initialize: function() {
> @@ -17,6 +18,10 @@ Conductor.Models.Pool = Backbone.Model.extend({
>   Conductor.Models.Pools = Backbone.Collection.extend({
>     model: Backbone.Model.Pool,
>     queryParams: {},
> +  parse: function(response) {
> +    this.userInfo = new Conductor.Models.UserInfo(response.user_info);
> +    return response.collection;
> +  },
>     url: function() {
>       var path = Conductor.prefixedPath('/pools');
>       return Conductor.parameterizedPath(path, this.queryParams);
> diff --git a/src/public/javascripts/backbone/routers.js b/src/public/javascripts/backbone/routers.js
> index 8d99ac5..b9a712a 100644
> --- a/src/public/javascripts/backbone/routers.js
> +++ b/src/public/javascripts/backbone/routers.js
> @@ -12,13 +12,7 @@ Conductor.Routers.Pools = Backbone.Router.extend({
>       setInterval(function() {
>         var view = new Conductor.Views.PoolsIndex();
>
> -      if (view.currentView() == 'table') {
> -        view.collection = new Conductor.Models.Pools();
> -      }
> -      else if (view.currentView() == 'pretty') {
> -        view.collection = new Conductor.Models.Deployments();
> -      }
> -
> +      view.collection = new Conductor.Models.Pools();
>         view.collection.queryParams = view.queryParams();
>         view.collection.bind('change', function() { view.render() });
>
> diff --git a/src/public/javascripts/backbone/views.js b/src/public/javascripts/backbone/views.js
> index 55e2c35..e3cf278 100644
> --- a/src/public/javascripts/backbone/views.js
> +++ b/src/public/javascripts/backbone/views.js
> @@ -79,38 +79,36 @@ Conductor.Views.PoolsIndex = Backbone.View.extend({
>       }
>       else if (this.currentView() == 'pretty') {
>         var cardsPerRow = 5;
> -      var poolIds = this.collection.models.map(function(model) {
> -        return model.attributes.pool.id;
> -      });
> -      $.unique(poolIds);
> -      var deployments = this.collection.models.map(function(model) {
> -        return model.attributes;
> -      });
>
> -      for(var j = 0; j<  poolIds.length; j++) {
> -        var poolId = poolIds[j];
> -        var $rows = this.$('#deployment-arrays-' + poolId).empty();
> -        var poolDeployments = deployments.filter(function(attributes) {
> -          return attributes.pool.id == poolId;
> -        });
> +      var self = this;
> +      var headerTemplate = $('#poolPrettyListHeaderTemplate');
> +      $.each(this.collection.models, function(index, value) {
> +        var poolId = value.attributes.id;
> +        var $rows = self.$('#deployment-arrays-' + poolId).empty();
> +        var poolDeployments = value.attributes.user_deployments;
>           for(var i = 0; i<  poolDeployments.length; i += cardsPerRow) {
> -
> -          var deplyomentCarsHtml = '';
> +          var deploymentCardsHtml = '';
>             $.each(poolDeployments.slice(i, i + cardsPerRow), function(deploymentIndex, deployment) {
> -            deplyomentCarsHtml += Mustache.to_html($template.html(), deployment);
> +            deploymentCardsHtml += Mustache.to_html($template.html(), deployment);
>             });
>
> -          var $row = this.make('ul', {'class': 'deployment-array small'}, deplyomentCarsHtml);
> +          var $row = self.make('ul', {'class': 'deployment-array small'}, deploymentCardsHtml);
>             $rows.append($row);
>           }
> -      }
> +
> +        var $header = $('header.pool-header-' + poolId);
> +        $header.html(Mustache.to_html(headerTemplate.html(), value.toJSON()));
> +      });
>       }
> +
> +    var scoreboardTemplate = $('#poolScoreboardIndexTemplate');
> +    var $scoreboard = $('div.scoreboard');
> +    $scoreboard.html(Mustache.to_html(scoreboardTemplate.html(), this.collection.userInfo.toJSON()));
>     }
>   });
>
>   Conductor.Views.PoolsShow = Backbone.View.extend({
>     el: '#content',
> -
>     currentView: function() {
>       if ($('form.filterable-data').length>  0) {
>         return 'table'

Conditional ACK: I've only encountered one little issue with updating 
the 'scoreboard' div. It places another div with the same 'scoreboard' 
id inside of it. Please fix that.

There are 4 inline notes and you can find a few places where the lines 
are over the 80 chars limit.



More information about the aeolus-devel mailing list