From: Tom Clegg Date: Fri, 14 Mar 2014 15:12:16 +0000 (-0400) Subject: Merge branch '2257-inequality-conditions' into 2290-user-activity X-Git-Tag: 1.1.0~2709^2~41^2~5^2~3 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/cf7e30873ef4b92cc8ec099b2bb344391a070e93?hp=-c Merge branch '2257-inequality-conditions' into 2290-user-activity Conflicts: apps/workbench/app/controllers/users_controller.rb apps/workbench/app/models/arvados_base.rb apps/workbench/config/routes.rb --- cf7e30873ef4b92cc8ec099b2bb344391a070e93 diff --combined apps/workbench/app/controllers/application_controller.rb index 9cb17169ad,61351d6449..6b0492a90f --- a/apps/workbench/app/controllers/application_controller.rb +++ b/apps/workbench/app/controllers/application_controller.rb @@@ -24,6 -24,7 +24,7 @@@ class ApplicationController < ActionCon def unprocessable(message=nil) @errors ||= [] + @errors << message if message render_error status: 422 end @@@ -109,6 -110,7 +110,7 @@@ 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 { @@@ -147,8 -149,7 +149,8 @@@ 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 @@@ -319,14 -320,14 +321,14 @@@ } } - @@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 diff --combined apps/workbench/app/controllers/users_controller.rb index 6168cd5293,c33de2d034..b9f43ba76a --- a/apps/workbench/app/controllers/users_controller.rb +++ b/apps/workbench/app/controllers/users_controller.rb @@@ -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 @@@ -9,53 -10,23 +10,70 @@@ 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) diff --combined apps/workbench/app/helpers/application_helper.rb index 2927be8739,e608572f05..9066224b7e --- a/apps/workbench/app/helpers/application_helper.rb +++ b/apps/workbench/app/helpers/application_helper.rb @@@ -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 @@@ -55,15 -59,11 +59,15 @@@ 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 @@@ -104,4 -104,123 +108,123 @@@ :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("#{template[:output_of]}") + 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") + + lt + end end diff --combined apps/workbench/app/models/arvados_base.rb index 09e3d8cea2,fbf7ee5e79..4ba53b9529 --- a/apps/workbench/app/models/arvados_base.rb +++ b/apps/workbench/app/models/arvados_base.rb @@@ -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' @@@ -84,24 -87,27 +87,31 @@@ 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| @@@ -131,8 -137,11 +141,11 @@@ end end + @new_record = false + self end + def save! self.save or raise Exception.new("Save failed") end @@@ -172,6 -181,7 +185,7 @@@ @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, '', { @@@ -184,9 -194,11 +198,11 @@@ } @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 @@@ -209,8 -221,14 +225,14 @@@ end end @all_links = nil + @new_record = false self end + + def to_param + uuid + end + def dup super.forget_uuid! end @@@ -278,6 -296,10 +300,10 @@@ (name if self.respond_to? :name) || uuid end + def selection_label + friendly_link_name + end + protected def forget_uuid! diff --combined apps/workbench/config/routes.rb index 376934e91b,523771c0b1..0981d2ea37 --- a/apps/workbench/config/routes.rb +++ b/apps/workbench/config/routes.rb @@@ -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