myexperiment-hackers
[Top][All Lists]
Advanced

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

[myexperiment-hackers] [3547] branches/component-querying: Merged trunk


From: noreply
Subject: [myexperiment-hackers] [3547] branches/component-querying: Merged trunk 3527: 3546 into component-querying branch
Date: Mon, 20 May 2013 08:45:57 +0000 (UTC)

Revision
3547
Author
fbacall
Date
2013-05-20 08:45:57 +0000 (Mon, 20 May 2013)

Log Message

Merged trunk 3527:3546 into component-querying branch

Modified Paths

Added Paths

Diff

Modified: branches/component-querying/Gemfile (3546 => 3547)


--- branches/component-querying/Gemfile	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/Gemfile	2013-05-20 08:45:57 UTC (rev 3547)
@@ -1,6 +1,6 @@
 source "http://rubygems.org"
 
-gem "rails", "2.3.17"
+gem "rails", "2.3.18"
 gem "mysql2", "~> 0.2.18"
 gem "rubyzip", "~> 0.9.4"
 gem "oauth", "~> 0.4.3"
@@ -28,4 +28,4 @@
 gem "will_paginate", "~> 2.3.16"
 gem "open_id_authentication", "~> 1.1.0"
 gem "net-http-persistent", "~> 2.8"
-
+gem "simple-rss", "~> 1.2.3"

Modified: branches/component-querying/Rakefile (3546 => 3547)


--- branches/component-querying/Rakefile	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/Rakefile	2013-05-20 08:45:57 UTC (rev 3547)
@@ -199,42 +199,20 @@
   activities = []
 
   User.find(:all, :conditions => "activated_at IS NOT NULL", :include => :profile).map do |object|
-
-    activities << Activity.new(
-        :subject => object,
-        :subject_label => object.name,
-        :action ="" 'register',
-        :created_at => object.created_at)
-
+    activities += Activity.new_activities(:subject => object, :action ="" 'create', :object => object, :timestamp => object.created_at)
     if object.profile.updated_at && object.profile.updated_at != object.profile.created_at
-
-
-      activities << Activity.new(
-          :subject => object,
-          :subject_label => object.name,
-          :action ="" 'edit',
-          :created_at => object.profile.updated_at)
-
+      activities += Activity.new_activities(:subject => object, :action ="" 'edit', :object => object, :timestamp => object.profile.updated_at)
     end
   end
 
   (Workflow.all + Blob.all + Pack.all).map do |object|
-
-    activities << Activity.new(
-        :subject => object.contributor,
-        :action ="" 'create',
-        :objekt => object,
-        :auth => object,
-        :created_at => object.created_at)
-
+    activities += Activity.new_activities(:subject => object.contributor, :action ="" 'create', :object => object, :timestamp => object.created_at)
     if object.updated_at && object.updated_at != object.created_at
+      activities += Activity.new_activities(:subject => object.contributor, :action ="" 'edit', :object => object, :timestamp => object.updated_at)
+    end
 
-      activities << Activity.new(
-          :subject => object.contributor,
-          :action ="" 'edit',
-          :objekt => object,
-          :auth => object,
-          :created_at => object.updated_at)
+    object.contribution.policy.permissions.each do |permission|
+      activities += Activity.new_activities(:subject => object.contributor, :action ="" 'create', :object => permission, :timestamp => permission.created_at, :contributable => object)
     end
   end
   
@@ -243,182 +221,80 @@
   end
   
   workflow_versions.map do |object|
-
-    activities << Activity.new(
-        :subject => object.contributor,
-        :action ="" 'create',
-        :objekt => object,
-        :extra => object.version,
-        :auth => object.versioned_resource,
-        :created_at => object.created_at)
-
+    activities += Activity.new_activities(:subject => object.contributor, :action ="" 'create', :object => object, :timestamp => object.created_at)
     if object.updated_at && object.updated_at != object.created_at
-
-      activities << Activity.new(
-          :subject => object.contributor,
-          :action ="" 'edit',
-          :objekt => object,
-          :extra => object.version,
-          :auth => object.versioned_resource,
-          :created_at => object.updated_at)
+      activities += Activity.new_activities(:subject => object.contributor, :action ="" 'edit', :object => object, :timestamp => object.updated_at)
     end
   end
   
   (BlobVersion.find(:all, :conditions => "version > 1")).map do |object|
-
-    activities << Activity.new(
-        :subject => object.blob.contributor,
-        :action ="" 'create',
-        :objekt => object,
-        :extra => object.version,
-        :auth => object.versioned_resource,
-        :created_at => object.created_at)
-
+    activities += Activity.new_activities(:subject => object.blob.contributor, :action ="" 'create', :object => object, :timestamp => object.created_at)
     if object.updated_at && object.updated_at != object.created_at
-
-      activities << Activity.new(
-          :subject => object.blob.contributor,
-          :action ="" 'edit',
-          :objekt => object,
-          :extra => object.version,
-          :auth => object.versioned_resource,
-          :created_at => object.updated_at)
+      activities += Activity.new_activities(:subject => object.blob.contributor, :action ="" 'edit', :object => object, :timestamp => object.updated_at)
     end
   end
 
-  activities += Comment.all.map do |comment|
-
-    Activity.new(
-        :subject => comment.user,
-        :action ="" 'create',
-        :objekt => comment,
-        :auth => comment.commentable,
-        :created_at => comment.created_at)
+  Comment.all.each do |comment|
+    activities += Activity.new_activities(:subject => comment.user, :action ="" 'create', :object => comment, :timestamp => comment.created_at)
   end
 
-  activities += Bookmark.all.map do |bookmark|
-
-    Activity.new(
-        :subject => bookmark.user,
-        :action ="" 'create',
-        :objekt => bookmark,
-        :auth => bookmark.bookmarkable,
-        :created_at => bookmark.created_at)
+  Bookmark.all.each do |bookmark|
+    activities += Activity.new_activities(:subject => bookmark.user, :action ="" 'create', :object => bookmark, :timestamp => bookmark.created_at)
   end
 
-  Announcement.all.each do |object|
-
-    activities << Activity.new(
-        :subject => object.user,
-        :action ="" 'create',
-        :objekt => object,
-        :created_at => object.created_at)
-
-    if object.updated_at && object.updated_at != object.created_at
-
-
-      activities << Activity.new(
-          :subject => object.user,
-          :action ="" 'edit',
-          :objekt => object,
-          :created_at => object.updated_at)
+  Announcement.all.each do |announcement|
+    activities += Activity.new_activities(:subject => announcement.user, :action ="" 'create', :object => announcement, :timestamp => announcement.created_at)
+    if announcement.updated_at && announcement.updated_at != announcement.created_at
+      activities += Activity.new_activities(:subject => announcement.user, :action ="" 'edit', :object => announcement, :timestamp => announcement.updated_at)
     end
   end
 
-  Citation.all.each do |object|
-
-    activities << Activity.new(
-        :subject => object.user,
-        :action ="" 'create',
-        :objekt => object,
-        :auth => object.workflow,
-        :created_at => object.created_at)
-
-    if object.updated_at && object.updated_at != object.created_at
-
-      activities << Activity.new(
-          :subject => object.user,
-          :action ="" 'edit',
-          :objekt => object,
-          :auth => object.workflow,
-          :created_at => object.updated_at)
+  Citation.all.each do |citation|
+    activities += Activity.new_activities(:subject => citation.user, :action ="" 'create', :object => citation, :timestamp => citation.created_at)
+    if citation.updated_at && citation.updated_at != citation.created_at
+      activities += Activity.new_activities(:subject => citation.user, :action ="" 'edit', :object => citation, :timestamp => citation.updated_at)
     end
   end
 
-  Rating.all.each do |object|
-
-    activities << Activity.new(
-        :subject => object.user,
-        :action ="" 'create',
-        :objekt => object,
-        :auth => object.rateable,
-        :extra => object.rating,
-        :created_at => object.created_at)
+  Rating.all.each do |rating|
+    activities += Activity.new_activities(:subject => rating.user, :action ="" 'create', :object => rating, :timestamp => rating.created_at)
   end
 
-  Review.all.each do |object|
-
-    activities << Activity.new(
-        :subject => object.user,
-        :action ="" 'create',
-        :objekt => object,
-        :auth => object.reviewable,
-        :created_at => object.created_at)
-
-    if object.updated_at && object.updated_at != object.created_at
-
-      activities << Activity.new(
-          :subject => object.user,
-          :action ="" 'edit',
-          :objekt => object,
-          :auth => object.reviewable,
-          :created_at => object.updated_at)
+  Review.all.each do |review|
+    activities += Activity.new_activities(:subject => review.user, :action ="" 'create', :object => review, :timestamp => review.created_at)
+    if review.updated_at && review.updated_at != review.created_at
+      activities += Activity.new_activities(:subject => review.user, :action ="" 'edit', :object => review, :timestamp => review.updated_at)
     end
   end
 
-  Tagging.all.each do |object|
-
-    activities << Activity.new(
-        :subject => object.user,
-        :action ="" 'create',
-        :objekt => object,
-        :auth => object.taggable,
-        :extra => object.tag.name,
-        :created_at => object.created_at)
+  Tagging.all.each do |tagging|
+    activities += Activity.new_activities(:subject => tagging.user, :action ="" 'create', :object => tagging, :timestamp => tagging.created_at)
   end
 
-  Network.all.each do |object|
-
-    activities << Activity.new(
-        :subject => object.owner,
-        :action ="" 'create',
-        :objekt => object,
-        :created_at => object.created_at)
-
-    if object.updated_at && object.updated_at != object.created_at
-
-      activities << Activity.new(
-          :subject => object.owner,
-          :action ="" 'edit',
-          :objekt => object,
-          :created_at => object.updated_at)
+  Network.all.each do |network|
+    activities += Activity.new_activities(:subject => network.owner, :action ="" 'create', :object => network, :timestamp => network.created_at)
+    if network.updated_at && network.updated_at != network.created_at
+      activities += Activity.new_activities(:subject => network.owner, :action ="" 'edit', :object => network, :timestamp => network.updated_at)
     end
   end
 
   Membership.all.each do |membership|
-
-    next unless membership.accepted?
-
-    activities << Activity.new(
-        :subject => membership.user,
-        :action ="" 'join',
-        :objekt => membership.network,
-        :created_at => membership.accepted_at)
+    if membership.accepted_at
+      activities += Activity.new_activities(:subject => membership.user, :action ="" 'create', :object => membership, :timestamp => membership.accepted_at)
+    end
   end
  
+  GroupAnnouncement.all.each do |group_announcement|
+    activities += Activity.new_activities(:subject => group_announcement.user, :action ="" 'create', :object => group_announcement, :timestamp => group_announcement.created_at)
+  end
+
+  Creditation.all.each do |credit|
+    activities += Activity.new_activities(:subject => credit.creditable.contributor, :action ="" 'create', :object => credit, :timestamp => credit.created_at)
+  end
+
   activities.sort! do |a, b|
-    if a.created_at && b.created_at
-      a.created_at <=> b.created_at
+    if a.timestamp && b.timestamp
+      a.timestamp <=> b.timestamp
     else
       a.object_id <=> b.object_id
     end
@@ -430,6 +306,18 @@
 
 end
 
+desc 'Synchronize all Atom feeds'
+task "myexp:feed:sync:all" do
+  require File.dirname(__FILE__) + '/config/environment'
+
+  Feed.all.each do |feed|
+    begin
+      feed.synchronize!
+    rescue
+    end
+  end
+end
+
 desc 'Perform spam analysis on user profiles'
 task "myexp:spam:run" do
   require File.dirname(__FILE__) + '/config/environment'

Copied: branches/component-querying/app/controllers/activities_controller.rb (from rev 3546, trunk/app/controllers/activities_controller.rb) (0 => 3547)


--- branches/component-querying/app/controllers/activities_controller.rb	                        (rev 0)
+++ branches/component-querying/app/controllers/activities_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,29 @@
+# myExperiment: app/controllers/activities_controller.rb
+#
+# Copyright (c) 2007-2013 The University of Manchester, the University of
+# Oxford, and the University of Southampton.  See license.txt for details.
+
+class ActivitiesController < ApplicationController
+
+  def feature
+
+    context = extract_resource_context(params)
+    render_404("Activity context not found.") if context.nil?
+    render_401("Not authorized.") unless Authorization.check('edit', context, current_user)
+
+    activity = context.activities.find(params[:id].to_i)
+    render_404("Activity not found.") if activity.nil?
+
+    case request.method
+    when :put
+      activity.update_attribute(:featured, true)
+
+    when :delete
+      activity.update_attribute(:featured, false)
+    end
+
+    redirect_to context
+  end
+
+end
+

Modified: branches/component-querying/app/controllers/application_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/application_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/application_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -184,106 +184,128 @@
     list = s.split(',')
   end
 
-  def update_policy(contributable, params)
+  def update_policy(contributable, params, user)
 
-    # this method will return an error message is something goes wrong (empty string in case of success)
-    error_msg = ""
+    def aux(contributable, params)
 
-    # BEGIN validation and initialisation
+      # this method will return an error message is something goes wrong (empty string in case of success)
+      error_msg = ""
 
-    # If a group policy was selected, use that, and delete the old custom one (if there was one).
-    if params[:policy_type] == "group"
-      if contributable.contribution.policy && !contributable.contribution.policy.group_policy?
-        contributable.contribution.policy.destroy
+      # BEGIN validation and initialisation
+
+      # If a group policy was selected, use that, and delete the old custom one (if there was one).
+      if params[:policy_type] == "group"
+        if contributable.contribution.policy && !contributable.contribution.policy.group_policy?
+          contributable.contribution.policy.destroy
+        end
+        contributable.contribution.policy_id = params[:group_policy]
+        contributable.contribution.save
+        return
       end
-      contributable.contribution.policy_id = params[:group_policy]
-      contributable.contribution.save
-      return
-    end
 
-    # This variable will hold current settings of the policy in case something
-    # goes wrong and a revert would be needed at some point
-    last_saved_policy = nil
-    
-    return if params[:sharing].nil? or params[:sharing][:class_id].blank?
+      # This variable will hold current settings of the policy in case something
+      # goes wrong and a revert would be needed at some point
+      last_saved_policy = nil
+      
+      return if params[:sharing].nil? or params[:sharing][:class_id].blank?
 
-    sharing_class  = params[:sharing][:class_id]
-    updating_class = (params[:updating] and !params[:updating][:class_id].blank?) ? params[:updating][:class_id] : "6"
+      sharing_class  = params[:sharing][:class_id]
+      updating_class = (params[:updating] and !params[:updating][:class_id].blank?) ? params[:updating][:class_id] : "6"
 
-    # Check allowed sharing_class values
-    return unless [ "0", "1", "2", "3", "4", "7" ].include? sharing_class
-    
-    # Check allowed updating_class values
-    return unless [ "0", "1", "5", "6" ].include? updating_class
-    
-    view_protected     = 0
-    view_public        = 0
-    download_protected = 0
-    download_public    = 0
-    edit_protected     = 0
-    edit_public        = 0
-    
-    # BEGIN initialisation and validation
+      # Check allowed sharing_class values
+      return unless [ "0", "1", "2", "3", "4", "7" ].include? sharing_class
+      
+      # Check allowed updating_class values
+      return unless [ "0", "1", "5", "6" ].include? updating_class
+      
+      view_protected     = 0
+      view_public        = 0
+      download_protected = 0
+      download_public    = 0
+      edit_protected     = 0
+      edit_public        = 0
+      
+      # BEGIN initialisation and validation
 
-    if contributable.contribution.policy.nil? || contributable.contribution.policy.group_policy?
-      last_saved_policy = Policy._default(current_user, nil) # second parameter ensures that this policy is not applied anywhere
+      if contributable.contribution.policy.nil? || contributable.contribution.policy.group_policy?
+        last_saved_policy = Policy._default(current_user, nil) # second parameter ensures that this policy is not applied anywhere
 
-      policy = Policy.new(:name => 'auto',
-          :contributor_type => 'User', :contributor_id => current_user.id,
-          :share_mode         => sharing_class,
-          :update_mode        => updating_class)
-      contributable.contribution.policy = policy  # by doing this the new policy object is saved implicitly too
-      contributable.contribution.save
-    else
-       policy = contributable.contribution.policy
-       last_saved_policy = policy.clone # clone required, not 'dup' (which still works through reference, so the values in both get changed anyway - which is not what's needed here)
-       
-       policy.share_mode = sharing_class
-       policy.update_mode = updating_class
-       policy.save
-    end
+        policy = Policy.new(:name => 'auto',
+            :contributor_type => 'User', :contributor_id => current_user.id,
+            :share_mode         => sharing_class,
+            :update_mode        => updating_class)
+        contributable.contribution.policy = policy  # by doing this the new policy object is saved implicitly too
+        contributable.contribution.save
+      else
+         policy = contributable.contribution.policy
+         last_saved_policy = policy.clone # clone required, not 'dup' (which still works through reference, so the values in both get changed anyway - which is not what's needed here)
+         
+         policy.share_mode = sharing_class
+         policy.update_mode = updating_class
+         policy.save
+      end
 
 
-    # Process 'update' permissions for "Some of my Friends"
+      # Process 'update' permissions for "Some of my Friends"
 
-    if updating_class == "5"
-      if params[:updating_somefriends]
-        # Delete old User permissions
+      if updating_class == "5"
+        if params[:updating_somefriends]
+          # Delete old User permissions
+          policy.delete_all_user_permissions
+          
+          # Now create new User permissions, if required
+          params[:updating_somefriends].each do |f|
+            Permission.new(:policy => policy,
+                :contributor => (User.find f[1].to_i),
+                :view => 1, :download => 1, :edit => 1).save
+          end
+        else # none of the 'some of my friends' were selected, error
+          # revert changes made to policy (however any permissions updated will preserve the state)
+          policy.copy_values_from( last_saved_policy )
+          policy.save
+          error_msg += "You have selected to set 'update' permissions for 'Some of your Friends', but didn't select any from the list.</br>Previous (if any) or default sharing permissions have been set."
+          return error_msg
+        end
+      else
+        # Delete all User permissions - as this isn't mode 5 (i.e. the mode has changed),
+        # where some explicit permissions to friends are set
         policy.delete_all_user_permissions
-        
-        # Now create new User permissions, if required
-        params[:updating_somefriends].each do |f|
-          Permission.new(:policy => policy,
-              :contributor => (User.find f[1].to_i),
-              :view => 1, :download => 1, :edit => 1).save
-        end
-      else # none of the 'some of my friends' were selected, error
-        # revert changes made to policy (however any permissions updated will preserve the state)
-        policy.copy_values_from( last_saved_policy )
-        policy.save
-        error_msg += "You have selected to set 'update' permissions for 'Some of your Friends', but didn't select any from the list.</br>Previous (if any) or default sharing permissions have been set."
-        return error_msg
       end
-    else
-      # Delete all User permissions - as this isn't mode 5 (i.e. the mode has changed),
-      # where some explicit permissions to friends are set
-      policy.delete_all_user_permissions
+      
+
+      # Process explicit Group permissions now
+      process_permissions(policy, params)
+
+      logger.debug("------ Workflow create summary ------------------------------------")
+      logger.debug("current_user   = #{current_user.id}")
+      logger.debug("updating_class = #{updating_class}")
+      logger.debug("sharing_class  = #{sharing_class}")
+      logger.debug("policy         = #{policy}")
+      logger.debug("group_sharing  = #{params[:group_sharing]}")
+      logger.debug("-------------------------------------------------------------------")
+
+      # returns some message in case of errors (or empty string in case of success)
+      return error_msg
     end
-    
 
-    # Process explicit Group permissions now
-    process_permissions(policy, params)
+    # Remember which groups have view access to the contributable before
+    # changes are made.
 
-    logger.debug("------ Workflow create summary ------------------------------------")
-    logger.debug("current_user   = #{current_user.id}")
-    logger.debug("updating_class = #{updating_class}")
-    logger.debug("sharing_class  = #{sharing_class}")
-    logger.debug("policy         = #{policy}")
-    logger.debug("group_sharing  = #{params[:group_sharing]}")
-    logger.debug("-------------------------------------------------------------------")
+    conditions = { :contributor_type => 'Network', :view => true }
 
-    # returns some message in case of errors (or empty string in case of success)
-    return error_msg
+    old_groups = contributable.contribution.policy.permissions.find(:all, :conditions => conditions).map { |p| p.contributor }
+
+    result = aux(contributable, params)
+
+    # Work out which groups have view access after the changes were made and
+    # generate activities for them.
+
+    contributable.contribution.policy.permissions.find(:all, :conditions => conditions).each do |permission|
+      next if old_groups.include?(permission.contributor)
+      Activity.create_activities(:subject => user, :action ="" 'create', :object => permission, :contributable => contributable)
+    end
+
+    result
   end
 
   def process_permissions(policy, params)
@@ -393,6 +415,33 @@
     
   end
  
+  def update_feed_definition(resource, params)
+  
+    attributes = { :uri => params[:feed_uri], :username => params[:feed_user] }
+
+    # Only set the password if one was provided
+
+    attributes[:password] = params[:feed_pass] unless params[:feed_pass].empty?
+
+    # Create the feed if necessary
+
+    if resource.feed.nil? && !params[:feed_uri].empty?
+      resource.create_feed(attributes)
+    end
+
+    # Delete the feed if necessary
+
+    if resource.feed && params[:feed_uri].empty?
+      resource.feed.destroy
+    end
+
+    # Update the feed if necessary
+
+    if resource.feed && !params[:feed_uri].empty?
+      resource.feed.update_attributes(attributes)
+    end
+  end
+
   # helper function to determine the context of a polymorphic nested resource
 
   def extract_resource_context(params)

Modified: branches/component-querying/app/controllers/blobs_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/blobs_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/blobs_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -177,7 +177,7 @@
           # update policy
           @blob.contribution.update_attributes(params[:contribution])
         
-          policy_err_msg = update_policy(@blob, params)
+          policy_err_msg = update_policy(@blob, params, current_user)
 
           update_credits(@blob, params)
           update_attributions(@blob, params)
@@ -246,7 +246,7 @@
 
         @blob.refresh_tags(convert_tags_to_gem_format(params[:blob][:tag_list]), current_user) if params[:blob][:tag_list]
         
-        policy_err_msg = update_policy(@blob, params)
+        policy_err_msg = update_policy(@blob, params, current_user)
         update_credits(@blob, params)
         update_attributions(@blob, params)
 

Modified: branches/component-querying/app/controllers/comments_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/comments_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/comments_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -5,6 +5,8 @@
 
 class CommentsController < ApplicationController
   
+  include ActivitiesHelper
+
   before_filter :find_context, : [ :create, :index, :timeline ]
   before_filter :find_comment, : [ :destroy ]
 
@@ -32,19 +34,28 @@
       ajaxy = false
     end
 
+    if Authorization.check('create', Comment, current_user, @context) == false
+      render_401("You are not authorized to create this comment.")
+      return
+    end
+
     if text and text.length > 0
       comment = Comment.new(:user => current_user, :comment => text, :commentable => @context)
 
       success = comment.save
 
       if success
-        Activity.create(:subject => current_user, :action ="" 'create', :objekt => comment, :auth => @context)
+        Activity.create_activities(:subject => current_user, :action ="" 'create', :object => comment, :auth => @context)
         @context.solr_index if @context.respond_to?(:solr_index)
       end
     end
     
     respond_to do |format|
-      if ajaxy
+      if params[:activity_feed] || @context.kind_of?(Activity)
+        @context = @context.context if @context.kind_of?(Activity)
+        activities = activities_for_feed(:context => @context, :user => current_user)
+        format.html { render :partial => "activities/list", :locals => { :context => @context, :activities => activities, :user => current_user } }
+      elsif ajaxy
         format.html { render :partial => "comments/comments", :locals => { :commentable => @context } }
       else
         format.html { redirect_to rest_resource_uri(@context) }
@@ -83,7 +94,11 @@
   end
 
   def find_context
-    @context = extract_resource_context(params)
+    if request.path_parameters.include?("activity_id")
+      @context = Activity.find(request.path_parameters["activity_id"])
+    else
+      @context = extract_resource_context(params)
+    end
 
     if @context.nil?
       render_404("Comment context not found.")

Modified: branches/component-querying/app/controllers/experiments_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/experiments_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/experiments_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -93,7 +93,7 @@
     
     if params[:assign_to_group]
       network = Network.find(params[:assign_to_group_id])
-      if network and network.member?(current_user.id)
+      if network and network.member?(current_user)
         @experiment.contributor = network
       else
         flash[:error] = "Experiment could not be created because could not assign ownership to Group."

Modified: branches/component-querying/app/controllers/group_announcements_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/group_announcements_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/group_announcements_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -65,6 +65,9 @@
 
     respond_to do |format|
       if @announcement.save
+
+        Activity.create_activities(:subject => @announcement.user, :action ="" 'create', :object => @announcement)
+
         flash[:notice] = 'Group announcement was successfully created.'
         format.html { redirect_to group_announcements_url(@group) }
       else
@@ -77,6 +80,9 @@
   def update
     respond_to do |format|
       if @announcement.update_attributes(params[:announcement])
+
+        Activity.create_activities(:subject => @announcement.user, :action ="" 'edit', :object => @announcement)
+
         flash[:notice] = 'GroupAnnouncement was successfully updated'
         format.html { redirect_to group_announcement_url(@group, @announcement) }
       else
@@ -108,7 +114,7 @@
 
   
   def check_admin
-    unless @group.administrator?(current_user.id)
+    unless @group.administrator?(current_user)
       render_401("Only group administrators are allowed to create new announcements.")
     end
   end
@@ -131,27 +137,18 @@
 
       # at this point, group announcement is found and it definitely belongs to the group in URL;
       # now go through different actions and check which links are allowed for current user
-      not_auth = false
       case action_name.to_s.downcase
         when "show"
           # if the announcement is private, show it only to group members
-          unless @announcement.public || @group.member?(current_user.id)
-            not_auth = true
+          unless @announcement.public || (logged_in? && @group.member?(current_user))
+            render_401("You are not authorized to view this group announcement.")
           end
         when "edit","update","destroy"
           # only owner of the group can destroy the announcement
-          unless (@announcement.user == current_user) || (@group.owner?(current_user.id))
-            not_auth = true
+          unless logged_in? && ((@announcement.user == current_user) || (@group.owner?(current_user)))
+            render_401("You are not authorized to #{action_name.to_s.downcase} this group announcement.")
           end
-        else
-          # don't allow anything else, for now
-          not_auth = true
       end
-
-      # check if we had any errors
-      if not_auth
-        raise ActiveRecord::RecordNotFound, "Group announcement was not found"
-      end
     end
   end
 end

Modified: branches/component-querying/app/controllers/group_policies_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/group_policies_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/group_policies_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -103,7 +103,7 @@
 
   
   def check_admin
-    unless @group.administrator?(current_user.id)
+    unless @group.administrator?(current_user)
       render_401("Only group administrators are allowed to manage policies.")
     end
   end

Modified: branches/component-querying/app/controllers/memberships_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/memberships_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/memberships_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -82,6 +82,9 @@
 
     respond_to do |format|
       if @membership.accept!
+
+        Activity.create_activities(:subject => @membership.user, :action ="" 'create', :object => @membership)
+
         flash[:notice] = 'Membership was successfully accepted.'
         format.html { redirect_to network_url(@membership.network_id) }
       else
@@ -144,8 +147,14 @@
   def create
     # TODO: test if "user_established_at" and "network_established_at" can be hacked (ie: set) through API calls,
     # thereby creating memberships that are already 'accepted' at creation.
-    if (@membership = Membership.new(params[:membership]) unless Membership.find_by_user_id_and_network_id(params[:membership][:user_id], params[:membership][:network_id]) or Network.find(params[:membership][:network_id]).owner? params[:membership][:user_id])
-      
+    user = User.find_by_id(params[:membership][:user_id])
+    if user.nil?
+      render_404("User not found.")
+    elsif !Membership.find_by_user_id_and_network_id(params[:membership][:user_id], params[:membership][:network_id]) ||
+        Network.find(params[:membership][:network_id]).owner?(user)
+
+      @membership = Membership.new(params[:membership])
+
       @membership.user_established_at = nil
       @membership.network_established_at = nil
       if @membership.message.blank?
@@ -375,14 +384,14 @@
               not_auth = true
             end
           elsif @membership.network_established_at == nil
-            unless @membership.network.administrator?(current_user.id) # TODO: CHECK WHY?! && params[:user_id].to_i == @membership.network.owner.id
+            unless @membership.network.administrator?(current_user) # TODO: CHECK WHY?! && params[:user_id].to_i == @membership.network.owner.id
               not_auth = true
             end
           end
         when "show", "destroy", "update"
           # Only the owner of the network OR the person who the membership is for can view/delete memberships;
           # link - just user to whom the membership belongs
-          unless (@membership.network.administrator?(current_user.id) ||
+          unless (@membership.network.administrator?(current_user) ||
               @membership.user_id == current_user.id) && @membership.user_id == params[:user_id].to_i
             not_auth = true
           end

Modified: branches/component-querying/app/controllers/networks_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/networks_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/networks_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -8,14 +8,15 @@
 class NetworksController < ApplicationController
 
   include ApplicationHelper
+  include ActivitiesHelper
 
   before_filter :login_required, :except => [:index, :show, :content, :search, :all]
   
   before_filter :find_networks, : [:all]
   before_filter :find_network, : [:membership_request, :show, :tag, :content,
                                          :edit, :update, :destroy, :invite, :membership_invite,
-                                         :membership_invite_external]
-  before_filter :find_network_auth_admin, : [:invite, :membership_invite, :membership_invite_external]
+                                         :membership_invite_external, :sync_feed, :subscription]
+  before_filter :find_network_auth_admin, : [:invite, :membership_invite, :membership_invite_external, :sync_feed]
   before_filter :find_network_auth_owner, : [:edit, :update, :destroy]
   
   # declare sweepers and which actions should invoke them
@@ -55,7 +56,10 @@
   def membership_invite
     @membership = Membership.new(:user_id => params[:user_id], :network_id => @network.id, :message => params[:membership][:message], :invited_by => current_user)
 
-    unless address@hidden || Membership.find_by_user_id_and_network_id(params[:user_id], @network.id) || Network.find(@network.id).owner?(params[:user_id])
+    if (user = User.find_by_id(params[:user_id]))
+      render_404("User not found.")
+    elsif !(address@hidden || Membership.find_by_user_id_and_network_id(params[:user_id], @network.id) ||
+           Network.find(@network.id).owner?(user))
       @membership.user_established_at = nil
       @membership.network_established_at = nil
       if @membership.message.blank?
@@ -155,16 +159,16 @@
       existing_db_addr_existing_membership_err_list = []
       existing_db_addr_successful_membership_invites_list = []
       
-      db_user_addresses.each { |db_addr, usr_id|
+      db_user_addresses.each { |db_addr, user|
         if db_addr == current_user.email
           own_address_err += db_addr
-        elsif Network.find(params[:id]).member?(usr_id) || User.find(usr_id).membership_pending?(params[:id]) # email doesn't belong to current user
+        elsif Network.find(params[:id]).member?(user) || User.find(usr_id).membership_pending?(params[:id]) # email doesn't belong to current user
           # the invited user is already a member of that group
           existing_db_addr_existing_membership_err_list << db_addr
         else
           # need to create internal membership invite, as one not yet exists
           existing_db_addr_successful_membership_invites_list << db_addr
-          req = Membership.new(:user_id => usr_id, :network_id => params[:id], :user_established_at => nil, :network_established_at => Time.now, :message => params[:invitations][:msg_text])
+          req = Membership.new(:user_id => user.id, :network_id => params[:id], :user_established_at => nil, :network_established_at => Time.now, :message => params[:invitations][:msg_text])
           req.save
         end
       }
@@ -275,6 +279,15 @@
           render :inline => `#{Conf.rdfgen_tool} groups address@hidden
         }
       end
+
+      format.atom {
+        @title = @network.title
+        @id = @resource = network_url(@network)
+        @updated = @network.updated_at.to_datetime.rfc3339
+        @entries = activities_for_feed(:context => @network, :user => current_user, :no_combine => true)
+
+        render "activities/feed.atom"
+      }
     end
   end
 
@@ -322,7 +335,10 @@
 
     respond_to do |format|
       if @network.save
-        Activity.create(:subject => current_user, :action ="" 'create', :objekt => @network)
+        Activity.create_activities(:subject => current_user, :action ="" 'create', :object => @network)
+
+        update_feed_definition(@network, params)
+
         if params[:network][:tag_list]
           @network.tags_user_id = current_user
           @network.tag_list = convert_tags_to_gem_format params[:network][:tag_list]
@@ -343,7 +359,8 @@
 
     respond_to do |format|
       if @network.update_attributes(params[:network])
-        Activity.create(:subject => current_user, :action ="" 'edit', :objekt => @network)
+        Activity.create_activities(:subject => current_user, :action ="" 'edit', :object => @network)
+        update_feed_definition(@network, params)
         @network.refresh_tags(convert_tags_to_gem_format(params[:network][:tag_list]), current_user) if params[:network][:tag_list]
         flash[:notice] = 'Group was successfully updated.'
         format.html { redirect_to network_url(@network) }
@@ -377,6 +394,7 @@
           page.replace_html "mini_nav_tag_link", "(#{unique_tag_count})"
           page.replace_html "tags_box_header_tag_count_span", "(#{unique_tag_count})"
           page.replace_html "tags_inner_box", :partial => "tags/tags_box_inner", :locals => { :taggable => @network, :owner_id => @network.user_id } 
+          page.replace_html "activities", :partial => "activities/list", :locals => { :context => @network, :activities => activities_for_feed(:context => @network, :user => current_user), :user => current_user }
         end
       }
     end
@@ -394,7 +412,30 @@
     render :partial => 'networks/autocomplete_list', :locals => { :networks => groups }
   end
 
+  def sync_feed
+    @network.feed.synchronize! if @network.feed
+    redirect_to network_path(@network)
+  end
   
+  # PUT/DELETE /groups/1/subscription
+  def subscription
+
+    object = @network
+
+    existing_subscription = current_user.subscriptions.find(:first,
+        :conditions => { :objekt_type => object.class.name, :objekt_id => object.id } )
+
+    case request.method
+    when :put
+      current_user.subscriptions.create(:objekt => object) unless existing_subscription
+
+    when :delete
+      current_user.subscriptions.delete(existing_subscription) if existing_subscription
+    end
+
+    redirect_to object
+  end
+
 protected
 
   def find_networks
@@ -421,7 +462,7 @@
   end
   
   def find_network_auth_admin
-    unless @network.administrator?(current_user.id)
+    unless @network.administrator?(current_user)
       render_401("You must be a group administrator to perform this action.")
     end
   end

Modified: branches/component-querying/app/controllers/packs_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/packs_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/packs_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -143,7 +143,7 @@
         end
         
         # update policy
-        policy_err_msg = update_policy(@pack, params)
+        policy_err_msg = update_policy(@pack, params, current_user)
         if policy_err_msg.blank?
           update_layout(@pack, params[:layout]) unless params[:policy_type] == "group"
           flash[:notice] = 'Pack was successfully created.'
@@ -171,7 +171,7 @@
     respond_to do |format|
       if @pack.update_attributes(params[:pack])
         @pack.refresh_tags(convert_tags_to_gem_format(params[:pack][:tag_list]), current_user) if params[:pack][:tag_list]
-        policy_err_msg = update_policy(@pack, params)
+        policy_err_msg = update_policy(@pack, params, current_user)
         if policy_err_msg.blank?
           update_layout(@pack, params[:layout]) unless params[:policy_type] == "group"
           flash[:notice] = 'Pack was successfully updated.'

Modified: branches/component-querying/app/controllers/policies_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/policies_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/policies_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -9,7 +9,7 @@
     @policy = Policy.find(params[:id])
 
     unless current_user == @policy.contributor ||
-           @policy.contributor_type == 'Network' && @policy.contributor.administrator?(current_user.id)
+           @policy.contributor_type == 'Network' && @policy.contributor.administrator?(current_user)
       render :code => 401
     end
   end

Modified: branches/component-querying/app/controllers/runners_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/runners_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/runners_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -105,7 +105,7 @@
     
     if params[:assign_to_group]
       network = Network.find(params[:assign_to_group_id])
-      if network and network.member?(current_user.id)
+      if network and network.member?(current_user)
         @runner.contributor = network
       else
         flash[:error] = "Experiment could not be created because could not assign ownership to Group."

Modified: branches/component-querying/app/controllers/users_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/users_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/users_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -491,7 +491,7 @@
       existing_db_addr_successful_friendship_requests_list = []
       
       is_friendship_request = (!params[:invitations][:as_friendship].nil? && params[:invitations][:as_friendship] == "true" ? true : false)
-      db_user_addresses.each { |db_addr, usr_id|
+      db_user_addresses.each { |db_addr, user|
         if db_addr == current_user.email
           own_address_err += db_addr
         elsif !is_friendship_request 
@@ -499,12 +499,12 @@
           existing_db_addr_plain_invite_err_list << db_addr
         else
           # email doesn't belong to current user & it's a friendship request
-          if current_user.friend?(usr_id) || current_user.friendship_pending?(usr_id)
+          if current_user.friend?(user.id) || current_user.friendship_pending?(user.id)
             existing_db_addr_existing_friendship_err_list << db_addr
           else
             # need to create internal friendship request, as one not yet exists
             existing_db_addr_successful_friendship_requests_list << db_addr
-            req = Friendship.new(:user_id => current_user.id, :friend_id => usr_id, :accepted_at => nil, :message => params[:invitations][:msg_text])
+            req = Friendship.new(:user_id => current_user.id, :friend_id => user.id, :accepted_at => nil, :message => params[:invitations][:msg_text])
             req.save
           end
         end
@@ -597,88 +597,92 @@
     @to   = params[:to].to_i
 
     if @to > 0
+      users = User.users_to_check.find(:all, :conditions => ["id >= ? AND id <= ?", @from, @to])
+    else
+      users = User.users_to_check.find(:all)
+    end
 
-      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 != 'suspect' AND account_status != 'whitelist'))", @from, @to])
+    @userlist = users.map do |user|
 
-      @userlist = users.map do |user|
+      strings = []
 
-        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(", "))
 
-        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|
 
-        user.networks_owned.each do |network|
+        add(strings, :label  => "group title",
+                     :link   => polymorphic_path(network),
+                     :string => network.title) 
 
-          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
 
-          add(strings, :label  => "group description",
-                       :link   => polymorphic_path(network),
-                       :string => network.description_html,
-                       :escape => :false) 
-        end
+      user.packs.each do |pack|
 
-        user.packs.each do |pack|
+        add(strings, :label  => "pack title",
+                     :link   => polymorphic_path(pack),
+                     :string => pack.title) 
 
-          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
 
-          add(strings, :label  => "pack description",
-                       :link   => polymorphic_path(pack),
-                       :string => pack.description_html,
-                       :escape => :false) 
-        end
+      user.workflows.each do |workflow|
 
-        user.workflows.each do |workflow|
+        add(strings, :label  => "workflow title",
+                     :link   => polymorphic_path(workflow),
+                     :string => workflow.title) 
 
-          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
 
-          add(strings, :label  => "workflow description",
-                       :link   => polymorphic_path(workflow),
-                       :string => workflow.body_html,
-                       :escape => :false) 
-        end
+      user.blobs.each do |blob|
 
-        user.blobs.each do |blob|
+        add(strings, :label  => "file title",
+                     :link   => polymorphic_path(blob),
+                     :string => blob.title) 
 
-          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
 
-          add(strings, :label  => "file description",
-                       :link   => polymorphic_path(blob),
-                       :string => blob.body_html,
-                       :escape => :false) 
-        end
+      user.comments.each do |comment|
 
-        user.comments.each do |comment|
+        commentable = comment.commentable
+        commentable = commentable.context if commentable.kind_of?(Activity)
 
-          add(strings, :label  => "comment",
-                       :link   => polymorphic_path(comment.commentable),
-                       :string => comment.comment,
-                       :escape => :white_list) 
-        end
+        add(strings, :label  => "comment",
+                     :link   => polymorphic_path(commentable),
+                     :string => comment.comment,
+                     :escape => :white_list) 
+      end
 
-        { :ob => user, :strings => strings }
+      { :ob => user, :strings => strings }
 
-      end
     end
   end
 

Modified: branches/component-querying/app/controllers/workflows_controller.rb (3546 => 3547)


--- branches/component-querying/app/controllers/workflows_controller.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/controllers/workflows_controller.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -369,7 +369,7 @@
           raise unless Rails.env == "production"
         end
 
-        policy_err_msg = update_policy(@workflow, params)
+        policy_err_msg = update_policy(@workflow, params, current_user)
 
         # Credits and Attributions:
         update_credits(@workflow, params)
@@ -553,7 +553,7 @@
           @workflow.solr_index if Conf.solr_enable
         end
 
-        policy_err_msg = update_policy(@workflow, params)
+        policy_err_msg = update_policy(@workflow, params, current_user)
         update_credits(@workflow, params)
         update_attributions(@workflow, params)
 

Copied: branches/component-querying/app/helpers/activities_helper.rb (from rev 3546, trunk/app/helpers/activities_helper.rb) (0 => 3547)


--- branches/component-querying/app/helpers/activities_helper.rb	                        (rev 0)
+++ branches/component-querying/app/helpers/activities_helper.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,301 @@
+# myExperiment: app/helpers/activities_helper.rb
+#
+# Copyright (c) 2007-2013 The University of Manchester, the University of
+# Oxford, and the University of Southampton.  See license.txt for details.
+
+module ActivitiesHelper
+
+  def activity_link(activity, source)
+
+    case source
+    when :subject
+      thing = activity.subject
+      label = activity.subject_label
+    when :object
+      thing = activity.objekt
+      label = activity.objekt_label
+    when :context
+      thing = activity.context
+      label = activity.context.label
+    when :auth
+      thing = activity.auth
+      label = activity.auth.label
+    end
+
+    thing = thing.versioned_resource if thing.respond_to?(:versioned_resource)
+
+    if thing
+      path = case thing.class.name
+        when "Bookmark"
+          polymorphic_path(thing.bookmarkable)
+        when "Comment"
+          polymorphic_path(thing.commentable)
+        when "Citation"
+          polymorphic_path(thing.workflow)
+        when "GroupAnnouncement"
+          group_announcement_path(thing.network, thing)
+        else
+          polymorphic_path(thing)
+      end
+
+      link_to(h(label), path)
+    else
+      h(label)
+    end
+  end
+  
+  def combine_activities?(a, b)
+
+    return false if a.action != b.action
+    return false if a.objekt_type != b.objekt_type
+
+    return true if a.action == 'create' && a.objekt_type == 'Membership'
+    return true if a.action == 'create' && a.objekt_type == 'Tagging' && a.subject == b.subject
+
+    false
+  end
+
+  def activities_for_feed(opts)
+
+    page     = opts.delete(:page)     || 1
+    per_page = opts.delete(:per_page) || 12
+
+    first    = (page - 1) * per_page
+    last     = first + (per_page - 1)
+
+    # Create the conditions based on the contexts (resources to which news
+    # items belong) and also the types of new items to show.
+
+    context_bits = []
+    context_vars = []
+
+    if opts[:context]
+      context_bits << "(activities.context_type = ? AND activities.context_id = ?)"
+      context_vars << opts[:context].class.name
+      context_vars << opts[:context].id
+    else
+      
+    end
+
+    type_bits = []
+    type_vars = []
+
+    type_bits << "(activities.objekt_type = 'Network' AND activities.action = '')"
+    type_bits << "(activities.objekt_type = 'FeedItem' AND activities.action = '')"
+    type_bits << "(activities.objekt_type = 'Permission' AND activities.action = '')"
+    type_bits << "(activities.objekt_type = 'Comment' AND activities.action = '')"
+    type_bits << "(activities.objekt_type = 'GroupAnnouncement' AND activities.action = '')"
+    type_bits << "(activities.objekt_type = 'Membership' AND activities.action = '')"
+
+    # Create the conditions
+
+    if (context_bits.empty? && type_bits.empty?)
+      conditions = nil
+    elsif (!context_bits.empty? && type_bits.empty?)
+      conditions = ["(" + context_bits.join(" OR ") + ")", *context_vars]
+    elsif (context_bits.empty? && !type_bits.empty?)
+      conditions = ["(" + type_bits.join(" OR ") + ")", *type_vars]
+    else
+      conditions = ["((" + context_bits.join(" OR ") + ") AND (" + type_bits.join(" OR ") + "))", *(context_vars + type_vars)]
+    end
+
+    order = 'featured DESC, timestamp DESC, priority ASC'
+
+    activities = Authorization.scoped(Activity,
+        :auth_type       => 'activities.auth_type',
+        :auth_id         => 'activities.auth_id',
+        :group           => 'activities.id',
+        :authorised_user => opts[:user])
+    
+    results = []
+    pos = 0
+
+    while results.length <= last
+      incoming = activities.all(:conditions => conditions, :order => order, :limit => "#{pos}, #{per_page}")
+      
+      break if incoming.length == 0
+
+      incoming.each do |activity|
+
+        # Special case for group announcements as they can be made private.
+
+        if activity.objekt.kind_of?(GroupAnnouncement) && !activity.objekt.public
+          next unless logged_in?
+          next unless activity.objekt.network.member?(current_user)
+        end
+
+        if results.length > 0 && !opts[:no_combine] && combine_activities?(activity, results.last.first)
+          results.last << activity
+        else
+          results << [activity]
+        end
+      end
+
+      pos = pos + per_page
+    end
+    
+    results[first..last]
+  end
+
+  def sentence(bits)
+    result = ""
+
+    bits.each_index do |i|
+      result << bits[i]
+      result << ", " unless i == bits.length - 1
+      result << "and " if i == bits.length - 2
+    end
+
+    result
+  end
+
+  def activity_text_summary(text, opts = {})
+
+    tokens = HTML::Tokenizer.new(CGI::unescapeHTML(text))
+
+    result = ""
+
+    while (token = tokens.next) do
+      node = HTML::Node.parse(nil, 0, 0, token, false)
+      result << node.to_s if node.kind_of?(HTML::Text) || node.kind_of?(String)
+      result << " "
+    end
+
+    result = result.gsub(/\s+/, ' ').strip
+
+    min_chars = opts[:min_chars] || 200
+
+    if (result.length > min_chars)
+      result = h("#{result[0..min_chars]}") + " &#8230;"
+    end
+
+    "<div class='summary'>#{result}</div>"
+  end
+
+  def news_item_avatar(news_items)
+
+    news_item = news_items.first
+
+    # Only show an image if all the subjects match
+
+    if news_items.length > 1
+      news_items.each do |news_item|
+        return if news_item.subject != news_item.subject
+      end
+    end
+  
+    if news_item.subject_type == 'User'
+      avatar(news_item.subject_id, 48)
+    elsif news_item.subject_type == 'Network'
+      avatar(news_item.subject.owner.id, 48)
+    end
+  end
+
+  def activity_title(activity_set)
+
+    activity = activity_set.first
+
+    case activity.objekt ? "#{activity.objekt_type} #{activity.action}" : activity.action
+    when "Announcement create"
+      "#{activity_link(activity, :subject)} announced #{activity_link(activity, :object)}"
+    when "Announcement edit"
+      "#{activity_link(activity, :subject)} edited #{activity_link(activity, :object)}"
+    when "Blob create"
+      "#{activity_link(activity, :subject)} uploaded #{activity_link(activity, :object)}"
+    when "Blob edit"
+      "#{activity_link(activity, :subject)} edited #{activity_link(activity, :object)}"
+    when "BlobVersion create"
+      "#{activity_link(activity, :subject)} uploaded version #{activity.extra} of #{activity_link(activity, :object)}"
+    when "BlobVersion edit"
+      "#{activity_link(activity, :subject)} edited version #{activity.extra} of #{activity_link(activity, :object)}"
+    when "Bookmark create"
+      "#{activity_link(activity, :subject)} favourited #{activity_link(activity, :object)}"
+    when "Citation create"
+      "#{activity_link(activity, :subject)} added the citation #{activity_link(activity, :object)} to #{activity_link(activity, :auth)}"
+    when "Citation edit"
+      "#{activity_link(activity, :subject)} edited the citation #{activity_link(activity, :object)} on #{activity_link(activity, :auth)}"
+    when "Comment create"
+      "#{activity_link(activity, :subject)} commented:"
+    when "Friendship create"
+      user1 = activity.subject = activity.context ? activity.objekt.user : activity.objekt.friend
+      user2 = activity.subject = activity.context ? activity.objekt.friend : activity.objekt.user
+      "#{link_to(h(user1.name), polymorphic_path(user1))} is friends with #{link_to(h(user2.name), polymorphic_path(user2))}"
+    when "Network create"
+      "#{activity_link(activity, :subject)} created the #{activity_link(activity, :object)} group"
+    when "Network edit"
+      "#{activity_link(activity, :subject)} edited the #{activity_link(activity, :object)} group"
+    when "Pack create"
+      "#{activity_link(activity, :subject)} created #{activity_link(activity, :object)}"
+    when "Pack edit"
+      "#{activity_link(activity, :subject)} edited #{activity_link(activity, :object)}"
+    when "Rating create"
+      "#{activity_link(activity, :subject)} rated #{activity_link(activity, :auth)} with #{activity.extra}"
+    when "Review create"
+      "#{activity_link(activity, :subject)} reviewed #{activity_link(activity, :auth)}"
+    when "Review edit"
+      "#{activity_link(activity, :subject)} edited a review on #{activity_link(activity, :auth)}"
+    when "Tagging create"
+      "#{activity_link(activity, :subject)} tagged #{activity_link(activity, :auth)} with #{sentence(activity_set.map { |a| link_to(h(a.objekt.tag.name), tag_path(a.objekt.tag)) })}"
+    when "Workflow create"
+      "#{activity_link(activity, :subject)} uploaded #{activity_link(activity, :object)}"
+    when "Workflow edit"
+      "#{activity_link(activity, :subject)} edited #{activity_link(activity, :object)}"
+    when "WorkflowVersion create"
+      "#{activity_link(activity, :subject)} uploaded version #{activity.extra} of #{activity_link(activity, :object)}"
+    when "WorkflowVersion edit"
+      "#{activity_link(activity, :subject)} edited version #{activity.extra} of #{activity_link(activity, :object)}"
+    when "edit"
+      "#{activity_link(activity, :subject)} edited their profile"
+    when "register"
+      "#{activity_link(activity, :subject)} joined #{Conf.sitename}"
+    when "Membership create"
+      "#{sentence(activity_set.map { |a| activity_link(a, :subject) })} joined the #{activity_link(activity, :context)} group"
+    when "Permission create"
+      "#{activity_link(activity, :subject)} shared #{activity_link(activity, :auth)}"
+    when "FeedItem create"
+      link_to(h(activity.objekt.title), activity.objekt.link, :rel => "nofollow")
+    when "GroupAnnouncement create"
+      activity_link(activity, :object)
+    end
+  end
+
+  def activity_description(activity_set, opts = {})
+
+    min_chars = opts[:min_chars] || 300
+
+    activity = activity_set.first
+
+    case activity.objekt ? "#{activity.objekt_type} #{activity.action}" : activity.action
+    when "BlobVersion create"
+      activity.objekt.body_html
+    when "Comment create"
+      "<a name='comment_#{activity.objekt.id}'></a>#{activity_text_summary(activity.objekt.comment, :min_chars => min_chars)}"
+    when "Workflow create"
+      "<div style='float: left; width: 64px'>#{link_to(image_tag(workflow_version_preview_path(activity.objekt, 1, 'thumb'), :width => 64, :height => 64), workflow_version_path(activity.objekt 1))}</div><div class='activity-text'>#{activity.objekt.body_html}</div>"
+    when "WorkflowVersion create"
+      "<div style='float: left; width: 64px'>#{link_to(image_tag(workflow_version_preview_path(activity.objekt.workflow, activity.objekt.version, 'thumb'), :width => 64, :height => 64), workflow_version_path(activity.objekt.workflow, activity.objekt.version))}</div><div class='activity-text'>#{white_list(activity.objekt.revision_comments)}</div>"
+    when "Permission create"
+      case activity.auth
+      when Workflow
+        "<div><div style='float: left; margin: 6px'>#{link_to(image_tag(workflow_preview_path(activity.auth, 'thumb'), :width => 64, :height => 64), workflow_path(activity.auth))}</div>#{activity_text_summary(activity.auth.body_html, :min_chars => min_chars)}<div style='clear: both'></div></div>"
+      when Blob, Pack
+        "<div>#{activity_text_summary(activity.auth.body_html, :min_chars => min_chars)}</div>"
+      end
+    when "FeedItem create"
+      "<div class='summary'>#{activity_text_summary(activity.objekt.content, :min_chars => min_chars)}</div>"
+    when "GroupAnnouncement create"
+      activity_text_summary(activity.objekt.body_html, :min_chars => min_chars)
+    end
+  end
+
+  def activity_extra(activity_set, opts = {})
+
+    activity = activity_set.first
+
+    case activity.objekt ? "#{activity.objekt_type} #{activity.action}" : activity.action
+    when "FeedItem create"
+      "<div class='extra'>#{image_tag("feed_gray.png", :size => "10x10", :alt_text => "Original atom feed for this news item")} Content via #{link_to(h(activity.objekt.feed.uri), activity.objekt.feed.uri)}</div>"
+    end
+  end
+end
+

Modified: branches/component-querying/app/helpers/application_helper.rb (3546 => 3547)


--- branches/component-querying/app/helpers/application_helper.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/helpers/application_helper.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -964,7 +964,7 @@
       if membership.user_established_at == nil
         return membership.user_id == current_user.id
       elsif membership.network_established_at == nil
-        return membership.network.administrator?(current_user.id)
+        return membership.network.administrator?(current_user)
       end 
     else
       return false

Modified: branches/component-querying/app/models/activity.rb (3546 => 3547)


--- branches/component-querying/app/models/activity.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/models/activity.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -3,12 +3,17 @@
 # Copyright (c) 2012 University of Manchester and the University of Southampton.
 # See license.txt for details.
 
+require 'securerandom'
+
 class Activity < ActiveRecord::Base
 
   belongs_to :subject, :polymorphic => true
   belongs_to :objekt,  :polymorphic => true
+  belongs_to :context, :polymorphic => true
   belongs_to :auth,    :polymorphic => true
 
+  has_many :comments, :as => :commentable, :dependent => :destroy
+
   validates_presence_of :subject
   validates_presence_of :action
   validates_presence_of :subject_label
@@ -33,5 +38,129 @@
       e.objekt_label = e.auth.name  if e.auth.respond_to?(:name)
     end
   end
+
+  def self.new_activities(opts)
+
+    subject   = opts[:subject]
+    action    = ""
+    object    = opts[:object]
+    timestamp = opts[:timestamp]
+    auth      = nil
+    extra     = nil
+    contexts  = [subject]
+    priority  = 0
+
+    return [] if opts[:auth].kind_of?(Activity)
+
+    # Set the timestamp to the current time if no timestamp was provided.
+
+    timestamp = Time.now if timestamp.nil?
+
+    case object.class.name
+
+      when "Workflow", "Blob", "Pack"
+
+        contexts << object
+        auth = object
+        
+        priority = 100 if action == 'create'
+
+      when "WorkflowVersion", "BlobVersion"
+
+        contexts << object.versioned_resource
+        extra = object.version
+        auth = object.versioned_resource
+
+        priority = 50 if action == 'create'
+
+      when "Comment"
+
+        contexts << object.commentable
+        auth = object.commentable
+
+      when "Bookmark"
+
+        contexts << object.bookmarkable
+        auth = object.bookmarkable
+
+      when "Citation"
+
+        contexts << object.workflow
+        auth = object.workflow
+
+      when "Rating"
+
+        contexts << object.rateable
+        auth = object.rateable
+        extra = object.rating
+
+      when "Review"
+
+        contexts << object.reviewable
+        auth = object.reviewable
+
+      when "Tagging"
+
+        contexts << object.taggable
+        auth = object.taggable
+        extra = object.tag.name
+
+      when "Network"
+
+        contexts << object
+
+        priority = 100 if action == 'create'
+
+      when "Membership"
+
+        contexts << object.network
+
+      when "Permission"
+ 
+        contexts << opts[:contributable]
+        contexts << object.contributor
+        auth = opts[:contributable]
+
+      when "GroupAnnouncement"
+
+        contexts << object.network
+        extra = object.public
+
+      when "Creditation"
+
+        contexts << object.creditable
+        contexts << object.creditor if object.creditor != subject
+        auth = object.creditable
+
+      when "FeedItem"
+
+        auth = subject.feed.context
+    end
+
+    uuid = SecureRandom.uuid
+
+    contexts.map do |context|
+      Activity.new(
+          :subject => subject,
+          :action ="" action,
+          :objekt => object,
+          :extra => extra,
+          :auth => auth,
+          :uuid => uuid,
+          :timestamp => timestamp,
+          :priority => priority,
+          :context => context)
+    end
+  end
+
+
+  def self.create_activities(opts)
+    activities = self.new_activities(opts)
+
+    activities.each do |activity|
+      activity.save
+    end
+  end
+
 end
 

Copied: branches/component-querying/app/models/feed.rb (from rev 3546, trunk/app/models/feed.rb) (0 => 3547)


--- branches/component-querying/app/models/feed.rb	                        (rev 0)
+++ branches/component-querying/app/models/feed.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,72 @@
+# myExperiment: app/models/feeds.rb
+#
+# Copyright (c) 2007-2013 The University of Manchester, the University of
+# Oxford, and the University of Southampton.  See license.txt for details.
+
+require 'simple-rss'
+require 'open-uri'
+require 'encrypted_attributes'
+require 'curb'
+
+class Feed < ActiveRecord::Base
+
+  encrypts :password, :mode => :symmetric, :password => Conf.sym_encryption_key
+
+  belongs_to :context, :polymorphic => true
+
+  has_many :feed_items, :dependent => :destroy
+
+  def synchronize!
+
+    if uri
+
+       begin
+
+        c = Curl::Easy.new(uri)
+        c.http_auth_types = :basic
+
+        if username && password
+          c.username = username
+          c.password = password.decrypt
+        end
+
+        c.perform
+
+        result = SimpleRSS.parse(c.body_str)
+
+        result.feed.items.each do |item|
+
+          # Obtain a unique identifier for use within the context of this feed.
+          identifier = item[:id]
+
+          # Try to find an existing item in this feed using the identifier.
+          object = feed_items.find_by_identifier(item[:id])
+
+          if object.nil?
+            # Create a new object if an existing object wasn't found.
+            object = feed_items.new if object.nil?
+
+            notify = true
+          end
+
+          object.identifier        = item[:id]
+          object.title             = item[:title]
+          object.content           = item[:content]
+          object.author            = item[:author]
+          object.link              = item[:link]
+          object.item_published_at = item[:published]
+
+          success = object.save
+
+          if (success && notify)
+            Activity.create_activities(:subject => context, :action ="" 'create', :object => object, :timestamp => object.item_published_at)
+          end
+        end
+
+      rescue
+        return false
+      end
+    end
+  end
+end
+

Copied: branches/component-querying/app/models/feed_item.rb (from rev 3546, trunk/app/models/feed_item.rb) (0 => 3547)


--- branches/component-querying/app/models/feed_item.rb	                        (rev 0)
+++ branches/component-querying/app/models/feed_item.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,10 @@
+# myExperiment: app/models/feed_item.rb
+#
+# Copyright (c) 2007-2013 The University of Manchester, the University of
+# Oxford, and the University of Southampton.  See license.txt for details.
+
+class FeedItem < ActiveRecord::Base
+  belongs_to :feed
+  has_many :activities, :as => :objekt
+end
+

Modified: branches/component-querying/app/models/group_announcement.rb (3546 => 3547)


--- branches/component-querying/app/models/group_announcement.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/models/group_announcement.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -7,16 +7,5 @@
   validates_presence_of :network_id
   
   format_attribute :body
-  
-  before_save :check_admin # this is done in addition to check in the controller 
-  
-  def check_admin
-    if !self.user_id.blank? and self.network.member?(self.user_id)
-      return true
-    else
-      errors.add_to_base("Only group administrators are allowed to create new announcements!")
-      return false
-    end
-  end
-  
+
 end

Modified: branches/component-querying/app/models/invitation.rb (3546 => 3547)


--- branches/component-querying/app/models/invitation.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/models/invitation.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -42,7 +42,7 @@
           # check if it is also present in the DB as registered address of some user -
           # if so, it needs to be treated differentrly
           if( u = User.find(:first, :conditions => ["email = ? OR unconfirmed_email = ?", email_addr, email_addr]) )
-            db_user_addresses[email_addr] = u.id    
+            db_user_addresses[email_addr] = u
           else
             validated_addr_cnt += 1
             valid_addresses << email_addr  

Modified: branches/component-querying/app/models/membership.rb (3546 => 3547)


--- branches/component-querying/app/models/membership.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/models/membership.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -42,6 +42,9 @@
       if self.network_established_at.nil?
         self.network_establish!
       end
+
+      Activity.create_activities(:subject => user, :action ="" 'create', :object => self)
+
       return true
     else
       return false

Modified: branches/component-querying/app/models/network.rb (3546 => 3547)


--- branches/component-querying/app/models/network.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/models/network.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -20,6 +20,8 @@
   has_many :blobs, :as => :contributor
   has_many :workflows, :as => :contributor
   has_many :policies, :as => :contributor
+  has_one  :feed, :as => :context
+  has_many :activities, :as => :context
 
   if Conf.solr_enable
     searchable do
@@ -68,8 +70,8 @@
              
   alias_method :contributor, :owner
 
-  def owner?(userid)
-    user_id.to_i == userid.to_i
+  def owner?(user)
+    user_id == user.id
   end
   
   def owner_name
@@ -97,7 +99,7 @@
            :dependent => :destroy
   
   def announcements_for_user(user)
-    if user.is_a?(User) && self.member?(user.id)
+    if user.is_a?(User) && self.member?(user)
       return self.announcements
     else
       return self.announcements_public
@@ -105,7 +107,7 @@
   end
   
   def announcements_in_public_mode_for_user(user)
-    return (!user.is_a?(User) || !self.member?(user.id))
+    return (!user.is_a?(User) || !self.member?(user))
   end
   
   # memberships
@@ -150,15 +152,9 @@
     return incl_owner ? ( [owner] + explicit_members ) : explicit_members
   end
                           
-  def member?(userid)
+  def member?(user)
     # the owner is automatically a member of the network
-    return true if owner? userid
-    
-    members.each do |m|
-      return true if m.id.to_i == userid.to_i
-    end
-    
-    return false
+    owner?(user) || members.include?(user)
   end
   
   def administrators(incl_owner=true)
@@ -171,15 +167,9 @@
     return incl_owner ? ( [owner] + explicit_administrators ) : explicit_administrators
   end
 
-  def administrator?(userid)
+  def administrator?(user)
     # the owner is automatically an adminsitrator of the network
-    return true if owner? userid
-    
-    administrators(false).each do |a|
-      return true if a.id.to_i == userid.to_i
-    end
-    
-    return false
+    owner?(user) || administrators(false).include?(user)
   end
                           
   # Finds all the contributions that have been explicitly shared via Permissions

Copied: branches/component-querying/app/models/subscription.rb (from rev 3546, trunk/app/models/subscription.rb) (0 => 3547)


--- branches/component-querying/app/models/subscription.rb	                        (rev 0)
+++ branches/component-querying/app/models/subscription.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,12 @@
+# myExperiment: app/models/subscription.rb
+#
+# Copyright (c) 2007-2013 The University of Manchester, the University of
+# Oxford, and the University of Southampton.  See license.txt for details.
+
+class Subscription < ActiveRecord::Base
+  belongs_to :user
+  belongs_to :objekt, :polymorphic => true
+
+  validates_uniqueness_of :objekt_id, :scope => [:user_id, :objekt_type]
+end
+

Modified: branches/component-querying/app/models/user.rb (3546 => 3547)


--- branches/component-querying/app/models/user.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/models/user.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -26,6 +26,10 @@
 
   has_many :curation_events, :dependent => :destroy
 
+  has_many :subscriptions, :dependent => :destroy
+
+  named_scope :users_to_check, :conditions => "activated_at IS NOT NULL AND (account_status IS NULL OR (account_status != 'sleep' AND account_status != 'suspect' AND account_status != 'whitelist'))"
+
   def self.most_recent(limit=5)
     self.find(:all,
               :order => "users.created_at DESC",

Copied: branches/component-querying/app/views/contributions/_subscription_box.html.erb (from rev 3546, trunk/app/views/contributions/_subscription_box.html.erb) (0 => 3547)


--- branches/component-querying/app/views/contributions/_subscription_box.html.erb	                        (rev 0)
+++ branches/component-querying/app/views/contributions/_subscription_box.html.erb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,19 @@
+<% if logged_in? %>
+  <div class="contribution_section_box">
+    <p class="heading">
+      <%= info_icon_with_tooltip("By subscribing you can view the news items of this resource on your home page, personal atom feed or email notifications.") %>
+      Subscription
+      <% if current_user.subscriptions.find(:first, :conditions => { :objekt_type => object.class.name, :objekt_id => object.id } ) %>
+        <p>You have subscribed to this resource.</p>
+        <% form_tag polymorphic_path([:subscription, @network]), :method => :delete do %>
+          <%= submit_tag "Unsubscribe" -%>
+        <% end %>
+      <% else %>
+        <p>Subscribe to this resource to get notifications on your home page.</p>
+        <% form_tag polymorphic_path([:subscription, @network]), :method => :put do %>
+          <%= submit_tag "Subscribe" -%>
+        <% end %>
+      <% end %>
+    </p>
+  </div>
+<% end %>

Modified: branches/component-querying/app/views/gadgets/_user_monitor.rhtml (3546 => 3547)


--- branches/component-querying/app/views/gadgets/_user_monitor.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/gadgets/_user_monitor.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -18,18 +18,20 @@
     <li><%= friendships_pending_link(current_user) %></li>
     <li><%= memberships_link(current_user) %></li>
   </ul>
-  <div class="header"><%= icon 'contributions', nil, nil, nil, 'Contributions'-%></div>
-  <ul class="gadget_list">
-    <li><%= icon "workflow", user_workflows_url(current_user), nil, nil, " My Workflows" %>
-      (<%= current_user.workflows.size-%>)
-    </li>
-    <li><%= icon "blob", user_blobs_url(current_user), nil, nil, " My Files" %>
-      (<%= current_user.blobs.size-%>)
-    </li>
-    <li><%= icon "pack", user_packs_url(current_user), nil, nil, " My Packs" %>
-      (<%= current_user.packs.size-%>)
-    </li>
-  </ul>
+  <% cache(:controller => 'sidebar_cache', :action ="" 'asset_manager', :id => current_user.id) do -%>
+    <div class="header"><%= icon 'contributions', nil, nil, nil, 'Contributions'-%></div>
+    <ul class="gadget_list">
+      <li><%= icon "workflow", user_workflows_url(current_user), nil, nil, " My Workflows" %>
+        (<%= current_user.workflows.size-%>)
+      </li>
+      <li><%= icon "blob", user_blobs_url(current_user), nil, nil, " My Files" %>
+        (<%= current_user.blobs.size-%>)
+      </li>
+      <li><%= icon "pack", user_packs_url(current_user), nil, nil, " My Packs" %>
+        (<%= current_user.packs.size-%>)
+      </li>
+    </ul>
+  <% end %>
   <%= render :partial => 'gadgets/user_favourites' %>
   <% if admin? %>
     <div class="header"><%= icon 'admin', nil, nil, nil, 'Administration'-%></div>

Modified: branches/component-querying/app/views/group_announcements/_table.rhtml (3546 => 3547)


--- branches/component-querying/app/views/group_announcements/_table.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/group_announcements/_table.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -30,7 +30,7 @@
 					</td>
 			    <td class="actions"  style="width: 80px;">
 		      	<%= icon "show", group_announcement_path(group, announcement), nil, nil, "View" %>
-						<% if (current_user != 0) && ((announcement.user==current_user) || (group.owner?(current_user.id))) %>
+						<% if (current_user != 0) && ((announcement.user==current_user) || (group.owner?(current_user))) %>
 							<%= icon('edit', edit_group_announcement_path(group, announcement), nil, nil, 'Edit') %>
 							<%= icon("destroy", group_announcement_path(group, announcement), "Delete", :confirm => "Are you sure you want to delete this announcement?", :method => :delete) %>
 						<% end %>

Modified: branches/component-querying/app/views/group_announcements/index.rhtml (3546 => 3547)


--- branches/component-querying/app/views/group_announcements/index.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/group_announcements/index.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -1,4 +1,4 @@
-<% if (current_user != 0) && @group.owner?(current_user.id) %>
+<% if (current_user != 0) && @group.owner?(current_user) %>
 	<ul class="sectionIcons">
 	  <li><%= icon('announcement', new_group_announcement_path, nil, nil, 'New Announcement') %></li>
 	</ul>

Modified: branches/component-querying/app/views/group_announcements/show.rhtml (3546 => 3547)


--- branches/component-querying/app/views/group_announcements/show.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/group_announcements/show.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -1,6 +1,6 @@
 <ul class="sectionIcons">
   <li><%= icon('announcement', group_announcements_path(@group), "Return to All Announcements", nil, 'Return to All Announcements') %></li>
-	<% if (current_user != 0) && @group.owner?(current_user.id) %>
+	<% if (current_user != 0) && @group.owner?(current_user) %>
 	  <li><%= icon('edit', edit_group_announcement_path(@group, @announcement), nil, nil, 'Edit') %></li>
 		<li>
 			<%= icon('destroy', group_announcement_path(@group, @announcement), 'Delete', { :confirm => 'Are you sure you want to delete this announcement?', :method => :delete }, 'Delete') %>

Modified: branches/component-querying/app/views/home/_latest_comments.rhtml (3546 => 3547)


--- branches/component-querying/app/views/home/_latest_comments.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/home/_latest_comments.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -10,9 +10,11 @@
 			<ul class="list">
 				<% comments.each do |c| %>
 					<% if Authorization.check("view", c.commentable, current_user) %>
+            <% commentable = c.commentable.kind_of?(Activity) ? c.commentable.context : c.commentable %>
+            <% commentable_type = commentable.class.name; commentable_id = commentable.id %>
 						<li>
-							<b><%= c_type = visible_name(c.commentable_type); icon(c.commentable_type.to_s, nil, nil, c_type, c_type) %>:</b>
-							<span><%= c.commentable_type == 'Network' ? title(c.commentable_id) : contributable(c.commentable_id, c.commentable_type) %></span>
+							<b><%= c_type = visible_name(commentable_type); icon(commentable_type.to_s, nil, nil, c_type, c_type) %>:</b>
+							<span><%= commentable_type == 'Network' ? title(commentable_id) : contributable(commentable_id, commentable_type) %></span>
 							<br/>
 							<span style="padding-left: 2em;">
 								<b><%= name c.user %></b> said:
@@ -20,7 +22,7 @@
 							</span>
 							<div class="box_standout" style="font-size: 85%; margin: 0.4em 2em; padding: 0.2em 0.5em;">
 								<%= truncate(strip_html(white_list(c.comment)), :length => 150) %>
-								<p style="text-align: right;">[ <%= link_to "More", (c.commentable_type == 'Network' ? network_url(c.commentable) + "#comment_#{c.id}" : contributable_url(c.commentable_id, c.commentable_type) + "#comment_#{c.id}") %> ]</p>
+								<p style="text-align: right;">[ <%= link_to "More", (commentable_type == 'Network' ? network_url(c.commentable) + "#comment_#{c.id}" : contributable_url(commentable_id, commentable_type) + "#comment_#{c.id}") %> ]</p>
 							</div>
 							<br/>
 						</li>

Modified: branches/component-querying/app/views/memberships/_table.rhtml (3546 => 3547)


--- branches/component-querying/app/views/memberships/_table.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/memberships/_table.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -20,12 +20,12 @@
 <% for membership in collection %>
   <% allow_approval = allow_membership_pending_approval(membership) %>
   <tr class="<%= (odd_row = !odd_row) ? "odd_row" : "even_row" %>">
-    <% if user %><td width="100"><%= "<b>" unless membership.accepted? %><%= contributor(membership.user_id, "User", true, 60) %><%= "</b>" unless membership.accepted? %><%= '<div style="text-align: left"><b>Group Admin</b></div>' if membership.network.administrator?(membership.user_id) %></td><% end %>
+    <% if user %><td width="100"><%= "<b>" unless membership.accepted? %><%= contributor(membership.user_id, "User", true, 60) %><%= "</b>" unless membership.accepted? %><%= '<div style="text-align: left"><b>Group Admin</b></div>' if membership.network.administrator?(membership.user) %></td><% end %>
     <% if network %><td width="100"><%= "<b>" unless membership.accepted? %><%= contributor(membership.network_id, "Network", true, 60) %><%= "</b>" unless membership.accepted? %></td><% end %>
     <td><%= "<b>" unless membership.accepted? %><%=datetime membership.created_at, false %><%= "</b>" unless membership.accepted? %></td>
     <td><%= "<b>" unless membership.accepted? %><%=datetime(membership.accepted_at, false) || "Pending" %><%= "</b>" unless membership.accepted? %></td>
     <td class="actions">
-      <% if my_page? membership.user or (logged_in? and membership.network.administrator?(current_user.id)) %>
+      <% if my_page? membership.user or (logged_in? and membership.network.administrator?(current_user)) %>
         <%= icon "show", user_membership_path(membership.user_id, membership), nil, nil, "View" %>
 				<% if membership.accepted? %>
 					<%= icon "destroy", user_membership_path(membership.user_id, membership), nil, { :confirm => "Are you sure?", :method => :delete }, "Remove" %>
@@ -38,7 +38,7 @@
 				<% end %>
       <% end %>
       <% if membership.accepted? %>
-        <% if membership.network.administrator?(membership.user_id) %>
+        <% if membership.network.administrator?(membership.user) %>
 		      <%= icon "remove_group_admin", user_membership_path(membership.user_id, membership)+'?membership[administrator]=0', nil, {:method => :put}, "Remove group admin status" %>
           <% if membership.network.owner == current_user %>
             <%= icon "transfer_ownership", network_path(membership.network, :network => {:user_id => membership.user_id}),

Modified: branches/component-querying/app/views/memberships/show.rhtml (3546 => 3547)


--- branches/component-querying/app/views/memberships/show.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/memberships/show.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -21,7 +21,7 @@
 						<% elsif (@membership.is_invite? && allow_approval) || (address@hidden && !allow_approval) %>
 							<% #= avatar @membership.network, 80 # will start to work once the group avatars are introduced %>
 						<% end %>
-						<% if (@membership.network.administrator?(@membership.user_id)) -%>
+						<% if (@membership.network.administrator?(@membership.user)) -%>
 							<div style="text-align: left"><b>Group Admin</b></div>
 						<% end -%>
 					</td>

Modified: branches/component-querying/app/views/networks/_announcements.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/_announcements.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/_announcements.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -31,7 +31,7 @@
 			<p class="none_text">None</p>
 		<% end %>
 		<p style="font-size: 77%; text-align: center;">
-			<% if (current_user != 0) && group.owner?(current_user.id) %>
+			<% if (current_user != 0) && group.owner?(current_user) %>
 				[ <%= link_to "New", new_group_announcement_url(group) %> ]
 			<% end %>
 			[ <%= link_to "See All", group_announcements_url(group) %> ]

Modified: branches/component-querying/app/views/networks/_banner.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/_banner.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/_banner.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -2,7 +2,7 @@
 <div class="network_banner">
   <p>
     <strong><%= link_to h(network.title), network_path(network.id) %></strong>
-    <% if logged_in? and network.owner? current_user.id %>
+    <% if logged_in? and network.owner?(current_user) %>
       <%= icon "edit", edit_network_path(network) %>
       <%= icon "destroy", network_path(network), nil, :confirm => "Are you sure?", :method => "destroy" %>
     <% end %>

Modified: branches/component-querying/app/views/networks/_form.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/_form.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/_form.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -37,9 +37,26 @@
       <%= form.select :new_member_policy, Network::NEW_MEMBER_POLICY_OPTIONS.map {|o| [o[1],o[0]]} %>
     </p>
   </fieldset>
-  
-  <br/>
 	
+  <fieldset class="atom-feed">
+    <legend>Atom feed</legend>
+    <p>
+      You can specify an Atom feed which will be used to insert items into this group's activity stream.
+    </p>
+    <p>
+      <b>Atom feed URL</b><br />
+      <%= text_field_tag :feed_uri, (@network.feed ? @network.feed.uri : nil) -%>
+    </p>
+    <p>
+      <b>Atom feed username (optional)</b><br />
+      <%= text_field_tag :feed_user, (@network.feed ? @network.feed.username : nil) -%>
+    </p>
+    <p>
+      <b>Atom feed password (optional)</b><br />
+      <%= password_field_tag :feed_pass -%>
+    </p>
+  </fieldset>
+
 	<p>
   	<strong>Description: </strong>
 	</p>

Modified: branches/component-querying/app/views/networks/_invite.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/_invite.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/_invite.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -37,7 +37,7 @@
 
   function inviteAndDisable() {
     <% networks.each do |n| %>
-      <% unless n.member?(user.id) || user.membership_pending?(n.id) %>
+      <% unless n.member?(user) || user.membership_pending?(n.id) %>
         if ($("my_network_<%= n.id -%>").checked && !$("my_network_<%= n.id -%>").disabled) {
           <%= remote_function(:url ="" membership_invite_network_path(n),
                               :method => :post,
@@ -64,7 +64,7 @@
 
 <form>
   <% networks.each_with_index do |n, index| %>
-    <% if n.member?(user.id) %>
+    <% if n.member?(user) %>
       <input type="checkbox" id="my_network_<%= n.id -%>" value="<%= n.id -%>" disabled=true CHECKED /> - <span style="color: green"><%= h(n.title) -%></span> (already a member)
     <% elsif user.membership_pending?(n.id) %>
       <input type="checkbox" id="my_network_<%= n.id -%>" value="<%= n.id -%>" disabled=true CHECKED /> - <span style="color: green"><%= h(n.title) -%></span> (waiting for the user to confirm)

Modified: branches/component-querying/app/views/networks/_statistics_box.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/_statistics_box.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/_statistics_box.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -7,11 +7,6 @@
 	 	<b><%= pluralize items.length, "shared item" %></b>
 	</p>
 	
-	<p style="font-size: 108%;">
-	  <% # all announcements, private and public -%>
-	 	<b><%= pluralize network.announcements.length, "announcements" %></b>
-	</p>
-	
 	<% if mine? network %>
 		<p>
 			<%= pluralize network.memberships_requested.length, "request" %> pending
@@ -21,4 +16,4 @@
 		</p>
 	<% end %>
 	
-</div>
\ No newline at end of file
+</div>

Modified: branches/component-querying/app/views/networks/_table.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/_table.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/_table.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -16,7 +16,7 @@
         <% if mine? network -%>
           <%= icon "manage", edit_network_path(network) %>
         <% elsif logged_in? %> <!-- admins can't leave the group or request membership! -->
-          <% if network.member?(current_user.id) %>
+          <% if network.member?(current_user) %>
             <!-- user is not an admin, but a member already -->
             <% cur_membership = Membership.find(:first, :conditions => ["network_id = ? AND user_id = ?", network.id, current_user.id] ) %>
             <% if cur_membership %>

Modified: branches/component-querying/app/views/networks/show.rhtml (3546 => 3547)


--- branches/component-querying/app/views/networks/show.rhtml	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/app/views/networks/show.rhtml	2013-05-20 08:45:57 UTC (rev 3547)
@@ -13,7 +13,7 @@
 		<% end %>
 
     <% unless mine? @network %>
-		  <% if @network.member? current_user.id  %>
+		  <% if @network.member?(current_user)  %>
 			  <% cur_membership = Membership.find(:first, :conditions => ["network_id = ? AND user_id = ?", @network.id, current_user.id] ) %>
 			  <% if false %>
 			    <li><%= icon('network-leave', user_membership_path(cur_membership.user_id, cur_membership), nil, { :confirm => "Are you sure want to leave this group?", :method => :delete }, 'Leave Group') %></li>
@@ -23,8 +23,7 @@
 			<% end %>
 		<% end %>
 
-    <% if @network.administrator?(current_user.id) %>
-      <li><%= icon('announcement', new_group_announcement_path(@network), 'Make a new Group Announcement', nil, 'Make a Group Announcement') -%></li>
+    <% if @network.administrator?(current_user) %>
 			<li><%= icon('network-invite', invite_network_path(@network), 'Invite People', nil, 'Invite People') -%></li>
       <li><%= icon('policy', network_policies_path(@network), 'Group Policies', nil, 'Group Policies') -%></li>
     <% end %>
@@ -66,10 +65,6 @@
 	<% end %>
 	<%= link_to "Tags <span id='mini_nav_tag_link'>(address@hidden)</span>", "#tags" %>
 	|
-	<%= link_to "Announcements", "#group_announcements" -%>
-	|
-	<%= link_to "Comments (address@hidden)", "#comments" %>
-	|
 </div>
 
 <div id="tabsContainer" class="tabsContainer"></div>
@@ -99,13 +94,34 @@
       <% end %>
 
       <a name="news"></a>
-      <h3>News</h3>
-      <%= render :partial => "layouts/news", :locals => { :collection => news(@network, true) } %>
+      
+      <div>
+        <div style="float: right"><%= link_to(image_tag("feed-icon.png", :alt_text => "Atom feed for the news items of this group"), network_url(@network, :format => :atom)) -%></div>
+        <h3>News</h3>
+        <div style="clear: both"></div>
+      </div>
 
+      <% if @network.feed && Authorization.check("edit", @network, current_user) %>
+        <% form_tag sync_feed_network_path(@network), :method => :post do %>
+          <%= submit_tag "Synchronize feed" -%>
+        <% end %>
+      <% end %>
+
+      <br />
+
+      <% activities = activities_for_feed(:context => @network, :user => current_user) %>
+
+      <div id="activities">
+        <%= render(:partial => "activities/list", :locals => { :context => @network, :activities => activities, :user => current_user, :enable_feature => true } ) -%>
+      </div>
+
     </div>
 
     <div class="contribution_right_box">
       <%= render :partial => "owner_box", :locals => { :network => @network } %>
+      <% if false %>
+      <%= render :partial => "contributions/subscription_box", :locals => { :object => @network } -%>
+      <% end %>
       <%= render :partial => "statistics_box", :locals => { :network => @network, :items => @shared_items } %>
 
       <div class="contribution_section_box"> <!-- style="width: 130px; padding: 0.4em 0.8em; font-size: 93%;" -->
@@ -123,8 +139,6 @@
                                                            :add_path => tag_network_path(@network),
                                                            :edit_path => edit_network_path(@network),
                                                            :allow_edit => logged_in? ? @network.user_id == current_user.id : false } %>
-
-      <%= render :partial => "announcements", :locals => { :group => @network, :count => 5 } -%>
     </div>
     <div class="clearer">&nbsp;</div>
   </div>
@@ -184,7 +198,7 @@
   </div>
 </div>
 
-<% if logged_in? && @network.administrator?(current_user.id) %>
+<% if logged_in? && @network.administrator?(current_user) %>
 
   <% memberships = @network.memberships_accepted %>
 	<div class="tabContainer">
@@ -238,15 +252,11 @@
 
 <% end %>
 
-<% if logged_in? and @network.member? current_user.id and address@hidden %>
+<% if logged_in? and @network.member?(current_user) and address@hidden %>
   <%= render :partial => "contributions/tabs", :locals => { :collection => @network.contributions } %>
 <% end %>
 
 <br/>
 
-<div id="commentsBox">
-	<%= render :partial => "comments/comments", :locals => { :commentable => @network } %>
-</div>
-
 <%= render :partial => "contributions/alternative_formats" %>
 

Modified: branches/component-querying/config/environment.rb (3546 => 3547)


--- branches/component-querying/config/environment.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/config/environment.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -1,7 +1,7 @@
 # Be sure to restart your server when you modify this file
 
 # Specifies gem version of Rails to use when vendor/rails is not present
-RAILS_GEM_VERSION = '2.3.17' unless defined? RAILS_GEM_VERSION
+RAILS_GEM_VERSION = '2.3.18' unless defined? RAILS_GEM_VERSION
 
 # Bootstrap the Rails environment, frameworks, and default configuration
 require File.join(File.dirname(__FILE__), 'boot')

Modified: branches/component-querying/config/routes.rb (3546 => 3547)


--- branches/component-querying/config/routes.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/config/routes.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -223,10 +223,15 @@
                  :membership_invite_external => :post,
                  :membership_request => :get, 
                  :rate => :post, 
+                 :sync_feed => :post,
+                 :subscription => [:put, :delete],
                  :tag => :post } do |network|
     network.resources :group_announcements, :as => :announcements, :name_prefix => nil
     network.resources :comments, :collection => { :timeline => :get }
     network.resources :policies, :controller => 'group_policies'
+    network.resources :activities, :member => { :feature => [:put, :delete] } do |activity|
+      activity.resources :comments
+    end
 
     # resources shared with network
     network.resources :workflows, : :index

Modified: branches/component-querying/db/migrate/099_add_activities.rb (3546 => 3547)


--- branches/component-querying/db/migrate/099_add_activities.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/db/migrate/099_add_activities.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -7,26 +7,41 @@
   def self.up
     create_table :activities do |t|
 
-      t.string  :subject_type
-      t.integer :subject_id
-      t.string  :subject_label
+      t.string   :subject_type
+      t.integer  :subject_id
+      t.string   :subject_label
 
-      t.string  :action
+      t.string   :action
 
-      t.string  :objekt_type
-      t.integer :objekt_id
-      t.string  :objekt_label
+      t.string   :objekt_type
+      t.integer  :objekt_id
+      t.string   :objekt_label
 
-      t.string  :auth_type
-      t.integer :auth_id
+      t.string   :context_type
+      t.integer  :context_id
 
-      t.string  :extra
+      t.string   :auth_type
+      t.integer  :auth_id
 
-      t.datetime :created_at
+      t.string   :extra
+      t.string   :uuid
+      t.integer  :priority, :default => 0
+
+      t.boolean  :featured, :default => false
+      t.boolean  :hidden,   :default => false
+
+      t.datetime :timestamp
     end
+
+    create_table :subscriptions do |t|
+      t.integer :user_id
+      t.string  :objekt_type
+      t.integer :objekt_id
+    end
   end
 
   def self.down
+    drop_table :subscriptions
     drop_table :activities
   end
 end

Copied: branches/component-querying/db/migrate/20130423091433_create_atom_feed_tables.rb (from rev 3546, trunk/db/migrate/20130423091433_create_atom_feed_tables.rb) (0 => 3547)


--- branches/component-querying/db/migrate/20130423091433_create_atom_feed_tables.rb	                        (rev 0)
+++ branches/component-querying/db/migrate/20130423091433_create_atom_feed_tables.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -0,0 +1,41 @@
+# myExperiment: db/migrate/20130423091433_create_atom_feed_tables.rb
+#
+# Copyright (c) 2007-2013 The University of Manchester, the University of
+# Oxford, and the University of Southampton.  See license.txt for details.
+
+class CreateAtomFeedTables < ActiveRecord::Migration
+  def self.up
+
+    create_table :feeds do |t|
+
+      t.string  :title
+      t.text    :uri
+      t.string  :context_type
+      t.integer :context_id
+      t.string  :username 
+      t.string  :password
+
+      t.timestamps
+    end
+
+    create_table :feed_items do |t|
+
+      t.integer  :feed_id
+      t.string   :identifier
+      t.string   :title
+      t.text     :content
+      t.string   :author
+      t.string   :link
+      t.datetime :item_published_at
+      t.datetime :item_updated_at
+      t.text     :data
+
+      t.timestamps
+    end
+  end
+
+  def self.down
+    drop_table :feed_items
+    drop_table :feeds
+  end
+end

Modified: branches/component-querying/db/schema.rb (3546 => 3547)


--- branches/component-querying/db/schema.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/db/schema.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -9,7 +9,7 @@
 #
 # It's strongly recommended to check this file into your version control system.
 
-ActiveRecord::Schema.define(:version => 20130308085716) do
+ActiveRecord::Schema.define(:version => 20130423091433) do
 
   create_table "activities", :force => true do |t|
     t.string   "subject_type"
@@ -19,10 +19,16 @@
     t.string   "objekt_type"
     t.integer  "objekt_id"
     t.string   "objekt_label"
+    t.string   "context_type"
+    t.integer  "context_id"
     t.string   "auth_type"
     t.integer  "auth_id"
     t.string   "extra"
-    t.datetime "created_at"
+    t.string   "uuid"
+    t.integer  "priority",      :default => 0
+    t.boolean  "featured",      :default => false
+    t.boolean  "hidden",        :default => false
+    t.datetime "timestamp"
   end
 
   create_table "activity_limits", :force => true do |t|
@@ -54,11 +60,6 @@
     t.datetime "updated_at"
   end
 
-  create_table "auto_tables", :force => true do |t|
-    t.string "name"
-    t.text   "schema"
-  end
-
   create_table "blob_versions", :force => true do |t|
     t.integer  "blob_id"
     t.integer  "version"
@@ -98,27 +99,6 @@
 
   add_index "bookmarks", ["user_id"], :name => "index_bookmarks_on_user_id"
 
-  create_table "checksums", :id => false, :force => true do |t|
-    t.integer "id"
-    t.string  "sha1"
-  end
-
-  add_index "checksums", ["id"], :name => "i1", :unique => true
-
-  create_table "checksums_new", :id => false, :force => true do |t|
-    t.integer "id"
-    t.string  "sha1"
-  end
-
-  add_index "checksums_new", ["id"], :name => "i1", :unique => true
-
-  create_table "checksums_new_new", :id => false, :force => true do |t|
-    t.integer "id"
-    t.string  "sha1"
-  end
-
-  add_index "checksums_new_new", ["id"], :name => "ii", :unique => true
-
   create_table "citations", :force => true do |t|
     t.integer  "user_id"
     t.integer  "workflow_id"
@@ -267,6 +247,31 @@
     t.string "name"
   end
 
+  create_table "feed_items", :force => true do |t|
+    t.integer  "feed_id"
+    t.string   "identifier"
+    t.string   "title"
+    t.text     "content"
+    t.string   "author"
+    t.string   "link"
+    t.datetime "item_published_at"
+    t.datetime "item_updated_at"
+    t.text     "data"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
+  create_table "feeds", :force => true do |t|
+    t.string   "title"
+    t.text     "uri"
+    t.string   "context_type"
+    t.integer  "context_id"
+    t.string   "username"
+    t.string   "password"
+    t.datetime "created_at"
+    t.datetime "updated_at"
+  end
+
   create_table "friendships", :force => true do |t|
     t.integer  "user_id"
     t.integer  "friend_id"
@@ -511,11 +516,6 @@
     t.integer "user_id"
   end
 
-  create_table "plugin_schema_info", :id => false, :force => true do |t|
-    t.string  "plugin_name"
-    t.integer "version"
-  end
-
   create_table "policies", :force => true do |t|
     t.integer  "contributor_id"
     t.string   "contributor_type"
@@ -704,6 +704,12 @@
   add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id"
   add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at"
 
+  create_table "subscriptions", :force => true do |t|
+    t.integer "user_id"
+    t.string  "objekt_type"
+    t.integer "objekt_id"
+  end
+
   create_table "taggings", :force => true do |t|
     t.integer  "tag_id"
     t.integer  "taggable_id"
@@ -852,6 +858,8 @@
     t.text     "body_html"
     t.datetime "created_at"
     t.datetime "updated_at"
+    t.string   "license"
+    t.integer  "preview_id"
     t.string   "image"
     t.string   "svg"
     t.text     "revision_comments"
@@ -859,8 +867,6 @@
     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"
@@ -874,15 +880,15 @@
     t.string   "unique_name"
     t.text     "body"
     t.text     "body_html"
+    t.integer  "current_version"
+    t.integer  "preview_id"
     t.datetime "created_at"
     t.datetime "updated_at"
-    t.integer  "current_version"
     t.integer  "content_blob_id"
     t.string   "file_ext"
     t.string   "last_edited_by"
     t.integer  "content_type_id"
     t.integer  "license_id"
-    t.integer  "preview_id"
   end
 
   create_table "wsdl_deprecations", :force => true do |t|

Modified: branches/component-querying/lib/authorization.rb (3546 => 3547)


--- branches/component-querying/lib/authorization.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/lib/authorization.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -107,6 +107,12 @@
         case action
           when "create"
 
+            # You can only comment on a Group if you are a member
+            if context.kind_of?(Network)
+              return false if user.nil?
+              return false unless context.member?(user)
+            end
+
             # Comments can be created by authenticated users that can view the context
             return !user.nil? && Authorization.check('view', context, user)
 
@@ -176,7 +182,7 @@
         when "User"
           return object.contributor_id.to_i == user.id.to_i
         when "Network"
-          return object.contributor.member?(user.id)
+          return object.contributor.member?(user)
         else
           return false
         end 
@@ -192,7 +198,7 @@
           if ['edit', 'destroy'].include?(action.downcase)
             return object.contributor.owner?(user.id)
           else
-            return object.contributor.member?(user.id)
+            return object.contributor.member?(user)
           end
         else
           return false
@@ -206,7 +212,7 @@
         when "User"
           return object.experiment.contributor_id.to_i == user.id.to_i
         when "Network"
-          return object.experiment.contributor.member?(user.id)
+          return object.experiment.contributor.member?(user)
         else
           return false
         end 

Copied: branches/component-querying/public/images/feed_gray.png (from rev 3546, trunk/public/images/feed_gray.png)


(Binary files differ)

Modified: branches/component-querying/public/_javascript_s/tabs.js (3546 => 3547)


--- branches/component-querying/public/_javascript_s/tabs.js	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/public/_javascript_s/tabs.js	2013-05-20 08:45:57 UTC (rev 3547)
@@ -1,7 +1,5 @@
 // tabs.js
 
-var tabImagesRoot = '/images/tabs/';
-
 function parent_el(el) {
 
   if (el.parentElement != undefined)
@@ -24,46 +22,31 @@
 
 function selectTab(tabsDiv, t) {
 
-  var html = '<table cellspacing=0 cellpadding=0><tr>';
+  var html = '';
 
-  if (tabsDiv.titles.length > 0)
-    html += '<td><img class="tabSeparator" src="" + tabImagesRoot + '/tab_separator.png"></td>';
-
   for (var i = 0; i < tabsDiv.titles.length; i++) {
 
     if (i == t) {
 
       tabsDiv.panes[i].style.display = 'block';
 
-      html += '<td class="tabSelIMG"><img src="" + tabImagesRoot;
-      html += '/selected_tab_start.png"></td>';
-      html += '<td class="tabSelected"><span 
+      html += '<span class="tab selected" 
       html += '_javascript_:return false;">';
-      html += tabsDiv.titles[i];
-      html += '</span></td>';
-      html += '<td class="tabSelIMG"><img src="" + tabImagesRoot;
-      html += '/selected_tab_end.png"></td>';
+      html += '<span class="inner">' + tabsDiv.titles[i] + '</span>';
+      html += '</span>';
 
     } else {
 
       tabsDiv.panes[i].style.display = 'none';
 
-      html += '<td class="tabUnselIMG"><img src="" + tabImagesRoot;
-      html += '/unselected_tab_start.png"></td>';
-      html += '<td class="tabUnselected"><span 
-      html += '_javascript_:selectTab(parent_el(parent_el(parent_el(parent_el(parent_el(this))))), ' + i +
+      html += '<span class="tab unselected" 
+      html += '_javascript_:selectTab(parent_el(this), ' + i +
           '); return false;">';
-      html += tabsDiv.titles[i];
-      html += '</span></td>';
-      html += '<td class="tabUnselIMG"><img src="" + tabImagesRoot;
-      html += '/unselected_tab_end.png"></td>';
+      html += '<span class="inner">' + tabsDiv.titles[i] + '</span>';
+      html += '</span>';
     }
-
-    html += '<td><img class="tabSeparator" src="" + tabImagesRoot + '/tab_separator.png"></td>';
   }
 
-  html += '</td></tr></table>';
-
   tabsDiv.innerHTML = html;
 }
 

Modified: branches/component-querying/public/stylesheets/styles.css (3546 => 3547)


--- branches/component-querying/public/stylesheets/styles.css	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/public/stylesheets/styles.css	2013-05-20 08:45:57 UTC (rev 3547)
@@ -668,63 +668,50 @@
 	border: 0;
 	position: relative;
 	top: 1px;
+  padding-top: 6px;
+  padding-bottom: 6px;
 }
 
-.tabsContainer IMG {
-	border: 0;
-	margin: 0;
-	padding: 0;
-	vertical-align: middle;
+.tabsContainer .unselected {
+	border-bottom: 1px solid #909090;
+	color: #333333;
+	background: #d8d8d8;
 }
 
-.tabsContainer TABLE {
-	height: 24px;
-	border-spacing: 0;
+.tabsContainer .selected {
+  background: white;
 }
 
-.tabsContainer TABLE TR TD {
-	padding: 0;
-	vertical-align: middle;
-}
-
-.tabSeparator {
-  width: 1px;
-}
-
-.tabSelected {
+.tabsContainer .tab {
+  border-radius: 6px 6px 0px 0px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  -webkit-border-top-left-radius: 6px;
+  -webkit-border-top-right-radius: 6px;
 	border-top: 1px solid #909090;
-	border-bottom: 1px solid white;
-	padding: 0;
-	padding-left: 0.5em;
-	padding-right: 0.5em;
-	vertical-align: middle;
+	border-left: 1px solid #909090;
+	border-right: 1px solid #909090;
+	padding-top: 4px;
+	padding-bottom: 4px;
+	padding-left: 0px;
+	padding-right: 0px;
 	white-space: nowrap;
 	pointer: pointer;
 	cursor: pointer;
+  margin-right: -1px;
 }
 
-.tabUnselected {
-	border-top: 1px solid #909090;
-	border-bottom: 1px solid #909090;
-	color: #333333;
-	background: #d8d8d8;
-	padding: 0;
-	padding-left: 0.5em;
-	padding-right: 0.5em;
-	vertical-align: middle;
-	white-space: nowrap;
-	pointer: pointer;
-	cursor: pointer;
+.tabsContainer .tab .inner {
+  padding-left: 6px;
+  padding-right: 6px;
+  padding-bottom: 4px;
 }
 
-.tabSelIMG {
-	border-bottom: 1px solid white;
-  width: 6px;
+.tabsContainer .unselected .inner {
+  border-bottom: 1px solid #909090;
 }
 
-.tabUnselIMG {
-	border-bottom: 1px solid #909090;
-  width: 6px;
+.tabsContainer .selected .inner {
+  border-bottom: 1px solid white;
 }
 
 .tabTitle {
@@ -1274,14 +1261,64 @@
 	margin-bottom: 1em;
 }
 
+.commentSection {
+	margin-top: 10px;
+}
+
 .addCommentBox {
-	margin-top: 3em;
-	padding: 1em;
-	width: 500px;
-	background-color: #EEEEEE;
-	border: 1px dotted #999999;
+	background-color: #E8E8E8;
+  width: 510px;
+  padding: 8px;
+  margin: 8px;
 }
 
+.addCommentBox TEXTAREA {
+  padding: 4px;
+  width: 500px;
+}
+
+.addCommentBox INPUT {
+  margin-top: 4px;
+}
+
+.activityCommentBox {
+  padding: 4px;
+	background-color: #E8E8E8;
+  width: 380px;
+}
+
+.activityCommentBox + .activityCommentBox {
+  border-top: 1px solid #F4F4F4;
+}
+
+.activityCommentBox .avatar {
+}
+
+.activityCommentBox .username {
+/*  font-weight: bold; */
+}
+
+.activityCommentBox .username:after {
+/*  content: ": "; */
+}
+
+.activityCommentBox .comment-body {
+  font-size: 11px;
+}
+
+.activityCommentBox .rhs {
+  padding-left: 32px;
+}
+
+.activityCommentBox TEXTAREA {
+  padding: 4px;
+  width: 334px;
+}
+
+.activityCommentBox INPUT {
+  margin-top: 4px;
+}
+
 /* End Comments styles */
 
 /* Begin Reviews styles */
@@ -2422,12 +2459,142 @@
   margin-top: 0;
 }
 
+OL.activity-feed {
+  margin: 0;
+}
+
+.activity-feed LI {
+  list-style: none;
+}
+
+.activity-feed LI + LI {
+  border-top: 1px SOLID #E0E0E0;
+}
+
+.activity-feed LI + LI.featured,
+.activity-feed LI.featured + LI {
+  border-top: none;
+}
+
+DIV.activity IMG.framed  {
+  border: 0;
+  padding: 0;
+}
+
+.activity {
+  padding-top: 12px;
+  padding-bottom: 12px;
+}
+
+.activity-feed LI.featured {
+  padding: 8px;
+  background: #ffffcc;
+  border: 1px dotted #999999;
+}
+
+.activity-feed LI.featured .activityCommentBox {
+	background-color: #E8E8C0;
+}
+
+.activity .avatar-column {
+  width: 64px;
+  float: left;
+}
+
+.activity .activity-column {
+  margin-left: 72px;
+}
+
+.activity .actions {
+  font-size: 8pt;
+  color: gray;
+}
+
+.activity .actions DIV,
+.activity .actions FORM {
+  display: inline;
+}
+
+.activity .date {
+}
+
+.activity SPAN + SPAN:before {
+  content: " \0000a0\0000a0 ";
+  color: gray;
+}
+
+.activity .summary {
+  padding-top: 4px;
+  padding-bottom: 4px;
+  font-size: 8pt;
+}
+
+.activity .extra {
+  color: gray;
+  margin-bottom: 4px;
+  font-size: 8pt;
+}
+
+.activity .actions INPUT {
+  display: inline;
+  border: none;
+  background: transparent;
+  padding: 0;
+  margin: 0;
+  color: #009;
+}
+
+.activity .actions INPUT:hover {
+	color: red;
+	text-decoration: underline;
+}
+
+.activity .comment-timestamp {
+  font-size: 8pt;
+  color: gray;
+}
+
+.activity .actions FORM.button-to,
+.activity .actions FORM.button-to DIV {
+  display: inline;
+}
+
+.inset-preview {
+  float: left;
+  margin-right: 16px;
+  margin-bottom: 16px;
+}
+
+.inset-preview IMG {
+  max-width: 200px;
+}
+
+.workflow-type {
+}
+
+.metadata-datetime {
+  font-size: 8pt;
+}
+
+FIELDSET.atom-feed INPUT {
+  width: 700px;
+}
+
+.new-session-sign-in {
+  width: 190px;
+  border: 1px solid #CCCCCC;
+  border-radius: 6px 6px 6px 6px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  -webkit-border-bottom-left-radius: 6px;
+  -webkit-border-bottom-right-radius: 6px;
+}
+
 #user_menu {
   position: absolute;
   background-color: white;
   text-align: left;
   margin-top: 12px;
-  box-shadow: 0 6px 8px 4px #666666
+  box-shadow: 0 4px 9px 0px #000000;
 }
 
 #user_menu a{

Modified: branches/component-querying/test/functional/networks_controller_test.rb (3546 => 3547)


--- branches/component-querying/test/functional/networks_controller_test.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/test/functional/networks_controller_test.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -26,7 +26,7 @@
     old_count = Network.count
 
     login_as(:john)
-    post :create, :network => { :title => 'test network', :unique_name => 'test_network', :new_member_policy => 'open', :description => "..." }
+    post :create, :network => { :title => 'test network', :unique_name => 'test_network', :new_member_policy => 'open', :description => "..." }, :feed_uri => "", :feed_user => "", :feed_pass => ""
 
     assert_equal old_count+1, Network.count    
     assert_redirected_to network_path(assigns(:network))
@@ -47,7 +47,7 @@
   def test_should_update_network
     login_as(:john)
     put :update, :id => 1, 
-                 :network => { :title => 'test network', :unique_name => 'update_network', :new_member_policy => 'open', :description => ".?."}
+                 :network => { :title => 'test network', :unique_name => 'update_network', :new_member_policy => 'open', :description => ".?."}, :feed_uri => "", :feed_user => "", :feed_pass => ""
 
     assert_redirected_to network_path(assigns(:network))
   end

Modified: branches/component-querying/vendor/plugins/acts_as_taggable_redux/lib/tag.rb (3546 => 3547)


--- branches/component-querying/vendor/plugins/acts_as_taggable_redux/lib/tag.rb	2013-05-20 08:38:14 UTC (rev 3546)
+++ branches/component-querying/vendor/plugins/acts_as_taggable_redux/lib/tag.rb	2013-05-20 08:45:57 UTC (rev 3547)
@@ -32,8 +32,11 @@
   
   # Tag a taggable with this tag, optionally add user to add owner to tagging
   def tag(taggable, user_id = nil)
-    taggings.create :taggable => taggable, :user_id => user_id
+    t = taggings.create :taggable => taggable, :user_id => user_id
     taggings.reset
+
+    Activity.create_activities(:subject => User.find(user_id), :action ="" 'create', :object => t, :timestamp => t.created_at)
+
     @tagged = nil
   end
   

reply via email to

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