Merge branch '2257-inequality-conditions' into 2290-user-activity
authorTom Clegg <tom@curoverse.com>
Fri, 14 Mar 2014 15:12:16 +0000 (11:12 -0400)
committerTom Clegg <tom@curoverse.com>
Fri, 14 Mar 2014 15:12:16 +0000 (11:12 -0400)
Conflicts:
apps/workbench/app/controllers/users_controller.rb
apps/workbench/app/models/arvados_base.rb
apps/workbench/config/routes.rb

1  2 
apps/workbench/app/controllers/application_controller.rb
apps/workbench/app/controllers/users_controller.rb
apps/workbench/app/helpers/application_helper.rb
apps/workbench/app/models/arvados_base.rb
apps/workbench/config/routes.rb

index 9cb17169ad8dcb3c80392100727e3f7d7917bf63,61351d644974a657da435b7d39e9699cabfe7706..6b0492a90f50e3b9dafd312bd0db52c57ac2a6e6
@@@ -24,6 -24,7 +24,7 @@@ class ApplicationController < ActionCon
  
    def unprocessable(message=nil)
      @errors ||= []
      @errors << message if message
      render_error status: 422
    end
    def create
      @object ||= model_class.new params[model_class.to_s.underscore.singularize]
      @object.save!
      respond_to do |f|
        f.json { render json: @object }
        f.html {
  
    def breadcrumb_page_name
      (@breadcrumb_page_name ||
 -     (@object.friendly_link_name if @object.respond_to? :friendly_link_name))
 +     (@object.friendly_link_name if @object.respond_to? :friendly_link_name) ||
 +     action_name)
    end
  
    def index_pane_list
      }
    }
  
-   @@notification_tests.push lambda { |controller, current_user|
-     Job.limit(1).where(created_by: current_user.uuid).each do
-       return nil
-     end
-     return lambda { |view|
-       view.render partial: 'notifications/jobs_notification'
-     }
-   }
+   #@@notification_tests.push lambda { |controller, current_user|
+   #  Job.limit(1).where(created_by: current_user.uuid).each do
+   #    return nil
+   #  end
+   #  return lambda { |view|
+   #    view.render partial: 'notifications/jobs_notification'
+   #  }
+   #}
  
    @@notification_tests.push lambda { |controller, current_user|
      Collection.limit(1).where(created_by: current_user.uuid).each do
index 6168cd52931c302a8099195cc6f481759c9133e7,c33de2d034a1630b56a3ca0000aa87440ad82c7a..b9f43ba76a03d3e27141559aa8d24e1e046f48dc
@@@ -1,6 -1,7 +1,7 @@@
  class UsersController < ApplicationController
 -  skip_before_filter :find_object_by_uuid, :only => :welcome
 +  skip_before_filter :find_object_by_uuid, :only => [:welcome, :activity]
    skip_around_filter :thread_with_mandatory_api_token, :only => :welcome
+   before_filter :ensure_current_user_is_admin, only: :sudo
  
    def welcome
      if current_user
      end
    end
  
 +  def activity
 +    @breadcrumb_page_name = nil
 +    @users = User.all
 +    @user_activity = {}
 +    @activity = {
 +      logins: {},
 +      jobs: {},
 +      pipeline_instances: {}
 +    }
 +    @spans = [['This week', Time.now.beginning_of_week, Time.now],
 +              ['Last week',
 +               Time.now.beginning_of_week.advance(weeks:-1),
 +               Time.now.beginning_of_week],
 +              ['This month', Time.now.beginning_of_month, Time.now],
 +              ['Last month',
 +               1.month.ago.beginning_of_month,
 +               Time.now.beginning_of_month]]
 +    @spans.each do |span, threshold_start, threshold_end|
 +      @activity[:logins][span] = Log.
 +        filter([[:event_type, '=', 'login'],
 +                [:object_kind, '=', 'arvados#user'],
 +                [:created_at, '>=', threshold_start],
 +                [:created_at, '<', threshold_end]])
 +      @activity[:jobs][span] = Job.
 +        filter([[:created_at, '>=', threshold_start],
 +                [:created_at, '<', threshold_end]])
 +      @activity[:pipeline_instances][span] = PipelineInstance.
 +        filter([[:created_at, '>=', threshold_start],
 +                [:created_at, '<', threshold_end]])
 +      @activity.each do |type, act|
 +        records = act[span]
 +        @users.each do |u|
 +          @user_activity[u.uuid] ||= {}
 +          @user_activity[u.uuid][span + ' ' + type.to_s] ||= 0
 +        end
 +        records.each do |record|
 +          @user_activity[record.modified_by_user_uuid] ||= {}
 +          @user_activity[record.modified_by_user_uuid][span + ' ' + type.to_s] ||= 0
 +          @user_activity[record.modified_by_user_uuid][span + ' ' + type.to_s] += 1
 +        end
 +      end
 +    end
 +    @users = @users.sort_by do |a|
 +      [-@user_activity[a.uuid].values.inject(:+), a.full_name]
 +    end
 +  end
 +
+   def show_pane_list
+     if current_user.andand.is_admin
+       super | %w(Admin)
+     else
+       super
+     end
+   end
+   def sudo
+     resp = $arvados_api_client.api(ApiClientAuthorization, '', {
+                                      api_client_authorization: {
+                                        owner_uuid: @object.uuid
+                                      }
+                                    })
+     redirect_to root_url(api_token: resp[:api_token])
+   end
    def home
      @showallalerts = false
      @my_ssh_keys = AuthorizedKey.where(authorized_user_uuid: current_user.uuid)
index 2927be8739df409e0c869261ebd11a167a9f6a1f,e608572f05f23495e4f15f886582f7adc637b8c8..9066224b7e80e473328bf7fcda8da6ceece8209f
@@@ -3,6 -3,10 +3,10 @@@ module ApplicationHelpe
      controller.current_user
    end
  
+   def self.match_uuid(uuid)
+     /^([0-9a-z]{5})-([0-9a-z]{5})-([0-9a-z]{15})$/.match(uuid.to_s)
+   end
    def current_api_host
      Rails.configuration.arvados_v1_base.gsub /https?:\/\/|\/arvados\/v1/,''
    end
          link_name = link_uuid
  
          if opts[:friendly_name]
 -          begin
 -            link_name = resource_class.find(link_uuid).friendly_link_name
 -          rescue RuntimeError
 -            # If that lookup failed, the link will too. So don't make one.
 -            return attrvalue
 +          if attrvalue.respond_to? :friendly_link_name
 +            link_name = attrvalue.friendly_link_name
 +          else
 +            begin
 +              link_name = resource_class.find(link_uuid).friendly_link_name
 +            rescue RuntimeError
 +              # If that lookup failed, the link will too. So don't make one.
 +              return attrvalue
 +            end
            end
          end
          if opts[:with_class_name]
@@@ -71,7 -71,7 +75,7 @@@
          end
        end
        style_opts[:class] = (style_opts[:class] || '') + ' nowrap'
-       link_to link_name, { controller: resource_class.to_s.underscore.pluralize, action: 'show', id: link_uuid }, style_opts
+       link_to link_name, { controller: resource_class.to_s.tableize, action: 'show', id: link_uuid }, style_opts
      else
        attrvalue
      end
        :class => "editable"
      }.merge(htmloptions)
    end
+   def render_editable_subattribute(object, attr, subattr, template, htmloptions={})
+     if object
+       attrvalue = object.send(attr)
+       subattr.each do |k|
+         if attrvalue and attrvalue.is_a? Hash
+           attrvalue = attrvalue[k]
+         else
+           break
+         end
+       end
+     end
+     datatype = nil
+     required = true
+     if template
+       #puts "Template is #{template.class} #{template.is_a? Hash} #{template}"
+       if template.is_a? Hash
+         if template[:output_of]
+           return raw("<span class='label label-default'>#{template[:output_of]}</span>")
+         end
+         if template[:dataclass]
+           dataclass = template[:dataclass]
+         end
+         if template[:optional] != nil
+           required = (template[:optional] != "true")
+         end
+         if template[:required] != nil
+           required = template[:required]
+         end
+       end
+     end
+     rsc = template
+     if template.is_a? Hash
+       if template[:value]
+         rsc = template[:value]
+       elsif template[:default]
+         rsc = template[:default]
+       end
+     end
+     return link_to_if_arvados_object(rsc) if !object
+     return link_to_if_arvados_object(attrvalue) if !object.attribute_editable? attr
+     if dataclass
+       begin
+         dataclass = dataclass.constantize
+       rescue NameError
+       end
+     else
+       dataclass = ArvadosBase.resource_class_for_uuid(rsc)
+     end
+     if dataclass && dataclass.is_a?(Class)
+       datatype = 'select'
+     elsif dataclass == 'number'
+       datatype = 'number'
+     else
+       if template.is_a? Array
+         # ?!?
+       elsif template.is_a? String
+         if /^\d+$/.match(template)
+           datatype = 'number'
+         else
+           datatype = 'text'
+         end
+       end
+     end
+     id = "#{object.uuid}-#{subattr.join('-')}"
+     dn = "[#{attr}]"
+     subattr.each do |a|
+       dn += "[#{a}]"
+     end
+     if attrvalue.is_a? String
+       attrvalue = attrvalue.strip
+     end
+     if dataclass and dataclass.is_a? Class
+       items = []
+       if attrvalue and !attrvalue.empty?
+         items.append({name: attrvalue, uuid: attrvalue, type: dataclass.to_s})
+       end
+       #dataclass.where(uuid: attrvalue).each do |item|
+       #  items.append({name: item.uuid, uuid: item.uuid, type: dataclass.to_s})
+       #end
+       dataclass.limit(10).each do |item|
+         items.append({name: item.uuid, uuid: item.uuid, type: dataclass.to_s})
+       end
+     end
+     lt = link_to attrvalue, '#', {
+       "data-emptytext" => "none",
+       "data-placement" => "bottom",
+       "data-type" => datatype,
+       "data-url" => url_for(action: "update", id: object.uuid, controller: object.class.to_s.pluralize.underscore),
+       "data-title" => "Set value for #{subattr[-1].to_s}",
+       "data-name" => dn,
+       "data-pk" => "{id: \"#{object.uuid}\", key: \"#{object.class.to_s.underscore}\"}",
+       "data-showbuttons" => "false",
+       "data-value" => attrvalue,
+       :class => "editable #{'required' if required}",
+       :id => id
+     }.merge(htmloptions)
+     lt += raw("\n<script>")
+     
+     if items and items.length > 0
+       lt += raw("add_form_selection_sources(#{items.to_json});\n")
+     end
+     lt += raw("$('##{id}').editable({source: function() { return select_form_sources('#{dataclass}'); } });\n")
+     lt += raw("</script>")
+     lt 
+   end
  end
index 09e3d8cea286f4ff8695b74f02f449536bb658f2,fbf7ee5e799e48a07c831d553733b8c56bca9855..4ba53b952992d043e8ee04fce98db7f307f84286
@@@ -61,13 -61,16 +61,16 @@@ class ArvadosBase < ActiveRecord::Bas
      attr_reader :kind
      @columns
    end
    def self.column(name, sql_type = nil, default = nil, null = true)
      ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
    end
    def self.attribute_info
      self.columns
      @attribute_info
    end
    def self.find(uuid, opts={})
      if uuid.class != String or uuid.length < 27 then
        raise 'argument to find() must be a uuid string. Acceptable formats: warehouse locator or string with format xxxxx-xxxxx-xxxxxxxxxxxxxxx'
      end
      new.private_reload(hash)
    end
    def self.order(*args)
      ArvadosResourceList.new(self).order(*args)
    end
 +  def self.filter(*args)
 +    ArvadosResourceList.new(self).filter(*args)
 +  end
++
    def self.where(*args)
      ArvadosResourceList.new(self).where(*args)
    end
    def self.limit(*args)
      ArvadosResourceList.new(self).limit(*args)
    end
    def self.eager(*args)
      ArvadosResourceList.new(self).eager(*args)
    end
    def self.all(*args)
      ArvadosResourceList.new(self).all(*args)
    end
    def save
      obdata = {}
      self.class.columns.each do |col|
        end
      end
  
+     @new_record = false
      self
    end
    def save!
      self.save or raise Exception.new("Save failed")
    end
      @links = $arvados_api_client.api Link, '', { _method: 'GET', where: o, eager: true }
      @links = $arvados_api_client.unpack_api_response(@links)
    end
    def all_links
      return @all_links if @all_links
      res = $arvados_api_client.api Link, '', {
      }
      @all_links = $arvados_api_client.unpack_api_response(res)
    end
    def reload
      private_reload(self.uuid)
    end
    def private_reload(uuid_or_hash)
      raise "No such object" if !uuid_or_hash
      if uuid_or_hash.is_a? Hash
        end
      end
      @all_links = nil
+     @new_record = false
      self
    end
+   def to_param
+     uuid
+   end
    def dup
      super.forget_uuid!
    end
      (name if self.respond_to? :name) || uuid
    end
  
+   def selection_label
+     friendly_link_name
+   end
    protected
  
    def forget_uuid!
index 376934e91b8b1835c54866f0b5364eb315c9fa21,523771c0b172cf4000e0da80d4f656f328918597..0981d2ea37689e7b99635ed8bd1747e4fb409f93
@@@ -2,8 -2,10 +2,10 @@@ ArvadosWorkbench::Application.routes.dr
    themes_for_rails
  
    resources :keep_disks
-   resources :user_agreements
-   post '/user_agreements/sign' => 'user_agreements#sign'
+   resources :user_agreements do
+     put 'sign', on: :collection
+     get 'signatures', on: :collection
+   end
    get '/user_agreements/signatures' => 'user_agreements#signatures'
    resources :nodes
    resources :humans
@@@ -19,7 -21,7 +21,8 @@@
    resources :users do
      get 'home', :on => :member
      get 'welcome', :on => :collection
 +    get 'activity', :on => :collection
+     post 'sudo', :on => :member
    end
    resources :logs
    resources :factory_jobs
@@@ -34,6 -36,9 +37,9 @@@
    match '/collections/graph' => 'collections#graph'
    resources :collections
    get '/collections/:uuid/*file' => 'collections#show_file', :format => false
+   post 'actions' => 'actions#post'
    root :to => 'users#welcome'
  
    # Send unroutable requests to an arbitrary controller