myexperiment-hackers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[myexperiment-hackers] [3086] branches/wf4ever: cd branches/wf4ever ; sv


From: noreply
Subject: [myexperiment-hackers] [3086] branches/wf4ever: cd branches/wf4ever ; svn merge -r 3004:3085 ^/ trunk
Date: Sat, 11 Aug 2012 14:01:50 +0000 (UTC)

Revision
3086
Author
dgc
Date
2012-08-11 14:01:49 +0000 (Sat, 11 Aug 2012)

Log Message

cd branches/wf4ever ; svn merge -r 3004:3085 ^/trunk

Modified Paths

Added Paths

Removed Paths

Diff

Modified: branches/wf4ever/Rakefile (3085 => 3086)


--- branches/wf4ever/Rakefile	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/Rakefile	2012-08-11 14:01:49 UTC (rev 3086)
@@ -184,7 +184,7 @@
   doc.root = LibXML::XML::Node.new("results")
 
   ids.each do |id|
-    components = Workflow::Version.find(id).components
+    components = WorkflowVersion.find(id).components
     components['workflow-version'] = id.to_s
     doc.root << components
   end
@@ -192,6 +192,37 @@
   puts doc.to_s
 end
 
+desc 'Perform spam analysis on user profiles'
+task "myexp:spam:run" do
+  require File.dirname(__FILE__) + '/config/environment'
+  
+  conditions = [[]]
+
+  if ENV['FROM']
+    conditions[0] << 'users.id >= ?'
+    conditions << ENV['FROM']
+  end
+
+  if ENV['TO']
+    conditions[0] << 'users.id <= ?'
+    conditions << ENV['TO']
+  end
+
+  if conditions[0].empty?
+    conditions = nil
+  else
+    conditions[0] = conditions[0].join(" AND ")
+  end
+
+  User.find(:all, :conditions => conditions).each do |user|
+    user.calculate_spam_score
+
+    if user.save == false
+      puts "Unable to save user #{user.id} (spam score = #{user.spam_score})"
+    end
+  end
+end
+
 desc 'Rebuild checksums in the content blob store'
 task "myexp:blobstore:checksum:rebuild" do
   require File.dirname(__FILE__) + '/config/environment'

Modified: branches/wf4ever/app/controllers/application_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/application_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/application_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -19,10 +19,21 @@
 
   include AuthenticatedSystem
   before_filter :login_from_cookie
+  before_filter :login_from_basic_auth
   before_filter :oauth_required
-  
+  before_filter :check_for_sleeper
+  before_filter :check_external_site_request
+
   include ActionView::Helpers::NumberHelper
   
+  def check_for_sleeper
+    if request.method != :get && logged_in?
+      if current_user.account_status == "sleep"
+        current_user.update_attribute(:account_status, "recheck")
+      end
+    end
+  end
+
   def base_host
     request.host_with_port
   end
@@ -381,6 +392,10 @@
       hash
     when "Symbol"
       ob
+    when "TrueClass"
+      ob
+    when "FalseClass"
+      ob
     else
       ob.clone
     end
@@ -397,200 +412,29 @@
   end
 
   # Pivot code
-  
-  def pivot_options
-    {
-      :order => 
-      [
-        {
-          :option => 'rank',
-          :label  => 'Rank',
-          :order  => 'contributions.rank DESC'
-        },
-        
-        {
-          :option => 'title',
-          :label  => 'Title',
-          :order  => 'contributions.label, contributions.rank DESC'
-        },
 
-        {
-          :option => 'latest',
-          :label  => 'Latest',
-          :order  => 'contributions.created_at DESC, contributions.rank DESC'
-        },
+  def calculate_pivot(opts = {})
 
-        {
-          :option => 'last_updated',
-          :label  => 'Last updated',
-          :order  => 'contributions.updated_at DESC, contributions.rank DESC'
-        },
+    begin
+      expr = parse_filter_expression(opts[:params]["filter"], opts[:pivot_options], :active_filters => opts[:active_filters])
+    rescue Exception => ex
+      problem = "Problem with query _expression_: #{ex}"
+    end
 
-        {
-          :option => 'member',
-          :label  => 'User',
-          :joins  => [ :users ],
-          :order  => 'users.name, contributions.rank DESC'
-        },
+    pivot = contributions_list(opts[:params], opts[:user], opts[:pivot_options],
+        :model            => opts[:model],
+        :auth_type        => opts[:auth_type],
+        :auth_id          => opts[:auth_id],
+        :group_by         => opts[:group_by],
+        :active_filters   => opts[:active_filters],
+        :lock_filter      => opts[:locked_filters],
+        :search_models    => opts[:search_models],
+        :search_limit     => opts[:search_limit],
+        :filters          => expr)
 
-        {
-          :option => 'rating',
-          :label  => 'Community rating',
-          :order  => 'contributions.rating DESC, contributions.rank DESC'
-        },
-
-        {
-          :option => 'viewings',
-          :label  => 'Most viewed',
-          :order  => 'contributions.site_viewings_count DESC, contributions.rank DESC'
-        },
-
-        {
-          :option => 'downloads',
-          :label  => 'Most downloaded',
-          :order  => 'contributions.site_downloads_count DESC, contributions.rank DESC'
-        },
-
-        {
-          :option => 'type',
-          :label  => 'Type',
-          :joins  => [ :content_types ],
-          :order  => 'content_types.title, contributions.rank DESC'
-        },
-
-        {
-          :option => 'licence',
-          :label  => 'Licence',
-          :joins  => [ :licences ],
-          :order  => 'licenses.title, contributions.rank DESC'
-        },
-
-        {
-          :option => 'topic',
-          :label  => 'Topic',
-          :joins  => [ :topic_workflow_map ],
-          :order  => 'topic_workflow_map.probability, rank DESC'
-        }
-      ],
-
-      :num_options => ['10', '20', '25', '50', '100'],
-
-      :filters =>
-      [
-        {
-          :title        => 'category',
-          :query_option => 'CATEGORY',
-          :id_column    => :auth_type,
-          :label_column => :auth_type,
-          :visible_name => true
-        },
-
-        {
-          :title        => 'type',
-          :query_option => 'TYPE_ID',
-          :id_column    => 'content_types.id',
-          :label_column => 'content_types.title',
-          :joins        => [ :content_types ],
-          :not_null     => true
-        },
-
-        {
-          :title        => 'tag',
-          :query_option => 'TAG_ID',
-          :id_column    => 'tags.id',
-          :label_column => 'tags.name',
-          :joins        => [ :taggings, :tags ]
-        },
-
-        {
-          :title        => 'user',
-          :query_option => 'USER_ID',
-          :id_column    => 'users.id',
-          :label_column => 'users.name',
-          :joins        => [ :users ]
-        },
-
-        {
-          :title        => 'licence',
-          :query_option => 'LICENSE_ID',
-          :id_column    => 'licenses.id',
-          :label_column => 'licenses.unique_name',
-          :joins        => [ :licences ],
-          :not_null     => true
-        },
-
-        {
-          :title        => 'group',
-          :query_option => 'GROUP_ID',
-          :id_column    => 'networks.id',
-          :label_column => 'networks.title',
-          :joins        => [ :networks ]
-        },
-
-        {
-          :title        => 'wsdl',
-          :query_option => 'WSDL_ENDPOINT',
-          :id_column    => 'workflow_processors.wsdl',
-          :label_column => 'workflow_processors.wsdl',
-          :joins        => [ :workflow_processors ],
-          :not_null     => true
-        },
-
-        {
-          :title        => 'curation',
-          :query_option => 'CURATION_EVENT',
-          :id_column    => 'curation_events.category',
-          :label_column => 'curation_events.category',
-          :joins        => [ :curation_events ],
-          :capitalize   => true
-        },
-
-        {
-          :title        => 'provider',
-          :query_option => 'SERVICE_PROVIDER',
-          :id_column    => 'service_providers.id',
-          :label_column => 'service_providers.name',
-          :joins        => [ :services, :service_providers ]
-        },
-
-        {
-          :title        => 'country',
-          :query_option => 'SERVICE_COUNTRY',
-          :id_column    => 'services.country',
-          :label_column => 'services.country',
-          :joins        => [ :services ]
-        },
-
-        {
-          :title        => 'service status',
-          :query_option => 'SERVICE_STATUS',
-          :id_column    => 'services.monitor_label',
-          :label_column => 'services.monitor_label',
-          :joins        => [ :services ]
-        },
-
-
-      ],
-
-      :joins =>
-      {
-        :content_types       => "LEFT OUTER JOIN content_types ON contributions.content_type_id = content_types.id",
-        :licences            => "LEFT OUTER JOIN licenses ON contributions.license_id = licenses.id",
-        :users               => "INNER JOIN users ON contributions.contributor_type = 'User' AND contributions.contributor_id = users.id",
-        :taggings            => "LEFT OUTER JOIN taggings ON AUTH_TYPE = taggings.taggable_type AND AUTH_ID = taggings.taggable_id",
-        :tags                => "INNER JOIN tags ON taggings.tag_id = tags.id",
-        :networks            => "INNER JOIN networks ON permissions.contributor_type = 'Network' AND permissions.contributor_id = networks.id",
-        :credits             => "INNER JOIN creditations ON creditations.creditable_type = AUTH_TYPE AND creditations.creditable_id = AUTH_ID",
-        :curation_events     => "INNER JOIN curation_events ON curation_events.object_type = AUTH_TYPE AND curation_events.object_id = AUTH_ID",
-        :workflow_processors => "INNER JOIN workflow_processors ON AUTH_TYPE = 'Workflow' AND workflow_processors.workflow_id = AUTH_ID",
-        :search              => "RIGHT OUTER JOIN search_results ON search_results.result_type = AUTH_TYPE AND search_results.result_id = AUTH_ID",
-        :topic_workflow_map  => "INNER JOIN topic_workflow_map ON contributions.id = topic_workflow_map.workflow_id",
-        :services            => "INNER JOIN services ON AUTH_TYPE = 'Service' AND AUTH_ID = services.id",
-        :service_providers   => "INNER JOIN service_providers ON AUTH_TYPE = 'Service' AND service_providers.uri = services.provider_uri",
-      }
-    }
+    [pivot, problem]
   end
-
+  
   TOKEN_UNKNOWN         = 0x0000
   TOKEN_AND             = 0x0001
   TOKEN_OR              = 0x0002
@@ -609,12 +453,14 @@
   STATE_EXPECT_END      = 0x0400
   STATE_COMPLETE        = 0x0500
 
-  def parse_filter_expression(expr)
+  def parse_filter_expression(expr, pivot_options, opts = {})
 
     def unescape_string(str)
       str.match(/^"(.*)"$/)[1].gsub(/\\"/, '"')
     end
 
+    return nil if expr.nil?
+
     state  = STATE_INITIAL
     data   = ""
 
@@ -663,7 +509,8 @@
 
     # validate and reduce expressions to current capabilities
 
-    valid_filters = pivot_options[:filters].map do |f| f[:query_option] end
+    valid_filters = pivot_options["filters"].map do |f| f["query_option"] end
+    valid_filters = valid_filters.select do |f| opts[:active_filters].include?(f) end
 
     data.each do |category|
       case category
@@ -703,22 +550,22 @@
     data
   end
 
-  def contributions_list(klass = nil, params = nil, user = nil, opts = {})
+  def contributions_list(params = nil, user = nil, pivot_options = nil, opts = {})
 
     def escape_sql(str)
       str.gsub(/\\/, '\&\&').gsub(/'/, "''")
     end
 
-    def build_url(params, opts, expr, parts, extra = {})
+    def build_url(params, opts, expr, parts, pivot_options, extra = {})
 
       query = {}
 
       if parts.include?(:filter)
         bits = []
-        pivot_options[:filters].each do |filter|
-          if !opts[:lock_filter] || opts[:lock_filter][filter[:query_option]].nil?
-            if find_filter(expr, filter[:query_option])
-              bits << filter[:query_option] + "(\"" + find_filter(expr, filter[:query_option])[:expr][:terms].map do |t| t.gsub(/"/, '\"') end.join("\" OR \"") + "\")"
+        pivot_options["filters"].each do |filter|
+          if !opts[:lock_filter] || opts[:lock_filter][filter["query_option"]].nil?
+            if find_filter(expr, filter["query_option"])
+              bits << filter["query_option"] + "(\"" + find_filter(expr, filter["query_option"])[:expr][:terms].map do |t| t.gsub(/"/, '\"') end.join("\" OR \"") + "\")"
             end
           end
         end
@@ -745,18 +592,18 @@
       end
     end
 
-    def create_search_results_table(search_query, models)
+    def create_search_results_table(search_query, opts)
 
       begin
-        solr_results = models.first.multi_solr_search(search_query,
-            :models         => models,
-            :results_format => :ids,
-            :limit          => Conf.max_search_size)
+        solr_results = opts[:search_models].first.multi_solr_search(search_query,
+            :models         => opts[:search_models],
+            :limit          => opts[:search_limit],
+            :results_format => :ids)
       rescue
         return false
       end
 
-      conn =  ActiveRecord::Base.connection
+      conn = ActiveRecord::Base.connection
 
       conn.execute("CREATE TEMPORARY TABLE search_results (id INT AUTO_INCREMENT UNIQUE KEY, result_type VARCHAR(255), result_id INT)")
 
@@ -782,56 +629,35 @@
       ActiveRecord::Base.connection.execute("DROP TABLE IF EXISTS search_results")
     end
 
-    def calculate_having_clause(filter, opts)
-
-      having_bits = []
-
-      pivot_options[:filters].each do |f|
-        if f != filter
-#         if opts[:filters][f[:query_option]] && opts[:filters]["and_#{f[:query_option]}"] == "yes"
-#           having_bits << "(GROUP_CONCAT(DISTINCT #{f[:id_column]} ORDER BY #{f[:id_column]}) = '#{escape_sql(opts[:filters][f[:query_option]])}')"
-#         end
-        end
-      end
-
-      return nil if having_bits.empty?
-
-      "HAVING " + having_bits.join(" OR ")
-    end
-
     def column(column, opts)
       if column == :auth_type
-        if opts[:auth_type]
-          opts[:auth_type]
-        else
-          "contributions.contributable_type"
-        end
+        opts[:auth_type]
       else
         column
       end
     end
 
-    def calculate_filter(params, filter, user, opts = {})
+    def calculate_filter(collection, params, filter, pivot_options, user, opts = {})
 
       # apply all the joins and conditions except for the current filter
 
       joins      = []
       conditions = []
 
-      pivot_options[:filters].each do |other_filter|
-        if filter_list = find_filter(opts[:filters], other_filter[:query_option])
+      pivot_options["filters"].each do |other_filter|
+        if filter_list = find_filter(opts[:filters], other_filter["query_option"])
           unless opts[:inhibit_other_conditions]
-            conditions << comparison(column(other_filter[:id_column], opts), filter_list[:expr][:terms]) unless other_filter == filter
+            conditions << comparison(column(other_filter["id_column"], opts), filter_list[:expr][:terms]) unless other_filter == filter
           end
-          joins += other_filter[:joins] if other_filter[:joins]
+          joins += other_filter["joins"] if other_filter["joins"]
         end
       end
 
-      filter_id_column    = column(filter[:id_column],    opts)
-      filter_label_column = column(filter[:label_column], opts)
+      filter_id_column    = column(filter["id_column"],    opts)
+      filter_label_column = column(filter["label_column"], opts)
 
-      joins += filter[:joins] if filter[:joins]
-      conditions << "#{filter_id_column} IS NOT NULL" if filter[:not_null]
+      joins += filter["joins"] if filter["joins"]
+      conditions << "#{filter_id_column} IS NOT NULL" if filter["not_null"]
 
       unless opts[:inhibit_filter_query]
         if params[:filter_query]
@@ -839,10 +665,8 @@
         end
       end
 
-      joins.push(:search) if params[:query] && !opts[:arbitrary_models]
+      current = find_filter(opts[:filters], filter["query_option"]) ? find_filter(opts[:filters], filter["query_option"])[:expr][:terms] : []
 
-      current = find_filter(opts[:filters], filter[:query_option]) ? find_filter(opts[:filters], filter[:query_option])[:expr][:terms] : []
-
       if opts[:ids].nil?
         limit = 10
       else
@@ -852,26 +676,17 @@
 
       conditions = conditions.length.zero? ? nil : conditions.join(" AND ")
 
-      if opts[:auth_type] && opts[:auth_id]
-        count_expr = "COUNT(DISTINCT #{opts[:auth_type]}, #{opts[:auth_id]})"
-      else
-        count_expr = "COUNT(DISTINCT contributions.contributable_type, contributions.contributable_id)"
-      end
+      count_expr = "COUNT(DISTINCT #{opts[:auth_type]}, #{opts[:auth_id]})"
 
-      objects = Authorization.authorised_index(params[:query] && opts[:arbitrary_models] ? SearchResult : Contribution,
+      objects = collection.find(
           :all,
-          :include_permissions => true,
           :select => "#{filter_id_column} AS filter_id, #{filter_label_column} AS filter_label, #{count_expr} AS filter_count",
-          :arbitrary_models => opts[:arbitrary_models],
-          :auth_type => opts[:auth_type],
-          :auth_id => opts[:auth_id],
-          :joins => merge_joins(joins, :auth_type => opts[:auth_type], :auth_id => opts[:auth_id]),
+          :joins => merge_joins(joins, pivot_options, :auth_type => opts[:auth_type], :auth_id => opts[:auth_id]),
           :conditions => conditions,
-          :group => "#{filter_id_column} #{calculate_having_clause(filter, opts)}",
+          :group => "#{filter_id_column}",
           :limit => limit,
-          :order => "#{count_expr} DESC, #{filter_label_column}",
-          :authorised_user => user)
-      
+          :order => "#{count_expr} DESC, #{filter_label_column}")
+
       objects = objects.select do |x| !x[:filter_id].nil? end
 
       objects = objects.map do |object|
@@ -880,15 +695,15 @@
         selected = current.include?(value)
 
         label_expr = deep_clone(opts[:filters])
-        label_expr -= [find_filter(label_expr, filter[:query_option])] if find_filter(label_expr, filter[:query_option])
+        label_expr -= [find_filter(label_expr, filter["query_option"])] if find_filter(label_expr, filter["query_option"])
 
         unless selected && current.length == 1
-          label_expr << { :name => filter[:query_option], :expr => { :terms => [value] } }
+          label_expr << { :name => filter["query_option"], :expr => { :terms => [value] } }
         end
 
         checkbox_expr = deep_clone(opts[:filters])
 
-        if expr_filter = find_filter(checkbox_expr, filter[:query_option])
+        if expr_filter = find_filter(checkbox_expr, filter["query_option"])
 
           if selected
             expr_filter[:expr][:terms] -= [value]
@@ -899,16 +714,16 @@
           checkbox_expr -= [expr_filter] if expr_filter[:expr][:terms].empty?
 
         else
-          checkbox_expr << { :name => filter[:query_option], :expr => { :terms => [value] } }
+          checkbox_expr << { :name => filter["query_option"], :expr => { :terms => [value] } }
         end
 
-        label_uri = build_url(params, opts, label_expr, [:filter, :order], "page" => nil)
+        label_uri = build_url(params, opts, label_expr, [:filter, :order], pivot_options, "page" => nil)
 
-        checkbox_uri = build_url(params, opts, checkbox_expr, [:filter, :order], "page" => nil)
+        checkbox_uri = build_url(params, opts, checkbox_expr, [:filter, :order], pivot_options, "page" => nil)
 
         label = object.filter_label.clone
-        label = visible_name(label) if filter[:visible_name]
-        label = label.capitalize    if filter[:capitalize]
+        label = visible_name(label) if filter["visible_name"]
+        label = label.capitalize    if filter["capitalize"]
 
         plain_label = object.filter_label
 
@@ -931,18 +746,18 @@
       [current, objects]
     end
 
-    def calculate_filters(params, opts, user)
+    def calculate_filters(collection, params, opts, pivot_options, user)
 
       # produce the filter list
 
-      filters = pivot_options[:filters].clone
+      filters = deep_clone(pivot_options["filters"])
       cancel_filter_query_url = nil
 
       filters.each do |filter|
 
         # calculate the top n items of the list
 
-        filter[:current], filter[:objects] = calculate_filter(params, filter, user, opts)
+        filter[:current], filter[:objects] = calculate_filter(collection, params, filter, pivot_options, user, opts)
 
         # calculate which active filters are missing (because they weren't in the
         # top part of the list or have a count of zero)
@@ -950,7 +765,7 @@
         missing_filter_ids = filter[:current] - filter[:objects].map do |ob| ob[:value] end
 
         if missing_filter_ids.length > 0
-          filter[:objects] += calculate_filter(params, filter, user, opts.merge(:ids => missing_filter_ids))[1]
+          filter[:objects] += calculate_filter(collection, params, filter, pivot_options, user, opts.merge(:ids => missing_filter_ids))[1]
         end
 
         # calculate which active filters are still missing (because they have a
@@ -959,7 +774,7 @@
         missing_filter_ids = filter[:current] - filter[:objects].map do |ob| ob[:value] end
         
         if missing_filter_ids.length > 0
-          zero_list = calculate_filter(params, filter, user, opts.merge(:ids => missing_filter_ids, :inhibit_other_conditions => true))[1]
+          zero_list = calculate_filter(collection, params, filter, pivot_options, user, opts.merge(:ids => missing_filter_ids, :inhibit_other_conditions => true))[1]
 
           zero_list.each do |x| x[:count] = 0 end
 
@@ -978,23 +793,23 @@
       end
     end
 
-    def merge_joins(joins, opts = {})
-
-      opts[:auth_type] ||= 'contributions.contributable_type'
-      opts[:auth_id]   ||= 'contributions.contributable_id'
-
+    def merge_joins(joins, pivot_options, opts = {})
       if joins.length.zero?
         nil
       else
         joins.uniq.map do |j|
-          text = pivot_options[:joins][j]
-          text.gsub!(/AUTH_TYPE/, opts[:auth_type])
-          text.gsub!(/AUTH_ID/,   opts[:auth_id])
+          text = pivot_options["joins"][j].clone
+          text.gsub!(/RESULT_TYPE/, opts[:auth_type])
+          text.gsub!(/RESULT_ID/,   opts[:auth_id])
           text
         end.join(" ")
       end
     end
 
+    pivot_options["filters"] = pivot_options["filters"].select do |f|
+      opts[:active_filters].include?(f["query_option"])
+    end
+
     joins      = []
     conditions = []
 
@@ -1021,52 +836,50 @@
 
     # perform search if requested
 
-    group_by = "contributions.contributable_type, contributions.contributable_id"
-
     query_problem = false
 
     if params["query"]
       drop_search_results_table
-      if create_search_results_table(params["query"], [Workflow, Blob, Pack, User, Network, Service])
-        joins.push(:search) unless opts[:arbitrary_models]
-      else
+      if !create_search_results_table(params["query"], opts)
         params["query"] = nil
         query_problem = true
       end
     end
 
-    if opts[:arbitrary_models] && params[:query]
-      klass = SearchResult
-      contribution_records = false
+    if params[:query]
+      klass     = SearchResult
       auth_type = "search_results.result_type"
       auth_id   = "search_results.result_id"
       group_by  = "search_results.result_type, search_results.result_id"
     else
-      contribution_records = true
+      klass     = opts[:model]     || Contribution
+      auth_type = opts[:auth_type] || "contributions.contributable_type"
+      auth_id   = opts[:auth_id]   || "contributions.contributable_id"
+      group_by  = opts[:group_by]  || "contributions.contributable_type, contributions.contributable_id"
     end
 
     # determine joins, conditions and order for the main results
 
-    pivot_options[:filters].each do |filter|
-      if filter_list = find_filter(opts[:filters], filter[:query_option])
-        conditions << comparison(column(filter[:id_column], opts.merge( { :auth_type => auth_type, :auth_id => auth_id } )), filter_list[:expr][:terms])
-        joins += filter[:joins] if filter[:joins]
+    pivot_options["filters"].each do |filter|
+      if filter_list = find_filter(opts[:filters], filter["query_option"])
+        conditions << comparison(column(filter["id_column"], opts.merge( { :auth_type => auth_type, :auth_id => auth_id } )), filter_list[:expr][:terms])
+        joins += filter["joins"] if filter["joins"]
       end
     end
 
-    order_options = pivot_options[:order].find do |x|
-      x[:option] == params[:order]
+    order_options = pivot_options["order"].find do |x|
+      x["option"] == params[:order]
     end
 
-    order_options ||= pivot_options[:order].first
+    order_options ||= pivot_options["order"].first
 
-    joins += order_options[:joins] if order_options[:joins]
+    joins += order_options["joins"] if order_options["joins"]
 
     having_bits = []
 
-#   pivot_options[:filters].each do |filter|
-#     if params["and_#{filter[:query_option]}"]
-#       having_bits << "GROUP_CONCAT(DISTINCT #{filter[:id_column]} ORDER BY #{filter[:id_column]}) = \"#{escape_sql(opts[:filters][filter[:query_option]])}\""
+#   pivot_options["filters"].each do |filter|
+#     if params["and_#{filter["query_option"]}"]
+#       having_bits << "GROUP_CONCAT(DISTINCT #{filter["id_column"]} ORDER BY #{filter["id_column"]}) = \"#{escape_sql(opts[:filters][filter["query_option"]])}\""
 #     end
 #   end
 
@@ -1078,28 +891,28 @@
 
     # perform the results query
 
-    results = Authorization.authorised_index(klass,
-        :all,
+    collection = Authorization.scoped(klass,
         :authorised_user => user,
         :include_permissions => true,
-        :contribution_records => contribution_records,
-        :arbitrary_models => opts[:arbitrary_models],
         :auth_type => auth_type,
-        :auth_id => auth_id,
+        :auth_id => auth_id)
+
+    results = collection.find(
+        :all,
         :page => { :size => params["num"] ? params["num"].to_i : nil, :current => params["page"] },
-        :joins => merge_joins(joins, :auth_type => auth_type, :auth_id => auth_id),
+        :joins => merge_joins(joins, pivot_options, :auth_type => auth_type, :auth_id => auth_id),
         :conditions => conditions.length.zero? ? nil : conditions.join(" AND "),
         :group => "#{group_by} #{having_clause}",
-        :order => order_options[:order])
-
+        :order => order_options["order"])
+        
     # produce a query hash to match the current filters
 
     opts[:filter_params] = {}
 
-    pivot_options[:filters].each do |filter|
-      if params[filter[:query_option]]
-        next if opts[:lock_filter] && opts[:lock_filter][filter[:query_option]]
-        opts[:filter_params][filter[:query_option]] = params[filter[:query_option]]
+    pivot_options["filters"].each do |filter|
+      if params[filter["query_option"]]
+        next if opts[:lock_filter] && opts[:lock_filter][filter["query_option"]]
+        opts[:filter_params][filter["query_option"]] = params[filter["query_option"]]
       end
     end
 
@@ -1108,13 +921,13 @@
     opts_for_filter_query = opts.merge( { :auth_type => auth_type,
         :auth_id => auth_id, :group_by => group_by } )
 
-    filters, cancel_filter_query_url = calculate_filters(params, opts_for_filter_query, user)
+    filters, cancel_filter_query_url = calculate_filters(collection, params, opts_for_filter_query, pivot_options, user)
 
     # produce the summary.  If a filter query is specified, then we need to
     # recalculate the filters without the query to get all of them.
 
     if params[:filter_query]
-      filters2 = calculate_filters(params, opts_for_filter_query.merge( { :inhibit_filter_query => true } ), user)[0]
+      filters2 = calculate_filters(collection, params, opts_for_filter_query.merge( { :inhibit_filter_query => true } ), pivot_options, user)[0]
     else
       filters2 = filters
     end
@@ -1123,7 +936,7 @@
 
     filters2.select do |filter|
 
-      next if opts[:lock_filter] && opts[:lock_filter][filter[:query_option]]
+      next if opts[:lock_filter] && opts[:lock_filter][filter["query_option"]]
 
       selected = filter[:objects].select do |x| x[:selected] end
       current  = selected.map do |x| x[:value] end
@@ -1133,29 +946,29 @@
 
           expr = deep_clone(opts[:filters])
 
-          f = find_filter(expr, filter[:query_option])
+          f = find_filter(expr, filter["query_option"])
   
           expr -= f[:expr][:terms] -= [x[:value]]
           expr -= [f] if f[:expr][:terms].empty?
 
           x[:plain_label] + ' <a href="" + url_for(build_url(params, opts, expr,
-          [:filter, :filter_query, :order])) +
+          [:filter, :filter_query, :order], pivot_options)) +
             '">' + " <img src='' /></a>"
 
         end
 
         bits = selected_labels.map do |label| label end.join(" <i>or</i> ")
 
-        summary << '<span class="filter-in-use"><b>' + filter[:title].capitalize + "</b>: " + bits + "</span> "
+        summary << '<span class="filter-in-use"><b>' + filter["title"].capitalize + "</b>: " + bits + "</span> "
       end
     end
 
     if params[:filter_query]
-      cancel_filter_query_url = build_url(params, opts, opts[:filters], [:filter, :order])
+      cancel_filter_query_url = build_url(params, opts, opts[:filters], [:filter, :order], pivot_options)
     end
 
     if include_reset_url
-      reset_filters_url = build_url(params, opts, opts[:filters], [:order])
+      reset_filters_url = build_url(params, opts, opts[:filters], [:order], pivot_options)
     end
 
     # remove filters that do not help in narrowing down the result set
@@ -1163,7 +976,7 @@
     filters = filters.select do |filter|
       if filter[:objects].empty?
         false
-      elsif opts[:lock_filter] && opts[:lock_filter][filter[:query_option]]
+      elsif opts[:lock_filter] && opts[:lock_filter][filter["query_option"]]
         false
       else
         true
@@ -1175,8 +988,9 @@
       :filters                 => filters,
       :reset_filters_url       => reset_filters_url,
       :cancel_filter_query_url => cancel_filter_query_url,
-      :filter_query_url        => build_url(params, opts, opts[:filters], [:filter]),
+      :filter_query_url        => build_url(params, opts, opts[:filters], [:filter], pivot_options),
       :summary                 => summary,
+      :pivot_options           => pivot_options,
       :query_problem           => query_problem
     }
   end
@@ -1198,4 +1012,39 @@
     end
 
   end
+
+  # Applies a header to the page
+  def check_external_site_request
+    unless params.empty?
+      external_url_keys = params.keys & Conf.external_site_integrations.keys.collect {|s| s + "_url"}
+
+      if external_url_keys.size == 1
+        external_url_key = external_url_keys.first
+        external_url = params[external_url_key]
+
+        if %w(http https).include?(URI.parse(external_url).scheme)
+          session[:came_from] = external_url_key[0..-5] # Strip the _url part
+          session[:return_url] = CGI.unescape(external_url)
+        else
+          raise("Invalid return URL given for #{external_url_key}: \n\t#{external_url}")
+        end
+      elsif external_url_keys.size > 1
+        raise("#{external_url_keys.size} external URLs specified. Can only cope with one!")
+      end
+    end
+  end
+
+  # Remove external site information from session
+  #  and then go back the page we were at, or /home
+  def clear_external_site_session_info
+    params.delete("#{session.delete(:came_from)}_url")
+    session.delete(:return_url)
+
+    referrer = request.headers["Referer"]
+    target = referrer.blank? ? '/home' : URI.parse(referrer).path
+
+    respond_to do |format|
+      format.html { redirect_to target, (referrer.blank? ? nil : params) }
+    end
+  end
 end

Modified: branches/wf4ever/app/controllers/blobs_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/blobs_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/blobs_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -7,21 +7,21 @@
 
   include ApplicationHelper
 
-  before_filter :login_required, :except => [:index, :show, :download, :named_download, :statistics, :search]
+  before_filter :login_required, :except => [:index, :show, :download, :named_download, :named_download_with_version, :statistics, :search, :auto_complete]
+
+  before_filter :find_blob_auth, :except => [:search, :index, :new, :create, :auto_complete]
   
-  before_filter :find_blob_auth, :except => [:search, :index, :new, :create]
-  
   before_filter :initiliase_empty_objects_for_new_pages, : [:new, :create]
   before_filter :set_sharing_mode_variables, : [:show, :new, :create, :edit, :update]
   
-  before_filter :check_is_owner, : [:edit, :update]
+  before_filter :check_is_owner, : [:edit, :update, :suggestions, :process_suggestions]
   
   # declare sweepers and which actions should invoke them
   cache_sweeper :blob_sweeper, : [ :create, :update, :destroy ]
   cache_sweeper :permission_sweeper, : [ :create, :update, :destroy ]
   cache_sweeper :bookmark_sweeper, : [ :destroy, :favourite, :favourite_delete ]
   cache_sweeper :tag_sweeper, : [ :create, :update, :tag, :destroy ]
-  cache_sweeper :download_viewing_sweeper, : [ :show, :download, :named_download ]
+  cache_sweeper :download_viewing_sweeper, : [ :show, :download, :named_download, :named_download_with_version ]
   cache_sweeper :comment_sweeper, : [ :comment, :comment_delete ]
   cache_sweeper :rating_sweeper, : [ :rate ]
   
@@ -36,7 +36,7 @@
       @download = Download.create(:contribution => @blob.contribution, :user => (logged_in? ? current_user : nil), :user_agent => request.env['HTTP_USER_AGENT'], :accessed_from_site => accessed_from_website?())
     end
     
-    send_data(@blob.content_blob.data, :filename => @blob.local_name, :type => @blob.content_type.mime_type)
+    send_data(@version.content_blob.data, :filename => @version.local_name, :type => @version.content_type.mime_type)
     
     #send_file("#{RAILS_ROOT}/#{controller_name}/address@hidden/address@hidden/address@hidden", :filename => @blob.local_name, :type => @blob.content_type.mime_type)
   end
@@ -52,24 +52,39 @@
     end
   end
 
+  # GET /files/:id/versions/:version/download/:name
+  def named_download_with_version
+
+    # check that we got the right filename for this workflow
+    if params[:name] == @version.local_name
+      download
+    else
+      render :nothing => true, :status => "404 Not Found"
+    end
+  end
+
   # GET /files
   def index
     respond_to do |format|
       format.html {
-        @pivot_options = pivot_options
 
-        begin
-          expr = parse_filter_expression(params["filter"]) if params["filter"]
-        rescue Exception => ex
-          puts "ex = #{ex.inspect}"
-          flash.now[:error] = "Problem with query _expression_: #{ex}"
-          expr = nil
-        end
+        @pivot, problem = calculate_pivot(
 
-        @pivot = contributions_list(Contribution, params, current_user,
-            :lock_filter => { 'CATEGORY' => 'Blob' },
-            :filters     => expr)
+            :pivot_options  => Conf.pivot_options,
+            :params         => params,
+            :user           => current_user,
+            :search_models  => [Blob],
+            :search_limit   => Conf.max_search_size,
 
+            :locked_filters => { 'CATEGORY' => 'Blob' },
+
+            :active_filters => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                                "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                                "CURATION_EVENT", "SERVICE_PROVIDER",
+                                "SERVICE_COUNTRY", "SERVICE_STATUS"])
+
+        flash.now[:error] = problem if problem
+
         @query = params[:query]
         @query_type = 'files'
 
@@ -133,12 +148,8 @@
       @blob = Blob.new(params[:blob])
       @blob.content_blob = ContentBlob.new(:data ="" data)
 
-      @blob.content_type = ContentType.find_by_mime_type(content_type)
+      @blob.content_type = ContentType.find_or_create_by_mime_type(:user => current_user, :mime_type => content_type, :category=> 'Blob')
 
-      if @blob.content_type.nil?
-        @blob.content_type = ContentType.create(:user_id => current_user.id, :mime_type => content_type, :title => content_type, :category => 'Blob')
-      end
-
       respond_to do |format|
         if @blob.save
           if params[:blob][:tag_list]
@@ -156,8 +167,18 @@
           update_attributions(@blob, params)
         
           if policy_err_msg.blank?
-            flash[:notice] = 'File was successfully created.'
-            format.html { redirect_to blob_url(@blob) }
+
+            @version = @blob.find_version(1)
+
+            format.html {
+              if @version.suggestions?
+                redirect_to(blob_version_suggestions_path(@blob, @version.version))
+              else
+                flash[:notice] = 'File was successfully created.'
+                  redirect_to blob_url(@blob)
+              end
+            }
+
           else
             flash[:notice] = "File was successfully created. However some problems occurred, please see these below.</br></br><span style='color: red;'>" + policy_err_msg + "</span>"
             format.html { redirect_to :controller => 'blobs', :id => @blob, :action ="" "edit" }
@@ -186,8 +207,14 @@
     
     params[:blob][:license_id] = nil if params[:blob][:license_id] && params[:blob][:license_id] == "0"
 
-    # 'Data' (ie: the actual file) cannot be updated!
-    params[:blob].delete('data') if params[:blob][:data]
+    # Create a new content blob entry if new data is provided.
+    if params[:blob][:data] && params[:blob][:data].size > 0
+      @blob.build_content_blob(:data ="" params[:blob][:data].read)
+      @blob.local_name = params[:blob][:data].original_filename
+      @blob.content_type = ContentType.find_or_create_by_mime_type(:user => current_user, :title => params[:blob][:data].content_type, :mime_type => params[:blob][:data].content_type, :category => 'Blob')
+    end
+
+    params[:blob].delete(:data)
     
     respond_to do |format|
       if @blob.update_attributes(params[:blob])
@@ -199,8 +226,21 @@
         update_layout(@blob, params[:layout])
         
         if policy_err_msg.blank?
-          flash[:notice] = 'File was successfully updated.'
-          format.html { redirect_to blob_url(@blob) }
+          format.html {
+
+            if @blob.new_version_number
+              @version = @blob.find_version(@blob.new_version_number)
+            else
+              @version.reload
+            end
+
+            if @version.suggestions?
+              redirect_to(blob_version_suggestions_path(@blob, @version.version))
+            else
+              flash[:notice] = 'File was successfully updated.'
+              redirect_to blob_url(@blob)
+            end
+          }
         else
           flash[:error] = policy_err_msg
           format.html { redirect_to :controller => 'blobs', :id => @blob, :action ="" "edit" }
@@ -288,7 +328,46 @@
       format.html { redirect_to redirect_url }
     end
   end
+
+  def auto_complete
+    text = params[:file_name] || ''
+
+    files = Blob.find(:all,
+                     :conditions => ["LOWER(title) LIKE ?", text.downcase + '%'],
+                     :order => 'title ASC',
+                     :limit => 20,
+                     :select => 'DISTINCT *')
+
+    files = files.select {|f| Authorization.is_authorized?('view', nil, f, current_user) }
+
+    render :partial => 'contributions/autocomplete_list', :locals => { :contributions => files }
+  end
   
+  # GET /files/1/versions/1/suggestions
+  def suggestions
+    @suggestions = @version.suggestions
+  end
+
+  # POST /files/1/versions/1/process_suggestions
+  def process_suggestions
+
+    @version.revision_comments = params[:revision_comments] if params[:revision_comments]
+    @version.body = params[:description] if params[:description]
+
+    success = @version.save
+
+    respond_to do |format|
+      format.html {
+        if success
+          flash[:notice] = 'File was successfully updated.'
+          redirect_to blob_version_path(@blob, @version.version)
+        else
+          render :action ="" "suggestions"  
+        end
+      }
+    end
+  end
+
   protected
   
   def find_blob_auth
@@ -298,14 +377,21 @@
       if Authorization.is_authorized?(action_name, nil, blob, current_user)
         @blob = blob
         
+        if params[:version]
+          @version = @blob.find_version(params[:version])
+        else
+          @version = @blob.versions.last
+        end
+
         @blob_entry_url = url_for : false,
                             :host => base_host,
                             :id => @blob.id
 
-        @named_download_url = url_for :controller => 'files',
-                                      :action ="" 'named_download',
+        @named_download_url = url_for :controller => 'blobs',
+                                      :action ="" 'named_download_with_version',
                                       :id => @blob.id, 
-                                      :name => @blob.local_name
+                                      :version => @version.version, 
+                                      :name => @version.local_name
 
       else
         if logged_in? 

Modified: branches/wf4ever/app/controllers/content_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/content_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/content_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -10,19 +10,22 @@
   def index
     respond_to do |format|
       format.html do
-        @pivot_options = pivot_options
 
-        begin
-          expr = parse_filter_expression(params["filter"]) if params["filter"]
-        rescue Exception => ex
-          puts "ex = #{ex.inspect}"
-          flash.now[:error] = "Problem with query _expression_: #{ex}"
-          expr = nil
-        end
+        @pivot, problem = calculate_pivot(
 
-        @pivot = contributions_list(Contribution, params, current_user,
-            :filters => expr, :arbitrary_models => true)
+            :pivot_options    => Conf.pivot_options,
+            :params           => params,
+            :user             => current_user,
+            :search_models    => [Workflow, Blob, Pack, Service],
+            :search_limit     => Conf.max_search_size,
 
+            :active_filters   => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                                  "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                                  "CURATION_EVENT", "SERVICE_PROVIDER",
+                                  "SERVICE_COUNTRY", "SERVICE_STATUS"])
+
+        flash.now[:error] = problem if problem
+
         @query = params[:query]
 
         # index.rhtml

Modified: branches/wf4ever/app/controllers/memberships_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/memberships_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/memberships_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -164,7 +164,7 @@
             begin
               user = @membership.user
               network = @membership.network
-              Notifier.deliver_auto_join_group(user, network, base_host) if network.owner.send_notifications?
+              Notifier.deliver_auto_join_group(user, network, base_host) if network.administrators(true).any? {|a| a.send_notifications?}
             rescue
               logger.error("ERROR: failed to send email notification for auto join group. Membership ID: address@hidden")
             end
@@ -176,7 +176,7 @@
             begin
               user = @membership.user
               network = @membership.network
-              Notifier.deliver_membership_request(user, network, @membership, base_host) if network.owner.send_notifications?
+              Notifier.deliver_membership_request(user, network, @membership, base_host) if network.administrators(true).any? {|a| a.send_notifications?}
             rescue Exception => e
               logger.error("ERROR: failed to send Membership Request email notification. Membership ID: address@hidden")
               logger.error("EXCEPTION:" + e)

Modified: branches/wf4ever/app/controllers/networks_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/networks_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/networks_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -432,6 +432,19 @@
       }
     end
   end
+
+  def auto_complete
+    text = params[:group_name] || ''
+
+    groups = Network.find(:all,
+                     :conditions => ["LOWER(title) LIKE ?", text.downcase + '%'],
+                     :order => 'title ASC',
+                     :limit => 20,
+                     :select => 'DISTINCT *')
+
+    render :partial => 'networks/autocomplete_list', :locals => { :networks => groups }
+  end
+
   
 protected
 

Modified: branches/wf4ever/app/controllers/packs_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/packs_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/packs_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -29,20 +29,24 @@
   def index
     respond_to do |format|
       format.html {
-        @pivot_options = pivot_options
 
-        begin
-          expr = parse_filter_expression(params["filter"]) if params["filter"]
-        rescue Exception => ex
-          puts "ex = #{ex.inspect}"
-          flash.now[:error] = "Problem with query _expression_: #{ex}"
-          expr = nil
-        end
+        @pivot, problem = calculate_pivot(
 
-        @pivot = contributions_list(Contribution, params, current_user,
-            :lock_filter => { 'CATEGORY' => 'Pack' },
-            :filters     => expr)
+            :pivot_options  => Conf.pivot_options,
+            :params         => params,
+            :user           => current_user,
+            :search_models  => [Pack],
+            :search_limit   => Conf.max_search_size,
 
+            :locked_filters => { 'CATEGORY' => 'Pack' },
+
+            :active_filters => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                                "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                                "CURATION_EVENT", "SERVICE_PROVIDER",
+                                "SERVICE_COUNTRY", "SERVICE_STATUS"])
+
+        flash.now[:error] = problem if problem
+
         @query = params[:query]
         @query_type = 'packs'
 

Modified: branches/wf4ever/app/controllers/pictures_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/pictures_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/pictures_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -3,6 +3,8 @@
 # Copyright (c) 2007 University of Manchester and the University of Southampton.
 # See license.txt for details.
 
+require 'RMagick'
+
 class PicturesController < ApplicationController
   before_filter :login_required, :except => [:index, :show]
 

Modified: branches/wf4ever/app/controllers/previews_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/previews_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/previews_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -44,26 +44,35 @@
 
     type = params[:id]
 
+    mime_type = nil
+
     case type
 
-      when 'full';   name = 'full';   source = 'image'; size = nil; mime_type = 'image/jpeg'
-      when 'medium'; name = 'medium'; source = 'image'; size = 500; mime_type = 'image/jpeg'
-      when 'thumb';  name = 'thumb';  source = 'image'; size = 100; mime_type = 'image/jpeg'
-      when 'svg';    name = 'svg';    source = 'svg';   size = nil; mime_type = 'image/svg+xml'
+      when 'full';   source = 'image'; size = nil; mime_type = 'image/jpeg'
+      when 'medium'; source = 'image'; size = 500; mime_type = 'image/jpeg'
+      when 'thumb';  source = 'image'; size = 100; mime_type = 'image/jpeg'
+      when 'svg';    source = 'svg';   size = nil; mime_type = 'image/svg+xml'
       else
         render(:inline => 'Bad preview type', :status => "400 Bad Request")
         return
     end
 
+    content_blob = nil
+
+    case source
+      when 'image'
+        content_blob = @context.preview.image_blob
+        if content_blob.nil? && @context.preview.svg_blob # If no image, but an SVG, render a JPG from the SVG.
+          content_blob = @context.preview.svg_blob
+          mime_type = 'image/svg+xml' if size.nil? # Just show the SVG when "full" image is requested
+        end
+      when 'svg';   content_blob = @context.preview.svg_blob
+    end
+
     file_name = @context.preview.file_name(type)
 
     send_cached_data(file_name, :type => mime_type, :disposition => 'inline') {
 
-      case source
-        when 'image'; content_blob = @context.preview.image_blob
-        when 'svg';   content_blob = @context.preview.svg_blob
-      end
-
       data = ""
 
       if size

Modified: branches/wf4ever/app/controllers/profiles_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/profiles_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/profiles_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -76,6 +76,8 @@
     # maintain legal value for "null avatar"
     (params[:profile][:picture_id] = nil) if (params[:profile][:picture_id].to_i == 0)
     
+    raise "Cannot update profile until user is activated" unless @profile.owner.activated_at
+
     respond_to do |format|
       if @profile.update_attributes(params[:profile])
         flash[:notice] = 'Profile was successfully updated.'

Modified: branches/wf4ever/app/controllers/research_objects_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/research_objects_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/research_objects_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -16,20 +16,24 @@
   def index
     respond_to do |format|
       format.html {
-        @pivot_options = pivot_options
 
-        begin
-          expr = parse_filter_expression(params["filter"]) if params["filter"]
-        rescue Exception => ex
-          puts "ex = #{ex.inspect}"
-          flash.now[:error] = "Problem with query _expression_: #{ex}"
-          expr = nil
-        end
+        @pivot, problem = calculate_pivot(
 
-        @pivot = contributions_list(Contribution, params, current_user,
-            :lock_filter => { 'CATEGORY' => 'ResearchObject' },
-            :filters     => expr)
+            :pivot_options  => Conf.pivot_options,
+            :params         => params,
+            :user           => current_user,
+            :search_models  => [ResearchObject],
+            :search_limit   => Conf.max_search_size,
 
+            :locked_filters => { 'CATEGORY' => 'ResearchObject' },
+
+            :active_filters => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                                "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                                "CURATION_EVENT", "SERVICE_PROVIDER",
+                                "SERVICE_COUNTRY", "SERVICE_STATUS"])
+
+        flash.now[:error] = problem if problem
+
         @query = params[:query]
         @query_type = 'research_objects'
 

Modified: branches/wf4ever/app/controllers/search_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/search_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/search_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -186,19 +186,20 @@
 
     @query = params[:query]
 
-    @pivot_options = pivot_options
+    @pivot, problem = calculate_pivot(
 
-    begin
-      expr = parse_filter_expression(params["filter"]) if params["filter"]
-    rescue Exception => ex
-      puts "ex = #{ex.inspect}"
-      flash.now[:error] = "Problem with query _expression_: #{ex}"
-      expr = nil
-    end
+        :pivot_options    => Conf.pivot_options,
+        :params           => params,
+        :user             => current_user,
+        :search_models    => [Workflow, Blob, Pack, User, Network, Service],
+        :search_limit     => Conf.max_search_size,
 
-    @pivot = contributions_list(Contribution, params, current_user,
-        :filters => expr, :arbitrary_models => true)
+        :active_filters   => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                              "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                              "CURATION_EVENT", "SERVICE_PROVIDER",
+                              "SERVICE_COUNTRY", "SERVICE_STATUS"])
 
+    flash.now[:error] = problem if problem
   end
 
   def search_model

Modified: branches/wf4ever/app/controllers/services_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/services_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/services_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -27,20 +27,24 @@
   def index
     respond_to do |format|
       format.html {
-        @pivot_options = pivot_options
 
-        begin
-          expr = parse_filter_expression(params["filter"]) if params["filter"]
-        rescue Exception => ex
-          puts "ex = #{ex.inspect}"
-          flash.now[:error] = "Problem with query _expression_: #{ex}"
-          expr = nil
-        end
+        @pivot, problem = calculate_pivot(
 
-        @pivot = contributions_list(Contribution, params, current_user,
-            :lock_filter => { 'CATEGORY' => 'Service' },
-            :filters     => expr)
+            :pivot_options  => Conf.pivot_options,
+            :params         => params,
+            :user           => current_user,
+            :search_models  => [Service],
+            :search_limit   => Conf.max_search_size,
 
+            :locked_filters => { 'CATEGORY' => 'Service' },
+
+            :active_filters => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                                "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                                "CURATION_EVENT", "SERVICE_PROVIDER",
+                                "SERVICE_COUNTRY", "SERVICE_STATUS"])
+
+        flash.now[:error] = problem if problem
+
         @query = params[:query]
         @query_type = 'services'
 

Modified: branches/wf4ever/app/controllers/users_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/users_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/users_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -3,6 +3,8 @@
 # Copyright (c) 2007 University of Manchester and the University of Southampton.
 # See license.txt for details.
 
+require 'open-uri'
+
 class UsersController < ApplicationController
 
   contributable_actions = [:workflows, :files, :packs, :blogs]
@@ -174,9 +176,36 @@
     @user = User.new(params[:user])
     
     respond_to do |format|
-      if @user.save
-        # DO NOT log in user yet, since account needs to be validated and activated first (through email).
-        @user.send_email_confirmation_email
+
+      sent_email = false
+      spammer = false
+
+      if @user.valid?
+
+        # basic spam check
+
+        url = ""
+
+        sfs_response = ActiveSupport::JSON.decode(open(url).read)
+
+        if (sfs_response["success"] == 1)
+          if ((sfs_response["email"]["appears"] == 1) || (sfs_response["ip"]["appears"] == 1))
+            spammer = true
+          end
+        end
+
+        begin
+            # DO NOT log in user yet, since account needs to be validated and activated first (through email).
+            if !spammer
+              @user.send_email_confirmation_email
+              sent_email = true
+            end
+        rescue
+          @user.errors.add_to_base("Unable to send confirmation email")
+        end
+      end
+
+      if sent_email && !spammer && @user.save
         
         # If required, copy the email address to the Profile
         if params[:make_email_public]
@@ -195,7 +224,7 @@
           }
         end
         
-        flash[:notice] = "Thank you for registering! We have sent a confirmation email to address@hidden with instructions on how to activate your account."
+        flash[:notice] = "Thank you for registering! An email has been sent to address@hidden with instructions on how to activate your account."
         format.html { redirect_to(:action ="" "index") }
       else
         format.html { render :action ="" "new" }
@@ -276,29 +305,27 @@
 
     confirmed = false
     
-    for user in @users
-      unless user.unconfirmed_email.blank?
-        # Check if hash matches user, in which case confirm the user's email
-        if user.email_confirmation_hash == params[:hash]
-          confirmed = user.confirm_email!
-          # BEGIN DEBUG
-          logger.error("ERRORS!") unless user.errors.empty?
-          user.errors.full_messages.each { |e| logger.error(e) } 
-          #END DEBUG
-          if confirmed
-            self.current_user = user
-            self.current_user.process_pending_invitations! # look up any pending invites for this user + transfer them to relevant tables from 'pending_invitations' table
-            confirmed = false if !logged_in?
-          end
-          @user = user
-          break
-        end
+    user = User.find(:first,
+        :conditions => ['SHA1(CONCAT(users.unconfirmed_email, ?)) = ?', Conf.secret_word,
+        params[:hash]])
+
+    if user
+      confirmed = user.confirm_email!
+      # BEGIN DEBUG
+      logger.error("ERRORS!") unless user.errors.empty?
+      user.errors.full_messages.each { |e| logger.error(e) } 
+      #END DEBUG
+      if confirmed
+        self.current_user = user
+        self.current_user.process_pending_invitations! # look up any pending invites for this user + transfer them to relevant tables from 'pending_invitations' table
+        confirmed = false if !logged_in?
       end
+      @user = user
     end
-    
+
     respond_to do |format|
       if confirmed
-        flash[:notice] = "Thank you for confirming your email. Your account is now active (if it wasn't before), and the new email address registered on your account. We hope you enjoy using #{Conf.sitename}!"
+        flash[:notice] = "Thank you for confirming your email address.  Welcome to #{Conf.sitename}!"
         format.html { redirect_to user_url(@user) }
       else
         flash[:error] = "Invalid confirmation URL"
@@ -371,7 +398,7 @@
   
   # For simile timeline
   def users_for_timeline
-    @users = User.find(:all, :conditions => [ "users.activated_at IS NOT NULL AND users.created_at > ? AND users.created_at < ?", params[:start].to_time, params[:end].to_time ], :include => [ :profile ] )
+    @users = User.find(:all, :conditions => [ "users.activated_at IS NOT NULL AND users.spam_score < 50 AND users.created_at > ? AND users.created_at < ?", params[:start].to_time, params[:end].to_time ], :include => [ :profile ] )
     respond_to do |format|
       format.json { render :partial => 'users/timeline_json', :layout => false }
     end
@@ -549,7 +576,176 @@
       end
     end
   end
-  
+
+  def check
+
+    def add(strings, opts = {})
+      if opts[:string] && opts[:string] != ""
+
+        label  = opts[:label]
+        label = self.class.helpers.link_to(label, opts[:link]) if opts[:link]
+
+        strings << { :label => label, :string => opts[:string], :escape => opts[:escape] }
+      end
+    end
+
+    unless logged_in? && Conf.admins.include?(current_user.username)
+      render :text => "Not authorised"
+      return
+    end
+
+    @from = params[:from].to_i
+    @to   = params[:to].to_i
+
+    if @to > 0
+
+      users = User.find(:all, :conditions => ["activated_at IS NOT NULL AND id >= ? AND id <= ? AND (account_status IS NULL OR (account_status != 'sleep' AND account_status != 'whitelist'))", @from, @to])
+
+      @userlist = users.map do |user|
+
+        strings = []
+
+        add(strings, :label => "email",        :string => user.email)
+        add(strings, :label => "openid",       :string => user.openid_url)
+        add(strings, :label => "created at",   :string => user.created_at)
+        add(strings, :label => "last login",   :string => user.last_seen_at ? user.last_seen_at : "never logged back in")
+        add(strings, :label => "name",         :string => user.name)
+        add(strings, :label => "public email", :string => user.profile.email)
+        add(strings, :label => "website",      :string => user.profile.website, :escape => :website)
+        add(strings, :label => "description",  :string => user.profile.body_html, :escape => :false)
+        add(strings, :label => "field / ind",  :string => user.profile.field_or_industry)
+        add(strings, :label => "occ / roles",  :string => user.profile.occupation_or_roles)
+        add(strings, :label => "city",         :string => user.profile.location_city)
+        add(strings, :label => "country",      :string => user.profile.location_country)
+        add(strings, :label => "interests",    :string => user.profile.interests)
+        add(strings, :label => "contact",      :string => user.profile.contact_details)
+        add(strings, :label => "tags",         :string => user.tags.map do |tag| tag.name end.join(", "))
+
+        user.networks_owned.each do |network|
+
+          add(strings, :label  => "group title",
+                       :link   => polymorphic_path(network),
+                       :string => network.title) 
+
+          add(strings, :label  => "group description",
+                       :link   => polymorphic_path(network),
+                       :string => network.description_html,
+                       :escape => :false) 
+        end
+
+        user.packs.each do |pack|
+
+          add(strings, :label  => "pack title",
+                       :link   => polymorphic_path(pack),
+                       :string => pack.title) 
+
+          add(strings, :label  => "pack description",
+                       :link   => polymorphic_path(pack),
+                       :string => pack.description_html,
+                       :escape => :false) 
+        end
+
+        user.workflows.each do |workflow|
+
+          add(strings, :label  => "workflow title",
+                       :link   => polymorphic_path(workflow),
+                       :string => workflow.title) 
+
+          add(strings, :label  => "workflow description",
+                       :link   => polymorphic_path(workflow),
+                       :string => workflow.body_html,
+                       :escape => :false) 
+        end
+
+        user.blobs.each do |blob|
+
+          add(strings, :label  => "file title",
+                       :link   => polymorphic_path(blob),
+                       :string => blob.title) 
+
+          add(strings, :label  => "file description",
+                       :link   => polymorphic_path(blob),
+                       :string => blob.body_html,
+                       :escape => :false) 
+        end
+
+        user.comments.each do |comment|
+
+          add(strings, :label  => "comment",
+                       :link   => polymorphic_path(comment.commentable),
+                       :string => comment.comment,
+                       :escape => :white_list) 
+        end
+
+        { :ob => user, :strings => strings }
+
+      end
+    end
+  end
+
+  def change_status
+
+    unless logged_in? && Conf.admins.include?(current_user.username)
+      render :text => "Not authorised"
+      return
+    end
+
+    from = params[:from].to_i
+    to   = params[:to].to_i
+
+    params.keys.each do |key|
+
+      match_data = key.match(/user-([0-9]*)/)
+
+      if match_data
+        if user = User.find_by_id(match_data[1])
+          puts "Processing user #{user.id}"
+          case params[key]
+          when "whitelist"
+            user.update_attributes(:account_status => "whitelist")
+          when "sleep"
+            user.update_attributes(:account_status => "sleep")
+          when "delete"
+
+            # build an "all elements" user.xml record
+
+            elements = {}
+
+            TABLES['Model'][:data]['user']['REST Attribute'].each do |attr|
+              add_to_element_hash(attr, elements)
+            end
+
+            doc  = LibXML::XML::Document.new()
+            root = rest_get_request_aux(user, nil, {}, elements) 
+            doc.root = root
+
+            File.open("#{Conf.deleted_data_directory}#{user.id}.xml", "wb+") { |f| f.write(doc.to_s) }
+
+            user.destroy
+          end
+        end
+      end
+    end
+
+    respond_to do |format|
+      format.html {
+        redirect_to(url_for(:controller => "users", :action ="" "check", :from => params[:from], :to => params[:to]))
+      }
+    end
+  end
+
+  def auto_complete
+    text = params[:user_name] || ''
+
+    users = User.find(:all,
+                     :conditions => ["LOWER(name) LIKE ?", text.downcase + '%'],
+                     :order => 'name ASC',
+                     :limit => 20,
+                     :select => 'DISTINCT *')
+
+    render :partial => 'users/autocomplete_list', :locals => { :users => users }
+  end
+
 protected
 
   def find_users

Modified: branches/wf4ever/app/controllers/workflows_controller.rb (3085 => 3086)


--- branches/wf4ever/app/controllers/workflows_controller.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/controllers/workflows_controller.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -7,11 +7,11 @@
 
   include ApplicationHelper
 
-  before_filter :login_required, :except => [:index, :show, :download, :named_download, :galaxy_tool, :galaxy_tool_download, :statistics, :launch, :search]
+  before_filter :login_required, :except => [:index, :show, :download, :named_download, :galaxy_tool, :galaxy_tool_download, :statistics, :launch, :search, :auto_complete]
   
   before_filter :store_callback, : [:index, :search]
   before_filter :find_workflows_rss, : [:index]
-  before_filter :find_workflow_auth, :except => [:search, :index, :new, :create]
+  before_filter :find_workflow_auth, :except => [:search, :index, :new, :create, :auto_complete]
   
   before_filter :initiliase_empty_objects_for_new_pages, : [:new, :create, :new_version, :create_version]
   before_filter :set_sharing_mode_variables, : [:show, :new, :create, :edit, :update]
@@ -117,7 +117,7 @@
       @download = Download.create(:contribution => @workflow.contribution, :user => (logged_in? ? current_user : nil), :user_agent => request.env['HTTP_USER_AGENT'], :accessed_from_site => accessed_from_website?())
     end
     
-    send_data(@viewing_version.content_blob.data, :filename => @workflow.filename(@viewing_version_number), :type => @viewing_version.content_type.mime_type)
+    send_data(@viewing_version.content_blob.data, :filename => @workflow.filename(@viewing_version_number), :type => @viewing_version.content_type.mime_type, :disposition => (params[:disposition] || 'attachment'))
   end
   
   # GET /workflows/:id/download/:name
@@ -199,20 +199,24 @@
   def index
     respond_to do |format|
       format.html do
-        @pivot_options = pivot_options
 
-        begin
-          expr = parse_filter_expression(params["filter"]) if params["filter"]
-        rescue Exception => ex
-          puts "ex = #{ex.inspect}"
-          flash.now[:error] = "Problem with query _expression_: #{ex}"
-          expr = nil
-        end
+        @pivot, problem = calculate_pivot(
 
-        @pivot = contributions_list(Contribution, params, current_user,
-            :lock_filter => { 'CATEGORY' => 'Workflow' },
-            :filters     => expr)
+            :pivot_options  => Conf.pivot_options,
+            :params         => params,
+            :user           => current_user,
+            :search_models  => [Workflow],
+            :search_limit   => Conf.max_search_size,
 
+            :locked_filters => { 'CATEGORY' => 'Workflow' },
+
+            :active_filters => ["CATEGORY", "TYPE_ID", "TAG_ID", "USER_ID",
+                                "LICENSE_ID", "GROUP_ID", "WSDL_ENDPOINT",
+                                "CURATION_EVENT", "SERVICE_PROVIDER",
+                                "SERVICE_COUNTRY", "SERVICE_STATUS"])
+
+        flash.now[:error] = problem if problem
+
         @query = params[:query]
         @query_type = 'workflows'
 
@@ -445,9 +449,12 @@
     if @workflow.valid?
       # Save content blob first now and set it on the workflow.
       # TODO: wrap this in a transaction!
-      @workflow.content_blob_id = ContentBlob.create(:data ="" file.read).id
-      if @workflow.save_as_new_version(params[:new_workflow][:rev_comments])
+      @workflow.content_blob = ContentBlob.create(:data ="" file.read)
+      @workflow.preview = nil
+      @workflow[:revision_comments] = params[:new_workflow][:rev_comments]
 
+      if @workflow.save
+
         # Extract workflow metadata using a Workflow object that includes the
         # newly created version.
 
@@ -509,7 +516,7 @@
     respond_to do |format|
       # Here we assume that no actual workflow metadata is being updated that affects workflow versions,
       # so we need to prevent the timestamping update of workflow version objects.
-      Workflow.versioned_class.record_timestamps = false
+      Workflow.record_timestamps = false
       
       if @workflow.update_attributes(params[:workflow])
 
@@ -536,49 +543,40 @@
         format.html { render :action ="" "edit" }
       end
       
-      Workflow.versioned_class.record_timestamps = true
+      Workflow.record_timestamps = true
     end
   end
   
   # PUT /workflows/1;update_version
   def update_version
-    workflow_title = @workflow.title
-    
+
+    success = false
+
     if params[:version]
-      # Update differently based on whether a new preview image has been specified or not:
-      # (But only set image if platform is not windows).
-      if params[:workflow][:preview].blank? || params[:workflow][:preview].size == 0
-        success = @workflow.update_version(params[:version], 
-                                           :title => params[:workflow][:title], 
-                                           :body => params[:workflow][:body],
-                                           :last_edited_by => current_user.id) 
-      else
-        logger.debug("Preview image provided. Attempting to set the version's preview image.")
-        
-        # Disable updating image on windows due to issues to do with file locking, that prevent file_column from working sometimes.
-        #
-        # The dependency on file_column has been removed, but this code remains
-        # disabled on Windows until it is confirmed as working.
-        if RUBY_PLATFORM =~ /mswin32/
-          success = false
-        else
-          success = @workflow.update_version(params[:version], 
-                                             :title => params[:workflow][:title], 
-                                             :body => params[:workflow][:body], 
-                                             :image => params[:workflow][:preview].read,
-                                             :last_edited_by => current_user.id)
-        end
-      end
-    else
-      success = false
+
+      original_title = @workflow.title
+      version        = @workflow.find_version(params[:version])
+      do_preview     = !params[:workflow][:preview].blank? && params[:workflow][:preview].size > 0
+      
+      attributes_to_update = {
+        :title          => params[:workflow][:title], 
+        :body           => params[:workflow][:body],
+        :last_edited_by => current_user.id
+      }
+
+      # only set the preview to update if one was provided
+
+      attributes_to_update[:image] = params[:workflow][:preview] if do_preview
+
+      success = version.update_attributes(attributes_to_update)
     end
-    
+
     respond_to do |format|
       if success
-        flash[:notice] = "Workflow version #{params[:version]}: \"#{workflow_title}\" has been updated."
+        flash[:notice] = "Workflow version #{version.version}: \"#{original_title}\" has been updated."
         format.html { redirect_to(workflow_url(@workflow) + "?version=#{params[:version]}") }
       else
-        flash[:error] = "Failed to update Workflow version."
+        flash[:error] = "Failed to update Workflow."
         if params[:version]
           format.html { render :action ="" :edit_version }
         else
@@ -654,6 +652,20 @@
     redirect_to(workflow_url(@workflow))
   end
 
+  def auto_complete
+    text = params[:workflow_name] || ''
+
+    wfs = Workflow.find(:all,
+                     :conditions => ["LOWER(title) LIKE ?", text.downcase + '%'],
+                     :order => 'title ASC',
+                     :limit => 20,
+                     :select => 'DISTINCT *')
+
+    wfs = wfs.select {|w| Authorization.is_authorized?('view', nil, w, current_user) }
+
+    render :partial => 'contributions/autocomplete_list', :locals => { :contributions => wfs }
+  end
+
 protected
 
   def store_callback
@@ -679,7 +691,7 @@
   def find_workflows_rss
     # Only carry out if request is for RSS
     if params[:format] and params[:format].downcase == 'rss'
-      @rss_workflows = Authorization.authorised_index(Workflow, :all, :limit => 30, :order => 'updated_at DESC', :authorised_user => current_user)
+      @rss_workflows = Authorization.scoped(Workflow, :authorised_user => current_user).find(:all, :limit => 30, :order => 'updated_at DESC')
     end
   end
   
@@ -736,7 +748,7 @@
         logger.debug("@viewing_version_number = address@hidden")
         logger.debug("@workflow.image != nil = address@hidden != nil}")
       else
-        error("Workflow not found (id not authorized)", "is invalid (not authorized)")
+        error("Workflow not found (id not authorized)", "is invalid (not authorized)", nil, 401)
         return false
       end
     rescue ActiveRecord::RecordNotFound
@@ -881,12 +893,16 @@
     end
   end
 
-  def error(notice, message, attr=:id)
+  def error(notice, message, attr=:id, status=nil)
     flash[:error] = notice
     (err = Workflow.new.errors).add(attr, message)
     
     respond_to do |format|
       format.html { redirect_to workflows_url }
+      format.xml do
+        headers["WWW-Authenticate"] = %(Basic realm="Web Password") if status == 401
+        render :text => notice, :status => status
+      end
     end
   end
   

Modified: branches/wf4ever/app/helpers/application_helper.rb (3085 => 3086)


--- branches/wf4ever/app/helpers/application_helper.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/helpers/application_helper.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -775,6 +775,8 @@
       return "famfamfam_silk/award_star_delete.png"
     when "service"
       return "biocat_icon.png"
+    when "usercheck"
+      return "famfamfam_silk/flag_red.png"
     else
       return Conf.label_icons[method.to_s] if Conf.label_icons[method.to_s]
     end
@@ -1614,8 +1616,6 @@
       end
     end
 
-
-
     @layout = layout || {"layout" => Conf.page_template, "stylesheets" => [Conf.stylesheet]}
   end
 

Modified: branches/wf4ever/app/models/blob.rb (3085 => 3086)


--- branches/wf4ever/app/models/blob.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/blob.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -25,7 +25,14 @@
   acts_as_attributor
   acts_as_attributable
   
-  acts_as_solr(:fields => [:title, :local_name, :body, :kind, :uploader, :tag_list],
+  has_versions :blob_versions,
+
+    :attributes => [ :title, :body, :body_html, :content_type, :content_blob,
+                     :local_name ],
+
+    :mutable => [ :title, :body, :body_html ]
+
+  acts_as_solr(:fields => [:title, :local_name, :body, :kind, :contributor_name, :tag_list],
                :boost => "rank",
                :include => [ :comments ]) if Conf.solr_enable
 
@@ -54,8 +61,10 @@
 
   def rank
 
+    boost = 0
+
     # initial boost depends on viewings count
-    boost = contribution.viewings_count / 100
+    boost = contribution.viewings_count / 100 if contribution
 
     # Take curation events into account
     boost += CurationEvent.curation_score(CurationEvent.find_all_by_object_type_and_object_id('Blob', id))

Copied: branches/wf4ever/app/models/blob_version.rb (from rev 3085, trunk/app/models/blob_version.rb) (0 => 3086)


--- branches/wf4ever/app/models/blob_version.rb	                        (rev 0)
+++ branches/wf4ever/app/models/blob_version.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,30 @@
+# myExperiment: app/models/blob_versions.rb
+#
+# Copyright (c) 2012 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+class BlobVersion < ActiveRecord::Base
+
+  is_version_of :blob
+
+  format_attribute :body
+
+  belongs_to :content_blob, :dependent => :destroy
+  belongs_to :content_type
+
+  validates_presence_of :content_blob
+  validates_presence_of :content_type
+  validates_presence_of :title
+
+  def suggestions
+    {
+      :revision_comments => version > 1 && (revision_comments.nil? || revision_comments.empty?),
+      :description => body.nil? || body.empty?
+    }
+  end
+
+  def suggestions?
+    suggestions.select do |k, v| v end.length > 0
+  end
+end
+

Modified: branches/wf4ever/app/models/contribution.rb (3085 => 3086)


--- branches/wf4ever/app/models/contribution.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/contribution.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -47,13 +47,15 @@
   # returns the 'most recent' Contributions
   # the maximum number of results is set by #limit#
   def self.most_recent(limit = 10, klass = 'Contribution')
-    Authorization.authorised_index(Object.const_get(klass), :all, :contribution_records => true, :limit => limit, :order => 'created_at DESC')
+    conditions = ['contributions.contributable_type = ?', klass] if klass != 'Contribution'
+    Authorization.scoped(Contribution).find(:all, :conditions => conditions, :limit => limit, :order => 'created_at DESC')
   end
   
   # returns the 'last updated' Contributions
   # the maximum number of results is set by #limit#
   def self.last_updated(limit = 10, klass = 'Contribution')
-    Authorization.authorised_index(Object.const_get(klass), :all, :contribution_records => true, :limit => limit, :order => 'updated_at DESC')
+    conditions = ['contributions.contributable_type = ?', klass] if klass != 'Contribution'
+    Authorization.scoped(Contribution).find(:all, :conditions => conditions, :limit => limit, :order => 'updated_at DESC')
   end
   
   # returns the 'most favourited' Contributions

Modified: branches/wf4ever/app/models/pack.rb (3085 => 3086)


--- branches/wf4ever/app/models/pack.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/pack.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -931,8 +931,10 @@
   
   def rank
 
+    boost = 0
+
     # initial boost depends on viewings count
-    boost = contribution.viewings_count / 100
+    boost = contribution.viewings_count / 100 if contribution
 
     # Take curation events into account
     boost += CurationEvent.curation_score(CurationEvent.find_all_by_object_type_and_object_id('Pack', id))

Modified: branches/wf4ever/app/models/preview.rb (3085 => 3086)


--- branches/wf4ever/app/models/preview.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/preview.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -7,13 +7,17 @@
 
   PREFIX = "tmp/previews"
 
+  after_save :clear_cache
+
   belongs_to :image_blob, :class_name  => "ContentBlob",
                           :foreign_key => :image_blob_id,
-                          :dependent   => :destroy
+                          :dependent   => :destroy,
+                          :autosave    => true
 
   belongs_to :svg_blob,   :class_name  => "ContentBlob",
                           :foreign_key => :svg_blob_id,
-                          :dependent   => :destroy
+                          :dependent   => :destroy,
+                          :autosave    => true
 
   def file_name(type)
     "#{PREFIX}/#{id}/#{type}"

Modified: branches/wf4ever/app/models/topic_run.rb (3085 => 3086)


--- branches/wf4ever/app/models/topic_run.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/topic_run.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -6,7 +6,6 @@
 require 'acts_as_creditable'
 require 'acts_as_attributor'
 require 'acts_as_attributable'
-require 'explicit_versioning'
 require 'acts_as_reviewable'
 require 'acts_as_runnable'
 

Modified: branches/wf4ever/app/models/topic_tag_map.rb (3085 => 3086)


--- branches/wf4ever/app/models/topic_tag_map.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/topic_tag_map.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -3,7 +3,6 @@
 require 'acts_as_creditable'
 require 'acts_as_attributor'
 require 'acts_as_attributable'
-require 'explicit_versioning'
 require 'acts_as_reviewable'
 require 'acts_as_runnable'
 
@@ -26,4 +25,4 @@
 	  :all,
 	  :order => 'topic_tag_map.probability DESC')
   end
-end
\ No newline at end of file
+end

Modified: branches/wf4ever/app/models/topic_workflow_map.rb (3085 => 3086)


--- branches/wf4ever/app/models/topic_workflow_map.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/topic_workflow_map.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -3,7 +3,6 @@
 require 'acts_as_creditable'
 require 'acts_as_attributor'
 require 'acts_as_attributable'
-require 'explicit_versioning'
 require 'acts_as_reviewable'
 require 'acts_as_runnable'
 
@@ -18,4 +17,4 @@
   
   belongs_to :workflow
   validates_presence_of :workflow
-end
\ No newline at end of file
+end

Modified: branches/wf4ever/app/models/user.rb (3085 => 3086)


--- branches/wf4ever/app/models/user.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/user.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -158,7 +158,10 @@
       self.unconfirmed_email = nil
       
       # Activate user if not previously activated
-      self.activated_at = Time.now unless self.activated?
+      unless self.activated?
+        self.activated_at = Time.now
+        self.account_status = "sleep"
+      end
       
       return self.save
     else
@@ -277,7 +280,7 @@
   
   acts_as_creditor
 
-  acts_as_solr(:fields => [ :name, :tag_list ], :include => [ :profile ]) if Conf.solr_enable
+  acts_as_solr(:fields => [ :name, :tag_list ], :include => [ :profile ], :if => "activated_at") if Conf.solr_enable
 
   validates_presence_of :name
   
@@ -596,6 +599,23 @@
     Digest::SHA1.hexdigest(unconfirmed_email + Conf.secret_word)
   end
 
+  def calculate_spam_score
+
+    score = 0
+
+    patterns = Conf.spam_patterns
+
+    patterns["email"].each do |pattern|
+      if unconfirmed_email
+        score = score + 80 if unconfirmed_email.match(pattern)
+      elsif email
+        score = score + 80 if email.match(pattern)
+      end
+    end
+
+    self.spam_score = score
+  end
+
 protected
 
   # clean up emails and username before validation

Modified: branches/wf4ever/app/models/workflow.rb (3085 => 3086)


--- branches/wf4ever/app/models/workflow.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/workflow.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -8,7 +8,6 @@
 require 'acts_as_creditable'
 require 'acts_as_attributor'
 require 'acts_as_attributable'
-require 'explicit_versioning'
 require 'acts_as_reviewable'
 require 'acts_as_runnable'
 require 'lib/previews'
@@ -49,47 +48,15 @@
 
   has_previews
 
-  explicit_versioning(:version_column => "current_version",
-                      :extra_attributes => ["image", "svg"],
-                      :white_list_columns => ["body"]) do
-    
-    format_attribute :body
+  has_versions :workflow_versions,
+  
+    :attributes => [ :contributor, :title, :unique_name, :body, :body_html,
+                     :content_blob_id, :file_ext, :last_edited_by,
+                     :content_type_id, :preview_id, :image, :svg ],
 
-    belongs_to :content_blob, :dependent => :destroy
-    belongs_to :content_type
+    :mutable => [ :contributor, :title, :unique_name, :body, :body_html,
+                  :file_ext, :last_edited_by, :content_type_id, :image, :svg ]
 
-    validates_presence_of :content_blob
-    validates_presence_of :content_type
-    
-    # Update the parent contribution model buy only if this isn't the current version (because the workflow model will take care of that).
-    # This is required to keep the contribution's updated_at field accurate.
-    after_save { |wv| wv.workflow.contribution.save if wv.workflow.contribution && wv.version != wv.workflow.current_version }
-
-    has_previews
-
-    def components
-      if workflow.processor_class
-        workflow.processor_class.new(content_blob.data).get_components
-      else
-        XML::Node.new('components')
-      end
-    end
-
-    def processor_class
-      if self.content_type
-          @processor_class ||= WorkflowTypesHandler.processor_class_for_type_display_name(self.content_type.title)
-      end
-    end
-
-    def display_data_format
-      klass = self.processor_class
-      @display_data_format = (klass.nil? ? self.file_ext : klass.display_data_format)
-    end
-
-  end
-  
-  non_versioned_columns.push("license_id", "tag_list", "preview_id")
-  
   acts_as_solr(:fields => [ :title, :body, :tag_list, :contributor_name, :kind, :get_all_search_terms ],
                :boost => "rank",
                :include => [ :comments ]) if Conf.solr_enable
@@ -227,11 +194,12 @@
   # End acts_as_runnable overridden methods
 
   def filename(version=nil)
+
     if version.blank?
-      return "#{unique_name}.#{file_ext}"
+      return "#{unique_name}.#{file_ext || self.processor_class.default_file_extension}"
     else
       return nil unless (workflow_version = self.find_version(version))
-      return "#{workflow_version.unique_name}.#{workflow_version.file_ext}"
+      return "#{workflow_version.unique_name}.#{workflow_version.file_ext || workflow_version.processor_class.default_file_extension}"
     end
   end
   
@@ -290,8 +258,10 @@
 
   def rank
 
+    boost = 0
+
     # initial boost depends on viewings count
-    boost = contribution.viewings_count / 100
+    boost = contribution.viewings_count / 100 if contribution
 
     # Take curation events into account
     boost += CurationEvent.curation_score(CurationEvent.find_all_by_object_type_and_object_id('Workflow', id))

Modified: branches/wf4ever/app/models/workflow_sweeper.rb (3085 => 3086)


--- branches/wf4ever/app/models/workflow_sweeper.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/models/workflow_sweeper.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -15,7 +15,7 @@
   end
 
   def after_update(workflow)
-    expire_sidebar_assets(workflow.contribution.contributor_id) if workflow.contribution.contributor_type == 'User'
+    expire_sidebar_assets(workflow.contributor_id) if workflow.contributor_type == 'User'
     expire_multiple_sidebar_favourites(workflow.id, 'Workflow')
     expire_listing(workflow.id, 'Workflow')
     expire_home_cache

Copied: branches/wf4ever/app/models/workflow_version.rb (from rev 3085, trunk/app/models/workflow_version.rb) (0 => 3086)


--- branches/wf4ever/app/models/workflow_version.rb	                        (rev 0)
+++ branches/wf4ever/app/models/workflow_version.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,44 @@
+# myExperiment: app/models/workflow_version.rb
+#
+# Copyright (c) 2012 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+class WorkflowVersion < ActiveRecord::Base
+
+  is_version_of :workflow
+
+  format_attribute :body
+
+  belongs_to :content_blob, :dependent => :destroy
+  belongs_to :content_type
+
+  validates_presence_of :content_blob
+  validates_presence_of :content_type
+  
+  # Update the parent contribution model buy only if this isn't the current version (because the workflow model will take care of that).
+  # This is required to keep the contribution's updated_at field accurate.
+  after_save { |wv| wv.workflow.contribution.save if wv.workflow.contribution && wv.version != wv.workflow.current_version }
+
+  has_previews
+
+  def components
+    if workflow.processor_class
+      workflow.processor_class.new(content_blob.data).get_components
+    else
+      XML::Node.new('components')
+    end
+  end
+
+  def processor_class
+    if self.content_type
+        @processor_class ||= WorkflowTypesHandler.processor_class_for_type_display_name(self.content_type.title)
+    end
+  end
+
+  def display_data_format
+    klass = self.processor_class
+    @display_data_format = (klass.nil? ? self.file_ext : klass.display_data_format)
+  end
+
+end
+

Modified: branches/wf4ever/app/views/blobs/_breadcrumbs.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/blobs/_breadcrumbs.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/blobs/_breadcrumbs.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,6 +1,6 @@
 <li><%= link_to 'Files', blobs_path -%></li>
 
-<% if ["show", "new", "edit", "all", "search"].include? controller.action_name.to_s -%>
+<% if ["show", "new", "edit", "all", "search", "suggestions"].include? controller.action_name.to_s -%>
   <li>&gt;</li>
   
   <% case controller.action_name.to_s; when "show" -%>
@@ -15,6 +15,10 @@
     <li>All Files</li>
 	<% when "search" %>  
     <li>Search Results</li>
+	<% when "suggestions" %>  
+		<li><%= link_to "#{contributable_name(@blob.id, 'Blob')}", blob_path(@blob) -%></li>
+		<li>&gt;</li>
+    <li>Suggestions</li>
   <% else %>
     <!-- no breadcrumb -->
   <% end %>

Modified: branches/wf4ever/app/views/blobs/edit.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/blobs/edit.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/blobs/edit.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -7,8 +7,18 @@
 
 <%= error_messages_for :blob %>
 
-<% form_for(:blob, :url ="" blob_path(@blob), :html => { :method => :put }) do |f| %>
+<% form_for(:blob, :url ="" blob_path(@blob), :html => { :method => :put, :multipart => true }) do |f| %>
 
+  <div style="text-align: center;">
+    <div>
+      <strong>File to upload: </strong>
+      <%= file_field :blob, :data %>
+    </div>
+    <div><small><em>Leave this field blank unless you want to replace the file content</em></small></div>
+  </div>
+  
+  <br/>
+  
   <p style="text-align: center;">
   	<strong>Title: </strong>
 	<br/>

Modified: branches/wf4ever/app/views/blobs/show.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/blobs/show.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/blobs/show.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -31,12 +31,13 @@
 	|
 	<%= link_to "Favourited By (address@hidden)", "#favourited_by" %>
 	| 
+  <br/>
+  |
+  <%= link_to("Version History", "#version_history") -%>
+  |
 	<% if logged_in? and @blob.owner?(current_user) %>
-	  <br/>
+	  <a href=""
 	  |
-		<!-- NB! Index of the 'sharing' tab might change! -->
-	  <a href="" 
-	  |
 	<% end %>
 	<%= link_to "Comments (address@hidden)", "#comments" %> 
 	|
@@ -44,20 +45,23 @@
 
 <div class="contribution_left_box">
 	<div class="contribution_version_box">
-		<div class="contribution_version_inner_box">
+
+    <%= render(:partial => "contributions/version_selector", :locals => { :resource => @blob, :version => @version, :path => :blob_version_path }) %>
+
+    <div class="contribution_version_inner_box">
 			<p>
 			    <b>Title:</b>
-			    <span class="title"><%=h @blob.title %></span>
+			    <span class="title"><%=h @version.title %></span>
 			</p>
 			
 			<p>
 			    <b>File name:</b>
-			    <%=h @blob.local_name %>
+			    <%=h @version.local_name %>
 			</p>
 			
 			<p>
 			    <b>File type:</b>
-			    <%=h @blob.content_type.title %>
+			    <%=h @version.content_type.title %>
 			</p>
 			
 			<br/>
@@ -67,9 +71,9 @@
 				Description
 			</h3>
 			
-			<% unless @blob.body.blank? %>
+			<% unless @version.body.blank? %>
 				<div class="contribution_description">
-					<%= @blob.body_html %>
+					<%= @version.body_html %>
 				</div>
 			<% else %>
 				<p class="none_text">
@@ -136,14 +140,22 @@
 <br/>
 
 <div id="tabsContainer" class="tabsContainer"></div>
-	
+
+<div class="tabContainer">
+  <div class="tabTitle">Version History</div>
+  <div class="tabContent">
+    <a name="version_history"></a>
+    <%= render :partial => "contributions/versions", :locals => { :resource => @blob, :path => :blob_version_path } %>
+  </div>
+</div>
+
 <% if logged_in? and @blob.owner? current_user %>
   
-	<a name="sharing"></a>
 	<div class="tabContainer">
     <div class="tabTitle">Sharing</div>
     <div class="tabContent">
 
+      <a name="sharing"></a>
       <%= render :partial => "contributions/sharing_summary",  :locals => { :contributable => @blob } %>
       <%= render :partial => "contributions/updating_summary", :locals => { :contributable => @blob } %>
 	  

Copied: branches/wf4ever/app/views/blobs/suggestions.rhtml (from rev 3085, trunk/app/views/blobs/suggestions.rhtml) (0 => 3086)


--- branches/wf4ever/app/views/blobs/suggestions.rhtml	                        (rev 0)
+++ branches/wf4ever/app/views/blobs/suggestions.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,58 @@
+<% t "#{contributable_name(@version.id, 'Blob')} (#{h @blob.contributor_name})" -%>
+
+<%= _javascript__include_tag "fckeditor/fckeditor.js" %>
+
+<h1>Suggestions</h1>
+
+<% form_for(:blob_version, :url ="" blob_version_process_suggestions_path(@blob, @version.version), :html => { :method => :post } ) do |f| %>
+
+  <% if @suggestions[:description] %>
+
+    <h2>Enter description</h2>
+
+    <p><em>The file has no description!  By entering a description here, you
+    will increase the chances of others finding your file and help understand
+    its purpose.</em></p>
+
+    <p>
+      <textarea id='description_editor' name='description'></textarea>
+      <script type="text/_javascript_">
+      //<![CDATA[
+      var oFCKeditor = new FCKeditor('description_editor', '600px', '300px', 'Simple');
+      oFCKeditor.BasePath = "/_javascript_s/fckeditor/"
+      oFCKeditor.Config['CustomConfigurationsPath'] = '/_javascript_s/fckcustom.js';
+      oFCKeditor.ReplaceTextarea();
+      //]]>
+      </script>
+    </p>
+
+  <% end %>
+
+  <% if @suggestions[:revision_comments] %>
+
+    <h2>Enter revision comment</h2>
+
+    <p>Please enter a brief comment about the changes that have been made to
+    the file.  This will help others know if they need to update to this
+    version.</p>
+
+    <p>
+      <textarea id='revision_comments_editor' name='revision_comments'></textarea>
+      <script type="text/_javascript_">
+      //<![CDATA[
+      var oFCKeditor = new FCKeditor('revision_comments_editor', '600px', '300px', 'Simple');
+      oFCKeditor.BasePath = "/_javascript_s/fckeditor/"
+      oFCKeditor.Config['CustomConfigurationsPath'] = '/_javascript_s/fckcustom.js';
+      oFCKeditor.ReplaceTextarea();
+      //]]>
+      </script>
+    </p>
+
+  <% end %>
+
+  <p>
+    <%= submit_tag "Continue" %>
+  </p>
+
+<% end %>
+

Modified: branches/wf4ever/app/views/content/_index.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/content/_index.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/content/_index.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -22,9 +22,9 @@
         <% @pivot[:filters].each do |filter| %>
           <% query_name = "#{filter[:query_option]}_query" %>
           <% if @pivot[:cancel_filter_query_url] %>
-            <div class="category"><%= filter[:title].capitalize -%> results</div>
+            <div class="category"><%= filter["title"].capitalize -%> results</div>
           <% else %>
-            <div class="category">Filter by <%= filter[:title] -%></div>
+            <div class="category">Filter by <%= filter["title"] -%></div>
           <% end %>
           <div id="<%= query_name -%>" style="display: <%= @pivot[:cancel_filter_query_url] ? "block" : "none" -%>">
           </div>
@@ -53,9 +53,9 @@
     <div class="sort">
       Sort by:
       <select  = this.options[this.selectedIndex].value;">
-        <% @pivot_options[:order].each do |args| %>
-          <option value="<%= url_for(request.query_parameters.merge("order" => args[:option])) -%>"
-          <% if params[:order] == args[:option] -%> selected="selected"<% end -%>><%= args[:label] -%></option>
+        <% @pivot[:pivot_options]["order"].each do |args| %>
+          <option value="<%= url_for(request.query_parameters.merge("order" => args["option"])) -%>"
+          <% if params[:order] == args["option"] -%> selected="selected"<% end -%>><%= args["label"] -%></option>
         <% end %>
       </select>
     </div>
@@ -114,7 +114,7 @@
       </div>
     <% end %>
     <div>
-      <%= render :partial => "layouts/paginate", :locals => { :collection => @pivot[:results], :sort_by => @pivot_options[:order], :num_options => @pivot_options[:num_options] } %>
+      <%= render :partial => "layouts/paginate", :locals => { :collection => @pivot[:results], :sort_by => @pivot[:pivot_options]["order"], :num_options => @pivot[:pivot_options]["num_options"] } %>
     </div>
   </div>
 </div>

Copied: branches/wf4ever/app/views/contributions/_autocomplete_list.html.erb (from rev 3085, trunk/app/views/contributions/_autocomplete_list.html.erb) (0 => 3086)


--- branches/wf4ever/app/views/contributions/_autocomplete_list.html.erb	                        (rev 0)
+++ branches/wf4ever/app/views/contributions/_autocomplete_list.html.erb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,10 @@
+<ul>
+  <% contributions.each do |c| %>
+    <li data-cont-id="<%= c.id -%>" data-cont-name="<%= h c.title -%>" style="border-bottom: 1px dashed #bbb">
+      <%= h c.title -%><br/>
+      <span style="font-weight: normal; color: #777">
+        (ID: <%= c.id -%>) Uploader: <%= h c.contributor.name -%>
+      </span>
+    </li>
+  <% end %>
+</ul>
\ No newline at end of file

Modified: branches/wf4ever/app/views/contributions/_citations_tab.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/contributions/_citations_tab.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/contributions/_citations_tab.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -2,6 +2,7 @@
   <div class="tabTitle">Citations (<%= item.citations.length -%>)</div>
   <div class="tabContent">
 
+    <a name="citations"></a>
     <% unless (citations = item.citations).empty? %>
       <% citations.each_index do |i| %>
         <p>

Modified: branches/wf4ever/app/views/contributions/_credit_attribution_form.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/contributions/_credit_attribution_form.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/contributions/_credit_attribution_form.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -29,141 +29,184 @@
       	You can also attribute the Workflows/Files that this <%= c_type %> is <strong>based on</strong> (if any).
 			</p>                           
     </div>
-    <br/>
+
+    <!--- CREDITS --->
+
     <p><b>Which users/groups get the credit for this <%= c_type %>?</b></p>
-		<div class="box_editing" style="padding-left: 1em;">
-			<p style="color: #666666;">Build up the list of credits below by adding from the options</p>
-      <p id="authors_list" class="box_editing_inner">
-          Me&nbsp;&nbsp;&nbsp;<small>[<a href="" t="me"  null); return false;">delete</a>]</small><br/>
-      </p>
-      <div class="box_simple" style="font-size: 93%; margin-top: 1em;">
-        Select an option then click on 'Add' to add to the list:
-        <br />
-        <br />
+		<div id="credit_section" class="box_editing" style="padding-left: 1em; overflow: auto">
+			<p style="color: #666666;">Build up the list of credits on the right by adding from the options on the left.</p>
+      <div id="author_selection" class="box_simple" style="width: 50%; float: left; font-size: 93%;">
 
-				<p>
-            <label for="" id="author_option_1" name="add_author_option" checked="checked"
-                value="1" type="radio"  />
-            - Me</label> (<%= name current_user %>)
-        </p>
+        <!--- Credit me --->
 
-        <p>
-            <label for="" id="author_option_2" name="add_author_option"
-                value="2" type="radio"  />
-            - One of my Friends</label>
-        </p>
-        <div id="author_friends_box" style="display: none; padding-left: 2em;">
-            <p>
-                <select id="author_friends_dropdown">
-                	<% current_user.friends.each do |f| %>
-                    	<option value="<%= f.id %>"><%= h(f.name) %></option>
-                    <% end %>
-                </select>
-            </p>
+        <div id="author_me" class="credit_selection_box">
+          <span style="font-size: 120%;line-height: 1.5;">Me (<%= name current_user %>)
+          <button  false">Add ></button>        </span>
         </div>
-        
-				<p>
-            <label for="" id="author_option_3" name="add_author_option"
-                value="3" type="radio"  />
-            - A user on <%= Conf.sitename %> who is not a Friend.</label>
-        </p>
-        <div id="author_otheruser_box" style="display: none; padding-left: 2em;">
-            <p>
-                <select id="author_otheruser_dropdown">
-                    <% (nonfriends_for_credits_form(current_user)).each do |f| %>
-                    	<option value="<%= f.id %>"><%= h(f.name) %></option>
-                    <% end %>
-                </select>
-            </p>
+
+        <!--- Credit a friend --->
+
+        <div id="author_friends_box" class="credit_selection_box">
+          <p>A Friend</p>
+          <select id="author_friends_dropdown"  = (this.selectedIndex == 0)">
+            <option value="0" selected="selected">Select a friend...</option>
+            <% current_user.friends.each do |f| %>
+              <option value="<%= f.id %>"><%= h(f.name) %></option>
+            <% end %>
+          </select>
+          <button id="add_friend_author" disabled="disabled"  false">Add ></button>
         </div>
 
-				<p>
-            <label for="" id="author_option_4" name="add_author_option"
-                value="4" type="radio"  />
-            - A <%= Conf.sitename %> Group</label>
-        </p>
-        <div id="author_networks_box" style="display: none; padding-left: 2em;">
-            <p>
-                <select id="author_networks_dropdown">
-                    <% networks_for_credits_form.each do |n| %>
-                    	<option value="<%= n.id %>"><%= h(n.title) %></option>
-                    <% end %>
-                </select>
-            </p>
+        <!--- Credit a user --->
+
+        <div id="author_otheruser_box" class="credit_selection_box">
+          <p>A <%= Conf.sitename %> user
+            <%= help_icon_with_tooltip("Begin typing a #{Conf.sitename} user's name into the text box and a list of suggestions will appear. Select the correct user from the list and click the Add button.") -%>
+          </p>
+          <%= text_field_tag :user_name, '',
+                             : %(other_user_name = null; other_user_id = null; $('add_otheruser_author').disabled = true;),
+                             : %(if(event.keyCode == 13 && !$('add_otheruser_author').disabled)
+                                             addAuthor(3);)%>
+          <%= image_tag "/images/spinner.gif", :class => "auto_complete_spinner", :id => "add_user_indicator", :style => "vertical-align: middle; display: none;" %>
+          <script type="text/_javascript_">
+            var other_user_id;
+            var other_user_name;
+          </script>
+          <div class="auto_complete" id="users_auto_complete" ></div>
+          <%= auto_complete_field :user_name,
+                                  :update => "users_auto_complete",
+                                  :url ="" {:controller => 'users', :action ="" 'auto_complete', :authenticity_token => form_authenticity_token},
+                                  :frequency => 0.2,
+                                  :after_update_element => %(function(element,value){
+                                                               other_user_id = value.getAttribute('data-user-id');
+                                                               other_user_name = value.getAttribute('data-user-name');
+                                                               $('user_name').value = other_user_name;
+                                                               $('add_otheruser_author').disabled = false;
+                                                             }),
+                                  :indicator => 'add_user_indicator' -%>
+          <button id="add_otheruser_author" disabled="disabled"  false">Add ></button>
         </div>
-        
-				<% if false %>
 
-					<p>
-              <label for="" id="author_option_5" name="add_author_option"
-                  value="5" type="radio"  />
-              - Someone else</label>
-          </p>
-          <div id="author_someoneelse_box" style="display: none; padding-left: 2em;">
-              <p>
-                   <label for="" </label>
-                   <input id="author_someoneelse_forenames" size="25" value="" type="text"/>
-                   <label for="" </label>
-                   <input id="author_someoneelse_surname" size="25" value="" type="text"/>
-              </p>
-          </div>
-	
+        <!--- Credit a group --->
+
+        <div id="author_networks_box" class="credit_selection_box">
           <p>
-              <label for="" id="author_option_6" name="add_author_option"
-                  value="6" type="radio"  />
-              - An organisation</label>
+            A <%= Conf.sitename %> Group
+            <%= help_icon_with_tooltip("Begin typing a #{Conf.sitename} Groups's name into the text box and a list of suggestions will appear. Select the correct Group from the list and click the Add button.") -%>
           </p>
-          <div id="author_organisation_box" style="display: none; padding-left: 2em;">
-              <p>
-                   <input id="author__organisation" size="50" value="" type="text"/>
-              </p>
-          </div>
-        
-				<% end %>
+          <%= text_field_tag :group_name, '',
+                             : %(group_name = null; group_id = null; $('add_group_author').disabled = true;),
+                             : %(if(event.keyCode == 13 && !$('add_group_author').disabled)
+                                             addAuthor(4)) %>
+          <%= image_tag "/images/spinner.gif", :class => "auto_complete_spinner", :id => "add_group_indicator", :style => "vertical-align: middle; display: none;" %>
+          <script type="text/_javascript_">
+            var group_id;
+            var group_name;
+          </script>
+          <div class="auto_complete" id="groups_auto_complete" ></div>
+          <%= auto_complete_field :group_name,
+                                  :update => "groups_auto_complete",
+                                  :url ="" {:controller => 'networks', :action ="" 'auto_complete', :authenticity_token => form_authenticity_token},
+                                  :frequency => 0.2,
+                                  :after_update_element => %(function(element,value){
+                                                               group_id = value.getAttribute('data-network-id');
+                                                               group_name = value.getAttribute('data-network-name');
+                                                               $('group_name').value = group_name;
+                                                               $('add_group_author').disabled = false;
+                                                             }),
+                                  :indicator => 'add_group_indicator' -%>
+          <button id="add_group_author" disabled="disabled"  false">Add ></button>
+        </div>
+			</div>
 
-        <br />
-        <b><a href=""  return false;" >Add</a></b>
-			</div>
+      <!--- List of credits --->
+
+      <div style="width: 42%; float: right" class="box_simple">
+        <p>Current credits:</p>
+        <div id="authors_list" class="box_editing_inner">
+          Me&nbsp;&nbsp;&nbsp;<small>[<a href="" t="me"  null); return false;">delete</a>]</small><br/>
+        </div>
+      </div>
     </div>
-    <br/>
-		<br/>
+
+    <!--- ATTRIBUTIONS --->
+
     <p><b>If this <%= c_type %> is based on any existing Workflows or Files, please list them below:</b></p>
-    <div class="box_editing" style="padding-left: 1em;">
-			<p style="color: #666666;">Build up the list of attributions below by adding from the options</p>
-      <p id="attribution_list" class="box_editing_inner">
-          <i>None</i>
-      </p>
-      <div style="font-size: 93%; margin-top: 1em;">
-        <div class="box_simple" style="float: left; text-align: left; width: 300px;">
-          Existing Workflows on <%= Conf.sitename %>:
-          <br />
-          <br />
-          <select id="existingworkflows_dropdown" style="width: 280px;">
-            <% workflows_for_attribution_form.each do |w| %>
-            	<option value="<%= w.id %>"><%=h "#{w.id}: #{w.title} (#{w.name})" -%></option>
-            <% end %>
-          </select>
-          <br />
-          <br />
-          <b><a href=""  return false;" >Add</a></b>
+    <div id="attribution_section" class="box_editing" style="padding-left: 1em; overflow: auto">
+      <p style="color: #666666;">Build up the list of attributions on the right by adding from the options on the left.</p>
+      <div id="attribution_selection" class="box_simple" style="width: 50%; float: left; font-size: 93%;">
+
+        <!--- Attribute a workflow --->
+
+        <div id="attribute_workflows" class="credit_selection_box">
+          <p>
+            A Workflow on <%= Conf.sitename %>
+            <%= help_icon_with_tooltip("Begin typing a #{Conf.sitename} Workflows's title into the text box and a list of suggestions will appear. Select the correct Workflow from the list and click the Add button.") -%>
+          </p>
+          <%= text_field_tag :workflow_name, '',
+                             : %(workflow_name = null; workflow_id = null; $('add_workflow_attrib').disabled = true;),
+                             : %(if(event.keyCode == 13 && !$('add_workflow_attrib').disabled)
+                                             addAttribution('existing_workflow')) %>
+          <%= image_tag "/images/spinner.gif", :class => "auto_complete_spinner", :id => "add_workflow_indicator", :style => "vertical-align: middle; display: none;" %>
+          <script type="text/_javascript_">
+            var workflow_id;
+            var workflow_name;
+          </script>
+          <div class="auto_complete" id="workflows_auto_complete" ></div>
+          <%= auto_complete_field :workflow_name,
+                                  :update => "workflows_auto_complete",
+                                  :url ="" {:controller => 'workflows', :action ="" 'auto_complete', :authenticity_token => form_authenticity_token},
+                                  :frequency => 0.2,
+                                  :after_update_element => %(function(element,value){
+                                                               workflow_id = value.getAttribute('data-cont-id');
+                                                               workflow_name = value.getAttribute('data-cont-name');
+                                                               $('workflow_name').value = workflow_name;
+                                                               $('add_workflow_attrib').disabled = false;
+                                                             }),
+                                  :indicator => 'add_workflow_indicator' -%>
+          <button id="add_workflow_attrib" disabled="disabled"  ;return false">Add ></button>
         </div>
+
+        <!--- Attribute a file --->
 	
-        <div class="box_simple" style="float: left; margin-left: 1em; text-align: left; width: 300px;">
-          Existing Files on <%= Conf.sitename %>:
-          <br />
-          <br />
-          <select id="existingfiles_dropdown" style="width: 280px;">
-            <% blobs_for_attribution_form.each do |b| %>
-            	<option value="<%= b.id %>"><%=h "#{b.id}: #{b.title} (#{b.name})" -%></option>
-            <% end %>
-          </select>
-          <br />
-          <br />
-          <b><a href=""  return false;" >Add</a></b>
+        <div id="attribute_files" class="credit_selection_box">
+          <p>
+            A File on <%= Conf.sitename %>
+            <%= help_icon_with_tooltip("Begin typing a #{Conf.sitename} File's title into the text box and a list of suggestions will appear. Select the correct File from the list and click the Add button.") -%>
+          </p>
+          <%= text_field_tag :file_name, '',
+                             : %(file_name = null; file_id = null; $('add_file_attrib').disabled = true;),
+                             : %(if(event.keyCode == 13 && !$('add_file_attrib').disabled)
+                                             addAttribution('existing_file')) %>
+          <%= image_tag "/images/spinner.gif", :class => "auto_complete_spinner", :id => "add_file_indicator", :style => "vertical-align: middle; display: none;" %>
+          <script type="text/_javascript_">
+            var file_id;
+            var file_name;
+          </script>
+          <div class="auto_complete" id="files_auto_complete" ></div>
+          <%= auto_complete_field :file_name,
+                                  :update => "files_auto_complete",
+                                  :url ="" {:controller => 'blobs', :action ="" 'auto_complete', :authenticity_token => form_authenticity_token},
+                                  :frequency => 0.2,
+                                  :after_update_element => %(function(element,value){
+                                                               file_id = value.getAttribute('data-cont-id');
+                                                               file_name = value.getAttribute('data-cont-name');
+                                                               $('file_name').value = file_name;
+                                                               $('add_file_attrib').disabled = false;
+                                                             }),
+                                  :indicator => 'add_file_indicator' -%>
+          <button id="add_file_attrib" disabled="disabled"  false">Add ></button>
         </div>
-	
-        <div style="clear: both;">&nbsp;</div>  
-			</div>                     
+      </div>
+
+      <!--- Attribution list --->
+
+      <div style="width: 42%; float: right" class="box_simple">
+        <p>Current attributions:</p>
+        <div id="attribution_list" class="box_editing_inner">
+          <i>None</i>
+        </div>
+      </div>
     </div>
   </div>
 </div>
@@ -203,15 +246,15 @@
 		credit_me = false;
 		<% contributable.creditors.each do |c| %>
 	    <% if c.creditor_type == 'User' and c.creditor_id == current_user.id %>
-	  	credit_me = true;
-	  <% elsif c.creditor_type == 'User' %>
-	  	credit_users[<%= c.creditor_id %>] = '<%= escape_javascript contributor_name(c.creditor_id, 'User') %>';
-	  <% elsif c.creditor_type == 'Network' %>
-	  	credit_groups[<%= c.creditor_id %>] = '<%= escape_javascript contributor_name(c.creditor_id, 'Network') %>';
+	  	  credit_me = true;
+      <% elsif c.creditor_type == 'User' %>
+        credit_users[<%= c.creditor_id %>] = '<%= escape_javascript contributor_name(c.creditor_id, 'User') %>';
+      <% elsif c.creditor_type == 'Network' %>
+        credit_groups[<%= c.creditor_id %>] = '<%= escape_javascript contributor_name(c.creditor_id, 'Network') %>';
+      <% end %>
 	  <% end %>
-	  <% end %>
 	  updateAuthorList();
-	
+
 		// Attributions
 		<% contributable.attributors.each do |a| %>
 			<% if Authorization.is_authorized?("show", nil, a.attributor, current_user) -%>

Modified: branches/wf4ever/app/views/contributions/_in_packs_box.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/contributions/_in_packs_box.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/contributions/_in_packs_box.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -44,7 +44,7 @@
                         :id => "add_to_pack_form" } do %>
             <p>
               <select id="add_to_pack_selector" style="width: 99%"  = $(this).options[this.selectedIndex].value; return false">
-                <% potential_packs.each do |p| -%>
+                <% potential_packs.sort_by(&:updated_at).reverse!.each do |p| -%>
                   <option value="<%= quick_add_pack_url(p) -%>">
                     <%= h(p.title) -%>
                   </option>

Modified: branches/wf4ever/app/views/contributions/_statistics_box.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/contributions/_statistics_box.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/contributions/_statistics_box.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -42,9 +42,7 @@
 				
 				<% if allow_citations? type %>
 					<p>
-			      <!-- for this to work properly, view for every resource that supports citations will need to have -->
-						<!-- tab system with 'tabsContainer' element + anchor called 'citations' -->
-						<a href=""  pluralize contributable.citations.count, "citation" %></a>
+						<a href="" pluralize contributable.citations.count, "citation" %></a>
 			    </p>
 				<% end %>
 				

Modified: branches/wf4ever/app/views/contributions/_statistics_detailed.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/contributions/_statistics_detailed.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/contributions/_statistics_detailed.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -13,7 +13,7 @@
 
 
 <ul class="sectionIcons">
-	<li><%= icon(contributable.class.to_s.downcase, eval("#{contributable_display_type.downcase}_path(#{contributable.id})"), nil, nil, "Back to the #{contributable_display_type}") %></li>
+	<li><%= icon(contributable.class.to_s.downcase, polymorphic_path(contributable), nil, nil, "Back to the #{contributable_display_type}") %></li>
 </ul>
 
 <% # this will be changed to display the correct thing after event logging branch is merged into trunk %>

Copied: branches/wf4ever/app/views/contributions/_version_selector.rhtml (from rev 3085, trunk/app/views/contributions/_version_selector.rhtml) (0 => 3086)


--- branches/wf4ever/app/views/contributions/_version_selector.rhtml	                        (rev 0)
+++ branches/wf4ever/app/views/contributions/_version_selector.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,71 @@
+<script type="text/_javascript_">
+  function showVersion(form) {
+    var url = ""
+		location.href = ""
+		form.submit
+  }
+</script>
+
+<div class="contribution_version_selector_box">
+
+  <table>
+    <tbody>
+      <tr>
+        <td class="heading" style="vertical-align: top;">
+          <%= info_icon_with_tooltip("This box shows version #{version.version.to_s} for this entry") -%>
+          <span><%= "Version #{version.version.to_s} #{resource.describe_version(version.version)}" -%></span>
+          <span class="count_text">(of <%= resource.versions.length -%>)</span>
+          <a name="versions"></a>
+        </td>
+        <td>
+          <% if resource.versions.length > 1 %>
+             <form  return false;" style="text-align: right;">
+              <b>View version: </b>
+              <select id="resource_versions" 
+                <% resource.versions.reverse.each do |v| %>
+                  <option value="<%= send(path, resource, v.version.to_s) %>" <%= "selected" if v.version == version.version -%>>
+                      <%= "#{v.version.to_s} #{resource.describe_version(v.version)}" %>
+                  </option>
+                <% end %>
+              </select>
+            </form>
+          <% end %>
+        </td>
+      </tr>
+    </tbody>
+  </table>
+      
+  <div id="version_info_box" style="color: #666666;  font-size: 85%; margin: 0.6em 0.5em 0.2em 0.5em; border-top: 1px solid #DDDDDD; padding-top: 0.4em;">
+    <p style="text-align: center;">
+      <b>Version created on:</b>
+      <span><%= datetime version.created_at, false %></span>
+      <% if version.respond_to?(:contributor_id) && version.respond_to?(:contributor_type) %>
+        <b>by:</b>
+        <span><%= contributor(version.contributor_id, version.contributor_type) %></span>
+      <% end %>
+      <% if !version.revision_comments.blank? %>
+        <span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
+        <span><%= link_to_function "Revision comment " + expand_image, visual_effect(:toggle_blind, "version_info_box_comments", :duration => 0.3) %></span>
+      <% end %>
+    </p>
+    
+    <% unless version.created_at == version.updated_at %>
+      <p style="text-align: center;">
+        <b>Last edited on:</b>
+        <span><%= datetime version.updated_at, false %></span>
+        <% if version.respond_to?(:last_edited_by) %>
+          <b>by:</b>
+          <span><%= contributor(version.last_edited_by, "User") %></span>
+        <% end %>
+      </p>
+    <% end %>
+  </div>
+  
+  <% if !version.revision_comments.blank? -%>
+    <div id="version_info_box_comments" style="display: none; border: 1px dotted #CCCCCC; padding: 0.3em 0.5em;">
+      <%= white_list version.revision_comments %>
+    </div>
+  <% end %>
+
+</div>
+

Copied: branches/wf4ever/app/views/contributions/_versions.rhtml (from rev 3085, trunk/app/views/contributions/_versions.rhtml) (0 => 3086)


--- branches/wf4ever/app/views/contributions/_versions.rhtml	                        (rev 0)
+++ branches/wf4ever/app/views/contributions/_versions.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,41 @@
+<p>In chronological order:</p>
+
+<ol class="version_history">
+  <% resource.versions.each do |version| %>
+    <li>
+      <div class="title">
+        <%= link_to(version.title, send(path, resource, version.version)) %>
+      </div>
+      <div class="metadata">
+
+        <p>
+          Created
+          <% if version.respond_to?(:contributor_id) %>
+            by <%= contributor version.contributor_id, version.contributor_type %>
+          <% end %>
+          on <%= datetime version.created_at %>
+        </p>
+
+        <% unless version.created_at == version.updated_at %>
+          <p>
+            Last edited
+            <% if version.respond_to?(:last_edited_by) %>
+              by <%= contributor version.last_edited_by, "User" %>
+            <% end %>
+            on <%= datetime version.updated_at %>
+          </p>
+        <% end %>
+
+        <% if !version.revision_comments.blank? %>
+          <p>
+            <div>Revision comment:</div>
+            <div class="comment">
+              <%= white_list version.revision_comments %>
+            </div>
+          </p>
+        <% end %>
+      </div>
+    </li>
+  <% end %>
+</ol>
+

Modified: branches/wf4ever/app/views/gadgets/_user_monitor.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/gadgets/_user_monitor.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/gadgets/_user_monitor.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -26,6 +26,7 @@
 			<hr/>
 			<ul class="gadget_list">
 				<li><%= icon "announcement", announcements_url, nil, nil, "Manage Announcements" %></li>
+				<li><%= icon "usercheck", "/users/check", nil, nil, "Manage Users" %></li>
 			</ul>
 		<% end %>
 

Modified: branches/wf4ever/app/views/home/_new_users.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/home/_new_users.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/home/_new_users.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,4 +1,5 @@
 <!-- New Users -->
+<% if false %>
 <div class="box">
 	<b class="xtop"><b class="xb1"></b><b class="xb2"></b><b class="xb3"></b><b class="xb4"></b></b>
 	<div class="title">
@@ -15,3 +16,4 @@
 	</div>
 	<b class="xbottom"><b class="xb5"></b><b class="xb6"></b><b class="xb7"></b><b class="xb1"></b></b>
 </div>
+<% end %>

Modified: branches/wf4ever/app/views/layouts/_footer.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/layouts/_footer.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/layouts/_footer.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,5 +1,5 @@
 <p class="copyright">
-	Copyright &#169; 2007 - 2011
+	Copyright &#169; 2007 - 2012
 	<%= link_to "The University of Manchester", "http://www.manchester.ac.uk/", :target => '_blank' %>
 	and
 	<%= link_to "University of Southampton", "http://www.soton.ac.uk/", :target => '_blank' %>

Modified: branches/wf4ever/app/views/layouts/_myexperiment.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/layouts/_myexperiment.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/layouts/_myexperiment.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -21,9 +21,10 @@
 </head>
 <body>
 
+<%= render :partial => "layouts/integrations/#{session[:came_from]}" unless session[:came_from].blank? %>
+
 <div id="doc2" class="yui-t4">
 
-  <%# TODO: Rails 2: '@content_for_x' has changed to 'content_for?(:x)' in later versions of rails %>
   <% if @content_for_header %>
     <%= yield :header %>
   <% else %>

Modified: branches/wf4ever/app/views/layouts/_paginate.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/layouts/_paginate.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/layouts/_paginate.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -3,7 +3,7 @@
     Sort by:
     <select  = this.options[this.selectedIndex].value;">
       <% sort_by.each do |args| %>
-        <option value="<%= url_for(request.query_parameters.merge("order" => args[:option])) -%>" <% if params[:order] == args[:option] -%> selected="selected"<% end -%>><%= args[:label] -%></option>
+        <option value="<%= url_for(request.query_parameters.merge("order" => args["option"])) -%>" <% if params[:order] == args["option"] -%> selected="selected"<% end -%>><%= args["label"] -%></option>
       <% end %>
     </select>
 

Copied: branches/wf4ever/app/views/layouts/_scape.html.erb (from rev 3085, trunk/app/views/layouts/_scape.html.erb) (0 => 3086)


--- branches/wf4ever/app/views/layouts/_scape.html.erb	                        (rev 0)
+++ branches/wf4ever/app/views/layouts/_scape.html.erb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,9 @@
+<% @logo_link_url  = "http://www.scape-project.eu/" # The URL that the logo links to when clicked
+   @logo_image_url = "/images/scape_logo.png" # The logo image %>
+
+<% content_for :site_info_links do %>
+  <a target="_blank" href="" SCAPE</a> |
+  <a target="_blank" href="" Wiki</a>
+<% end %>
+
+<%= render :partial => "layouts/skin_template" %>

Modified: branches/wf4ever/app/views/messages/show.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/messages/show.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/messages/show.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -13,7 +13,7 @@
 	  <li><%= icon('messages_outbox_no_arrow', sent_messages_path, "Return to Sent Messages", nil, 'Return to Sent Messages') -%></li>
   <% end -%>
 	<li>
-	  <% complex_delete_url = "<a href=""  (confirm('Are you sure you want to delete this message?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = "" m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var n = document.createElement('input'); n.setAttribute('type', 'hidden'); n.setAttribute('name', 'deleted_from'); n.setAttribute('value', 'address@hidden'); f.appendChild(n); f.submit(); };return false;\">" -%>
+	  <% complex_delete_url = "<a href=""  (confirm('Are you sure you want to delete this message?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = "" m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m);var n = document.createElement('input'); n.setAttribute('type', 'hidden'); n.setAttribute('name', 'deleted_from'); n.setAttribute('value', 'address@hidden'); f.appendChild(n); var o = document.createElement('input'); o.setAttribute('type', 'hidden'); o.setAttribute('name', 'authenticity_token'); o.setAttribute('value', '#{form_authenticity_token}'); f.appendChild(o); f.submit(); };return false;\">" -%>
 		<%= icon_no_link_processing('message_delete', complex_delete_url, nil, 'Delete this Message') %>
 	</li>
 </ul>

Copied: branches/wf4ever/app/views/networks/_autocomplete_list.html.erb (from rev 3085, trunk/app/views/networks/_autocomplete_list.html.erb) (0 => 3086)


--- branches/wf4ever/app/views/networks/_autocomplete_list.html.erb	                        (rev 0)
+++ branches/wf4ever/app/views/networks/_autocomplete_list.html.erb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,8 @@
+<ul>
+  <% networks.each do |network| %>
+    <li data-network-id="<%= network.id -%>" data-network-name="<%= h network.title -%>" style="border-bottom: 1px dashed #bbb">
+      <%= h network.title -%><br/>
+      <span style="font-weight: normal; color: #777"><%= network.members.count -%> members</span>
+    </li>
+  <% end %>
+</ul>
\ No newline at end of file

Modified: branches/wf4ever/app/views/networks/invite.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/networks/invite.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/networks/invite.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -9,12 +9,12 @@
 <% invite_existing_selected = invite_existing_selected?(params[:radio_choice]) -%>
 
 <label for=""
-  <%= radio_button_tag ("radio_invite", "existing", invite_existing_selected, : "$('radio_invite_new').checked=false;$('div_invite_existing').show();$('div_invite_new').hide();return true;" ) -%>
+  <%= radio_button_tag("radio_invite", "existing", invite_existing_selected, : "$('radio_invite_new').checked=false;$('div_invite_existing').show();$('div_invite_new').hide();return true;" ) -%>
   Invite an existing <%= Conf.sitename %> user to your group
 </label>
 <br/>
 <label for=""
-  <%= radio_button_tag ("radio_invite", "new", !invite_existing_selected, : "$('radio_invite_existing').checked=false;$('div_invite_existing').hide();$('div_invite_new').show();return true;" ) -%>
+  <%= radio_button_tag("radio_invite", "new", !invite_existing_selected, : "$('radio_invite_existing').checked=false;$('div_invite_existing').hide();$('div_invite_new').show();return true;" ) -%>
   Invite someone to join <%= Conf.sitename -%> and your group
 </label>
 
@@ -25,15 +25,69 @@
   <fieldset>
     <legend>Invite an existing <%= Conf.sitename %> user to your group</legend>
     <p class="box_infotext" style="margin: 0.4em 0em 0.7em 0em" >
-      Select a name from the list, type in a message to the user and click "Invite".
+      Select a user by typing their name into the text box and choosing an option from the list which appears, then type in a message to the user and click "Invite".
     </p>
 
-    <% form_tag(membership_invite_network_path(@network), :method => :post) do %>
+    <% form_tag(membership_invite_network_path(@network), :method => :post, : "if(event.keyCode === 13) return false;") do %>
       <table cellpadding="0" cellspacing="0">
         <tr>
-          <td>&nbsp;</td>
+          <td><%= help_icon_with_tooltip("Begin typing a #{Conf.sitename} user's name into the text box and a list of suggestions will appear. Select the correct user from the list.") -%></td>
           <td style="text-align: left;">User:</td>
-          <td style="text-align: left;"><%= select_tag :user_id, options_from_collection_for_select(User.find(:all, :order => "name ASC"), :id.to_i, :name), :style => "width: 400px;" -%></td>
+          <td style="text-align: left;">
+            <%= text_field_tag :user_name, '', :class => "auto_complete_field" -%>
+            <%= hidden_field_tag :user_id, '' -%>
+            <script type="text/_javascript_">
+              function userSelectSuccess() {
+                $('user_name').addClassName('accepted');
+                $('user_name').removeClassName('error');
+                $('add_user_error_msg').hide();
+                $('user_name').disabled = true;
+                $('add_user_reset').show();
+              }
+              function userSelectError() {
+                $('user_name').addClassName('error');
+                $('user_name').removeClassName('accepted');
+                $('add_user_error_msg').show();
+                $('add_user_reset').show();
+              }
+              function userSelectReset() {
+                $('user_name').removeClassName('error');
+                $('user_name').removeClassName('accepted');
+                $('add_user_error_msg').hide();
+                $('user_id').value = '';
+                $('user_name').value = '';
+                $('user_name').disabled = false;
+                $('add_user_reset').hide();
+                $('user_name').focus();
+              }
+              // Make sure the user clicked a name from the list, or that user's ID won't be saved in the form!
+              Event.observe('user_name', 'blur', function(event) {
+                setTimeout(function(){ // Hack to avoid the error flashing briefly after the user clicks a name
+                  if(document.activeElement.id != 'user_name' && $('user_id').value == '')
+                    userSelectError();
+                }, 300);
+              });
+            </script>
+            <%= image_tag "/images/spinner.gif", :class => "auto_complete_spinner", :id => "add_user_indicator", :style => "vertical-align: middle; display: none;" %>
+            <%= image_tag "/images/famfamfam_silk/pencil.png", :id => "add_user_reset",
+                          :style => "vertical-align: middle; display: none; cursor: pointer;",
+                          : "userSelectReset(); return false;",
+                          :title => "Click to clear the selection" %>
+            <span id="add_user_error_msg" style="display: none; font-size: 75%; color: red">
+              Please make sure to <strong>click</strong> on the user you wish to invite from the dropdown menu.
+            </span>
+            <div class="auto_complete" id="users_auto_complete" ></div>
+            <%= auto_complete_field :user_name,
+                                    :update => "users_auto_complete",
+                                    :url ="" {:controller => 'users', :action ="" 'auto_complete', :authenticity_token => form_authenticity_token},
+                                    :frequency => 0.2,
+                                    :after_update_element => %(function(element,value){
+                                                                 $('user_id').value = value.getAttribute('data-user-id');
+                                                                 $('user_name').value = value.getAttribute('data-user-name');
+                                                                 userSelectSuccess();
+                                                               }),
+                                    :indicator => 'add_user_indicator' -%>
+          </td>
         </tr>
         <tr style="vertical-align: top;">
           <td><%= info_icon_with_tooltip("This message is optional: if you leave it blank, your invitation will be sent without it") -%></td>
@@ -55,7 +109,7 @@
       Type in email addresses you want to send invitations to, personal message to new users and click "Invite".
     </p>
 
-    <% form_tag (membership_invite_external_network_path(@network), :method => :post) do %>
+    <% form_tag(membership_invite_external_network_path(@network), :method => :post) do %>
       <%= hidden_field_tag "radio_choice", "" -%>
       <table>
         <tr>

Modified: branches/wf4ever/app/views/networks/show.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/networks/show.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/networks/show.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -42,21 +42,20 @@
 	|
 	<%= link_to "Members (address@hidden)", "#group_members" %>
 	|
-	<!-- NB! IDs of tabs for selectTab() might easily change! -->
-	<a href="" 
+	<a href=""
 	|
-	<a href=""  Items (<%= @shared_items.length -%>)</a>
+	<a href="" Items (<%= @shared_items.length -%>)</a>
 	|
-	<a href=""  (<%= @network.creditations.length -%>)</a>
+	<a href="" (<%= @network.creditations.length -%>)</a>
 	|
 	<% if mine? @network %>
-	  <a href=""  Memberships</a>
+	  <a href="" Memberships</a>
 		|
 		<% cnt = @network.memberships_requested.length %>
-		<a href=""  unless cnt == 0 %><b><% end %>Requests Pending (<%= cnt -%>)<% unless cnt == 0 %></b><% end %></a>
+		<a href="" unless cnt == 0 %><b><% end %>Requests Pending (<%= cnt -%>)<% unless cnt == 0 %></b><% end %></a>
 		|
 		<% cnt = @network.memberships_invited.length %>
-		<a href=""  unless cnt == 0 %><b><% end %>Invites Pending (<%= cnt -%>)<% unless cnt == 0 %></b><% end %></a>
+		<a href="" unless cnt == 0 %><b><% end %>Invites Pending (<%= cnt -%>)<% unless cnt == 0 %></b><% end %></a>
 		|
 		<br/>
 		|
@@ -134,7 +133,7 @@
 		<p>
 			<b>
 				This group has been credited
-				<a href=""  pluralize(@network.creditations.length, "time") -%></a>
+				<a href="" pluralize(@network.creditations.length, "time") -%></a>
 				<a name="group_creditations"></a>
 	  	</b>
 		</p>
@@ -155,18 +154,18 @@
 
 <div id="tabsContainer" class="tabsContainer"></div>
 
-<a name="news"></a>
 <div class="tabContainer">
   <div class="tabTitle">News</div>
   <div class="tabContent">  
+    <a name="news"></a>
     <%= render :partial => "layouts/news", :locals => { :collection => news(@network, true) } %>
   </div>
 </div>
 
-<a name="shared_items"></a>
 <div class="tabContainer">
   <div class="tabTitle">Shared Items (<%= @shared_items.length -%>)</div>
   <div class="tabContent" id="shared_items">
+    <a name="shared_items"></a>
 		<% unless @shared_items.empty? %>
   		<%= view_privileges_notice %>
 
@@ -189,11 +188,11 @@
 	</div>
 </div>
 
-<a name="creditations"></a>
 <div class="tabContainer">
   <div class="tabTitle">Creditations (<%= @network.creditations.length -%>)</div>
   <div class="tabContent">  
     
+    <a name="creditations"></a>
     <% unless (creditations = @network.creditations).empty? %>
 			<%= view_privileges_notice %>
       <% creditations.each do |c| %>
@@ -211,10 +210,10 @@
 <% if logged_in? && @network.administrator?(current_user.id) %>
   
   <% memberships = @network.memberships_accepted %>
-  <a name="manage_memberships"></a>
 	<div class="tabContainer">
     <div class="tabTitle">Manage Memberships</div>
     <div class="tabContent">
+      <a name="manage_memberships"></a>
     	<% unless memberships.empty? %>
       	<%= render :partial => "memberships/table", :locals => { :collection => memberships, :network => false } %>
 			<% else %>
@@ -224,10 +223,10 @@
   </div>
   
 	<% requests = @network.memberships_requested %>
-  <a name="requests_pending"></a>
   <div class="tabContainer">
     <div class="tabTitle">Requests Pending (<%= @network.memberships_requested.length -%>)</div>
     <div class="tabContent">
+      <a name="requests_pending"></a>
     	<% unless requests.empty? %>
 				<p></p>
       	<%= render :partial => "memberships/table", :locals => { :collection => requests, :network => false } %>
@@ -238,10 +237,10 @@
   </div>
 	
 	<% invited = @network.memberships_invited %>
-  <a name="invites_pending"></a>
 	<div class="tabContainer">
     <div class="tabTitle">Invites Pending (<%= @network.memberships_invited.length -%>)</div>
     <div class="tabContent">
+      <a name="invites_pending"></a>
     	<% unless invited.empty? %>
 				<p></p>
       	<%= render :partial => "memberships/table", :locals => { :collection => invited, :network => false } %>

Modified: branches/wf4ever/app/views/packs/show.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/packs/show.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/packs/show.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -22,8 +22,7 @@
 		|
 	<% end %>
 	<% if logged_in? and @pack.owner? current_user %>
-	  <!-- NB! Index of the 'sharing' tab might change! -->
-	  <a href="" 
+	  <a href=""
 		|
 	<% end %>
 	<%= link_to "Tags <span id='mini_nav_tag_link'>(address@hidden)</span>", "#tags" %>
@@ -169,11 +168,11 @@
 	
 <% if logged_in? and @pack.owner? current_user %>
   
-	<a name="sharing"></a>
 	<div class="tabContainer">
     <div class="tabTitle">Sharing</div>
     <div class="tabContent">
 
+      <a name="sharing"></a>
       <%= render :partial => "contributions/sharing_summary",  :locals => { :contributable => @pack } %>
       <%= render :partial => "contributions/updating_summary", :locals => { :contributable => @pack } %>
 	  

Copied: branches/wf4ever/app/views/users/_autocomplete_list.html.erb (from rev 3085, trunk/app/views/users/_autocomplete_list.html.erb) (0 => 3086)


--- branches/wf4ever/app/views/users/_autocomplete_list.html.erb	                        (rev 0)
+++ branches/wf4ever/app/views/users/_autocomplete_list.html.erb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,11 @@
+<ul>
+  <% users.each do |user| %>
+    <li data-user-id="<%= user.id -%>" data-user-name="<%= h user.name -%>" style="border-bottom: 1px dashed #bbb">
+      <%= flag_icon(user.profile.location_country, user.profile.location) if user.profile -%>
+      <%= h user.name -%><br/>
+      <% unless user.profile.nil? || user.profile.email.nil? || user.profile.email.empty? %>
+        <span style="font-weight: normal; color: #777"><%= user.profile.email.gsub("@", " [at] ") %></span>
+      <% end %>
+    </li>
+  <% end %>
+</ul>
\ No newline at end of file

Modified: branches/wf4ever/app/views/users/_listing.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/users/_listing.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/users/_listing.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,4 +1,3 @@
-<% cache(:controller => 'users_cache', :action ="" 'listing', :id => user.id) do -%>
   <td style="width: 100px"><div style="text-align: center; font-weight: bold">Member</div><br /><br /><center><%= contributor(user.id, 'User', true, 60) %></center></td>
   <td class="mid" style="text-align: left;">
 
@@ -9,6 +8,7 @@
       <%= admin_badge(user) %>
     </p>
           
+<% cache(:controller => 'users_cache', :action ="" 'listing', :id => user.id) do -%>
     <% unless user.created_at.blank? %>
       <p style="font-size: 85%;">
         <b>Joined:</b>
@@ -65,8 +65,8 @@
       </p>
 
     <% end %>
+<% end %>
   </td>
-<% end %>
 
 <td class="actions"  style="width: 90px;">
   <%= icon "show", user_path(user.id), nil, nil, "View" %>

Copied: branches/wf4ever/app/views/users/check.rhtml (from rev 3085, trunk/app/views/users/check.rhtml) (0 => 3086)


--- branches/wf4ever/app/views/users/check.rhtml	                        (rev 0)
+++ branches/wf4ever/app/views/users/check.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,248 @@
+<% t "Manage users" -%>
+
+<script type="text/ecmascript">
+
+  var keyScrollElementsID = "user-check-list";
+  var selectedKSElementID = "selected-user-check-element";
+
+  // return the currently selected keyscroll element (null if no selection)
+
+  function findSelectedKSE() {
+    return document.getElementById(selectedKSElementID);
+  }
+
+  // scroll to current keyscroll element (if exists)
+
+  function scrollToSelectedKSE() {
+
+    var selectedKSE = findSelectedKSE();
+
+    if (selectedKSE) {
+      window.scrollTo(window.pageXOffset, selectedKSE.offsetTop - 80);
+    } 
+  }
+
+  // select the first possible keyscroll element (if exists)
+
+  function selectFirstKSE() {
+
+    var possibleKSEs = document.getElementById(keyScrollElementsID).children;
+
+    for (var i = 0; i < possibleKSEs.length; i++) {
+      if (possibleKSEs[i].nodeType == 1) {
+        possibleKSEs[i].id = selectedKSElementID;
+        return;
+      }
+    }
+  }
+
+  // select the next keyscroll element
+
+  function selectNextKSE() {
+
+    var oldKSE = findSelectedKSE();
+
+    if (!oldKSE) {
+
+      selectFirstKSE();
+
+    } else {
+
+      for (var newKSE = oldKSE.nextSibling; newKSE != null; newKSE = newKSE.nextSibling) {
+        if (newKSE.nodeType == 1) {
+          oldKSE.id = null;
+          newKSE.id = selectedKSElementID;
+          break;
+        }
+      }
+    }
+
+    scrollToSelectedKSE();
+  }
+
+  // select the previous keyscroll element
+
+  function selectPreviousKSE() {
+
+    var oldKSE = findSelectedKSE();
+
+    if (!oldKSE) {
+
+      selectFirstKSE();
+
+    } else {
+
+      for (var newKSE = oldKSE.previousSibling; newKSE != null; newKSE = newKSE.previousSibling) {
+        if (newKSE.nodeType == 1) {
+          oldKSE.id = null;
+          newKSE.id = selectedKSElementID;
+          break;
+        }
+      }
+    }
+
+    scrollToSelectedKSE();
+  }
+
+  function updateKSE(id, value) {
+
+    // change the radio button
+
+    if (value != null) {
+      document.getElementById("user-" + id + "-" + value).checked = true;
+    }
+
+    // change visual class
+
+    var items  = document.forms["user-check"]["user-" + id].items
+    var length = document.forms["user-check"]["user-" + id].length
+
+    for (var i = 0; i < length; i++) {
+
+      var el = document.forms["user-check"]["user-" + id].item(i)
+
+      if (el.checked) {
+        document.getElementById(id).className = el.value;
+      }
+    }
+  }
+
+  function changeSelectedKSE(value) {
+
+    var currentKSE = findSelectedKSE();
+
+    if (currentKSE == null) {
+      selectFirstKSE();
+
+      currentKSE = findSelectedKSE();
+    }
+    
+    if (currentKSE == null)
+      return;
+
+    updateKSE(currentKSE.children[0].id, value);
+
+    // select the next one
+
+    selectNextKSE();
+  }
+
+  function processEventsforKS(evt) {
+
+    switch (evt.charCode) {
+
+      case 110: /* 'n' key */
+      case 106: /* 'j' key */
+
+        selectNextKSE();
+        break;
+
+      case 112: /* 'p' key */
+      case 107: /* 'k' key */
+
+        selectPreviousKSE();
+        break;
+    
+      case 119: /* 'w' key */
+
+        changeSelectedKSE("whitelist");
+        break;
+
+      case 115: /* 's' key */
+
+        changeSelectedKSE("sleep");
+        break;
+
+      case 120: /* 'x' key */
+
+        changeSelectedKSE("delete");
+        break;
+    }
+  }
+
+  // initialise keyscroll elements
+
+  function initialiseKSEs() {
+    var elements = document.getElementById(keyScrollElementsID).children;
+
+    for (var i = 0; i < elements.length; i++) {
+      if (elements[i].nodeType == 1) {
+        updateKSE(elements[i].children[0].id, null);
+      }
+    }
+  }
+
+  window.addEventListener("keypress", processEventsforKS, false);
+  window.addEventListener("load", initialiseKSEs, false);
+
+</script>
+
+<h1>Manage Users</h1>
+
+<div id="user-check-range">
+  <form method="GET">
+      Show users from <input type="text" name="from" value="<%= @from -%>"></input>
+      to <input type="text" name="to" value="<%= @to -%>"></input>
+      <input type="submit" value="Refresh">
+  </form>
+</div>
+
+<% if @userlist %>
+  <form id="user-check" method="post" action=""
+    <div id="user-check-list">
+      <% @userlist.each do |user| %>
+        <div>
+          <div id="<%= user[:ob].id -%>">
+            <h2><%= link_to("User: #{user[:ob].id}", user[:ob]) -%></h2>
+            <div class="user-check-buttons">
+              <% input_name = "user-#{user[:ob].id}" %>
+              <div>
+                <input name="<%= input_name -%>" id="<%= input_name -%>-nothing" value="nothing" type="radio" checked="checked"  user[:ob].id -%>').className = 'nothing';"/>
+                <label for="" input_name -%>-nothing">Do nothing</label>
+              </div>
+              <div>
+                <input name="<%= input_name -%>" id="<%= input_name -%>-whitelist" value="whitelist" type="radio"  user[:ob].id -%>').className = 'whitelist';"/>
+                <label for="" input_name -%>-whitelist">White list</label>
+              </div>
+              <div>
+                <input name="<%= input_name -%>" id="<%= input_name -%>-sleep" value="sleep" type="radio"  user[:ob].id -%>').className = 'sleep';"/>
+                <label for="" input_name -%>-sleep">Sleep</label>
+              </div>
+              <div>
+                <input name="<%= input_name -%>" id="<%= input_name -%>-delete" value="delete" type="radio"  user[:ob].id -%>').className = 'delete';"/>
+                <label for="" input_name -%>-delete">Delete</label>
+              </div>
+            </div>
+            <div class="table-div">
+              <table class="simple">
+                <% user[:strings].each do |string| %>
+                  <tr>
+                    <td><%= string[:label] -%></td>
+                    <td <%= 'class="ident"' if ["email", "openid"].include?(string[:label]) -%>>
+                      <% if string[:escape] == :false %>
+                        <%= string[:string] -%>
+                      <% elsif string[:escape] == :white_list %>
+                        <%= white_list(string[:string]) -%>
+                      <% elsif string[:escape] == :website %>
+                        <%= link_to(h(string[:string]), string[:string]) %>
+                      <% else %>
+                        <%= h(string[:string]) -%>
+                      <% end %>
+                    </td>
+                  </tr>
+                <% end %>
+              </table>
+            </div>
+          </div>
+        </div>
+      <% end %>
+    </div>
+    <input type="hidden" name="authenticity_token" value="<%= form_authenticity_token -%>"/>
+    <input type="hidden" name="from" value="<%= @from -%>"/>
+    <input type="hidden" name="to" value="<%= @to -%>"/>
+    <div id="user-check-submit">
+      <input type="submit" value="Process"/>
+    </div>
+  </form>
+<% end %>
+

Modified: branches/wf4ever/app/views/users/show.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/users/show.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/users/show.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -229,10 +229,10 @@
 						</b> 
 			    </p>
 					
-					<% filter_contributables(@user.contributions).each do |klass,contributables| %>
+					<% filter_contributables(@user.contributions).each do |klass, contributables| %>
 						<p>
 				      <b>
-				      	<%= link_to(pluralize(contributables.length, controller_visible_name(klass.humanize.pluralize)), url_for(:action ="" controller_visible_name(klass.humanize.pluralize).downcase)) %>
+				      	<%= link_to(pluralize(Authorization.scoped(klass.constantize, :authorised_user => current_user).find(:all, :select => "0", :conditions => { :contributor_type => 'User', :contributor_id => @user.id } ).length, controller_visible_name(klass.humanize.pluralize)), url_for(:action ="" controller_visible_name(klass.humanize.pluralize).downcase)) %>
 							</b>
 				    </p>
 					<% end %>

Modified: branches/wf4ever/app/views/workflows/_table.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/workflows/_table.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/workflows/_table.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -76,7 +76,7 @@
 					  
             <% desc_style = "font-size: 85%;" %>
 
-            <% unless workflow.image.nil? -%>
+            <% unless workflow.image.nil? && workflow.svg.nil? -%>
               <p style="margin: 0; border: 0; width: 101px; float: left">
                 <%= link_to image_tag(workflow_preview_path(workflow, 'thumb'), :class => 'framed_nospace'), workflow_path(workflow) %>
               </p>

Deleted: branches/wf4ever/app/views/workflows/_version_meta.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/workflows/_version_meta.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/workflows/_version_meta.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,34 +0,0 @@
-<p>
-	<b>Created on:</b>
-	<%= datetime version.created_at %>
-</p>
-
-<p>
-	<b>Created by:</b>
-	<%= contributor version.contributor_id, version.contributor_type %>
-</p>
-
-<% unless version.created_at == version.updated_at %>
-
-	<p>
-		<b>Last edited on:</b>
-		<%= datetime version.updated_at %>
-	</p>
-	
-	<p>
-		<b>Last edited by:</b>
-		<%= contributor version.last_edited_by, "User" %>
-	</p>
-
-<% end %>
-
-<p>
-	<b>Revision comments:</b>
-</p>
-<% unless version.revision_comments.blank? -%>
-	<div>
-		<%= white_list version.revision_comments %>
-	</div>
-<% else %>
-	<p><i>None</i></p>
-<% end %>

Deleted: branches/wf4ever/app/views/workflows/_versions.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/workflows/_versions.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/workflows/_versions.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,39 +0,0 @@
-<p>
-  <b>Earliest Version:</b><br/>
-  <%= versioned_workflow_link(workflow, workflow.versions.first.version ) %>
-	<div class="contribution_version_meta_info_box" style="margin-bottom: 0.6em;">
-		<%= render :partial => "version_meta", :locals => { :version => workflow.versions.first } %>
-	</div>
-</p>
-
-<% if @latest_version_number > 2 %>
-<p>
-  <b>Previous Versions:</b><br/>
-  <% (address@hidden).each do |v| %>
-		<% if (link = versioned_workflow_link(workflow, v)) %>
-    	<%= link %><br/>
-			<div class="contribution_version_meta_info_box" style="margin-bottom: 0.6em;">
-				<%= render :partial => "version_meta", :locals => { :version => workflow.find_version(v) } %>
-			</div>
-		<% else %>
-			<p>[<%= v.to_s %>] - <i>does not exist</i></p>
-		<% end %>
-  <% end %>
-</p>
-<% end %>
-
-<% if @latest_version_number > 1 %>
-  <p>
-    <b>Latest Version:</b><br/>
-    <%= versioned_workflow_link(workflow, @latest_version_number) %>
-		<div class="contribution_version_meta_info_box" style="margin-bottom: 0.6em;">
-			<%= render :partial => "version_meta", :locals => { :version => workflow.versions.last } %>
-		</div>
-  </p>
-<% end %>
-
-<% if workflow.versions.length == 1 %>
-  <p>
-    This Workflow only has one version.
-  </p>
-<% end %>

Modified: branches/wf4ever/app/views/workflows/galaxy/_run_options.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/workflows/galaxy/_run_options.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/workflows/galaxy/_run_options.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,4 +1,34 @@
-<p class="none_text">
-  Not implemented.
-</p>
+<% if session[:came_from] == 'galaxy' %>
+  <style type="text/css">
+    div.galaxy_import_form {
+      margin: 0.5em;
+      text-align: center;
+      border: 1px solid #D8B365;
+      font-family: Verdana, sans-serif;
+      padding-bottom: 0.5em;
+    }
 
+    div.galaxy_import_form div.header {
+      background-color: #EBD9B2;
+      border-bottom: 1px solid #D8B365;
+      font-weight: bold;
+      padding: 5px 10px;
+      color: #303030;
+      margin-bottom: 0.5em;
+    }
+  </style>
+
+  <div class="galaxy_import_form">
+    <div class="header">Import this workflow into Galaxy</div>
+    <form action="" session[:return_url].chomp("/") -%>/workflow/import_workflow" method="POST" name="import_workflow">
+      <input type="hidden" name="workflow_source" value="<%= Conf.sitename -%>"/>
+      <textarea name="workflow_text" style="display: none">
+        <%# Decode JSON and convert again to cut out formatting whitespace %>
+        <%= ActiveSupport::JSON.decode(@viewing_version.content_blob.data).to_json -%>
+      </textarea>
+      <input type="submit" value="Import" name="import_button"/>
+    </form>
+  </div>
+<% else %>
+  <p class="none_text">Not currently available.</p>
+<% end %>

Modified: branches/wf4ever/app/views/workflows/show.rhtml (3085 => 3086)


--- branches/wf4ever/app/views/workflows/show.rhtml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/app/views/workflows/show.rhtml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,13 +1,5 @@
 <% t "#{h @workflow.title} (#{h @workflow.contributor_name}) [#{h(@workflow.type_display_name)} Workflow]" -%>
 
-<script type="text/_javascript_">
-  function showWorkflowVersion(form) {
-    var url = ""
-		location.href = ""
-		form.submit
-  }
-</script>
-
 <ul class="sectionIcons">
 	<% if @authorised_to_edit -%>
 		<li><%= icon('new', new_version_workflow_path(@workflow), nil, nil, 'Upload New Version')%></li>
@@ -28,8 +20,6 @@
 
 <%= render :partial => "contributions/datetime_info", :locals => { :contributable => @workflow } -%>
 
-<!-- the code for 'selectTab()' should be refactored at some point to get -->
-<!-- tab name as a string, not it's ID; for now IDs are used -->
 <div class="contribution_mini_nav">
 	|
 	<%= link_to "License", "#license" %>
@@ -50,12 +40,12 @@
 	|
 	<br/>
 	|
-	<a href=""  (<%= @workflow.citations.length -%>)</a>
+	<a href="" (<%= @workflow.citations.length -%>)</a>
 	|
-	<a href=""  History</a>
-	|
+  <a href="" History</a>
+  |
 	<% if logged_in? and @workflow.owner?(current_user) %>
-	  <a href="" 
+	  <a href=""
 	  |
 	<% end %>
 	<%= link_to "Reviews (address@hidden)", "#reviews" %>
@@ -68,63 +58,9 @@
 <div class="contribution_left_box">
 	
 	<div class="contribution_version_box">
-		<div class="contribution_version_selector_box">
-			<table>
-				<tbody>
-					<tr>
-						<td class="heading" style="vertical-align: top;">
-							<%= info_icon_with_tooltip("This box shows version address@hidden of the Workflow file for this Workflow entry") -%>
-							<span><%= "Version address@hidden address@hidden(@viewing_version_number)}" -%></span>
-							<span class="count_text">(of <%= @workflow.versions.length -%>)</span>
-						  <a name="versions"></a>
-						</td>
-						<td>
-							<% if @latest_version_number > 1 %>
-	             	<form  return false;" style="text-align: right;">
-						    	<b>View version: </b>
-						    	<select id="workflow_versions" 
-							  		<% @workflow.versions.reverse.each do |w| %>
-							    		<option value="<%= versioned_workflow_url(@workflow, w.version.to_s) %>" <%= "selected" if w.version == @viewing_version_number -%>>
-							      			<%= "#{w.version.to_s} address@hidden(w.version)}" %>
-							    		</option>
-							  		<% end %>
-									</select>
-								</form>
-							<% end %>
-						</td>
-					</tr>
-				</tbody>
-			</table>
-			
-			<div id="version_info_box" style="color: #666666;	font-size: 85%; margin: 0.6em 0.5em 0.2em 0.5em; border-top: 1px solid #DDDDDD; padding-top: 0.4em;">
-				<p style="text-align: center;">
-					<b>Version created on:</b>
-					<span><%= datetime @viewing_version.created_at, false %></span>
-					<b>by:</b>
-					<span><%= contributor @viewing_version.contributor_id, @viewing_version.contributor_type %></span>
-					<span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
-					<span><%= link_to_function "Revision comments " + expand_image, visual_effect(:toggle_blind, "version_info_box_comments", :duration => 0.3) %></span>
-				</p>
-				
-				<% unless @viewing_version.created_at == @viewing_version.updated_at %>
-					<p style="text-align: center;">
-						<b>Last edited on:</b>
-						<span><%= datetime @viewing_version.updated_at, false %></span>
-						<b>by:</b>
-						<span><%= contributor @viewing_version.last_edited_by, "User" %></span>
-					</p>
-				<% end %>
-			</div>
-			
-			<div id="version_info_box_comments" style="display: none; border: 1px dotted #CCCCCC; padding: 0.3em 0.5em;">
-				<% unless @viewing_version.revision_comments.blank? -%>
-					<%= white_list @viewing_version.revision_comments %>
-				<% else %>
-					<p><i>None</i></p>
-				<% end %>
-			</div>
-		</div>
-		
+
+    <%= render(:partial => "contributions/version_selector", :locals => { :resource => @workflow, :version => @viewing_version, :path => :workflow_version_path }) %>
+
 		<% if @authorised_to_edit %>
 			<div style="margin-top: 1em;">
 				<ul class="sectionIcons" style="margin-top: 0.7em; margin-bottom: 0.6em;">
@@ -158,7 +94,7 @@
 				Preview
 			</h3>
 			
-			<% unless @viewing_version.image.nil? %>
+			<% unless @viewing_version.image.nil? && @viewing_version.svg.nil? %>
 				<p style="font-size: 85%; font-weight: normal; margin-bottom: 0.5em; text-align: center;">
 					 (Click on the image to get the full size)
 				</p>
@@ -251,7 +187,7 @@
 
 			<h3>
 				<%= info_icon_with_tooltip("This section provides options for running this version of the Workflow") %>
-				Run
+        <%= @viewing_version.content_type.title == "Galaxy" ? "Import" : "Run" %>
 			</h3>
 				
 			<% if @authorised_to_download %>
@@ -365,24 +301,23 @@
 
 <div id="tabsContainer" class="tabsContainer"></div>
 
-<a name="citations"></a>
 <%= render :partial => "contributions/citations_tab", :locals => { :item => @workflow } %>
 
-<a name="version_history"></a>
 <div class="tabContainer">
   <div class="tabTitle">Version History</div>
   <div class="tabContent">
-      <%= render :partial => "workflows/versions", :locals => { :workflow => @workflow } %>
+    <a name="version_history"></a>
+    <%= render :partial => "contributions/versions", :locals => { :resource => @workflow, :path => :workflow_version_path } %>
   </div>
 </div>
 
 <% if logged_in? and @workflow.owner?(current_user) %>
   
-	<a name="sharing"></a>
 	<div class="tabContainer">
     <div class="tabTitle">Sharing</div>
     <div class="tabContent">
 
+      <a name="sharing"></a>
       <%= render :partial => "contributions/sharing_summary",  :locals => { :contributable => @workflow } %>
       <%= render :partial => "contributions/updating_summary", :locals => { :contributable => @workflow } %>
 	  

Modified: branches/wf4ever/config/default_settings.yml (3085 => 3086)


--- branches/wf4ever/config/default_settings.yml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/config/default_settings.yml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -515,6 +515,169 @@
 #         - custom_stylesheet
 #       layout: layouts/myexperiment
 
+# deleted_data_directory - This is the directory where information about
+#                          deleted content is stored.
+#
+#                          Example:
+#
+#                            deleted_data_directory: spam/deleted/
+
+deleted_data_directory: ""
+
+# spam_patterns - These patterns are used to automatically hide users from
+#                 particular views, e.g. the timeline as they are likely to be
+#                 used at a later point by spammers.
+
+spam_patterns:
+
+  email:
+    - "[0-9]{2,address@hidden"
+
+# pivot_options - These control the joins, ordering and filtering of the pivot
+#                 views.
+
+pivot_options:
+
+  joins:
+
+    workflow_processors: INNER JOIN workflow_processors ON RESULT_TYPE = 'Workflow' AND workflow_processors.workflow_id = RESULT_ID
+    taggings: LEFT OUTER JOIN taggings ON RESULT_TYPE = taggings.taggable_type AND RESULT_ID = taggings.taggable_id
+    services: INNER JOIN services ON RESULT_TYPE = 'Service' AND RESULT_ID = services.id
+    curation_events: INNER JOIN curation_events ON curation_events.object_type = RESULT_TYPE AND curation_events.object_id = RESULT_ID
+    service_providers: INNER JOIN service_providers ON RESULT_TYPE = 'Service' AND service_providers.uri = services.provider_uri
+    tags: INNER JOIN tags ON taggings.tag_id = tags.id
+    content_types: LEFT OUTER JOIN content_types ON contributions.content_type_id = content_types.id
+    credits: INNER JOIN creditations ON creditations.creditable_type = RESULT_TYPE AND creditations.creditable_id = RESULT_ID
+    networks: INNER JOIN networks ON permissions.contributor_type = 'Network' AND permissions.contributor_id = networks.id
+    topic_workflow_map: INNER JOIN topic_workflow_map ON contributions.id = topic_workflow_map.workflow_id
+    users: INNER JOIN users ON contributions.contributor_type = 'User' AND contributions.contributor_id = users.id
+    licences: LEFT OUTER JOIN licenses ON contributions.license_id = licenses.id
+
+  order:
+
+  - option: rank
+    order: contributions.rank DESC
+    label: Rank
+
+  - option: title
+    order: contributions.label, contributions.rank DESC
+    label: Title
+
+  - option: latest
+    order: contributions.created_at DESC, contributions.rank DESC
+    label: Latest
+
+  - option: last_updated
+    order: contributions.updated_at DESC, contributions.rank DESC
+    label: Last updated
+
+  - option: member
+    joins: [users]
+    order: users.name, contributions.rank DESC
+    label: User
+
+  - option: rating
+    order: contributions.rating DESC, contributions.rank DESC
+    label: Community rating
+
+  - option: viewings
+    order: contributions.site_viewings_count DESC, contributions.rank DESC
+    label: Most viewed
+
+  - option: downloads
+    order: contributions.site_downloads_count DESC, contributions.rank DESC
+    label: Most downloaded
+
+  - option: type
+    joins: [content_types]
+    order: content_types.title, contributions.rank DESC
+    label: Type
+
+  - option: licence
+    joins: [licences]
+    order: licenses.title, contributions.rank DESC
+    label: Licence
+
+  - option: topic
+    joins: [topic_workflow_map]
+    order: topic_workflow_map.probability, rank DESC
+    label: Topic
+
+  filters:
+
+  - query_option: CATEGORY
+    title: category
+    id_column: :auth_type
+    label_column: :auth_type
+    visible_name: true
+
+  - query_option: TYPE_ID
+    title: type
+    id_column: content_types.id
+    label_column: content_types.title
+    joins: [content_types]
+    not_null: true
+
+  - query_option: TAG_ID
+    title: tag
+    id_column: tags.id
+    label_column: tags.name
+    joins: [taggings, tags]
+
+  - query_option: USER_ID
+    title: user
+    id_column: users.id
+    label_column: users.name
+    joins: [users]
+
+  - query_option: LICENSE_ID
+    title: licence
+    id_column: licenses.id
+    label_column: licenses.unique_name
+    joins: [licences]
+    not_null: true
+
+  - query_option: GROUP_ID
+    title: group
+    id_column: networks.id
+    label_column: networks.title
+    joins: [networks]
+
+  - query_option: WSDL_ENDPOINT
+    title: wsdl
+    id_column: workflow_processors.wsdl
+    label_column: workflow_processors.wsdl
+    joins: [workflow_processors]
+    not_null: true
+
+  - query_option: CURATION_EVENT
+    title: curation
+    id_column: curation_events.category
+    label_column: curation_events.category
+    joins: [curation_events]
+    capitalize: true
+
+  - query_option: SERVICE_PROVIDER
+    title: provider
+    id_column: service_providers.id
+    label_column: service_providers.name
+    joins: [services, service_providers]
+
+  - query_option: SERVICE_COUNTRY
+    title: country
+    id_column: services.country
+    label_column: services.country
+    joins: [services]
+
+  - query_option: SERVICE_STATUS
+    title: service status
+    id_column: services.monitor_label
+    label_column: services.monitor_label
+    joins: [services]
+
+  num_options: ["10", "20", "25", "50", "100"]
+
 research_object_endpoints:
 
   - http://sandbox.wf4ever-project.org/rosrs5/sparql
+

Modified: branches/wf4ever/config/environment.rb (3085 => 3086)


--- branches/wf4ever/config/environment.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/config/environment.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -54,7 +54,8 @@
     :recaptcha,
     :simile_timeline,
     :structured_data,
-    :validates_email_veracity_of
+    :validates_email_veracity_of,
+    :versioning
   ]
 
   # Skip frameworks you're not going to use. To use Rails without a database,

Modified: branches/wf4ever/config/routes.rb (3085 => 3086)


--- branches/wf4ever/config/routes.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/config/routes.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -132,6 +132,13 @@
   map.workflow_version           '/workflows/:id/versions/:version',         :conditions => { :method => :get }, :controller => 'workflows', :action ="" 'show'
   map.formatted_workflow_version '/workflows/:id/versions/:version.:format', :conditions => { :method => :get }, :controller => 'workflows', :action ="" 'show'
 
+  # blob redirect for linked data model
+  map.blob_version           '/files/:id/versions/:version',         :conditions => { :method => :get }, :controller => 'blobs', :action ="" 'show'
+  map.formatted_blob_version '/files/:id/versions/:version.:format', :conditions => { :method => :get }, :controller => 'blobs', :action ="" 'show'
+
+  map.blob_version_suggestions '/files/:id/versions/:version/suggestions', :conditions => { :method => :get }, :controller => 'blobs', :action ="" 'suggestions'
+  map.blob_version_process_suggestions '/files/:id/versions/:version/process_suggestions', :conditions => { :method => :post }, :controller => 'blobs', :action ="" 'process_suggestions'
+
   # versioned preview images
   ['workflow'].each do |x|
 
@@ -163,6 +170,8 @@
                  :favourite => :post,
                  :favourite_delete => :delete,
                  :rate => :post, 
+                 :suggestions => :get,
+                 :process_suggestions => :post,
                  :tag => :post } do |blob|
     # Due to restrictions in the version of Rails used (v1.2.3), 
     # we cannot have reviews as nested resources in more than one top level resource.
@@ -217,6 +226,8 @@
   # all users
   map.resources :users, 
     :collection => { :all => :get, 
+                     :check => :get,
+                     :change_status => :post,
                      :search => :get, 
                      :invite => :get } do |user|
 
@@ -274,6 +285,7 @@
   map.connect ':controller/:id/download/:name', :action ="" 'named_download', :requirements => { :name => /.*/ }
   
   map.connect 'files/:id/download/:name', :controller => 'blobs', :action ="" 'named_download', :requirements => { :name => /.*/ }
+  map.connect 'files/:id/versions/:version/download/:name', :controller => 'blobs', :action ="" 'named_download_with_version', :requirements => { :name => /.*/ }
 
   # map.connect 'topics', :controller => 'topics', :action ="" 'index'
   map.connect 'topics/tag_feedback', :controller => 'topics', :action ="" 'tag_feedback'
@@ -289,6 +301,13 @@
   map.resources :licenses
   map.resources :license_attributes
 
+  # Generate special alias routes for external sites point to
+  Conf.external_site_integrations.each_value do |data|
+    map.connect data["path"], data["redirect"].symbolize_keys #Convert string keys to symbols
+  end
+
+  map.connect 'clear_external_site_session_info', :controller => 'application', :action ="" 'clear_external_site_session_info'
+
   # Install the default route as the lowest priority.
   map.connect ':controller/:action/:id'
 end

Deleted: branches/wf4ever/config/schema.d/files.xml (3085 => 3086)


--- branches/wf4ever/config/schema.d/files.xml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/config/schema.d/files.xml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,21 +0,0 @@
-<?xml version="1.0"?>
-<schema>
-
-  <table name="blobs">
-
-    <column type="integer"  name="contributor_id"/>
-    <column type="string"   name="contributor_type"/>
-    <column type="string"   name="local_name"/>
-    <column type="datetime" name="created_at"/>
-    <column type="datetime" name="updated_at"/>
-    <column type="string"   name="title"/>
-    <column type="text"     name="body"/>
-    <column type="text"     name="body_html"/>
-    <column type="integer"  name="content_blob_id"/>
-    <column type="integer"  name="content_type_id"/>
-    <column type="integer"  name="license_id"/>
-
-  </table>
-
-</schema>
-

Modified: branches/wf4ever/config/schema.d/workflows.xml (3085 => 3086)


--- branches/wf4ever/config/schema.d/workflows.xml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/config/schema.d/workflows.xml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,28 +1,6 @@
 <?xml version="1.0"?>
 <schema>
 
-  <table name="workflows">
-
-    <column type="integer"    name="contributor_id"/>
-    <column type="string"     name="contributor_type"/>
-    <column type="string"     name="title"/>
-    <column type="string"     name="unique_name"/>
-    <column type="text"       name="body"/>
-    <column type="text"       name="body_html"/>
-    <column type="datetime"   name="created_at"/>
-    <column type="datetime"   name="updated_at"/>
-    <column type="string"     name="image"/>
-    <column type="string"     name="svg"/>
-    <column type="integer"    name="current_version"/>
-    <column type="integer"    name="content_blob_id"/>
-    <column type="string"     name="file_ext"/>
-    <column type="string"     name="last_edited_by"/>
-    <column type="integer"    name="content_type_id"/>
-    <column type="integer"    name="license_id"/>
-    <column type="integer"    name="preview_id"/>
-
-  </table>
-
   <table name="workflow_processors">
 
     <column type="integer"    name="workflow_id"/>

Modified: branches/wf4ever/config/tables.xml


(Binary files differ)

Modified: branches/wf4ever/db/migrate/012_create_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/012_create_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/012_create_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -5,18 +5,18 @@
 
 class CreateBlobs < ActiveRecord::Migration
   def self.up
-#   create_table :blobs do |t|
-#     t.column :contributor_id, :integer
-#     t.column :contributor_type, :string
-#     t.column :local_name, :string
-#     t.column :content_type, :string
-#     t.column :data, :binary
-#     t.column :created_at, :datetime
-#     t.column :updated_at, :datetime
-#   end
+    create_table :blobs do |t|
+      t.column :contributor_id, :integer
+      t.column :contributor_type, :string
+      t.column :local_name, :string
+      t.column :content_type, :string
+      t.column :data, :binary
+      t.column :created_at, :datetime
+      t.column :updated_at, :datetime
+    end
   end
 
   def self.down
-#   drop_table :blobs
+    drop_table :blobs
   end
 end

Modified: branches/wf4ever/db/migrate/013_create_workflows.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/013_create_workflows.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/013_create_workflows.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -5,27 +5,30 @@
 
 class CreateWorkflows < ActiveRecord::Migration
   def self.up
-#   create_table :workflows do |t|
-#     t.column :contributor_id, :integer
-#     t.column :contributor_type, :string
-#     
-#     t.column :scufl, :binary
-#     t.column :image, :string
-#     t.column :svg, :string
-#     
-#     t.column :title, :string
-#     t.column :unique_name, :string
-#     
-#     t.column :body, :text
-#     t.column :body_html, :text
-#     
-#     t.column :created_at, :datetime
-#     t.column :updated_at, :datetime
-#     
-#     t.column :license, :string, 
-#              :limit => 10, :null => false, 
-#              :default => "by-sa"
-#   end
+    create_table :workflows do |t|
+      t.column :contributor_id, :integer
+      t.column :contributor_type, :string
+      
+      t.column :scufl, :binary
+      t.column :image, :string
+      t.column :svg, :string
+      
+      t.column :title, :string
+      t.column :unique_name, :string
+      
+      t.column :body, :text
+      t.column :body_html, :text
+      
+      t.column :version, :integer
+      t.column :preview_id, :integer
+
+      t.column :created_at, :datetime
+      t.column :updated_at, :datetime
+      
+      t.column :license, :string, 
+               :limit => 10, :null => false, 
+               :default => "by-sa"
+    end
     
     create_table :workflow_versions do |t|
       t.column "workflow_id",       :integer
@@ -34,17 +37,11 @@
       t.column "contributor_type",  :string
       t.column "title",             :string
       t.column "unique_name",       :string
+      t.column "scufl",             :text
       t.column "body",              :text
       t.column "body_html",         :text
       t.column "created_at",        :datetime
       t.column "updated_at",        :datetime
-      t.column "image",             :string
-      t.column "svg",               :string
-      t.column "revision_comments", :text
-      t.column "content_blob_id",   :integer
-      t.column "file_ext",          :string
-      t.column "last_edited_by",    :string
-      t.column "content_type_id",   :integer
       t.column "license",           :string
       t.column "preview_id",        :integer
     end
@@ -53,7 +50,7 @@
   end
 
   def self.down
-#   drop_table :workflows
+    drop_table :workflows
     drop_table :workflow_versions
   end
 end

Modified: branches/wf4ever/db/migrate/029_modify_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/029_modify_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/029_modify_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,12 +1,12 @@
 
 class ModifyBlobs < ActiveRecord::Migration
   def self.up
-#   add_column :blobs, :title, :string
-#   add_column :blobs, :description, :text
+    add_column :blobs, :title, :string
+    add_column :blobs, :description, :text
   end
 
   def self.down
-#   remove_column :blobs, :title
-#   remove_column :blobs, :description
+    remove_column :blobs, :title
+    remove_column :blobs, :description
   end
 end

Modified: branches/wf4ever/db/migrate/030_add_license_to_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/030_add_license_to_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/030_add_license_to_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,10 +1,10 @@
 
 class AddLicenseToBlobs < ActiveRecord::Migration
   def self.up
-#   add_column :blobs, :license, :string, :limit => 10, :null => false, :default => "by-nd"
+    add_column :blobs, :license, :string, :limit => 10, :null => false, :default => "by-nd"
   end
 
   def self.down
-#   remove_column :blobs, :license
+    remove_column :blobs, :license
   end
 end

Modified: branches/wf4ever/db/migrate/031_rename_desc_to_body.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/031_rename_desc_to_body.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/031_rename_desc_to_body.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,12 +1,12 @@
 
 class RenameDescToBody < ActiveRecord::Migration
   def self.up
-#   rename_column :blobs, :description, :body
-#   add_column :blobs, :body_html, :text
+    rename_column :blobs, :description, :body
+    add_column :blobs, :body_html, :text
   end
 
   def self.down
-#   rename_column :blobs, :body, :description
-#   remove_column :blobs, :body_html
+    rename_column :blobs, :body, :description
+    remove_column :blobs, :body_html
   end
 end

Modified: branches/wf4ever/db/migrate/033_increase_blob_size.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/033_increase_blob_size.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/033_increase_blob_size.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,16 +1,16 @@
 
 class IncreaseBlobSize < ActiveRecord::Migration
   def self.up
-#   rename_column :blobs, :data, :temp
-#   add_column :blobs, :data, :binary, :limit => 1073741824
-#   execute 'UPDATE blobs SET data = ""
-#   remove_column :blobs, :temp
+    rename_column :blobs, :data, :temp
+    add_column :blobs, :data, :binary, :limit => 1073741824
+    execute 'UPDATE blobs SET data = ""
+    remove_column :blobs, :temp
   end
 
   def self.down
-#   rename_column :blobs, :data, :temp
-#   add_column :blobs, :data, :binary
-#   execute 'UPDATE blobs SET data = ""
-#   remove_column :blobs, :temp
+    rename_column :blobs, :data, :temp
+    add_column :blobs, :data, :binary
+    execute 'UPDATE blobs SET data = ""
+    remove_column :blobs, :temp
   end
 end

Modified: branches/wf4ever/db/migrate/034_update_for_new_versioning.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/034_update_for_new_versioning.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/034_update_for_new_versioning.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,17 +1,17 @@
 class UpdateForNewVersioning < ActiveRecord::Migration
   def self.up
-#   rename_column :workflows, :version, :current_version
+    rename_column :workflows, :version, :current_version
     
-#   add_column :workflow_versions, :image, :string
-#   add_column :workflow_versions, :svg, :string
-#   add_column :workflow_versions, :revision_comments, :text
+    add_column :workflow_versions, :image, :string
+    add_column :workflow_versions, :svg, :string
+    add_column :workflow_versions, :revision_comments, :text
   end
 
   def self.down
-#   rename_column :workflows, :current_version, :version
+    rename_column :workflows, :current_version, :version
     
-#   remove_column :workflow_versions, :image
-#   remove_column :workflow_versions, :svg
-#   remove_column :workflow_versions, :revision_comments
+    remove_column :workflow_versions, :image
+    remove_column :workflow_versions, :svg
+    remove_column :workflow_versions, :revision_comments
   end
 end

Modified: branches/wf4ever/db/migrate/035_increase_workflow_size.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/035_increase_workflow_size.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/035_increase_workflow_size.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,22 +1,22 @@
 
 class IncreaseWorkflowSize < ActiveRecord::Migration
   def self.up
-#   rename_column :workflows, :scufl, :temp
-#   add_column :workflows, :scufl, :binary, :limit => 1073741824
-#   execute 'UPDATE workflows SET scufl = temp'
-#   remove_column :workflows, :temp
+    rename_column :workflows, :scufl, :temp
+    add_column :workflows, :scufl, :binary, :limit => 1073741824
+    execute 'UPDATE workflows SET scufl = temp'
+    remove_column :workflows, :temp
 
-#   execute 'ALTER TABLE workflow_versions CHANGE COLUMN scufl scufl LONGBLOB'
+    execute 'ALTER TABLE workflow_versions CHANGE COLUMN scufl scufl LONGBLOB'
 
   end
 
   def self.down
-#   rename_column :workflows, :scufl, :temp
-#   add_column :workflows, :scufl, :binary
-#   execute 'UPDATE workflows SET scufl = temp'
-#   remove_column :workflows, :temp
+    rename_column :workflows, :scufl, :temp
+    add_column :workflows, :scufl, :binary
+    execute 'UPDATE workflows SET scufl = temp'
+    remove_column :workflows, :temp
 
-#   execute 'ALTER TABLE workflow_versions CHANGE COLUMN scufl scufl BLOB'
+    execute 'ALTER TABLE workflow_versions CHANGE COLUMN scufl scufl BLOB'
 
   end
 end

Modified: branches/wf4ever/db/migrate/046_add_type_to_workflows.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/046_add_type_to_workflows.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/046_add_type_to_workflows.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -2,16 +2,16 @@
 
 class AddTypeToWorkflows < ActiveRecord::Migration
   def self.up
-#   add_column :workflows, :content_type, :string
-#   add_column :workflow_versions, :content_type, :string
+    add_column :workflows, :content_type, :string
+    add_column :workflow_versions, :content_type, :string
 
-#   # Currently, all workflows are scufl workflows
-#   execute 'UPDATE workflows SET content_type = "application/vnd.taverna.scufl+xml"'
-#   execute 'UPDATE workflow_versions SET content_type = "application/vnd.taverna.scufl+xml"'
+    # Currently, all workflows are scufl workflows
+    execute 'UPDATE workflows SET content_type = "application/vnd.taverna.scufl+xml"'
+    execute 'UPDATE workflow_versions SET content_type = "application/vnd.taverna.scufl+xml"'
   end
 
   def self.down
-#   remove_column :workflows, :content_type
-#   remove_column :workflow_versions, :content_type
+    remove_column :workflows, :content_type
+    remove_column :workflow_versions, :content_type
   end
 end

Modified: branches/wf4ever/db/migrate/053_modify_blobs_for_content_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/053_modify_blobs_for_content_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/053_modify_blobs_for_content_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,9 +1,9 @@
 class ModifyBlobsForContentBlobs < ActiveRecord::Migration
   def self.up
-#   add_column :blobs, :content_blob_id, :integer
+    add_column :blobs, :content_blob_id, :integer
   end
 
   def self.down
-#   remove_column :blobs, :content_blob_id
+    remove_column :blobs, :content_blob_id
   end
 end

Modified: branches/wf4ever/db/migrate/054_move_blob_data_to_content_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/054_move_blob_data_to_content_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/054_move_blob_data_to_content_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,17 +1,17 @@
 class MoveBlobDataToContentBlobs < ActiveRecord::Migration
   def self.up
 
-#   Blob.find(:all).each do |b|
-#     b.content_blob = ContentBlob.new(:data ="" b.data)
-#     b.save
-#   end
+    Blob.find(:all).each do |b|
+      b.content_blob = ContentBlob.new(:data ="" b.data)
+      b.save
+    end
 
-#   remove_column :blobs, :data
+    remove_column :blobs, :data
   end
 
   def self.down
-#   add_column :blobs, :data, :binary, :limit => 1073741824
+    add_column :blobs, :data, :binary, :limit => 1073741824
 
-#   execute 'UPDATE blobs,content_blobs SET blobs.data = "" WHERE blobs.content_blob_id = content_blobs.id'
+    execute 'UPDATE blobs,content_blobs SET blobs.data = "" WHERE blobs.content_blob_id = content_blobs.id'
   end
 end

Modified: branches/wf4ever/db/migrate/055_modify_workflows_and_workflow_versions_for_content_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/055_modify_workflows_and_workflow_versions_for_content_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/055_modify_workflows_and_workflow_versions_for_content_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,11 +1,11 @@
 class ModifyWorkflowsAndWorkflowVersionsForContentBlobs < ActiveRecord::Migration
   def self.up
-#   add_column :workflows, :content_blob_id, :integer
-#   add_column :workflow_versions, :content_blob_id, :integer
+    add_column :workflows, :content_blob_id, :integer
+    add_column :workflow_versions, :content_blob_id, :integer
   end
 
   def self.down
-#   remove_column :workflows, :content_blob_id
-#   remove_column :workflow_versions, :content_blob_id
+    remove_column :workflows, :content_blob_id
+    remove_column :workflow_versions, :content_blob_id
   end
 end

Modified: branches/wf4ever/db/migrate/056_move_scufl_data_to_content_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/056_move_scufl_data_to_content_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/056_move_scufl_data_to_content_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,41 +1,41 @@
 class MoveScuflDataToContentBlobs < ActiveRecord::Migration
   def self.up
-#   ActiveRecord::Base.record_timestamps = false
+    ActiveRecord::Base.record_timestamps = false
 
-#   Workflow.find(:all).each do |w|
+    Workflow.find(:all).each do |w|
 
-#     w.versions.each do |wv|
-#       wv.content_blob = ContentBlob.new(:data ="" wv.scufl)
-#       wv.save
-#     end
+      w.versions.each do |wv|
+        wv.content_blob = ContentBlob.new(:data ="" wv.scufl)
+        wv.save
+      end
 
-#     current = w.find_version(w.current_version)
-#     w.content_blob = current.content_blob
+      current = w.find_version(w.current_version)
+      w.content_blob = current.content_blob
 
-#     w.save
-#   end
+      w.save
+    end
 
-#   remove_column :workflows, :scufl
-#   remove_column :workflow_versions, :scufl
+    remove_column :workflows, :scufl
+    remove_column :workflow_versions, :scufl
 
-#   ActiveRecord::Base.record_timestamps = true
+    ActiveRecord::Base.record_timestamps = true
   end
 
   def self.down
-#   ActiveRecord::Base.record_timestamps = false
+    ActiveRecord::Base.record_timestamps = false
 
-#   add_column :workflows, :scufl, :binary, :limit => 1073741824
-#   add_column :workflow_versions, :scufl, :binary, :limit => 1073741824
+    add_column :workflows, :scufl, :binary, :limit => 1073741824
+    add_column :workflow_versions, :scufl, :binary, :limit => 1073741824
 
-#   execute 'UPDATE workflows,content_blobs SET workflows.scufl = content_blobs.data WHERE workflows.content_blob_id = content_blobs.id'
-#   execute 'UPDATE workflow_versions,content_blobs SET workflow_versions.scufl = content_blobs.data WHERE workflow_versions.content_blob_id = content_blobs.id'
+    execute 'UPDATE workflows,content_blobs SET workflows.scufl = content_blobs.data WHERE workflows.content_blob_id = content_blobs.id'
+    execute 'UPDATE workflow_versions,content_blobs SET workflow_versions.scufl = content_blobs.data WHERE workflow_versions.content_blob_id = content_blobs.id'
 
-#   Workflow.find(:all).each do |w|
-#     w.versions.each do |wv|
-#       wv.content_blob.destroy
-#     end
-#   end
+    Workflow.find(:all).each do |w|
+      w.versions.each do |wv|
+        wv.content_blob.destroy
+      end
+    end
 
-#   ActiveRecord::Base.record_timestamps = true
+    ActiveRecord::Base.record_timestamps = true
   end
 end

Modified: branches/wf4ever/db/migrate/066_add_file_ext_to_workflow.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/066_add_file_ext_to_workflow.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/066_add_file_ext_to_workflow.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,15 +1,15 @@
 class AddFileExtToWorkflow < ActiveRecord::Migration
   def self.up
-#   add_column :workflows, :file_ext, :string
-#   add_column :workflow_versions, :file_ext, :string
+    add_column :workflows, :file_ext, :string
+    add_column :workflow_versions, :file_ext, :string
 
     # Currently, we assume that all workflows are scufl workflows!
-#   execute 'UPDATE workflows SET file_ext = "xml"'
-#   execute 'UPDATE workflow_versions SET file_ext = "xml"'
+    execute 'UPDATE workflows SET file_ext = "xml"'
+    execute 'UPDATE workflow_versions SET file_ext = "xml"'
   end
 
   def self.down
-#   remove_column :workflows, :file_ext
-#   remove_column :workflow_versions, :file_ext
+    remove_column :workflows, :file_ext
+    remove_column :workflow_versions, :file_ext
   end
 end

Modified: branches/wf4ever/db/migrate/067_add_last_edited_by_to_workflows.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/067_add_last_edited_by_to_workflows.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/067_add_last_edited_by_to_workflows.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,14 +1,14 @@
 class AddLastEditedByToWorkflows < ActiveRecord::Migration
   def self.up
-#   add_column :workflows, :last_edited_by, :string
-#   add_column :workflow_versions, :last_edited_by, :string
+    add_column :workflows, :last_edited_by, :string
+    add_column :workflow_versions, :last_edited_by, :string
     
-#   execute 'UPDATE workflows SET last_edited_by=contributor_id'
-#   execute 'UPDATE workflow_versions SET last_edited_by=contributor_id'
+    execute 'UPDATE workflows SET last_edited_by=contributor_id'
+    execute 'UPDATE workflow_versions SET last_edited_by=contributor_id'
   end
 
   def self.down
-#   remove_column :workflows, :last_edited_by
-#   remove_column :workflow_versions, :last_edited_by
+    remove_column :workflows, :last_edited_by
+    remove_column :workflow_versions, :last_edited_by
   end
 end

Modified: branches/wf4ever/db/migrate/076_create_content_types.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/076_create_content_types.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/076_create_content_types.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -15,9 +15,9 @@
 #     t.column :updated_at, :datetime
 #   end
 
-#   add_column :workflows,         :content_type_id, :integer
-#   add_column :workflow_versions, :content_type_id, :integer
-#   add_column :blobs,             :content_type_id, :integer
+    add_column :workflows,         :content_type_id, :integer
+    add_column :workflow_versions, :content_type_id, :integer
+    add_column :blobs,             :content_type_id, :integer
 
     # Create ContentType records for workflows with processors
 
@@ -94,20 +94,20 @@
 #     execute("UPDATE blobs SET content_type_id = #{blob_type_to_content_type_id[b.attributes["content_type"].strip]} WHERE id = #{b.id}")
 #   end
 
-#   remove_column :workflows,         :content_type
-#   remove_column :workflow_versions, :content_type
-#   remove_column :blobs,             :content_type
+    remove_column :workflows,         :content_type
+    remove_column :workflow_versions, :content_type
+  remove_column :blobs,             :content_type
   end
 
   def self.down
    
-#   add_column :workflows,         :content_type, :string
-#   add_column :workflow_versions, :content_type, :string
-#   add_column :blobs,             :content_type, :string
+    add_column :workflows,         :content_type, :string
+    add_column :workflow_versions, :content_type, :string
+  add_column :blobs,             :content_type, :string
 
-#   remove_column :workflows,         :content_type_id
-#   remove_column :workflow_versions, :content_type_id
-#   remove_column :blobs,             :content_type_id
+    remove_column :workflows,         :content_type_id
+    remove_column :workflow_versions, :content_type_id
+  remove_column :blobs,             :content_type_id
 
 #   drop_table :content_types
   end

Modified: branches/wf4ever/db/migrate/080_add_license_id_to_workflows_and_blobs.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/080_add_license_id_to_workflows_and_blobs.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/080_add_license_id_to_workflows_and_blobs.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,37 +1,37 @@
 class AddLicenseIdToWorkflowsAndBlobs < ActiveRecord::Migration
   def self.up
     #Need to rename columns so that license method and license field do not get confused
-#   rename_column :workflows, :license, :license_name
-#   rename_column :blobs, :license, :license_name
-#   
-#   add_column :workflows, :license_id, :integer, :default => nil
-#   add_column :blobs, :license_id, :integer, :default => nil
+    rename_column :workflows, :license, :license_name
+    rename_column :blobs, :license, :license_name
+
+    add_column :workflows, :license_id, :integer, :default => nil
+    add_column :blobs, :license_id, :integer, :default => nil
     
-#   Workflow.find(:all).each do |w|
-#     execute("UPDATE workflows SET license_id = #{License.find(:first,:conditions=>[ 'unique_name = ?', w.license_name ]).id } WHERE id = #{w.id}")
-#   end
-#   Blob.find(:all).each do |b|
-#     execute("UPDATE blobs SET license_id = #{License.find(:first,:conditions=>[ 'unique_name = ?', b.license_name ]).id } WHERE id = #{b.id}")
-#   end 
-#   remove_column :workflows, :license_name
-#   remove_column :blobs, :license_name
+    Workflow.find(:all).each do |w|
+      execute("UPDATE workflows SET license_id = #{License.find(:first,:conditions=>[ 'unique_name = ?', w.license_name ]).id } WHERE id = #{w.id}")
+    end
+    Blob.find(:all).each do |b|
+      execute("UPDATE blobs SET license_id = #{License.find(:first,:conditions=>[ 'unique_name = ?', b.license_name ]).id } WHERE id = #{b.id}")
+    end 
+    remove_column :workflows, :license_name
+    remove_column :blobs, :license_name
   end
   
   def self.down
-#   add_column :workflows, :license, :string, 
-#              :limit => 10, :null => false, 
-#              :default => "by-sa"
-#              
-#   add_column :blobs, :license, :string, 
-#              :limit => 10, :null => false, 
-#              :default => "by-sa"
-#   Workflow.find(:all).each do |w|
-#     execute("UPDATE workflows SET license = '#{License.find(w.license_id).unique_name }' WHERE id = #{w.id}")
-#   end
-#   Blob.find(:all).each do |b|
-#     execute("UPDATE blobs SET license = '#{License.find(b.license_id).unique_name }' WHERE id = #{b.id}")
-#   end
-#   remove_column :workflows, :license_id
-#   remove_column :blobs, :license_id
+    add_column :workflows, :license, :string, 
+               :limit => 10, :null => false, 
+               :default => "by-sa"
+
+    add_column :blobs, :license, :string, 
+               :limit => 10, :null => false, 
+               :default => "by-sa"
+    Workflow.find(:all).each do |w|
+      execute("UPDATE workflows SET license = '#{License.find(w.license_id).unique_name }' WHERE id = #{w.id}")
+    end
+    Blob.find(:all).each do |b|
+      execute("UPDATE blobs SET license = '#{License.find(b.license_id).unique_name }' WHERE id = #{b.id}")
+    end
+    remove_column :workflows, :license_id
+    remove_column :blobs, :license_id
   end
 end

Modified: branches/wf4ever/db/migrate/090_adjust_pictures.rb (3085 => 3086)


--- branches/wf4ever/db/migrate/090_adjust_pictures.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/migrate/090_adjust_pictures.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -20,7 +20,7 @@
       workflow_svg[workflow.id]   = workflow.svg_fc
     end
 
-    Workflow::Version.find(:all, :select => 'id, image AS image_fc, svg AS svg_fc').each do |workflow_version|
+    WorkflowVersion.find(:all, :select => 'id, image AS image_fc, svg AS svg_fc').each do |workflow_version|
       workflow_version_image[workflow_version.id] = workflow_version.image_fc
       workflow_version_svg[workflow_version.id]   = workflow_version.svg_fc
     end
@@ -44,7 +44,7 @@
       end
     end
       
-    Workflow::Version.find(:all).each do |workflow_version|
+    WorkflowVersion.find(:all).each do |workflow_version|
 
       if workflow_version_image[workflow_version.id] || workflow_version_svg[workflow_version.id]
 

Copied: branches/wf4ever/db/migrate/094_add_account_status_to_users.rb (from rev 3085, trunk/db/migrate/094_add_account_status_to_users.rb) (0 => 3086)


--- branches/wf4ever/db/migrate/094_add_account_status_to_users.rb	                        (rev 0)
+++ branches/wf4ever/db/migrate/094_add_account_status_to_users.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,15 @@
+# myExperiment: db/migrate/094_add_account_status_to_users.rb
+#
+# Copyright (c) 2012 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+class AddAccountStatusToUsers < ActiveRecord::Migration
+  def self.up
+    add_column :users, :account_status, :string
+  end
+
+  def self.down
+    remove_column :users, :account_status
+  end
+end
+

Copied: branches/wf4ever/db/migrate/095_add_spam_score_to_users.rb (from rev 3085, trunk/db/migrate/095_add_spam_score_to_users.rb) (0 => 3086)


--- branches/wf4ever/db/migrate/095_add_spam_score_to_users.rb	                        (rev 0)
+++ branches/wf4ever/db/migrate/095_add_spam_score_to_users.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,14 @@
+# myExperiment: db/migrate/095_add_spam_score_to_users.rb
+#
+# Copyright (c) 2012 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+class AddSpamScoreToUsers < ActiveRecord::Migration
+  def self.up
+    add_column :users, :spam_score, :integer
+  end
+
+  def self.down
+    remove_column :users, :spam_score
+  end
+end

Copied: branches/wf4ever/db/migrate/096_create_blob_versions.rb (from rev 3085, trunk/db/migrate/096_create_blob_versions.rb) (0 => 3086)


--- branches/wf4ever/db/migrate/096_create_blob_versions.rb	                        (rev 0)
+++ branches/wf4ever/db/migrate/096_create_blob_versions.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,36 @@
+# myExperiment: db/migrate/096_create_blob_versions.rb
+#
+# Copyright (c) 2012 University of Manchester and the University of Southampton.
+# See license.txt for details.
+
+class CreateBlobVersions < ActiveRecord::Migration
+
+  def self.up
+    create_table :blob_versions do |t|
+      t.integer  "blob_id"
+      t.integer  "version"
+      t.text     "revision_comments"
+      t.string   "title"
+      t.text     "body"
+      t.text     "body_html"
+      t.integer  "content_type_id"
+      t.integer  "content_blob_id"
+      t.string   "local_name"
+      t.datetime "created_at"
+      t.datetime "updated_at"
+    end
+
+    add_column :blobs, :current_version, :integer
+
+    execute "UPDATE blobs SET current_version = 1"
+
+    execute "INSERT INTO blob_versions (blob_id, version, title, body, body_html, content_type_id, content_blob_id, local_name, created_at, updated_at) SELECT id, 1, title, body, body_html, content_type_id, content_blob_id, local_name, created_at, updated_at FROM blobs"
+  end
+
+  def self.down
+    remove_column :blobs, :current_version
+
+    drop_table :blob_versions
+  end
+end
+

Modified: branches/wf4ever/db/schema.rb (3085 => 3086)


--- branches/wf4ever/db/schema.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/db/schema.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,816 +1,851 @@
-# This file is autogenerated. Instead of editing this file, please use the
-# migrations feature of ActiveRecord to incrementally modify your database, and
+# This file is auto-generated from the current state of the database. Instead of editing this file, 
+# please use the migrations feature of Active Record to incrementally modify your database, and
 # then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your database schema. If you need
+# to create the application database on another system, you should be using db:schema:load, not running
+# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 95) do
+ActiveRecord::Schema.define(:version => 20120605091404) do
 
   create_table "activity_limits", :force => true do |t|
-    t.column "contributor_type", :string,   :null => false
-    t.column "contributor_id",   :integer,  :null => false
-    t.column "limit_feature",    :string,   :null => false
-    t.column "limit_max",        :integer
-    t.column "limit_frequency",  :integer
-    t.column "current_count",    :integer,  :null => false
-    t.column "reset_after",      :datetime
-    t.column "promote_after",    :datetime
+    t.string   "contributor_type", :null => false
+    t.integer  "contributor_id",   :null => false
+    t.string   "limit_feature",    :null => false
+    t.integer  "limit_max"
+    t.integer  "limit_frequency"
+    t.integer  "current_count",    :null => false
+    t.datetime "reset_after"
+    t.datetime "promote_after"
   end
 
+  create_table "annotations", :force => true do |t|
+    t.integer  "research_object_id"
+    t.string   "subject_text"
+    t.string   "predicate_text"
+    t.string   "objekt_text"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
   create_table "announcements", :force => true do |t|
-    t.column "title",      :string
-    t.column "user_id",    :integer
-    t.column "created_at", :datetime
-    t.column "updated_at", :datetime
-    t.column "body",       :text
-    t.column "body_html",  :text
+    t.string   "title"
+    t.integer  "user_id"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.text     "body"
+    t.text     "body_html"
   end
 
   create_table "attributions", :force => true do |t|
-    t.column "attributor_id",     :integer
-    t.column "attributor_type",   :string
-    t.column "attributable_id",   :integer
-    t.column "attributable_type", :string
-    t.column "created_at",        :datetime
-    t.column "updated_at",        :datetime
+    t.integer  "attributor_id"
+    t.string   "attributor_type"
+    t.integer  "attributable_id"
+    t.string   "attributable_type"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "auto_tables", :force => true do |t|
-    t.column "name",   :string
-    t.column "schema", :text
+    t.string "name"
+    t.text   "schema"
   end
 
+  create_table "blob_versions", :force => true do |t|
+    t.integer  "blob_id"
+    t.integer  "version"
+    t.text     "revision_comments"
+    t.string   "title"
+    t.text     "body"
+    t.text     "body_html"
+    t.integer  "content_type_id"
+    t.integer  "content_blob_id"
+    t.string   "local_name"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
   create_table "blobs", :force => true do |t|
-    t.column "local_name",       :string
-    t.column "contributor_id",   :integer
-    t.column "body_html",        :text
-    t.column "created_at",       :datetime
-    t.column "body",             :text
-    t.column "title",            :string
-    t.column "content_blob_id",  :integer
-    t.column "updated_at",       :datetime
-    t.column "license_id",       :integer
-    t.column "content_type_id",  :integer
-    t.column "contributor_type", :string
+    t.datetime "updated_at"
+    t.string   "title"
+    t.integer  "content_blob_id"
+    t.string   "local_name"
+    t.text     "body"
+    t.integer  "content_type_id"
+    t.integer  "contributor_id"
+    t.datetime "created_at"
+    t.text     "body_html"
+    t.string   "contributor_type"
+    t.integer  "license_id"
+    t.integer  "current_version"
   end
 
   create_table "blog_posts", :force => true do |t|
-    t.column "blog_id",    :integer
-    t.column "title",      :string
-    t.column "body",       :text
-    t.column "created_at", :datetime
-    t.column "updated_at", :datetime
-    t.column "body_html",  :text
+    t.integer  "blog_id"
+    t.string   "title"
+    t.text     "body"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.text     "body_html"
   end
 
   create_table "blogs", :force => true do |t|
-    t.column "contributor_id",   :integer
-    t.column "contributor_type", :string
-    t.column "title",            :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.integer  "contributor_id"
+    t.string   "contributor_type"
+    t.string   "title"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "bookmarks", :force => true do |t|
-    t.column "title",             :string,   :limit => 50, :default => ""
-    t.column "created_at",        :datetime,                               :null => false
-    t.column "bookmarkable_type", :string,   :limit => 15, :default => "", :null => false
-    t.column "bookmarkable_id",   :integer,                :default => 0,  :null => false
-    t.column "user_id",           :integer,                :default => 0,  :null => false
+    t.string   "title",             :limit => 50, :default => ""
+    t.datetime "created_at",                                      :null => false
+    t.string   "bookmarkable_type", :limit => 15, :default => "", :null => false
+    t.integer  "bookmarkable_id",                 :default => 0,  :null => false
+    t.integer  "user_id",                         :default => 0,  :null => false
   end
 
   add_index "bookmarks", ["user_id"], :name => "index_bookmarks_on_user_id"
 
   create_table "citations", :force => true do |t|
-    t.column "user_id",          :integer
-    t.column "workflow_id",      :integer
-    t.column "workflow_version", :integer
-    t.column "authors",          :text
-    t.column "title",            :string
-    t.column "publication",      :string
-    t.column "published_at",     :datetime
-    t.column "accessed_at",      :datetime
-    t.column "url",              :string
-    t.column "isbn",             :string
-    t.column "issn",             :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.integer  "user_id"
+    t.integer  "workflow_id"
+    t.integer  "workflow_version"
+    t.text     "authors"
+    t.string   "title"
+    t.string   "publication"
+    t.datetime "published_at"
+    t.datetime "accessed_at"
+    t.string   "url"
+    t.string   "isbn"
+    t.string   "issn"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "client_applications", :force => true do |t|
-    t.column "name",         :string
-    t.column "url",          :string
-    t.column "support_url",  :string
-    t.column "callback_url", :string
-    t.column "key",          :string,   :limit => 50
-    t.column "secret",       :string,   :limit => 50
-    t.column "user_id",      :integer
-    t.column "key_type",     :string
-    t.column "created_at",   :datetime
-    t.column "updated_at",   :datetime
-    t.column "creator_id",   :integer
+    t.string   "name"
+    t.string   "url"
+    t.string   "support_url"
+    t.string   "callback_url"
+    t.string   "key",          :limit => 50
+    t.string   "secret",       :limit => 50
+    t.integer  "user_id"
+    t.string   "key_type"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.integer  "creator_id"
   end
 
   add_index "client_applications", ["key"], :name => "index_client_applications_on_key", :unique => true
 
   create_table "comments", :force => true do |t|
-    t.column "comment",          :text
-    t.column "created_at",       :datetime,                               :null => false
-    t.column "commentable_id",   :integer,                :default => 0,  :null => false
-    t.column "commentable_type", :string,   :limit => 15, :default => "", :null => false
-    t.column "user_id",          :integer,                :default => 0,  :null => false
+    t.text     "comment"
+    t.datetime "created_at",                                     :null => false
+    t.integer  "commentable_id",                 :default => 0,  :null => false
+    t.string   "commentable_type", :limit => 15, :default => "", :null => false
+    t.integer  "user_id",                        :default => 0,  :null => false
   end
 
   add_index "comments", ["user_id"], :name => "index_comments_on_user_id"
 
   create_table "concept_relations", :force => true do |t|
-    t.column "subject_concept_id", :integer
-    t.column "relation_type",      :string
-    t.column "object_concept_id",  :integer
+    t.string  "relation_type"
+    t.integer "object_concept_id"
+    t.integer "subject_concept_id"
   end
 
   create_table "concepts", :force => true do |t|
-    t.column "vocabulary_id",    :integer
-    t.column "created_at",       :datetime
-    t.column "description_html", :text
-    t.column "updated_at",       :datetime
-    t.column "phrase",           :string
-    t.column "description",      :text
+    t.datetime "updated_at"
+    t.text     "description_html"
+    t.text     "description"
+    t.string   "phrase"
+    t.datetime "created_at"
+    t.integer  "vocabulary_id"
   end
 
   create_table "content_blobs", :force => true do |t|
-    t.column "data", :binary
+    t.binary "data", :limit => 2147483647
+    t.string "md5",  :limit => 32
+    t.string "sha1", :limit => 40
   end
 
   create_table "content_types", :force => true do |t|
-    t.column "created_at",       :datetime
-    t.column "category",         :string
-    t.column "description_html", :text
-    t.column "title",            :string
-    t.column "updated_at",       :datetime
-    t.column "mime_type",        :string
-    t.column "user_id",          :integer
-    t.column "description",      :text
+    t.datetime "updated_at"
+    t.text     "description_html"
+    t.text     "description"
+    t.string   "title"
+    t.datetime "created_at"
+    t.string   "mime_type"
+    t.integer  "user_id"
+    t.string   "category"
   end
 
   create_table "contributions", :force => true do |t|
-    t.column "label",                :string
-    t.column "rating",               :float
-    t.column "contributable_type",   :string
-    t.column "contributor_id",       :integer
-    t.column "created_at",           :datetime
-    t.column "policy_id",            :integer
-    t.column "updated_at",           :datetime
-    t.column "license_id",           :integer
-    t.column "rank",                 :float
-    t.column "content_type_id",      :integer
-    t.column "site_downloads_count", :integer,  :default => 0
-    t.column "viewings_count",       :integer,  :default => 0
-    t.column "contributor_type",     :string
-    t.column "downloads_count",      :integer,  :default => 0
-    t.column "site_viewings_count",  :integer,  :default => 0
-    t.column "contributable_id",     :integer
-    t.column "layout",               :string
+    t.string   "layout"
+    t.datetime "updated_at"
+    t.string   "contributable_type"
+    t.string   "label"
+    t.float    "rating"
+    t.integer  "policy_id"
+    t.integer  "viewings_count",       :default => 0
+    t.integer  "site_downloads_count", :default => 0
+    t.integer  "content_type_id"
+    t.integer  "contributor_id"
+    t.integer  "contributable_id"
+    t.float    "rank"
+    t.integer  "site_viewings_count",  :default => 0
+    t.integer  "downloads_count",      :default => 0
+    t.datetime "created_at"
+    t.string   "contributor_type"
+    t.integer  "license_id"
   end
 
   add_index "contributions", ["contributable_id", "contributable_type"], :name => "index_contributions_on_contributable_id_and_contributable_type"
   add_index "contributions", ["contributor_id", "contributor_type"], :name => "index_contributions_on_contributor_id_and_contributor_type"
 
   create_table "creditations", :force => true do |t|
-    t.column "creditor_id",     :integer
-    t.column "creditor_type",   :string
-    t.column "creditable_id",   :integer
-    t.column "creditable_type", :string
-    t.column "created_at",      :datetime
-    t.column "updated_at",      :datetime
+    t.integer  "creditor_id"
+    t.string   "creditor_type"
+    t.integer  "creditable_id"
+    t.string   "creditable_type"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "curation_events", :force => true do |t|
-    t.column "user_id",      :integer
-    t.column "category",     :string
-    t.column "object_type",  :string
-    t.column "object_id",    :integer
-    t.column "details",      :text
-    t.column "details_html", :text
-    t.column "created_at",   :datetime
-    t.column "updated_at",   :datetime
+    t.integer  "user_id"
+    t.string   "category"
+    t.string   "object_type"
+    t.integer  "object_id"
+    t.text     "details"
+    t.text     "details_html"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
-  create_table "data_sets", :force => true do |t|
-    t.column "workflow_id", :integer
-    t.column "title",       :string
-    t.column "description", :text
-  end
-
   create_table "downloads", :force => true do |t|
-    t.column "kind",               :string
-    t.column "created_at",         :datetime
-    t.column "accessed_from_site", :boolean,  :default => false
-    t.column "user_id",            :integer
-    t.column "user_agent",         :string
-    t.column "contribution_id",    :integer
+    t.string   "kind"
+    t.string   "user_agent"
+    t.integer  "contribution_id"
+    t.datetime "created_at"
+    t.integer  "user_id"
+    t.boolean  "accessed_from_site", :default => false
   end
 
   add_index "downloads", ["contribution_id"], :name => "index_downloads_on_contribution_id"
 
   create_table "experiments", :force => true do |t|
-    t.column "title",            :string
-    t.column "description",      :text
-    t.column "description_html", :text
-    t.column "contributor_id",   :integer
-    t.column "contributor_type", :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.string   "title"
+    t.text     "description"
+    t.text     "description_html"
+    t.integer  "contributor_id"
+    t.string   "contributor_type"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "federation_sources", :force => true do |t|
-    t.column "name", :string
+    t.string "name"
   end
 
   create_table "friendships", :force => true do |t|
-    t.column "user_id",     :integer
-    t.column "friend_id",   :integer
-    t.column "created_at",  :datetime
-    t.column "accepted_at", :datetime
-    t.column "message",     :string,   :limit => 500
+    t.integer  "user_id"
+    t.integer  "friend_id"
+    t.datetime "created_at"
+    t.datetime "accepted_at"
+    t.string   "message",     :limit => 500
   end
 
   add_index "friendships", ["friend_id"], :name => "index_friendships_on_friend_id"
   add_index "friendships", ["user_id"], :name => "index_friendships_on_user_id"
 
   create_table "group_announcements", :force => true do |t|
-    t.column "title",      :string
-    t.column "network_id", :integer
-    t.column "user_id",    :integer
-    t.column "public",     :boolean,  :default => false
-    t.column "created_at", :datetime
-    t.column "updated_at", :datetime
-    t.column "body",       :text
-    t.column "body_html",  :text
+    t.string   "title"
+    t.integer  "network_id"
+    t.integer  "user_id"
+    t.boolean  "public",     :default => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.text     "body"
+    t.text     "body_html"
   end
 
   create_table "jobs", :force => true do |t|
-    t.column "title",            :string
-    t.column "description",      :text
-    t.column "description_html", :text
-    t.column "experiment_id",    :integer
-    t.column "user_id",          :integer
-    t.column "runnable_id",      :integer
-    t.column "runnable_version", :integer
-    t.column "runnable_type",    :string
-    t.column "runner_id",        :integer
-    t.column "runner_type",      :string
-    t.column "submitted_at",     :datetime
-    t.column "started_at",       :datetime
-    t.column "completed_at",     :datetime
-    t.column "last_status",      :string
-    t.column "last_status_at",   :datetime
-    t.column "job_uri",          :string
-    t.column "job_manifest",     :binary
-    t.column "inputs_uri",       :string
-    t.column "inputs_data",      :binary
-    t.column "outputs_uri",      :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
-    t.column "parent_job_id",    :integer
+    t.string   "title"
+    t.text     "description"
+    t.text     "description_html"
+    t.integer  "experiment_id"
+    t.integer  "user_id"
+    t.integer  "runnable_id"
+    t.integer  "runnable_version"
+    t.string   "runnable_type"
+    t.integer  "runner_id"
+    t.string   "runner_type"
+    t.datetime "submitted_at"
+    t.datetime "started_at"
+    t.datetime "completed_at"
+    t.string   "last_status"
+    t.datetime "last_status_at"
+    t.string   "job_uri"
+    t.binary   "job_manifest",     :limit => 2147483647
+    t.string   "inputs_uri"
+    t.binary   "inputs_data",      :limit => 2147483647
+    t.string   "outputs_uri"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.integer  "parent_job_id"
   end
 
   create_table "key_permissions", :force => true do |t|
-    t.column "client_application_id", :integer
-    t.column "for",                   :string
+    t.integer "client_application_id"
+    t.string  "for"
   end
 
   create_table "labels", :force => true do |t|
-    t.column "vocabulary_id", :integer
-    t.column "language",      :string
-    t.column "text",          :string
-    t.column "label_type",    :string
-    t.column "concept_id",    :integer
+    t.integer "concept_id"
+    t.string  "label_type"
+    t.string  "text"
+    t.integer "vocabulary_id"
+    t.string  "language"
   end
 
   create_table "license_attributes", :force => true do |t|
-    t.column "license_id",        :integer
-    t.column "license_option_id", :integer
-    t.column "created_at",        :datetime
+    t.integer  "license_id"
+    t.integer  "license_option_id"
+    t.datetime "created_at"
   end
 
   create_table "license_options", :force => true do |t|
-    t.column "user_id",          :integer
-    t.column "title",            :string
-    t.column "description",      :text
-    t.column "description_html", :text
-    t.column "uri",              :string
-    t.column "predicate",        :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.integer  "user_id"
+    t.string   "title"
+    t.text     "description"
+    t.text     "description_html"
+    t.string   "uri"
+    t.string   "predicate"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "licenses", :force => true do |t|
-    t.column "user_id",          :integer
-    t.column "unique_name",      :string
-    t.column "title",            :string
-    t.column "description",      :text
-    t.column "description_html", :text
-    t.column "url",              :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.integer  "user_id"
+    t.string   "unique_name"
+    t.string   "title"
+    t.text     "description"
+    t.text     "description_html"
+    t.string   "url"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "memberships", :force => true do |t|
-    t.column "user_id",                :integer
-    t.column "network_id",             :integer
-    t.column "created_at",             :datetime
-    t.column "user_established_at",    :datetime
-    t.column "network_established_at", :datetime
-    t.column "message",                :string,   :limit => 500
-    t.column "administrator",          :boolean,                 :default => false
+    t.integer  "user_id"
+    t.integer  "network_id"
+    t.datetime "created_at"
+    t.datetime "user_established_at"
+    t.datetime "network_established_at"
+    t.string   "message",                :limit => 500
+    t.boolean  "administrator",                         :default => false
   end
 
   add_index "memberships", ["network_id"], :name => "index_memberships_on_network_id"
   add_index "memberships", ["user_id"], :name => "index_memberships_on_user_id"
 
   create_table "messages", :force => true do |t|
-    t.column "from",                 :integer
-    t.column "to",                   :integer
-    t.column "subject",              :string
-    t.column "body",                 :text
-    t.column "reply_id",             :integer
-    t.column "created_at",           :datetime
-    t.column "read_at",              :datetime
-    t.column "body_html",            :text
-    t.column "deleted_by_sender",    :boolean,  :default => false
-    t.column "deleted_by_recipient", :boolean,  :default => false
+    t.integer  "from"
+    t.integer  "to"
+    t.string   "subject"
+    t.text     "body"
+    t.integer  "reply_id"
+    t.datetime "created_at"
+    t.datetime "read_at"
+    t.text     "body_html"
+    t.boolean  "deleted_by_sender",    :default => false
+    t.boolean  "deleted_by_recipient", :default => false
   end
 
   create_table "networks", :force => true do |t|
-    t.column "user_id",           :integer
-    t.column "title",             :string
-    t.column "unique_name",       :string
-    t.column "created_at",        :datetime
-    t.column "updated_at",        :datetime
-    t.column "description",       :text
-    t.column "description_html",  :text
-    t.column "new_member_policy", :string,   :default => "open"
-    t.column "inviter_id",        :integer
+    t.integer  "user_id"
+    t.string   "title"
+    t.string   "unique_name"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.text     "description"
+    t.text     "description_html"
+    t.string   "new_member_policy", :default => "open"
+    t.integer  "inviter_id"
   end
 
   add_index "networks", ["user_id"], :name => "index_networks_on_user_id"
 
   create_table "oauth_nonces", :force => true do |t|
-    t.column "nonce",      :string
-    t.column "timestamp",  :integer
-    t.column "created_at", :datetime
-    t.column "updated_at", :datetime
+    t.string   "nonce"
+    t.integer  "timestamp"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "oauth_nonces", ["nonce", "timestamp"], :name => "index_oauth_nonces_on_nonce_and_timestamp", :unique => true
 
   create_table "oauth_tokens", :force => true do |t|
-    t.column "user_id",               :integer
-    t.column "type",                  :string,   :limit => 20
-    t.column "client_application_id", :integer
-    t.column "token",                 :string,   :limit => 50
-    t.column "secret",                :string,   :limit => 50
-    t.column "authorized_at",         :datetime
-    t.column "invalidated_at",        :datetime
-    t.column "created_at",            :datetime
-    t.column "updated_at",            :datetime
+    t.integer  "user_id"
+    t.string   "type",                  :limit => 20
+    t.integer  "client_application_id"
+    t.string   "token",                 :limit => 50
+    t.string   "secret",                :limit => 50
+    t.datetime "authorized_at"
+    t.datetime "invalidated_at"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "oauth_tokens", ["token"], :name => "index_oauth_tokens_on_token", :unique => true
 
   create_table "ontologies", :force => true do |t|
-    t.column "created_at",       :datetime
-    t.column "description_html", :text
-    t.column "uri",              :string
-    t.column "prefix",           :string
-    t.column "title",            :string
-    t.column "updated_at",       :datetime
-    t.column "user_id",          :integer
-    t.column "description",      :text
+    t.datetime "updated_at"
+    t.text     "description_html"
+    t.text     "description"
+    t.string   "title"
+    t.string   "uri"
+    t.string   "prefix"
+    t.datetime "created_at"
+    t.integer  "user_id"
   end
 
   create_table "pack_contributable_entries", :force => true do |t|
-    t.column "comment",               :text
-    t.column "contributable_type",    :string
-    t.column "contributable_version", :integer
-    t.column "created_at",            :datetime
-    t.column "updated_at",            :datetime
-    t.column "pack_id",               :integer,  :null => false
-    t.column "user_id",               :integer,  :null => false
-    t.column "contributable_id",      :integer,  :null => false
+    t.datetime "updated_at"
+    t.string   "contributable_type"
+    t.integer  "contributable_version"
+    t.integer  "pack_id",               :null => false
+    t.integer  "contributable_id",      :null => false
+    t.datetime "created_at"
+    t.integer  "user_id",               :null => false
+    t.text     "comment"
   end
 
   create_table "pack_remote_entries", :force => true do |t|
-    t.column "comment",       :text
-    t.column "created_at",    :datetime
-    t.column "uri",           :string
-    t.column "title",         :string
-    t.column "updated_at",    :datetime
-    t.column "pack_id",       :integer,  :null => false
-    t.column "user_id",       :integer,  :null => false
-    t.column "alternate_uri", :string
+    t.datetime "updated_at"
+    t.string   "uri"
+    t.string   "title"
+    t.integer  "pack_id",       :null => false
+    t.string   "alternate_uri"
+    t.datetime "created_at"
+    t.integer  "user_id",       :null => false
+    t.text     "comment"
   end
 
   create_table "packs", :force => true do |t|
-    t.column "contributor_id",   :integer
-    t.column "created_at",       :datetime
-    t.column "description_html", :text
-    t.column "title",            :string
-    t.column "updated_at",       :datetime
-    t.column "description",      :text
-    t.column "contributor_type", :string
+    t.datetime "updated_at"
+    t.text     "description_html"
+    t.text     "description"
+    t.string   "title"
+    t.integer  "contributor_id"
+    t.datetime "created_at"
+    t.string   "contributor_type"
   end
 
   create_table "pending_invitations", :force => true do |t|
-    t.column "email",        :string
-    t.column "created_at",   :datetime
-    t.column "request_type", :string
-    t.column "requested_by", :integer
-    t.column "request_for",  :integer
-    t.column "message",      :string,   :limit => 500
-    t.column "token",        :string
+    t.string   "email"
+    t.datetime "created_at"
+    t.string   "request_type"
+    t.integer  "requested_by"
+    t.integer  "request_for"
+    t.string   "message",      :limit => 500
+    t.string   "token"
   end
 
   create_table "permissions", :force => true do |t|
-    t.column "contributor_id",   :integer
-    t.column "contributor_type", :string
-    t.column "policy_id",        :integer
-    t.column "download",         :boolean,  :default => false
-    t.column "edit",             :boolean,  :default => false
-    t.column "view",             :boolean,  :default => false
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.integer  "contributor_id"
+    t.string   "contributor_type"
+    t.integer  "policy_id"
+    t.boolean  "download",         :default => false
+    t.boolean  "edit",             :default => false
+    t.boolean  "view",             :default => false
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "permissions", ["policy_id"], :name => "index_permissions_on_policy_id"
 
   create_table "picture_selections", :force => true do |t|
-    t.column "user_id",    :integer
-    t.column "picture_id", :integer
-    t.column "created_at", :datetime
+    t.integer  "user_id"
+    t.integer  "picture_id"
+    t.datetime "created_at"
   end
 
   create_table "pictures", :force => true do |t|
-    t.column "data",    :binary
-    t.column "user_id", :integer
+    t.binary  "data",    :limit => 16777215
+    t.integer "user_id"
   end
 
   create_table "policies", :force => true do |t|
-    t.column "name",             :string
-    t.column "contributor_id",   :integer
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
-    t.column "update_mode",      :integer
-    t.column "share_mode",       :integer
-    t.column "contributor_type", :string
-    t.column "public_view",      :boolean,  :default => false
-    t.column "public_download",  :boolean,  :default => false
+    t.datetime "updated_at"
+    t.boolean  "public_download",  :default => false
+    t.integer  "update_mode"
+    t.integer  "share_mode"
+    t.integer  "contributor_id"
+    t.string   "name"
+    t.boolean  "public_view",      :default => false
+    t.datetime "created_at"
+    t.string   "contributor_type"
   end
 
   create_table "predicates", :force => true do |t|
-    t.column "created_at",       :datetime
-    t.column "description_html", :text
-    t.column "title",            :string
-    t.column "ontology_id",      :integer
-    t.column "updated_at",       :datetime
-    t.column "phrase",           :string
-    t.column "equivalent_to",    :text
-    t.column "description",      :text
+    t.datetime "updated_at"
+    t.text     "description_html"
+    t.text     "description"
+    t.string   "phrase"
+    t.string   "title"
+    t.text     "equivalent_to"
+    t.datetime "created_at"
+    t.integer  "ontology_id"
   end
 
   create_table "previews", :force => true do |t|
-    t.column "created_at",    :datetime
-    t.column "svg_blob_id",   :integer
-    t.column "image_blob_id", :integer
+    t.integer  "svg_blob_id"
+    t.datetime "created_at"
+    t.integer  "image_blob_id"
   end
 
   create_table "profiles", :force => true do |t|
-    t.column "user_id",             :integer
-    t.column "picture_id",          :integer
-    t.column "email",               :string
-    t.column "website",             :string
-    t.column "created_at",          :datetime
-    t.column "updated_at",          :datetime
-    t.column "body",                :text
-    t.column "body_html",           :text
-    t.column "field_or_industry",   :string
-    t.column "occupation_or_roles", :string
-    t.column "organisations",       :text
-    t.column "location_city",       :string
-    t.column "location_country",    :string
-    t.column "interests",           :text
-    t.column "contact_details",     :text
+    t.integer  "user_id"
+    t.integer  "picture_id"
+    t.string   "email"
+    t.string   "website"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.text     "body"
+    t.text     "body_html"
+    t.string   "field_or_industry"
+    t.string   "occupation_or_roles"
+    t.text     "organisations"
+    t.string   "location_city"
+    t.string   "location_country"
+    t.text     "interests"
+    t.text     "contact_details"
   end
 
   add_index "profiles", ["user_id"], :name => "index_profiles_on_user_id"
 
   create_table "ratings", :force => true do |t|
-    t.column "rating",        :integer,                :default => 0
-    t.column "created_at",    :datetime,                               :null => false
-    t.column "rateable_type", :string,   :limit => 15, :default => "", :null => false
-    t.column "rateable_id",   :integer,                :default => 0,  :null => false
-    t.column "user_id",       :integer,                :default => 0,  :null => false
+    t.integer  "rating",                      :default => 0
+    t.datetime "created_at",                                  :null => false
+    t.string   "rateable_type", :limit => 15, :default => "", :null => false
+    t.integer  "rateable_id",                 :default => 0,  :null => false
+    t.integer  "user_id",                     :default => 0,  :null => false
   end
 
   add_index "ratings", ["user_id"], :name => "index_ratings_on_user_id"
 
   create_table "relationships", :force => true do |t|
-    t.column "context_id",   :integer
-    t.column "created_at",   :datetime
-    t.column "context_type", :string
-    t.column "objekt_type",  :string
-    t.column "objekt_id",    :integer
-    t.column "subject_id",   :integer
-    t.column "predicate_id", :integer
-    t.column "subject_type", :string
-    t.column "user_id",      :integer
+    t.string   "context_type"
+    t.string   "subject_type"
+    t.string   "objekt_type"
+    t.integer  "subject_id"
+    t.integer  "context_id"
+    t.datetime "created_at"
+    t.integer  "predicate_id"
+    t.integer  "user_id"
+    t.integer  "objekt_id"
   end
 
   create_table "remote_workflows", :force => true do |t|
-    t.column "workflow_id",        :integer
-    t.column "workflow_version",   :integer
-    t.column "taverna_enactor_id", :integer
-    t.column "workflow_uri",       :string
+    t.integer "workflow_id"
+    t.integer "workflow_version"
+    t.integer "taverna_enactor_id"
+    t.string  "workflow_uri"
   end
 
+  create_table "research_objects", :force => true do |t|
+    t.string   "title"
+    t.text     "description"
+    t.text     "description_html"
+    t.text     "url"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.integer  "content_blob_id"
+    t.integer  "contributor_id"
+    t.string   "contributor_type"
+  end
+
   create_table "reviews", :force => true do |t|
-    t.column "title",           :string,                 :default => ""
-    t.column "review",          :text
-    t.column "created_at",      :datetime,                               :null => false
-    t.column "updated_at",      :datetime,                               :null => false
-    t.column "reviewable_id",   :integer,                :default => 0,  :null => false
-    t.column "reviewable_type", :string,   :limit => 15, :default => "", :null => false
-    t.column "user_id",         :integer,                :default => 0,  :null => false
+    t.string   "title",                         :default => ""
+    t.text     "review"
+    t.datetime "created_at",                                    :null => false
+    t.datetime "updated_at",                                    :null => false
+    t.integer  "reviewable_id",                 :default => 0,  :null => false
+    t.string   "reviewable_type", :limit => 15, :default => "", :null => false
+    t.integer  "user_id",                       :default => 0,  :null => false
   end
 
   add_index "reviews", ["user_id"], :name => "index_reviews_on_user_id"
 
   create_table "service_categories", :force => true do |t|
-    t.column "label",        :string
-    t.column "uri",          :string
-    t.column "retrieved_at", :datetime
-    t.column "created_at",   :datetime
-    t.column "updated_at",   :datetime
-    t.column "service_id",   :integer
+    t.datetime "updated_at"
+    t.string   "label"
+    t.string   "uri"
+    t.datetime "retrieved_at"
+    t.integer  "service_id"
+    t.datetime "created_at"
   end
 
   create_table "service_deployments", :force => true do |t|
-    t.column "service_provider_id",  :integer
-    t.column "iso3166_country_code", :string
-    t.column "city",                 :string
-    t.column "submitter_label",      :string
-    t.column "uri",                  :string
-    t.column "retrieved_at",         :datetime
-    t.column "created_at",           :datetime
-    t.column "submitter_uri",        :string
-    t.column "country",              :string
-    t.column "updated_at",           :datetime
-    t.column "service_id",           :integer
-    t.column "flag_url",             :string
-    t.column "created",              :datetime
-    t.column "endpoint",             :string
+    t.string   "iso3166_country_code"
+    t.datetime "updated_at"
+    t.datetime "created"
+    t.string   "flag_url"
+    t.string   "uri"
+    t.datetime "retrieved_at"
+    t.integer  "service_provider_id"
+    t.string   "endpoint"
+    t.integer  "service_id"
+    t.string   "submitter_label"
+    t.string   "country"
+    t.string   "submitter_uri"
+    t.datetime "created_at"
+    t.string   "city"
   end
 
   create_table "service_providers", :force => true do |t|
-    t.column "name",         :string
-    t.column "uri",          :string
-    t.column "retrieved_at", :datetime
-    t.column "created_at",   :datetime
-    t.column "updated_at",   :datetime
-    t.column "description",  :text
-    t.column "created",      :datetime
+    t.text     "description"
+    t.datetime "updated_at"
+    t.datetime "created"
+    t.string   "uri"
+    t.datetime "retrieved_at"
+    t.string   "name"
+    t.datetime "created_at"
   end
 
   create_table "service_tags", :force => true do |t|
-    t.column "label",        :string
-    t.column "uri",          :string
-    t.column "retrieved_at", :datetime
-    t.column "created_at",   :datetime
-    t.column "updated_at",   :datetime
-    t.column "service_id",   :integer
+    t.datetime "updated_at"
+    t.string   "label"
+    t.string   "uri"
+    t.datetime "retrieved_at"
+    t.integer  "service_id"
+    t.datetime "created_at"
   end
 
   create_table "service_types", :force => true do |t|
-    t.column "label",        :string
-    t.column "retrieved_at", :datetime
-    t.column "created_at",   :datetime
-    t.column "updated_at",   :datetime
-    t.column "service_id",   :integer
+    t.datetime "updated_at"
+    t.string   "label"
+    t.datetime "retrieved_at"
+    t.integer  "service_id"
+    t.datetime "created_at"
   end
 
   create_table "services", :force => true do |t|
-    t.column "iso3166_country_code",     :string
-    t.column "city",                     :string
-    t.column "name",                     :string
-    t.column "contributor_id",           :integer
-    t.column "submitter_label",          :string
-    t.column "uri",                      :string
-    t.column "retrieved_at",             :datetime
-    t.column "created_at",               :datetime
-    t.column "monitor_symbol_url",       :string
-    t.column "country",                  :string
-    t.column "submitter_uri",            :string
-    t.column "updated_at",               :datetime
-    t.column "monitor_message",          :text
-    t.column "monitor_label",            :string
-    t.column "monitor_last_checked",     :datetime
-    t.column "monitor_small_symbol_url", :string
-    t.column "description",              :text
-    t.column "flag_url",                 :string
-    t.column "wsdl",                     :string
-    t.column "provider_label",           :string
-    t.column "contributor_type",         :string
-    t.column "documentation_uri",        :string
-    t.column "endpoint",                 :string
-    t.column "provider_uri",             :string
-    t.column "created",                  :datetime
+    t.text     "description"
+    t.string   "documentation_uri"
+    t.string   "iso3166_country_code"
+    t.datetime "updated_at"
+    t.string   "flag_url"
+    t.string   "provider_label"
+    t.datetime "created"
+    t.string   "uri"
+    t.text     "monitor_message"
+    t.datetime "monitor_last_checked"
+    t.string   "monitor_symbol_url"
+    t.datetime "retrieved_at"
+    t.integer  "contributor_id"
+    t.string   "endpoint"
+    t.string   "name"
+    t.string   "country"
+    t.string   "submitter_label"
+    t.string   "submitter_uri"
+    t.datetime "created_at"
+    t.string   "wsdl"
+    t.string   "contributor_type"
+    t.string   "city"
+    t.string   "monitor_small_symbol_url"
+    t.string   "monitor_label"
+    t.string   "provider_uri"
   end
 
   create_table "sessions", :force => true do |t|
-    t.column "session_id", :string
-    t.column "data",       :text
-    t.column "updated_at", :datetime
+    t.string   "session_id"
+    t.text     "data"
+    t.datetime "updated_at"
   end
 
   add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
   add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
 
   create_table "taggings", :force => true do |t|
-    t.column "tag_id",        :integer
-    t.column "taggable_id",   :integer
-    t.column "taggable_type", :string
-    t.column "user_id",       :integer
-    t.column "created_at",    :datetime
+    t.integer  "tag_id"
+    t.integer  "taggable_id"
+    t.string   "taggable_type"
+    t.integer  "user_id"
+    t.datetime "created_at"
   end
 
   add_index "taggings", ["tag_id", "taggable_type"], :name => "index_taggings_on_tag_id_and_taggable_type"
+  add_index "taggings", ["taggable_id", "taggable_type"], :name => "index_taggings_on_taggable_id_and_taggable_type"
   add_index "taggings", ["user_id", "tag_id", "taggable_type"], :name => "index_taggings_on_user_id_and_tag_id_and_taggable_type"
-  add_index "taggings", ["taggable_id", "taggable_type"], :name => "index_taggings_on_taggable_id_and_taggable_type"
   add_index "taggings", ["user_id", "taggable_id", "taggable_type"], :name => "index_taggings_on_user_id_and_taggable_id_and_taggable_type"
 
   create_table "tags", :force => true do |t|
-    t.column "name",             :string
-    t.column "taggings_count",   :integer,  :default => 0, :null => false
-    t.column "vocabulary_id",    :integer
-    t.column "description",      :text
-    t.column "description_html", :text
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.string   "name"
+    t.integer  "taggings_count",   :default => 0, :null => false
+    t.integer  "vocabulary_id"
+    t.text     "description"
+    t.text     "description_html"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   add_index "tags", ["name"], :name => "index_tags_on_name"
   add_index "tags", ["taggings_count"], :name => "index_tags_on_taggings_count"
 
   create_table "taverna_enactors", :force => true do |t|
-    t.column "title",            :string
-    t.column "description",      :text
-    t.column "contributor_id",   :integer
-    t.column "contributor_type", :string
-    t.column "url",              :string
-    t.column "username",         :string
-    t.column "crypted_password", :string
-    t.column "created_at",       :datetime
-    t.column "updated_at",       :datetime
+    t.string   "title"
+    t.text     "description"
+    t.integer  "contributor_id"
+    t.string   "contributor_type"
+    t.string   "url"
+    t.string   "username"
+    t.string   "crypted_password"
+    t.datetime "created_at"
+    t.datetime "updated_at"
   end
 
   create_table "topic_feedbacks", :force => true do |t|
-    t.column "submit_dt", :datetime
-    t.column "user_id",   :integer
-    t.column "score",     :integer
-    t.column "topic_id",  :integer
+    t.integer  "score"
+    t.integer  "topic_id"
+    t.datetime "submit_dt"
+    t.integer  "user_id"
   end
 
   create_table "topic_runs", :force => true do |t|
-    t.column "runtime",     :datetime
-    t.column "description", :string
+    t.string   "description"
+    t.datetime "runtime"
   end
 
   create_table "topic_tag_map", :force => true do |t|
-    t.column "display_flag", :boolean
-    t.column "tag_id",       :integer
-    t.column "topic_id",     :integer
-    t.column "probability",  :float
+    t.boolean "display_flag"
+    t.float   "probability"
+    t.integer "tag_id"
+    t.integer "topic_id"
   end
 
   create_table "topic_workflow_map", :force => true do |t|
-    t.column "display_flag", :boolean
-    t.column "workflow_id",  :integer
-    t.column "topic_id",     :integer
-    t.column "probability",  :float
+    t.boolean "display_flag"
+    t.float   "probability"
+    t.integer "workflow_id"
+    t.integer "topic_id"
   end
 
   create_table "topics", :force => true do |t|
-    t.column "name",        :string
-    t.column "orig_run_id", :integer
-    t.column "run_id",      :integer
+    t.integer "orig_run_id"
+    t.integer "run_id"
+    t.string  "name"
   end
 
   create_table "user_reports", :force => true do |t|
-    t.column "report",       :text
-    t.column "created_at",   :datetime
-    t.column "subject_id",   :integer
-    t.column "subject_type", :string
-    t.column "user_id",      :integer
-    t.column "content",      :text
+    t.text     "content"
+    t.string   "subject_type"
+    t.text     "report"
+    t.integer  "subject_id"
+    t.datetime "created_at"
+    t.integer  "user_id"
   end
 
   create_table "users", :force => true do |t|
-    t.column "openid_url",                :string
-    t.column "name",                      :string
-    t.column "created_at",                :datetime
-    t.column "updated_at",                :datetime
-    t.column "last_seen_at",              :datetime
-    t.column "username",                  :string
-    t.column "crypted_password",          :string,   :limit => 40
-    t.column "salt",                      :string,   :limit => 40
-    t.column "remember_token",            :string
-    t.column "remember_token_expires_at", :datetime
-    t.column "downloads_count",           :integer,                :default => 0
-    t.column "viewings_count",            :integer,                :default => 0
-    t.column "email",                     :string
-    t.column "unconfirmed_email",         :string
-    t.column "email_confirmed_at",        :datetime
-    t.column "activated_at",              :datetime
-    t.column "receive_notifications",     :boolean,                :default => true
-    t.column "reset_password_code",       :string
-    t.column "reset_password_code_until", :datetime
+    t.string   "openid_url"
+    t.string   "name"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.datetime "last_seen_at"
+    t.string   "username"
+    t.string   "crypted_password",          :limit => 40
+    t.string   "salt",                      :limit => 40
+    t.string   "remember_token"
+    t.datetime "remember_token_expires_at"
+    t.integer  "downloads_count",                         :default => 0
+    t.integer  "viewings_count",                          :default => 0
+    t.string   "email"
+    t.string   "unconfirmed_email"
+    t.datetime "email_confirmed_at"
+    t.datetime "activated_at"
+    t.boolean  "receive_notifications",                   :default => true
+    t.string   "reset_password_code"
+    t.datetime "reset_password_code_until"
+    t.string   "account_status"
+    t.integer  "spam_score"
   end
 
   create_table "viewings", :force => true do |t|
-    t.column "contribution_id",    :integer
-    t.column "user_id",            :integer
-    t.column "created_at",         :datetime
-    t.column "user_agent",         :string
-    t.column "accessed_from_site", :boolean,  :default => false
+    t.integer  "contribution_id"
+    t.integer  "user_id"
+    t.datetime "created_at"
+    t.string   "user_agent"
+    t.boolean  "accessed_from_site", :default => false
   end
 
   add_index "viewings", ["contribution_id"], :name => "index_viewings_on_contribution_id"
 
   create_table "vocabularies", :force => true do |t|
-    t.column "created_at",       :datetime
-    t.column "description_html", :text
-    t.column "uri",              :string
-    t.column "prefix",           :string
-    t.column "title",            :string
-    t.column "updated_at",       :datetime
-    t.column "user_id",          :integer
-    t.column "description",      :text
+    t.datetime "updated_at"
+    t.text     "description_html"
+    t.text     "description"
+    t.string   "title"
+    t.string   "uri"
+    t.string   "prefix"
+    t.datetime "created_at"
+    t.integer  "user_id"
   end
 
-  create_table "workflow_ports", :force => true do |t|
-    t.column "workflow_id", :integer
-    t.column "port_type",   :string
-    t.column "name",        :string
-  end
-
   create_table "workflow_processors", :force => true do |t|
-    t.column "name",           :string
-    t.column "wsdl_operation", :string
-    t.column "workflow_id",    :integer
-    t.column "wsdl",           :string
+    t.string  "name"
+    t.string  "wsdl_operation"
+    t.integer "workflow_id"
+    t.string  "wsdl"
   end
 
   create_table "workflow_versions", :force => true do |t|
-    t.column "contributor_id",    :integer
-    t.column "revision_comments", :text
-    t.column "created_at",        :datetime
-    t.column "body_html",         :text
-    t.column "body",              :text
-    t.column "title",             :string
-    t.column "content_blob_id",   :integer
-    t.column "license",           :string
-    t.column "updated_at",        :datetime
-    t.column "last_edited_by",    :string
-    t.column "svg",               :string
-    t.column "unique_name",       :string
-    t.column "content_type_id",   :integer
-    t.column "version",           :integer
-    t.column "workflow_id",       :integer
-    t.column "contributor_type",  :string
-    t.column "preview_id",        :integer
-    t.column "image",             :string
-    t.column "file_ext",          :string
+    t.integer  "workflow_id"
+    t.integer  "version"
+    t.integer  "contributor_id"
+    t.string   "contributor_type"
+    t.string   "title"
+    t.string   "unique_name"
+    t.text     "body"
+    t.text     "body_html"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+    t.string   "image"
+    t.string   "svg"
+    t.text     "revision_comments"
+    t.integer  "content_blob_id"
+    t.string   "file_ext"
+    t.string   "last_edited_by"
+    t.integer  "content_type_id"
+    t.string   "license"
+    t.integer  "preview_id"
   end
 
   add_index "workflow_versions", ["workflow_id"], :name => "index_workflow_versions_on_workflow_id"
 
   create_table "workflows", :force => true do |t|
-    t.column "contributor_id",   :integer
-    t.column "created_at",       :datetime
-    t.column "body_html",        :text
-    t.column "body",             :text
-    t.column "title",            :string
-    t.column "content_blob_id",  :integer
-    t.column "updated_at",       :datetime
-    t.column "last_edited_by",   :string
-    t.column "svg",              :string
-    t.column "license_id",       :integer
-    t.column "unique_name",      :string
-    t.column "content_type_id",  :integer
-    t.column "current_version",  :integer
-    t.column "contributor_type", :string
-    t.column "preview_id",       :integer
-    t.column "image",            :string
-    t.column "file_ext",         :string
+    t.datetime "updated_at"
+    t.string   "unique_name"
+    t.string   "image"
+    t.string   "title"
+    t.integer  "content_blob_id"
+    t.text     "body"
+    t.integer  "content_type_id"
+    t.integer  "current_version"
+    t.integer  "contributor_id"
+    t.integer  "preview_id"
+    t.string   "svg"
+    t.string   "file_ext"
+    t.datetime "created_at"
+    t.text     "body_html"
+    t.string   "contributor_type"
+    t.string   "last_edited_by"
+    t.integer  "license_id"
   end
 
 end

Modified: branches/wf4ever/lib/authenticated_system.rb (3085 => 3086)


--- branches/wf4ever/lib/authenticated_system.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/authenticated_system.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -128,6 +128,15 @@
       end
     end
 
+    # Allows single requests to be authenticated using HTTP basic authentication
+    # (Used by Taverna, and possibly other REST clients when attempting to remotely open a private workflow)
+    def login_from_basic_auth
+      return if logged_in?
+      unless (credentials = get_auth_data).first.nil?
+        self.current_user = User.authenticate(credentials[0], credentials[1])
+      end
+    end
+
   private
     @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)
     # gets BASIC auth info

Modified: branches/wf4ever/lib/authorization.rb (3085 => 3086)


--- branches/wf4ever/lib/authorization.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/authorization.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -602,11 +602,11 @@
 
   def Authorization.categorize_action(action_name)
     case action_name
-      when 'show', 'index', 'view', 'search', 'favourite', 'favourite_delete', 'comment', 'comment_delete', 'comments', 'comments_timeline', 'rate', 'tag',  'items', 'statistics', 'curation', 'tag_suggestions', 'extra_metadata', 'read', 'verify'
+      when 'show', 'index', 'view', 'search', 'favourite', 'favourite_delete', 'comment', 'comment_delete', 'comments', 'comments_timeline', 'rate', 'tag',  'items', 'statistics', 'curation', 'suggestions', 'tag_suggestions', 'extra_metadata', 'read', 'verify'
         action = ''
-      when 'edit', 'new', 'create', 'update', 'new_version', 'create_version', 'destroy_version', 'edit_version', 'update_version', 'new_item', 'create_item', 'edit_item', 'update_item', 'quick_add', 'resolve_link', 'process_tag_suggestions', 'process_extra_metadata', 'edit_relationships'
+      when 'edit', 'new', 'create', 'update', 'new_version', 'create_version', 'destroy_version', 'edit_version', 'update_version', 'new_item', 'create_item', 'edit_item', 'update_item', 'quick_add', 'resolve_link', 'process_suggestions', 'process_tag_suggestions', 'process_extra_metadata', 'edit_relationships'
         action = ''
-      when 'download', 'named_download', 'launch', 'submit_job', 'save_inputs', 'refresh_status', 'rerun', 'refresh_outputs', 'render_output', 'outputs_xml', 'outputs_package', 'galaxy_tool', 'galaxy_tool_download'
+      when 'download', 'named_download', 'named_download_with_version', 'launch', 'submit_job', 'save_inputs', 'refresh_status', 'rerun', 'refresh_outputs', 'render_output', 'outputs_xml', 'outputs_package', 'galaxy_tool', 'galaxy_tool_download'
         action = ''
       when 'destroy', 'delete', 'destroy_item'
         action = ''
@@ -894,9 +894,9 @@
     end
   end
 
-  def self.authorised_index(model, *args)
+  def self.scoped(model, opts = {})
 
-    def self.view_conditions(user_id = nil, friends = nil, networks = nil)
+    def self.view_conditions(user_id, friends, networks)
 
       return "((contributions.id IS NULL) OR (share_mode = 0 OR share_mode = 1 OR share_mode = 2))" if user_id.nil?
 
@@ -909,7 +909,7 @@
       "((contributions.id IS NULL) OR (#{policy_part} OR #{permission_part(['view', 'download', 'edit'], user_id, networks)}))"
     end
 
-    def self.download_conditions(user_id = nil, friends = nil, networks = nil)
+    def self.download_conditions(user_id, friends, networks)
 
       return "((contributions.id IS NULL) OR (share_mode = 0))" if user_id.nil?
 
@@ -922,7 +922,7 @@
       "((contributions.id IS NULL) OR (#{policy_part} OR #{permission_part(['download', 'edit'], user_id, networks)}))"
     end
 
-    def self.edit_conditions(user_id = nil, friends = nil, networks = nil)
+    def self.edit_conditions(user_id, friends, networks)
 
       return "((contributions.id IS NULL) OR (share_mode = 0 AND update_mode = 0))" if user_id.nil?
 
@@ -944,15 +944,8 @@
          (permissions.contributor_type = 'Network' AND permissions.contributor_id IN #{networks})))"
     end
 
-    # extract the opts hash
-
-    opts = args.last.class == Hash ? args.pop.clone : {}
-
     user = opts.delete(:authorised_user)
 
-    joins      = []
-    conditions = []
-
     if (user != 0) && (user != nil)
 
       user_id = user.id
@@ -966,71 +959,44 @@
       networks = network_ids.empty? ? "(-1)" : "(#{network_ids.join(",")})"
     end
 
-    # filtering
+    # By default, the objects to authorize are the actual objects that the
+    # association returns.  However you can specify an alternate type/id if
+    # this is different.
+    #
+    # For example, the association might return Taggings but Tagging objects do
+    # not support authorization in themselves but by association with the
+    # taggable association.
+    #
+    # In thie case, :auth_type would be "taggings.taggable_type" and :auth_id
+    # authorize would be "taggings.taggable_id".
 
     auth_id   = opts.delete(:auth_id)   || "#{model.table_name}.id"
     auth_type = opts.delete(:auth_type) || "'#{model.name}'"
 
-    conditions.push(view_conditions(user_id, friends, networks))
-    conditions.push("contributions.contributable_type = #{auth_type}") if !opts.delete(:arbitrary_models) && model != Contribution
+    # Joins
 
-    # result model
+    joins = []
 
-    if opts.delete(:contribution_records)
-      model = Contribution
-    end
-
-    if model != Contribution
-      joins.push("LEFT OUTER JOIN contributions ON contributions.contributable_id = #{auth_id} AND contributions.contributable_type = #{auth_type}")
-    end
-
-    # selection
-
-    opts[:select] = "#{model.table_name}.*" unless opts[:select]
-
-    # add in the extra joins needed for the authorisation checks
-
+    joins.push("LEFT OUTER JOIN contributions ON contributions.contributable_id = #{auth_id} AND contributions.contributable_type = #{auth_type}") if model != Contribution
     joins.push("LEFT OUTER JOIN policies ON contributions.policy_id = policies.id")
-    joins.push("LEFT OUTER JOIN permissions ON policies.id = permissions.policy_id") if user_id || opts[:include_permissions]
+    joins.push("LEFT OUTER JOIN permissions ON policies.id = permissions.policy_id")
 
-    # include the effective permissions in the result?
+    # Include the effective permissions in the result?
 
     if opts.delete(:include_permissions)
 
+      opts[:select] = "#{model.table_name}.*"
+
       opts[:select] << ", BIT_OR(#{view_conditions(user_id, friends, networks)})     AS view_permission"
       opts[:select] << ", BIT_OR(#{download_conditions(user_id, friends, networks)}) AS download_permission"
       opts[:select] << ", BIT_OR(#{edit_conditions(user_id, friends, networks)})     AS edit_permission"
     end
 
-    # merge the joins
-
-    if joins.length > 0
-      opts[:joins] = [] unless opts[:joins]
-      opts[:joins] = [opts[:joins]] unless opts[:joins].class == Array
-      opts[:joins] = joins + opts[:joins]
-      opts[:joins] = opts[:joins].join(" ") # Rails 1 does not support arrays here
-    end
-
-    # merge the conditions
-
-    if conditions.length > 0
-
-      conditions = conditions.map do |c| "(#{c})" end
-
-      case opts[:conditions].class.name
-        when "Array";  opts[:conditions][0] = "(#{([opts[:conditions][0]] + conditions).join(') AND (')})"
-        when "String"; opts[:conditions]    = "(#{([opts[:conditions]] + conditions).join(') AND (')})"
-        else;          opts[:conditions]    = "(#{conditions.join(') AND (')})"
-      end
-    end
-
-    # default to grouping by contributable type and id
-
+    opts[:conditions] = view_conditions(user_id, friends, networks)
     opts[:group] ||= 'contributions.contributable_type, contributions.contributable_id'
+    opts[:joins] = joins
 
-    # do it
-
-    model.find(*args + [opts])
+    model.scoped(opts)
   end
 end
 

Modified: branches/wf4ever/lib/bio_catalogue_import.rb (3085 => 3086)


--- branches/wf4ever/lib/bio_catalogue_import.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/bio_catalogue_import.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -109,13 +109,7 @@
 
     service.save if service.changed?
 
-    if service.contribution.policy.nil?
-      service.contribution = Contribution.create(:contributor => @federation_source)
-      service.contribution.policy = create_default_policy(@federation_source)
-      service.contribution.policy.share_mode = 0 # Make public
-      service.contribution.policy.save
-      service.contribution.save
-    end
+    service.contribution.policy.update_attribute(:share_mode, 0) if service.contribution.policy.share_mode != 0
 
     # Service categories
 
@@ -325,7 +319,7 @@
 
     @federation_source = FederationSource.find_by_name("BioCatalogue")
 
-    import_biocatalogue_services("http://www.biocatalogue.org/services?include=summary,deployments&sort_order=asc")
+    import_biocatalogue_services("#{@@biocat_base_uri}services?include=summary,deployments&sort_order=asc")
   end
 end
 

Modified: branches/wf4ever/lib/conf.rb (3085 => 3086)


--- branches/wf4ever/lib/conf.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/conf.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -181,11 +181,27 @@
     self.fetch_entry('duplicable_mime_types')
   end
 
+  def self.deleted_data_directory
+    self.fetch_entry('deleted_data_directory')
+  end
+
+  def self.spam_patterns
+    self.fetch_entry('spam_patterns')
+  end
+
   def self.layouts
     layouts = self.fetch_entry('layouts', {})
     layouts.delete_if {|k,v| v["environment"] && (v["environment"] != ENV["RAILS_ENV"])}
   end
 
+  def self.external_site_integrations
+    self.fetch_entry('site_integrations',{})
+  end
+
+  def self.pivot_options
+    self.fetch_entry('pivot_options', {})
+  end
+
   def self.research_object_endpoints
     self.fetch_entry('research_object_endpoints')
   end

Deleted: branches/wf4ever/lib/explicit_versioning.rb (3085 => 3086)


--- branches/wf4ever/lib/explicit_versioning.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/explicit_versioning.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1,380 +0,0 @@
-module Jits
-  module Acts
-    # Based heavily on the acts_as_versioned plugin
-    module ExplicitVersioning
-      CALLBACKS = [:sync_latest_version]
-      def self.included(mod) # :nodoc:
-        mod.extend(ClassMethods)
-      end
-      
-      module ClassMethods
-        def explicit_versioning(options = {}, &extension)
-          # don't allow multiple calls
-          return if self.included_modules.include?(Jits::Acts::ExplicitVersioning::ActMethods)
-          
-          send :include, Jits::Acts::ExplicitVersioning::ActMethods
-          
-          cattr_accessor :versioned_class_name, :versioned_foreign_key, :versioned_table_name, :versioned_inheritance_column, 
-            :version_column, :version_sequence_name, :non_versioned_columns, :file_columns, :extra_attributes, :white_list_columns, :revision_comments_column, 
-            :version_association_options, :timestamp_columns, :sync_ignore_columns
-            
-          self.versioned_class_name         = options[:class_name]  || "Version"
-          self.versioned_foreign_key        = options[:foreign_key] || self.to_s.foreign_key
-          self.versioned_table_name         = options[:table_name]  || "#{table_name_prefix}#{base_class.name.demodulize.underscore}_versions#{table_name_suffix}"
-          self.versioned_inheritance_column = options[:inheritance_column] || "versioned_#{inheritance_column}"
-          self.version_column               = options[:version_column]     || 'version'
-          self.non_versioned_columns        = [self.primary_key, inheritance_column, 'version', 'lock_version', versioned_inheritance_column, version_column]
-          self.file_columns                 = options[:file_columns] || []
-          self.extra_attributes             = options[:extra_attributes] || []
-          self.white_list_columns           = options[:white_list_columns] || []
-          self.revision_comments_column     = options[:revision_comments_column]  || "revision_comments"
-          self.version_association_options  = {
-                                                :class_name  => "#{self.to_s}::#{versioned_class_name}",
-                                                :foreign_key => "#{versioned_foreign_key}",
-                                                :order       => 'version',
-                                                :dependent   => :destroy
-                                              }.merge(options[:association_options] || {})
-          self.timestamp_columns            = options[:timestamp_columns]  || [ "created_at", "updated_at" ]
-          self.sync_ignore_columns          = options[:sync_ignore_columns]  || []
-                                                      
-          class_eval do
-            has_many :versions, version_association_options
-            
-            before_create :set_new_version
-            after_create :save_version_on_create
-            after_update :sync_latest_version
-          end
-
-          # create the dynamic versioned model
-          const_set(versioned_class_name, Class.new(ActiveRecord::Base)).class_eval do
-            def self.reloadable? ; false ; end
-          end
-          
-          versioned_resource = self.to_s.demodulize.underscore.to_sym
-
-          versioned_class.set_table_name versioned_table_name
-          versioned_class.belongs_to versioned_resource, 
-            :class_name  => "::#{self.to_s}", 
-            :foreign_key => versioned_foreign_key
-
-          versioned_class.class_eval("alias_method :versioned_resource, :#{versioned_resource}")
-
-          if block_given?
-            versioned_class.class_eval(&extension)
-          end
-
-        end
-      end
-      
-      module ActMethods
-        def self.included(base) # :nodoc:
-          base.extend ClassMethods
-        end
-        
-        # Finds a specific version of this model.
-        def find_version(version)
-          return version if version.is_a?(self.class.versioned_class)
-          return nil if version.is_a?(ActiveRecord::Base)
-          find_versions(:conditions => ['version = ?', version], :limit => 1).first
-        end
-        
-        # Finds versions of this model.  Takes an options hash like <tt>find</tt>
-        def find_versions(options = {})
-          versions.find(:all, options)
-        end
-        
-        # Saves the object as a new version and also saves the original object as the new version.
-        # Make sure to create (and thus save) any inner associations beforehand as these won't be saved here.
-        def save_as_new_version(revision_comment=nil)
-          return false unless self.valid?
-          without_update_callbacks do 
-            set_new_version
-            save_version_on_create(revision_comment)
-            self.save
-          end
-        end
-        
-        def update_version(version_number_to_update, attributes)
-          return false if version_number_to_update.nil? or version_number_to_update.to_i < 1
-          return false if attributes.nil? or attributes.empty?
-          return false unless (ver = find_version(version_number_to_update))
-          
-          rtn = ver.update_attributes(attributes)
-          
-          if rtn
-            # if the latest version has been updated then update the main table as well
-            if version_number_to_update.to_i == eval("#{self.class.version_column}")
-              return update_main_to_version(version_number_to_update, true)
-            else
-              return true
-            end
-          else
-            return false
-          end
-        end
-        
-        def destroy_version(version_number)
-          if (ver = find_version(version_number))
-            without_update_callbacks do 
-              # For fault tolerance (ie: to prevent data loss through premature deletion), first...
-              # Check to see if the current (aka latest) version has to be deleted,
-              # and if so update the main table with the data from the version that will become the latest
-              if version_number.to_i == eval("#{self.class.version_column}")
-                if versions.count > 1
-                  to_be_latest_version = versions[versions.count-2].version
-                else
-                  return false
-                end
-                success = update_main_to_version(to_be_latest_version)
-              end
-              
-              # Then... delete the version
-              if success
-                retrn ver.destroy
-              else
-                return false
-              end
-            end
-          end
-        end
-
-        def describe_version(version_number)
-          return "" if versions.count < 2
-          return "(earliest)" if version_number == versions.first.version
-          return "(latest)" if version_number == versions.last.version
-          return ""
-        end
-        
-        def without_update_callbacks(&block)
-          self.class.without_update_callbacks(&block)
-        end
-        
-        def empty_callback() end #:nodoc:
-        
-        protected
-        
-          def set_new_version
-            self.send("#{self.class.version_column}=", self.next_version)
-          end
-          
-          # Saves a version of the model in the versioned table. This is called in the after_create callback by default
-          def save_version_on_create(revision_comment=nil)
-            rev = self.class.versioned_class.new
-            rev.version = send(self.class.version_column)
-            rev.send("#{self.class.revision_comments_column}=", revision_comment)
-            rev.send("#{self.class.versioned_foreign_key}=", self.id)
-            self.clone_versioned_model(self, rev)
-            saved = rev.save
-            
-            if saved
-              # Now update timestamp columns on main model. 
-              # Note: main model doesnt get saved yet.
-              update_timestamps(rev, self)
-            end
-            
-            return saved
-          end
-          
-          def update_timestamps(from, to)
-            begin  
-              self.timestamp_columns.each do |key|
-                if to.has_attribute?(key)
-                  logger.debug("explicit_versioning - update_timestamps method - setting timestamp_column '#{key}'")
-                  if eval("from.#{key}.nil?")
-                    to.send("#{key}=", nil)
-                  else
-                    to.send("#{key}=", eval("from.#{key}"))
-                  end
-                end
-              end
-            rescue => err
-              logger.error("ERROR: An error occurred in the explicit_versioning plugin during the update_timestamps method (setting timestamp columns).")
-              logger.error("ERROR DETAILS: #{err}")
-            end
-          end
-          
-          # This method updates the latest version entry in the versioned table with the data 
-          # from the main table (since those two entries should always have the same data).
-          def sync_latest_version
-            ver = versions.last
-            clone_versioned_model(self, ver)
-            ver.save
-          end
-          
-          # This method updates the entry in the main table with the data from the version specified,
-          # and also updates the corresponding version column in the main table to reflect this.
-          # Note: this method on its own should not be used to revert to previous versions as it doesn't actualy delete any versions.
-          def update_main_to_version(version_number, process_file_columns=true)
-            if (ver = find_version(version_number))
-              clone_versioned_model(ver, self, process_file_columns)
-              self.send("#{self.class.version_column}=", version_number)
-              
-              # Now update timestamp columns on main model. 
-              update_timestamps(ver, self)
-                
-              return self.save
-            else
-              return false
-            end
-          end
-          
-          # Clones a model.
-          def clone_versioned_model(orig_model, new_model, process_file_columns=true)
-            self.versioned_attributes.each do |key|
-              # Make sure to ignore file columns, white list columns, timestamp columns and any other ignore columns
-              unless self.file_columns.include?(key) || 
-                     self.white_list_columns.include?(key) || 
-                     self.timestamp_columns.include?(key) ||
-                     self.sync_ignore_columns.include?(key)
-                new_model.send("#{key}=", eval("orig_model.#{key}")) if orig_model.respond_to?(key)
-              end
-            end
-            
-            if process_file_columns
-              # Now copy over file columns
-              begin
-                self.file_columns.each do |key|
-                  if orig_model.has_attribute?(key)
-                    if eval("orig_model.#{key}.nil?")
-                      logger.debug("DEBUG: file column is nil")
-                      new_model.send("#{key}=", nil)
-                    else
-                      logger.debug("DEBUG: file column is not nil")
-                      new_model.send("#{key}=", File.open(eval("orig_model.#{key}")))
-                      FileUtils.cp(eval("orig_model.#{key}"), eval("new_model.#{key}"))
-                    end
-                  end
-                end
-              rescue => err
-                logger.error("ERROR: An error occurred in the explicit_versioning plugin during the clone_versioned_model method (copying file columns).")
-                logger.error("ERROR DETAILS: #{err}")
-              end
-            end
-            
-            # Now set white list columns
-            begin  
-              self.white_list_columns.each do |key|
-                if orig_model.has_attribute?(key)
-                  if eval("orig_model.#{key}.nil?")
-                    new_model.send("#{key}=", nil)
-                  else
-                    new_model.send("#{key}=", eval("orig_model.#{key}"))
-                  end
-                end
-              end
-            rescue => err
-              logger.error("ERROR: An error occurred in the explicit_versioning plugin during the clone_versioned_model method (setting white list columns).")
-              logger.error("ERROR DETAILS: #{err}")
-            end
-            
-            # Set version column accordingly.
-            if orig_model.is_a?(self.class.versioned_class)
-              new_model[new_model.class.inheritance_column] = orig_model[self.class.versioned_inheritance_column]
-            elsif new_model.is_a?(self.class.versioned_class)
-              new_model[self.class.versioned_inheritance_column] = orig_model[orig_model.class.inheritance_column]
-            end
-          end 
-          
-          # Gets the next available version for the current record, or 1 for a new record
-          def next_version
-            return 1 if new_record?
-            (versions.calculate(:max, :version) || 0) + 1
-          end
-          
-          # Returns an array of attribute keys that are versioned.  See non_versioned_columns
-          def versioned_attributes
-            self.attributes.keys.select { |k| !self.class.non_versioned_columns.include?(k) } + extra_attributes
-          end
-        
-        module ClassMethods
-          # Finds a specific version of a specific row of this model
-          def find_version(id, version)
-            find_versions(id, 
-              :conditions => ["#{versioned_foreign_key} = ? AND version = ?", id, version], 
-              :limit => 1).first
-          end
-        
-          # Finds versions of a specific model.  Takes an options hash like <tt>find</tt>
-          def find_versions(id, options = {})
-            versioned_class.find :all, {
-              :conditions => ["#{versioned_foreign_key} = ?", id],
-              :order      => 'version' }.merge(options)
-          end
-          
-          # Returns an array of columns that are versioned.  See non_versioned_columns
-          def versioned_columns
-            self.columns.select { |c| !non_versioned_columns.include?(c.name) }
-          end
-    
-          # Returns an instance of the dynamic versioned model
-          def versioned_class
-            const_get versioned_class_name
-          end
-
-          # Rake migration task to create the versioned table using options passed
-          def create_versioned_table(create_table_options = {})
-            # create version column in main table if it does not exist
-            if !self.content_columns.find { |c| %w(version lock_version).include? c.name }
-              self.connection.add_column table_name, :version, :integer
-            end
-            
-            self.connection.create_table(versioned_table_name, create_table_options) do |t|
-              t.column versioned_foreign_key, :integer
-              t.column :version, :integer
-              t.column revision_comments_column, :text
-            end
-            
-            updated_col = nil
-            self.versioned_columns.each do |col| 
-              updated_col = col if !updated_col && %(updated_at updated_on).include?(col.name)
-              self.connection.add_column versioned_table_name, col.name, col.type, 
-                :limit => col.limit, 
-                :default => col.default
-            end
-        
-            if type_col = self.columns_hash[inheritance_column]
-              self.connection.add_column versioned_table_name, versioned_inheritance_column, type_col.type, 
-                :limit => type_col.limit, 
-                :default => type_col.default
-            end
-    
-            if updated_col.nil?
-              self.connection.add_column versioned_table_name, :updated_at, :timestamp
-            end
-          end
-          
-          # Rake migration task to drop the versioned table
-          def drop_versioned_table
-            self.connection.drop_table versioned_table_name
-          end
-          
-          # Executes the block with the update callbacks disabled.
-          #
-          #   Foo.without_update_callbacks do
-          #     @foo.save
-          #   end
-          #
-          def without_update_callbacks(&block)
-            class_eval do 
-              CALLBACKS.each do |attr_name|
-                alias_method "orig_#{attr_name}".to_sym, attr_name
-                alias_method attr_name, :empty_callback
-              end
-            end
-            block.call
-          ensure
-            class_eval do 
-              CALLBACKS.each do |attr_name|
-                alias_method attr_name, "orig_#{attr_name}".to_sym
-              end
-            end
-          end
-        end
-      end
-    end
-  end
-end
-
-ActiveRecord::Base.class_eval do
-  include Jits::Acts::ExplicitVersioning
-end

Modified: branches/wf4ever/lib/previews.rb (3085 => 3086)


--- branches/wf4ever/lib/previews.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/previews.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -5,7 +5,7 @@
 
     self.class_eval do
 
-      belongs_to :preview, :dependent => :destroy
+      belongs_to :preview, :dependent => :destroy, :autosave => true
 
       def image
         preview.image_blob.data if preview && preview.image_blob
@@ -17,42 +17,31 @@
 
       def image=(x)
 
+        x = x.read if x.respond_to?(:read)
+
         self.preview = Preview.new if self.preview.nil?
-        self.preview.image_blob = ContentBlob.new if self.preview.image_blob.nil?
 
-        self.preview.image_blob.data = x
+        if x.nil?
+          self.preview.image_blob = nil
+        else
+          self.preview.image_blob = ContentBlob.new if self.preview.image_blob.nil?
+          self.preview.image_blob.data = x
+        end
       end
 
       def svg=(x)
 
+        x = x.read if x.respond_to?(:read)
+
         self.preview = Preview.new if self.preview.nil?
-        self.preview.svg_blob = ContentBlob.new if self.preview.svg_blob.nil?
 
-        self.preview.svg_blob.data = x
-      end
-
-      after_save { |ob|
-      
-        p = ob.preview
-
-        if p
-
-          ib = p.image_blob
-          sb = p.svg_blob
-
-          if ib && ib.data_changed?
-            ib.save
-            ob.preview.clear_cache
-          end
-
-          if sb && sb.data_changed?
-            sb.save
-            ob.preview.clear_cache
-          end
-          
-          p.save
+        if x.nil?
+          self.preview.svg_blob = nil
+        else
+          self.preview.svg_blob = ContentBlob.new if self.preview.svg_blob.nil?
+          self.preview.svg_blob.data = x
         end
-      }
+      end
     end
   end
 end

Modified: branches/wf4ever/lib/rest.rb (3085 => 3086)


--- branches/wf4ever/lib/rest.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/rest.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -114,9 +114,13 @@
   { :xml => doc.to_s, :status => "#{code} #{message}" }
 end
 
-def resource_preview_url(ob, type)
+def resource_preview_url(ob, type, query)
   url = ""
-  url.path << "/versions/#{ob.current_version}" if ob.respond_to?('current_version')
+  if query["version"]
+    url.path << "/versions/#{query["version"]}"
+  elsif ob.respond_to?('current_version')
+    url.path << "/versions/#{ob.current_version}"
+  end
   url.path << "/previews/#{type}"
   url.to_s
 end
@@ -227,8 +231,14 @@
 
               list_element << el
             else
-              el = rest_get_request_aux(list_element_item, user, query.merge({ "id" => list_element_item.id.to_s }), list_item_select_elements)
+              el = rest_get_request_aux(list_element_item, user, query.merge({ "id" => list_element_item.id.to_s, "version" => nil }), list_item_select_elements)
 
+              # hack to workaround an inconsistency in the established API
+
+              if el.name == "internal-pack-item"
+                el.name = rest_object_tag_text(list_element_item)
+              end
+
               if model_data['List Element Name'][i]
                 el.name = model_data['List Element Name'][i]
               end
@@ -285,7 +295,7 @@
 
         if model_data['Encoding'][i] == 'preview'
 
-          text = resource_preview_url(ob, model_data['Accessor'][i])
+          text = resource_preview_url(ob, model_data['Accessor'][i], query)
 
         else
 
@@ -343,6 +353,8 @@
 
   version = ob.version.to_s if ob.respond_to?(:versioned_resource)
 
+  version = query["version"] if query["version"]
+
   entity['uri'     ] = uri      if uri && query["show-uri"] != "no"
   entity['resource'] = resource if resource && query["show-resource"] != "no"
   entity['version' ] = version  if version && query["show-version"] != "no"
@@ -672,7 +684,7 @@
     when 'Attribution';     return nil
     when 'Tagging';         return nil
 
-    when 'Workflow::Version'; return "#{rest_resource_uri(ob.workflow)}?version=#{ob.version}"
+    when 'WorkflowVersion'; return "#{rest_resource_uri(ob.workflow)}?version=#{ob.version}"
   end
 
   raise "Class not processed in rest_resource_uri: #{ob.class.to_s}"
@@ -716,7 +728,7 @@
     when 'Creditation';     return "#{base}/credit.xml?id=#{ob.id}"
     when 'Attribution';     return nil
 
-    when 'Workflow::Version'; return "#{base}/workflow.xml?id=#{ob.workflow.id}&version=#{ob.version}"
+    when 'WorkflowVersion'; return "#{base}/workflow.xml?id=#{ob.workflow.id}&version=#{ob.version}"
   end
 
   raise "Class not processed in rest_access_uri: #{ob.class.to_s}"
@@ -740,7 +752,7 @@
     when 'Download';               return 'download'
     when 'PackContributableEntry'; return rest_object_tag_text(ob.contributable)
     when 'PackRemoteEntry';        return 'external'
-    when 'Workflow::Version';      return 'workflow'
+    when 'WorkflowVersion';        return 'workflow'
     when 'Comment';                return 'comment'
     when 'Bookmark';               return 'favourite'
     when 'ContentType';            return 'type'
@@ -772,7 +784,7 @@
     when 'Download';               return ''
     when 'PackContributableEntry'; return rest_object_label_text(ob.contributable)
     when 'PackRemoteEntry';        return ob.title     
-    when 'Workflow::Version';      return ob.title
+    when 'WorkflowVersion';        return ob.title
     when 'ContentType';            return ob.title
     when 'License';                return ob.title
     when 'CurationEvent';          return ob.category
@@ -1078,12 +1090,15 @@
       return rest_response(500, :reason => "Unable to extract metadata")
     end
 
-    success = if (action == 'create' and opts[:query]['id'])
-      ob.save_as_new_version(revision_comment)
-    else
-      ob.save
+    new_version = action == 'create' && opts[:query]['id']
+
+    if new_version
+      ob.preview = nil
+      ob[:revision_comments] = revision_comment
     end
 
+    success = ob.save
+
     return rest_response(400, :object => ob) unless success
 
     # Elements to update if we're not dealing with a workflow version
@@ -1125,7 +1140,11 @@
   case action
     when 'create':
       return rest_response(401, :reason => "Not authorised to create a file") unless Authorization.is_authorized_for_type?('create', 'Blob', opts[:user], nil)
-      ob = Blob.new(:contributor => opts[:user])
+      if opts[:query]['id']
+        ob, error = obtain_rest_resource('Blob', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
+      else
+        ob = Blob.new(:contributor => opts[:user])
+      end
     when 'read', 'update', 'destroy':
       ob, error = obtain_rest_resource('Blob', opts[:query]['id'], opts[:query]['version'], opts[:user], action)
     else
@@ -1136,18 +1155,21 @@
 
   if action == "destroy"
 
+    return rest_response(400, :reason => "Cannot delete individual versions") if opts[:query]['version']
+      
     ob.destroy
 
   else
 
     data = ""
 
-    title        = parse_element(data, :text,   '/file/title')
-    description  = parse_element(data, :text,   '/file/description')
-    license_type = parse_element(data, :text,   '/file/license-type')
-    type         = parse_element(data, :text,   '/file/type')
-    content_type = parse_element(data, :text,   '/file/content-type')
-    content      = parse_element(data, :binary, '/file/content')
+    title            = parse_element(data, :text,   '/file/title')
+    description      = parse_element(data, :text,   '/file/description')
+    license_type     = parse_element(data, :text,   '/file/license-type')
+    type             = parse_element(data, :text,   '/file/type')
+    content_type     = parse_element(data, :text,   '/file/content-type')
+    content          = parse_element(data, :binary, '/file/content')
+    revision_comment = parse_element(data, :text,   '/workflow/revision-comment')
 
     permissions  = data.find_first('/file/permissions')
 
@@ -1199,18 +1221,29 @@
 
     ob.content_blob = ContentBlob.new(:data ="" content) if content
 
-    if not ob.save
-      return rest_response(400, :object => ob)
+    new_version = action == 'create' && opts[:query][:id]
+
+    if new_version
+      ob[:revision_comments] = revision_comment
     end
 
-    if ob.contribution.policy.nil?
-      ob.contribution.policy = create_default_policy(opts[:user])
-      ob.contribution.save
+    success = ob.save
+
+    return rest_response(400, :object => ob) unless success
+
+    if opts[:query]['version'].nil?
+
+      if ob.contribution.policy.nil?
+        ob.contribution.policy = create_default_policy(opts[:user])
+        ob.contribution.save
+      end
+
+      update_permissions(ob, permissions)
     end
-
-    update_permissions(ob, permissions)
   end
 
+  ob = ob.versioned_resource if ob.respond_to?("versioned_resource")
+
   rest_get_request(ob, opts[:user], { "id" => ob.id.to_s })
 end
 

Modified: branches/wf4ever/lib/sanity_test.rb (3085 => 3086)


--- branches/wf4ever/lib/sanity_test.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/sanity_test.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -57,9 +57,10 @@
   blogs         = Blog.find(:all)
   blobs         = Blob.find(:all)
   packs         = Pack.find(:all)
+  services      = Service.find(:all)
   contributions = Contribution.find(:all)
 
-  known_contributables = workflows + blobs + blogs + packs
+  known_contributables = workflows + blobs + blogs + packs + services
 
   should_be_empty("All users must have a name",
       users.select do |u| u.name == nil or u.name.length == 0 end)

Modified: branches/wf4ever/lib/workflow_processors/galaxy.rb (3085 => 3086)


--- branches/wf4ever/lib/workflow_processors/galaxy.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/workflow_processors/galaxy.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -9,7 +9,7 @@
   
   class Galaxy < WorkflowProcessors::Interface
 
-    Mime::Type.register "application/vnd.galaxy.workflow+xml", :galaxy_workflow
+    Mime::Type.register "application/vnd.galaxy.workflow+json", :galaxy_workflow
 
     # Begin Class Methods
     
@@ -24,29 +24,36 @@
     end
     
     def self.display_data_format
-      "XML"
+      "JSON"
     end
     
     def self.mime_type
-      "application/vnd.galaxy.workflow+xml"
+      "application/vnd.galaxy.workflow+json"
     end
 
     # All the file extensions supported by this workflow processor.
     # Must be all in lowercase.
     def self.file_extensions_supported
-      []
+      ["ga"]
     end
+
+    def self.default_file_extension
+      "ga"
+    end
     
     def self.can_determine_type_from_file?
-      false
+      true
     end
     
     def self.recognised?(file)
-      false
+      rec = file.readline.strip == '{' &&
+            file.readline.strip == '"a_galaxy_workflow": "true",'
+      file.rewind
+      rec
     end
     
     def self.can_infer_metadata?
-      false
+      true
     end
     
     def self.can_generate_preview_image?
@@ -58,7 +65,7 @@
     end
     
     def self.show_download_section?
-      false
+      true
     end
 
     def initialize(workflow_definition)
@@ -95,6 +102,10 @@
       words.rewind
       words.read
     end
+
+    def get_title
+      @model.title
+    end
   end
 
   module GalaxyLib
@@ -113,72 +124,66 @@
       # The connections of the workflow.
       attr_accessor :connections
 
+      attr_accessor :title
+
       def self.parse(stream)
+        doc = ActiveSupport::JSON.decode(stream)
 
-        begin
+        workflow = GalaxyLib::Workflow.new
 
-          doc = LibXML::XML::Parser.string("<?xml version='1.0' encoding='UTF-8'?><content>#{stream}</content>").parse
+        workflow.inputs      = []
+        workflow.outputs     = []
+        workflow.steps       = []
+        workflow.connections = []
 
-          workflow = GalaxyLib::Workflow.new
+        workflow.title = doc["name"]
 
-          workflow.inputs      = []
-          workflow.outputs     = []
-          workflow.steps       = []
-          workflow.connections = []
+        # Parse the context of the workflow.
+        doc["steps"].each_key.sort.each do |step_id| # Need to sort because the steps are backwards in the JSON
+          step_element = doc["steps"][step_id]
 
-          # Parse the context of the workflow.
+          step = GalaxyLib::Step.new
 
-          doc.find("/content/steps/step/inputs/input").each do |input_element|
+          step.id          = step_id
+          step.name        = step_element["name"]
+          step.tool        = step_element["tool_id"] || "None"
+          #step.description = nil   # No description present in JSON
 
+          workflow.steps << step
+
+          step_element["inputs"].each do |input_element|
             input = GalaxyLib::Input.new
 
-            input.step_id     = input_element.find("../../id/text()")[0].to_s
-            input.name        = input_element.find("name/text()")[0].to_s
-            input.description = CGI.unescapeHTML(input_element.find("description/text()")[0].to_s)
+            input.step_id     = step_id
+            input.name        = input_element["name"]
+            input.description = input_element["description"]
 
             workflow.inputs << input
           end
 
-          doc.find("/content/steps/step/outputs/output").each do |output_element|
-
+          step_element["outputs"].each do |output_element|
             output = GalaxyLib::Output.new
 
-            output.step_id = output_element.find("../../id/text()")[0].to_s
-            output.name    = output_element.find("name/text()")[0].to_s
-            output.type    = output_element.find("type/text()")[0].to_s
+            output.step_id = step_id
+            output.name    = output_element["name"]
+            output.type    = output_element["type"]
 
             workflow.outputs << output
           end
 
-          doc.find("/content/steps/step").each do |step_element|
+          step_element["input_connections"].each do |conn_name, conn_element|
+            connection = GalaxyLib::Connection.new
 
-            step = GalaxyLib::Step.new
+            connection.source_id     = conn_element["id"].to_s
+            connection.source_output = conn_element["output_name"].to_s
+            connection.sink_id       = step_id
+            connection.sink_input    = conn_name
 
-            step.id          = step_element.find("id/text()")[0].to_s
-            step.name        = step_element.find("name/text()")[0].to_s
-            step.tool        = step_element.find("tool/text()")[0].to_s
-            step.description = CGI.unescapeHTML(step_element.find("description/text()")[0].to_s)
-
-            workflow.steps << step
+            workflow.connections << connection
           end
+        end
 
-          doc.find("/content/connections/connection").each do |conn_element|
-
-            conn = GalaxyLib::Connection.new
-
-            conn.source_id     = conn_element.find("source_id/text()")[0].to_s
-            conn.source_output = conn_element.find("source_output/text()")[0].to_s
-            conn.sink_id       = conn_element.find("sink_id/text()")[0].to_s
-            conn.sink_input    = conn_element.find("sink_input/text()")[0].to_s
-
-            workflow.connections << conn
-          end
-
-          workflow
-        rescue
-          Rails.logger.info $!
-          nil
-        end
+        workflow
       end
 
       def get_components

Modified: branches/wf4ever/lib/workflow_processors/interface.rb (3085 => 3086)


--- branches/wf4ever/lib/workflow_processors/interface.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/workflow_processors/interface.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -32,6 +32,10 @@
     def self.file_extensions_supported
       []
     end
+
+    def self.default_file_extension
+      nil
+    end
     
     def self.can_determine_type_from_file?
       false

Modified: branches/wf4ever/lib/workflow_processors/taverna2.rb (3085 => 3086)


--- branches/wf4ever/lib/workflow_processors/taverna2.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/workflow_processors/taverna2.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -41,6 +41,10 @@
     def self.file_extensions_supported
       [ "t2flow" ]
     end
+
+    def self.default_file_extension
+      "t2flow"
+    end
     
     def self.can_determine_type_from_file?
       true
@@ -81,7 +85,7 @@
 
     # End Object Initializer
     
-    
+
     # Begin Instance Methods
     
     # These provide more specific functionality for a given workflow definition, such as parsing for metadata and image generation.

Modified: branches/wf4ever/lib/workflow_types_handler.rb (3085 => 3086)


--- branches/wf4ever/lib/workflow_types_handler.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/lib/workflow_types_handler.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -97,7 +97,7 @@
         mime_type = processor_class.mime_type
 
         ct = ContentType.find_by_title(title)
-        ct = ContentType.create(:title => title, :mime_type => mime_type) if ct.nil?
+        ct = ContentType.create(:title => title, :mime_type => mime_type, :category => 'Workflow') if ct.nil?
 
         if ct.mime_type != mime_type
           ct.mime_type = mime_type

Copied: branches/wf4ever/public/images/galaxyIcon_noText.png (from rev 3085, trunk/public/images/galaxyIcon_noText.png)


(Binary files differ)

Copied: branches/wf4ever/public/images/scape_logo.png (from rev 3085, trunk/public/images/scape_logo.png)


(Binary files differ)

Modified: branches/wf4ever/public/_javascript_s/controls.js (3085 => 3086)


--- branches/wf4ever/public/_javascript_s/controls.js	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/public/_javascript_s/controls.js	2012-08-11 14:01:49 UTC (rev 3086)
@@ -208,16 +208,32 @@
     }
   },
 
+  // Added this fix: http://www.gilluminate.com/2009/01/20/scriptaculous-autocomplete-page-jump-using-arrow-keys/
+
   markPrevious: function() {
-    if(this.index > 0) this.index--;
-      else this.index = this.entryCount-1;
-    this.getEntry(this.index).scrollIntoView(true);
+   if(this.index > 0) {this.index--;}
+   else {
+    this.index = this.entryCount-1;
+    this.update.scrollTop = this.update.scrollHeight;
+   }
+   selection = this.getEntry(this.index);
+   selection_top = selection.offsetTop;
+   if(selection_top < this.update.scrollTop){
+    this.update.scrollTop = this.update.scrollTop-selection.offsetHeight;
+   }
   },
 
   markNext: function() {
-    if(this.index < this.entryCount-1) this.index++;
-      else this.index = 0;
-    this.getEntry(this.index).scrollIntoView(false);
+   if(this.index < this.entryCount-1) {this.index++;}
+   else {
+    this.index = 0;
+    this.update.scrollTop = 0;
+   }
+   selection = this.getEntry(this.index);
+   selection_bottom = selection.offsetTop+selection.offsetHeight;
+   if(selection_bottom > this.update.scrollTop+this.update.offsetHeight){
+    this.update.scrollTop = this.update.scrollTop+selection.offsetHeight;
+   }
   },
 
   getEntry: function(index) {
@@ -281,6 +297,7 @@
       }
 
       this.stopIndicator();
+      this.update.scrollTop = 0;
       this.index = 0;
 
       if(this.entryCount==1 && this.options.autoSelect) {

Modified: branches/wf4ever/public/_javascript_s/osp.js (3085 => 3086)


--- branches/wf4ever/public/_javascript_s/osp.js	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/public/_javascript_s/osp.js	2012-08-11 14:01:49 UTC (rev 3086)
@@ -158,45 +158,41 @@
 	document.getElementById('credits_groups').value = groups_list;
 }
 
-function addAuthor() {
+function addAuthor(author_option, author_id, author_name) {
     
 	// Me
-    if (document.getElementById('author_option_1').checked)
+  if (author_option == 1)
 	{
 		credit_me = true;
 	}
 	// One of my Friends 
-	else if (document.getElementById('author_option_2').checked)
+	else if (author_option == 2)
 	{
 		var x = document.getElementById('author_friends_dropdown');
 		
-		if (x.options.length > 0)
+		if (x.options.length > 0 && x.selectedIndex != 0)
 		{
 			var y = x.options[x.selectedIndex];
-	     	credit_users[y.value] = y.text;
+	    credit_users[y.value] = y.text;
 		}
 	}
 	// A user on myExperiment who is not a Friend.
-	else if (document.getElementById('author_option_3').checked)
+	else if (author_option == 3)
 	{
-		var x = document.getElementById('author_otheruser_dropdown');
-		
-		if (x.options.length > 0)
-		{
-			var y = x.options[x.selectedIndex];
-	     	credit_users[y.value] = y.text;
-		}
+    credit_users[other_user_id] = other_user_name;
+    other_user_id = null;
+    other_user_name = null;
+    $('user_name').value = '';
+    $('add_otheruser_author').disabled = true;
 	}
 	// A myExperiment Group
-	else if (document.getElementById('author_option_4').checked)
+	else if (author_option == 4)
 	{
-		var x = document.getElementById('author_networks_dropdown');
-		
-		if (x.options.length > 0)
-		{
-			var y = x.options[x.selectedIndex];
-	     	credit_groups[y.value] = y.text;
-		}
+    credit_groups[group_id] = group_name;
+    group_id = null;
+    group_name = null;
+    $('group_name').value = '';
+    $('add_group_author').disabled = true;
 	}
 	
 	updateAuthorList();
@@ -298,20 +294,18 @@
 function addAttribution(type) {
 	
 	if (type == 'existing_workflow') {
-		var x = document.getElementById('existingworkflows_dropdown');
-		
-		if (x.options.length > 0) {
-			var y = x.options[x.selectedIndex];
-			attributions_workflows[y.value] = y.text;
-		}
+    attributions_workflows[workflow_id] = workflow_name;
+    workflow_id = null;
+    workflow_name = null;
+    $('workflow_name').value = '';
+    $('add_workflow_attrib').disabled = true;
 	}
 	else if (type == 'existing_file') {
-		var x = document.getElementById('existingfiles_dropdown');
-		
-		if (x.options.length > 0) {
-			var y = x.options[x.selectedIndex];
-			attributions_files[y.value] = y.text;
-		}
+    attributions_files[file_id] = file_name;
+    file_id = null;
+    file_name = null;
+    $('file_name').value = '';
+    $('add_file_attrib').disabled = true;
 	} 
 	
 	updateAttributionsList();

Modified: branches/wf4ever/public/_javascript_s/tabs.js (3085 => 3086)


--- branches/wf4ever/public/_javascript_s/tabs.js	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/public/_javascript_s/tabs.js	2012-08-11 14:01:49 UTC (rev 3086)
@@ -69,20 +69,27 @@
 
 function showFragment(fragment, scroll) {
 
-  var root = document.all ? "BODY" : "HTML";
-  var el   = document.getElementById(fragment);
+  var root   = document.all ? "BODY" : "HTML";
+  var target = document.getElementById(fragment);
 
-  if (el != undefined) {
+  if (target == undefined) {
+    var namedElements = document.getElementsByName(fragment);
 
-    for (; el.tagName != root; el = parent_el(el)) {
-      if (el.className == 'tabContainer') {
-        selectTab(el.tabsDiv, el.tabsIndex);
-      }
+    if (namedElements.length > 0)
+      target = namedElements[0];
+  }
+
+  if (target == undefined)
+    return;
+
+  for (el = target; el.tagName != root; el = parent_el(el)) {
+    if (el.className == 'tabContainer') {
+      selectTab(el.tabsDiv, el.tabsIndex);
     }
   }
 
   if (scroll) {
-    document.getElementById(fragment).scrollIntoView(false);
+    target.scrollIntoView(false);
   }
 }
 

Copied: branches/wf4ever/public/stylesheets/scape.css (from rev 3085, trunk/public/stylesheets/scape.css) (0 => 3086)


--- branches/wf4ever/public/stylesheets/scape.css	                        (rev 0)
+++ branches/wf4ever/public/stylesheets/scape.css	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,6 @@
+/* Supplementary stylesheet for the template layout. Requires main myExperiment stylesheet. */
+
+/* Changes the colour of the sidebar/searchbar (normally blue): */
+#myexp_searchbar, #myexp_sidebar, .pagination a, .tabnav li a:hover, .tabnav li#selected_tabnav a  {
+  background-color: #3999b9;
+}

Modified: branches/wf4ever/public/stylesheets/styles.css (3085 => 3086)


--- branches/wf4ever/public/stylesheets/styles.css	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/public/stylesheets/styles.css	2012-08-11 14:01:49 UTC (rev 3086)
@@ -1254,16 +1254,6 @@
 	border: 1px solid #CCCCCC;
 }
 
-.contribution_version_meta_info_box {
-	padding: 0.3em 0.6em; 
-	border: 1px dotted #999999;
-	background-color: #FFFFCC;
-	color: #333333;
-	line-height: 1.2;
-	font-size: 85%;
-	margin-left: 2.5em;  
-}
-
 .contribution_currentlicense {
 	padding: 0 0 0.5em 0;
 }
@@ -2291,6 +2281,105 @@
   line-height: 1.4;
 }
 
+.user-check-buttons {
+	border: 1px solid #CCCCCC;
+  padding: 4px;
+  margin-left: 8px;
+  float: right;
+}
+
+#user-check-list TD {
+  background: #f0f0f0;
+}
+
+#user-check-list TD.ident {
+	font-weight: bold;
+}
+
+#user-check-submit,
+#user-check-range {
+  margin: 24px;
+  text-align: center;
+}
+
+#selected-user-check-element .table-div TABLE {
+  border: 2px solid black;
+}
+
+#user-check-list > DIV {
+  padding: 4px;
+}
+
+#user-check-list .whitelist TD {
+	border: 1px solid #80c080;
+  background: #c0ffc0;
+}
+
+#user-check-list .sleep TD {
+	border: 1px solid #808080;
+  background: #c0c0c0;
+}
+
+#user-check-list .delete TD {
+	border: 1px solid #c08080;
+  background: #ffc0c0;
+}
+
+div.credit_selection_box, div.credit_selection_box {
+  margin-top: 0.5em;
+  padding: 0.5em;
+  background-color: #eee;
+  overflow: auto;
+}
+
+div.credit_selection_box button {
+  float: right;
+  margin-left: 0.5em;
+}
+
+div.credit_selection_box input,
+div.credit_selection_box select {
+  width: 20em;
+  min-height: 19px;
+}
+
+.auto_complete_spinner {
+  margin-left: -24px;
+}
+
+input.auto_complete_field {
+  min-height: 20px;
+}
+
+input.auto_complete_field.accepted {
+  background-color: transparent;
+  border: none;
+  color: #4dbf00;
+}
+
+input.auto_complete_field.error {
+  background-color: #FFCCCC;
+}
+
+.version_history .title {
+  font-size: 16px;
+}
+
+.version_history .metadata {
+  margin-left: 12px;
+  margin-top: 6px;
+  margin-bottom: 6px;
+}
+
+.version_history .comment {
+	padding: 6px;
+	border: 1px dotted #999999;
+	background-color: #FFFFCC;
+	color: #333333;
+	line-height: 1.2;
+	font-size: 85%;
+}
+
 #annotation_list TABLE {
   border-collapse: collapse;
   margin-bottom: 16px;

Copied: branches/wf4ever/test/fixtures/blob_versions.yml (from rev 3085, trunk/test/fixtures/blob_versions.yml) (0 => 3086)


--- branches/wf4ever/test/fixtures/blob_versions.yml	                        (rev 0)
+++ branches/wf4ever/test/fixtures/blob_versions.yml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -0,0 +1,74 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+
+picture:
+  id: 1
+  blob_id: 1
+  version: 1
+  revision_comments: some revision comment
+  local_name: file_picture.png
+  title: Picture
+  body: some text
+  created_at: 2008-04-22 15:32:01
+  content_type_id: 1
+  content_blob_id: 1
+
+text:
+  id: 2
+  blob_id: 2
+  version: 1
+  revision_comments: some revision comment
+  local_name: file_text.txt
+  title: developers.txt
+  body: myExperiment instructions
+  created_at: 2007-01-01 00:00:03
+  content_type_id: 2
+  content_blob_id: 2
+
+for_true_policy:
+  id: 3
+  blob_id: 3
+  version: 1
+  revision_comments: some revision comment
+  local_name: file_picture.png
+  title: for true policy
+  body: some text
+  created_at: 2008-04-22 15:32:01
+  content_type_id: 1
+  content_blob_id: 1
+
+for_false_policy:
+  id: 4
+  blob_id: 4
+  version: 1
+  revision_comments: some revision comment
+  local_name: file_picture.png
+  title: for false policy
+  body: some text
+  created_at: 2008-04-22 15:32:01
+  content_type_id: 1
+  content_blob_id: 1
+
+for_protected_policy:
+  id: 5
+  blob_id: 5
+  version: 1
+  revision_comments: some revision comment
+  local_name: file_picture.png
+  title: for protected policy
+  body: some text
+  created_at: 2008-04-22 15:32:01
+  content_type_id: 1
+  content_blob_id: 1
+
+for_public_policy:
+  id: 6
+  blob_id: 6
+  version: 1
+  revision_comments: some revision comment
+  local_name: file_picture.png
+  title: for public policy
+  body: some text
+  created_at: 2008-04-22 15:32:01
+  content_type_id: 1
+  content_blob_id: 1
+

Modified: branches/wf4ever/test/fixtures/blobs.yml (3085 => 3086)


--- branches/wf4ever/test/fixtures/blobs.yml	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/test/fixtures/blobs.yml	2012-08-11 14:01:49 UTC (rev 3086)
@@ -2,6 +2,7 @@
 
 picture:
   id: 1
+  current_version: 1
   contributor_id: 1
   contributor_type: User
   local_name: file_picture.png
@@ -14,6 +15,7 @@
 
 text:
   id: 2
+  current_version: 1
   contributor_id: 2
   contributor_type: User
   local_name: file_text.txt
@@ -26,6 +28,7 @@
 
 for_true_policy:
   id: 3
+  current_version: 1
   contributor_id: 1
   contributor_type: User
   local_name: file_picture.png
@@ -38,6 +41,7 @@
 
 for_false_policy:
   id: 4
+  current_version: 1
   contributor_id: 1
   contributor_type: User
   local_name: file_picture.png
@@ -50,6 +54,7 @@
 
 for_protected_policy:
   id: 5
+  current_version: 1
   contributor_id: 1
   contributor_type: User
   local_name: file_picture.png
@@ -62,6 +67,7 @@
 
 for_public_policy:
   id: 6
+  current_version: 1
   contributor_id: 1
   contributor_type: User
   local_name: file_picture.png

Modified: branches/wf4ever/test/functional/api_controller_test.rb (3085 => 3086)


--- branches/wf4ever/test/functional/api_controller_test.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/test/functional/api_controller_test.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -115,11 +115,13 @@
 
     title        = "Test file title"
     title2       = "Updated test file title"
+    title3       = "Updated test file title for versions"
     license_type = "by-sa"
     content_type = "text/plain"
     description  = "A description of the test file."
 
-    content = Base64.encode64("This is the content of this test file.")
+    content  = Base64.encode64("This is the content of this test file.")
+    content2 = Base64.encode64("This is the content of this test file, version 2.")
 
     # post a file
 
@@ -140,6 +142,9 @@
 
     file = extra_files.first
 
+    assert_equal(file.versions.length, 1)
+    assert_equal(file.versions.first.version, 1)
+
     # get the file
 
     response = rest_request(:get, 'file', nil, "id" => file.id,
@@ -185,6 +190,53 @@
     assert_equal(title2,      response.find_first('/file/title').inner_xml)
     assert_equal(description, response.find_first('/file/description').inner_xml)
 
+    # add a new version of the file
+
+    rest_request(:post, 'file', "<?xml version='1.0'?>
+      <file>
+        <title>#{title2}</title>
+        <description>#{description}</description>
+        <license-type>#{license_type}</license-type>
+        <content-type>#{content_type}</content-type>
+        <content>#{content2}</content>
+      </file>", "id" => file.id)
+
+    assert_response(:success)
+
+    file.reload
+
+    assert_equal(2, file.versions.length)
+
+    # update the first version of the file
+
+    rest_request(:put, 'file', "<?xml version='1.0'?>
+      <file>
+        <title>#{title3}</title>
+      </file>", "id" => file.id, "version" => 1)
+
+    assert_response(:success)
+
+    file.reload
+    assert_equal(title3, file.find_version(1).title);
+    assert_equal(title2, file.find_version(2).title);
+    assert_equal(title2, file.title);
+
+    # get each version of the file
+
+    response = rest_request(:get, 'file', nil, "id" => file.id, "version" => "1",
+        "elements" => "title")
+
+    assert_response(:success)
+  
+    assert_equal(title3, response.find_first('/file/title').inner_xml)
+
+    response = rest_request(:get, 'file', nil, "id" => file.id, "version" => "2",
+        "elements" => "title")
+
+    assert_response(:success)
+  
+    assert_equal(title2, response.find_first('/file/title').inner_xml)
+
     # delete the file
 
     rest_request(:delete, 'file', nil, "id" => file.id)

Modified: branches/wf4ever/vendor/plugins/structured_data/lib/auto_migrate.rb (3085 => 3086)


--- branches/wf4ever/vendor/plugins/structured_data/lib/auto_migrate.rb	2012-08-11 12:05:32 UTC (rev 3085)
+++ branches/wf4ever/vendor/plugins/structured_data/lib/auto_migrate.rb	2012-08-11 14:01:49 UTC (rev 3086)
@@ -85,7 +85,7 @@
     # create and drop tables as appropriate
 
     (old_tables - new_tables.keys).each do |name|
-      puts "Note: Table '#{name}' has been removed from the XML schema."
+#     puts "Note: Table '#{name}' has been removed from the XML schema."
 #     conn.drop_table(name)
 #     AutoTable.find_by_name(name).destroy
     end 

reply via email to

[Prev in Thread] Current Thread [Next in Thread]