muck-activities 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +69 -0
  3. data/Rakefile +78 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/muck/activities_controller.rb +152 -0
  6. data/app/helpers/muck_activity_helper.rb +67 -0
  7. data/app/models/activity.rb +62 -0
  8. data/app/models/activity_feed.rb +16 -0
  9. data/app/views/activities/_activity_feed.html.erb +18 -0
  10. data/app/views/activities/_cached_activities.html.erb +8 -0
  11. data/app/views/activities/_comment.html.erb +6 -0
  12. data/app/views/activities/_comments.html.erb +7 -0
  13. data/app/views/activities/_current_status.html.erb +14 -0
  14. data/app/views/activities/_current_status_wrapper.html.erb +4 -0
  15. data/app/views/activities/_delete.html.erb +11 -0
  16. data/app/views/activities/_status_update.html.erb +35 -0
  17. data/app/views/activities/_template_filter.html.erb +6 -0
  18. data/app/views/activity_templates/_status_update.html.erb +12 -0
  19. data/config/muck_activities_routes.rb +3 -0
  20. data/db/migrate/20090402033319_add_muck_activities.rb +36 -0
  21. data/install.rb +1 -0
  22. data/lib/muck_activities/initialize_routes.rb +8 -0
  23. data/lib/muck_activities/tasks.rb +28 -0
  24. data/lib/muck_activities.rb +76 -0
  25. data/locales/ar.yml +24 -0
  26. data/locales/bg.yml +24 -0
  27. data/locales/ca.yml +24 -0
  28. data/locales/cs.yml +24 -0
  29. data/locales/da.yml +24 -0
  30. data/locales/de.yml +24 -0
  31. data/locales/el.yml +24 -0
  32. data/locales/en.yml +25 -0
  33. data/locales/es.yml +24 -0
  34. data/locales/fr.yml +24 -0
  35. data/locales/it.yml +24 -0
  36. data/locales/iw.yml +24 -0
  37. data/locales/ja.yml +24 -0
  38. data/locales/ko.yml +24 -0
  39. data/locales/lt.yml +24 -0
  40. data/locales/lv.yml +24 -0
  41. data/locales/nl.yml +24 -0
  42. data/locales/no.yml +25 -0
  43. data/locales/pl.yml +24 -0
  44. data/locales/pt.yml +24 -0
  45. data/locales/ro.yml +24 -0
  46. data/locales/ru.yml +24 -0
  47. data/locales/sk.yml +24 -0
  48. data/locales/sl.yml +24 -0
  49. data/locales/sr.yml +24 -0
  50. data/locales/sv.yml +24 -0
  51. data/locales/tl.yml +24 -0
  52. data/locales/uk.yml +24 -0
  53. data/locales/vi.yml +24 -0
  54. data/locales/zh-CN.yml +24 -0
  55. data/locales/zh-TW.yml +24 -0
  56. data/locales/zh.yml +24 -0
  57. data/public/images/loading.gif +0 -0
  58. data/public/javascripts/muck_activities.js +65 -0
  59. data/rails/init.rb +4 -0
  60. data/rdoc/classes/ActionController/Routing/RouteSet.html +148 -0
  61. data/rdoc/classes/ActionController/Routing.html +107 -0
  62. data/rdoc/classes/ActionController.html +107 -0
  63. data/rdoc/classes/MuckActivity/ActMethods.html +189 -0
  64. data/rdoc/classes/MuckActivity/InstanceMethods.html +244 -0
  65. data/rdoc/classes/MuckActivity/Tasks.html +146 -0
  66. data/rdoc/created.rid +1 -0
  67. data/rdoc/files/README_rdoc.html +212 -0
  68. data/rdoc/files/lib/muck_activity/initialize_routes_rb.html +101 -0
  69. data/rdoc/files/lib/muck_activity/tasks_rb.html +110 -0
  70. data/rdoc/files/lib/muck_activity_rb.html +108 -0
  71. data/rdoc/fr_class_index.html +32 -0
  72. data/rdoc/fr_file_index.html +30 -0
  73. data/rdoc/fr_method_index.html +33 -0
  74. data/rdoc/index.html +24 -0
  75. data/rdoc/rdoc-style.css +208 -0
  76. data/tasks/muck_activity_tasks.rake +1 -0
  77. data/test/factories.rb +41 -0
  78. data/test/functional/activities_controller_test.rb +64 -0
  79. data/test/shoulda_macros/controller.rb +43 -0
  80. data/test/test_helper.rb +38 -0
  81. data/test/unit/activity_feed_test.rb +5 -0
  82. data/test/unit/activity_test.rb +57 -0
  83. data/uninstall.rb +1 -0
  84. metadata +169 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Justin Ball
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,69 @@
1
+ = MuckActivity
2
+
3
+ == Installation
4
+ The muck activity engine is part of the muck framework and relies upon the muck_engine. The main engine can be found here:
5
+ http://github.com/jbasdf/muck_engine
6
+
7
+ The easiest way to get started with muck is to generate your application using a template:
8
+ $ rails <your-app> -m http://github.com/jbasdf/rails-templates/raw/master/muck.rb
9
+
10
+ Add optional functionality with the following command:
11
+ $ rake rails:template LOCATION=http://github.com/jbasdf/rails-templates/raw/master/mucktoo.rb
12
+
13
+ == Usage
14
+ This engine implements simple activity tracking.
15
+
16
+ Models that can have activity feed should call 'has_activities'
17
+
18
+ Example:
19
+ class User
20
+ has_activities
21
+ end
22
+
23
+ Adding an item to the activity feed requires 'acts_as_activity_source' which then profiles the method 'add_activity'
24
+
25
+ add_activity(feed_to, actor, item, template, check_method)
26
+
27
+ feed_to - contains an array of objects (typically users) that have use acts_as_activity_user
28
+ actor - the user performing the action
29
+ item - a reference to the object that
30
+ template - the template (partial) to use to render the activity
31
+ check_method - and optional method to call on each object in the feed_to array that determines whether or not to add the activity
32
+
33
+ Example:
34
+ add_activity(user.feed_to, user, comment, 'comment')
35
+
36
+ === Authorization
37
+ By default 'has_activities' will add a simple 'can_view?' method:
38
+
39
+ def can_view?(check_object)
40
+ self == check_object
41
+ end
42
+
43
+ This method determines whether or not the check_object has access to the current object's activity feeds. For example, if the
44
+ intent is to recover the activities for a given user where the user is '@parent' thus:
45
+
46
+ @parent.can_view?(current_user)
47
+
48
+ The can view method will determine whether or not the current_user has the right to view the activity feed.
49
+
50
+ In most instances you will need to override this method to implement proper security. For example, for a group that has an activity feed
51
+ you might add a can_view? method like this:
52
+
53
+ def can_view?(check_object)
54
+ self.member?(check_object) || (check_object.is_a?(User) && check_object.admin?)
55
+ end
56
+
57
+ == Configuration
58
+ If you would like to enable comments for your project's activities feeds you can do so by adding an entry to GlobalConfig.yml (configuration file added by muck)
59
+
60
+ enable_activity_comments: true
61
+
62
+ If you would like to add live updates to the user's activity feed you can do so by adding an entry to GlobalConfig.yml (configuration file added by muck)
63
+
64
+ enable_live_activity_updates: true
65
+ live_activity_update_interval: 5
66
+
67
+ Note that this will poll the server every 5 seconds and so will increase server load and bandwidth usage.
68
+
69
+ Copyright (c) 2009 Justin Ball, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,78 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the muck_activities plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the muck_activities plugin.'
17
+ Rake::RDocTask.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'MuckActivity'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README*')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
24
+
25
+ begin
26
+ require 'jeweler'
27
+ Jeweler::Tasks.new do |gemspec|
28
+ gemspec.name = "muck-activities"
29
+ gemspec.summary = "Activity engine for the muck system"
30
+ gemspec.email = "justinball@gmail.com"
31
+ gemspec.homepage = "http://github.com/jbasdf/muck_activities"
32
+ gemspec.description = "Activity engine for the muck system."
33
+ gemspec.authors = ["Justin Ball"]
34
+ gemspec.rubyforge_project = 'muck-activities'
35
+ gemspec.add_dependency "muck-engine"
36
+ gemspec.add_dependency "muck-users"
37
+ gemspec.add_dependency "muck-comments"
38
+ gemspec.files.include %w(
39
+ tasks/*
40
+ db/migrate/*.rb
41
+ app/**/**/**/*
42
+ config/*
43
+ locales/*
44
+ rails/*
45
+ test/*
46
+ lib/**/*
47
+ public/**/* )
48
+ end
49
+ rescue LoadError
50
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
51
+ end
52
+
53
+ # rubyforge tasks
54
+ begin
55
+ require 'rake/contrib/sshpublisher'
56
+ namespace :rubyforge do
57
+
58
+ desc "Release gem and RDoc documentation to RubyForge"
59
+ task :release => ["rubyforge:release:gem", "rubyforge:release:docs"]
60
+
61
+ namespace :release do
62
+ desc "Publish RDoc to RubyForge."
63
+ task :docs => [:rdoc] do
64
+ config = YAML.load(
65
+ File.read(File.expand_path('~/.rubyforge/user-config.yml'))
66
+ )
67
+
68
+ host = "#{config['username']}@rubyforge.org"
69
+ remote_dir = "/var/www/gforge-projects/muck-activities/"
70
+ local_dir = 'rdoc'
71
+
72
+ Rake::SshDirPublisher.new(host, remote_dir, local_dir).upload
73
+ end
74
+ end
75
+ end
76
+ rescue LoadError
77
+ puts "Rake SshDirPublisher is unavailable or your rubyforge environment is not configured."
78
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.7
@@ -0,0 +1,152 @@
1
+ class Muck::ActivitiesController < ApplicationController
2
+ unloadable
3
+
4
+ include ApplicationHelper
5
+ include MuckActivityHelper
6
+
7
+ before_filter :login_required
8
+ before_filter :find_parent, :only => [:index, :create]
9
+ before_filter :get_activity, :only => [:destroy]
10
+
11
+ def index
12
+ if @parent.can_view?(current_user)
13
+ @activities = get_activities(@parent)
14
+ respond_to do |format|
15
+ format.js do
16
+ render :partial => "activities/cached_activities", :locals => {:activities => @activities}
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def create
23
+ @activity = @parent.activities.build(params[:activity])
24
+ @activity.source = @parent
25
+ @activity.content.gsub!(@parent.display_name, '')
26
+ @parent.save!
27
+
28
+ @activity_html = get_activity_html(@activity)
29
+ if @activity.template == 'status_update'
30
+ @status_html = get_status_html(@parent)
31
+ else
32
+ @status_html = ''
33
+ end
34
+ respond_to do |format|
35
+ format.js do
36
+ render :update do |page|
37
+ page.insert_html :top, 'activity-feed-content', @activity_html
38
+ page.replace_html 'current-status', @status_html if @status_html
39
+ page.visual_effect :highlight, "#{@activity.dom_id}".to_sym
40
+ page << 'jQuery("#status_update").val(\'\');'
41
+ page << "jQuery('#status-update-field').removeClass('status-update-lit');"
42
+ page << "jQuery('#status-update-field').addClass('status-update-dim');"
43
+ page << 'jQuery("#status-update-field").show();'
44
+ page << 'jQuery("#submit_status").show();'
45
+ page << 'jQuery("#progress-bar").hide();'
46
+ page << 'setup_submit_delete();'
47
+ page << 'apply_comment_methods();'
48
+ end
49
+ end
50
+ format.html do
51
+ redirect_back_or_default(@parent)
52
+ end
53
+ format.json do
54
+ render :json => { :success => true,
55
+ :is_status_update => @activity.is_status_update,
56
+ :html => @activity_html,
57
+ :status_html => @status_html,
58
+ :message => t("muck.activities.created") }
59
+ end
60
+ end
61
+
62
+ rescue ActiveRecord::RecordInvalid => ex
63
+
64
+ if @activity
65
+ errors = @activity.errors.full_messages.to_sentence
66
+ else
67
+ errors = ex
68
+ end
69
+ message = t('muck.activities.update_error', :errors => errors)
70
+ respond_to do |format|
71
+ format.html do
72
+ flash[:error] = message
73
+ redirect_back_or_default(@parent)
74
+ end
75
+ format.js do
76
+ render :update do |page|
77
+ page_alert(page, message)
78
+ end
79
+ end
80
+ end
81
+
82
+ end
83
+
84
+ def destroy
85
+ @activities_object = @activity.source
86
+ @activity.destroy
87
+ respond_to do |format|
88
+ format.html do
89
+ flash[:notice] = t("muck.activities.item_removed")
90
+ redirect_back_or_default(@activities_object)
91
+ end
92
+ format.js do
93
+ if @activity.is_status_update
94
+ @new_status = get_status_html(@activities_object)
95
+ render(:update) do |page|
96
+ page << "jQuery('##{@activity.dom_id}').fadeOut();"
97
+ page.replace_html 'current-status', @new_status if @new_status
98
+ end
99
+ end
100
+ end
101
+ format.json do
102
+ @new_status = get_status_html(@activities_object)
103
+ render :json => { :success => true,
104
+ :is_status_update => @activity.is_status_update,
105
+ :html => @new_status,
106
+ :message => t("muck.activities.item_removed") }
107
+ end
108
+ end
109
+
110
+ rescue => ex
111
+ respond_to do |format|
112
+ format.html do
113
+ flash[:notice] = t("muck.activities.item_could_not_be_removed")
114
+ redirect_back_or_default(current_user)
115
+ end
116
+ format.js do
117
+ render(:update){ |page| page_alert(page, t("muck.activities.item_could_not_be_removed")) }
118
+ end
119
+ format.json { render :json => { :success => false, :message => t("muck.activities.item_could_not_be_removed") } }
120
+ end
121
+ end
122
+
123
+ protected
124
+
125
+ def get_status_html(activity)
126
+ @template.template_format = :html
127
+ render_to_string(:partial => 'activities/current_status', :locals => {:activities_object => activity})
128
+ end
129
+
130
+ def get_activity_html(activity)
131
+ render_to_string(:partial => "activity_templates/#{activity.template}", :locals => { :activity => activity })
132
+ end
133
+
134
+ def find_parent
135
+ @klass = params[:parent_type].to_s.capitalize.constantize
136
+ @parent = @klass.find(params[:parent_id])
137
+ end
138
+
139
+ def get_activity
140
+ @activity = Activity.find(params[:id])
141
+ unless @activity.can_edit?(current_user)
142
+ respond_to do |format|
143
+ format.html do
144
+ flash[:notice] = t("muck.activities.permission_denied")
145
+ redirect_back_or_default(current_user)
146
+ end
147
+ format.js { render(:update){|page| page_alert(page, t("muck.activities.permission_denied"))}}
148
+ end
149
+ end
150
+ end
151
+
152
+ end
@@ -0,0 +1,67 @@
1
+ module MuckActivityHelper
2
+
3
+ def activity_comments(activity)
4
+ render :partial => 'activities/comments', :locals => { :activity => activity }
5
+ end
6
+
7
+ def activity_comment_link(activity, comment = nil)
8
+ if GlobalConfig.enable_activity_comments
9
+ comment_form(activity, comment = nil)
10
+ end
11
+ end
12
+
13
+ def has_comments_css(activity)
14
+ if activity.has_comments?
15
+ 'activity-has-comments'
16
+ else
17
+ 'activity-no-comments'
18
+ end
19
+ end
20
+
21
+ def activity_feed_for(activities_object)
22
+ activities = get_activities(activities_object)
23
+ render :partial => 'activities/activity_feed', :locals => { :activities_object => activities_object, :activities => activities }
24
+ end
25
+
26
+ def status_update(activities_object)
27
+ render :partial => 'activities/status_update', :locals => { :activities_object => activities_object }
28
+ end
29
+
30
+ def current_status(activities_object)
31
+ render :partial => 'activities/current_status_wrapper', :locals => { :activities_object => activities_object }
32
+ end
33
+
34
+ def delete_activity(activity, button_type = :button, button_text = t("muck.activities.clear"))
35
+ render :partial => 'activities/delete', :locals => { :activity => activity, :button_type => button_type, :button_text => button_text }
36
+ end
37
+
38
+ def activity_filter(activities_object)
39
+ activity_types = activities_object.activities.all(:select => "DISTINCT activities.template")
40
+ render :partial => 'activities/template_filter', :locals => { :activity_types => activity_types }
41
+ end
42
+
43
+ def is_current_filter?(template)
44
+ if params[:activity_filter] == template
45
+ 'current'
46
+ end
47
+ end
48
+
49
+ def no_filter?
50
+ if params[:activity_filter].blank?
51
+ 'current'
52
+ end
53
+ end
54
+
55
+ def all_activities_url
56
+ request.url.gsub(request.query_string, '')
57
+ end
58
+
59
+ def get_activities(activities_object)
60
+ if !params[:latest_activity_id].blank?
61
+ activities_object.activities.filter_by_template(params[:activity_filter]).after(params[:latest_activity_id]).find(:all, :include => ['comments']).paginate(:page => @page, :per_page => @per_page)
62
+ else
63
+ activities_object.activities.filter_by_template(params[:activity_filter]).find(:all, :include => ['comments']).paginate(:page => @page, :per_page => @per_page)
64
+ end
65
+ end
66
+
67
+ end
@@ -0,0 +1,62 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: activities
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # item_id :integer(4)
7
+ # item_type :string(255)
8
+ # template :string(255)
9
+ # source_id :integer(4)
10
+ # source_type :string(255)
11
+ # content :text
12
+ # title :string(255)
13
+ # status_update :boolean(1)
14
+ # created_at :datetime
15
+ # updated_at :datetime
16
+ #
17
+
18
+ class Activity < ActiveRecord::Base
19
+ unloadable
20
+
21
+ belongs_to :item, :polymorphic => true
22
+ belongs_to :source, :polymorphic => true
23
+ has_many :activity_feeds
24
+
25
+ acts_as_commentable
26
+
27
+ validates_presence_of :source
28
+
29
+ named_scope :since, lambda { |time| {:conditions => ["activities.created_at > ?", time] } }
30
+ named_scope :before, lambda {|time| {:conditions => ["activities.created_at < ?", time] } }
31
+ named_scope :recent, :order => "activities.created_at DESC"
32
+ named_scope :after, lambda {|id| {:conditions => ["activities.id > ?", id] } }
33
+ named_scope :only_public, :conditions => ["activities.is_public = true"]
34
+ named_scope :filter_by_template, lambda { |template| { :conditions => ["activities.template = ?", template] } unless template.blank? }
35
+
36
+ def validate
37
+ errors.add_to_base(I18n.t('muck.activities.template_or_item_required')) if template.blank? && item.blank?
38
+ end
39
+
40
+ # Provides a template that can be used to render a view of this activity.
41
+ # If 'template' is not specified when the object created then the item class
42
+ # name will be used to generated a template
43
+ def partial
44
+ template || item.class.name.underscore
45
+ end
46
+
47
+ def has_comments?
48
+ @has_comments ||= !self.comments.blank?
49
+ end
50
+
51
+ # Checks to see if the specified object can edit this activity.
52
+ # Most likely check_object will be a user
53
+ def can_edit?(check_object)
54
+ if check_object.is_a?(User)
55
+ return true if check(check_object, :source_id)
56
+ else
57
+ source == check_object
58
+ end
59
+ false
60
+ end
61
+
62
+ end
@@ -0,0 +1,16 @@
1
+ # == Schema Information
2
+ #
3
+ # Table name: activity_feeds
4
+ #
5
+ # id :integer(4) not null, primary key
6
+ # activity_id :integer(4)
7
+ # ownable_id :integer(4)
8
+ # ownable_type :string(255)
9
+ #
10
+
11
+ class ActivityFeed < ActiveRecord::Base
12
+ unloadable
13
+
14
+ belongs_to :activity
15
+ belongs_to :ownable, :polymorphic => true
16
+ end
@@ -0,0 +1,18 @@
1
+ <div id="activity-feed">
2
+ <div id="activity-feed-content">
3
+ <%= render( :partial => "activities/cached_activities", :locals => {:activities => activities}) %>
4
+ </div>
5
+ </div>
6
+ <%= will_paginate activities, :previous_label => t('muck.activities.paging_newer'), :next_label => t('muck.activities.paging_older') -%>
7
+ <% content_for :head do -%>
8
+ <%= javascript_tag %[var COMMENT_PROMPT = '#{t('muck.activities.write_prompt')}';] %>
9
+ <% end -%>
10
+ <% content_for :javascript do -%>
11
+ jQuery(document).ready(function(){
12
+ setup_submit_delete();
13
+ <% if GlobalConfig.enable_live_activity_updates -%>
14
+ setInterval(function() {jQuery.ajax({success:function(request){update_feed(request);},url:'<%= activities_path(:parent_id => activities_object, :parent_type => activities_object.type, :activity_filter => params[:activity_filter], :format => 'js') %>&amp;latest_activity_id=' + get_latest_activity_id()})}, <%=GlobalConfig.live_activity_update_interval%> * 1000)
15
+ <% end -%>
16
+ });
17
+ <% end -%>
18
+ <%= javascript_include_tag 'muck_activities' %>
@@ -0,0 +1,8 @@
1
+ <% if !activities.blank? -%>
2
+ <% activities.each do |activity| -%>
3
+ <% cache ("activities/#{I18n.locale}/#{activity.id}") do -%>
4
+ <%= render( :partial => "activity_templates/#{activity.partial}", :locals => {:activity => activity}) %>
5
+ <hr class="space">
6
+ <% end -%>
7
+ <% end -%>
8
+ <% end -%>
@@ -0,0 +1,6 @@
1
+ <div class="activity-comment">
2
+ <div class="actor-icon"><%= icon activity.source %></div>
3
+ <p><span class="actor"><%= link_to activity.source.display_name, activity.source %></span>
4
+ <span class="activity-time"><%= t("muck.activities.time_ago", :time_in_words => time_ago_in_words(activity.created_at)) %></span></p>
5
+ <p><%= h comment.body %></p>
6
+ </div>
@@ -0,0 +1,7 @@
1
+ <% if activity.has_comments? -%>
2
+ <%= render( :partial => "activities/comment", :collection => activity.comments, :locals => { :activity => activity } ) %>
3
+ <% end -%>
4
+ <div id="comment_<%=activity.dom_id%>" class="activity-comment <%= has_comments_css(activity) %>">
5
+ <div class="actor-icon"><%= icon current_user %></div>
6
+ <%= activity_comment_link(activity) %>
7
+ </div>
@@ -0,0 +1,14 @@
1
+ <% if activities_object.status
2
+ status = h(activities_object.status.content)
3
+ time = activities_object.status.created_at
4
+ else
5
+ status = t('muck.activities.update_status_message')
6
+ time = false
7
+ end -%>
8
+ <p id="current-status-text"><span id="current-status-name"><%= activities_object.display_name %></span> <%= status %></p>
9
+ <span id="status-time" class="status-time"><%= t('muck.activities.time_ago', :time_in_words => time_ago_in_words(time)) if time %></span>
10
+ <span id="status-clear">
11
+ <% if activities_object.status -%>
12
+ - <%= delete_activity(activities_object.status, :text, t("muck.activities.clear")) %>
13
+ <% end -%>
14
+ </span>
@@ -0,0 +1,4 @@
1
+ <div id="current-status-wrapper">
2
+ <div id="activity-icon"><%= icon activities_object %></div>
3
+ <div id="current-status"><%= render :partial => 'activities/current_status', :locals => {:activities_object => activities_object} %></div>
4
+ </div>
@@ -0,0 +1,11 @@
1
+ <% if button_type == :text -%>
2
+ <%= link_to_remote( button_text, :url => activity_path(activity, :format => 'js'), :method => :delete) %>
3
+ <% else -%>
4
+ <% remote_form_for(:activity, :url => activity_path(activity, :format => 'js'), :html => { :class => "delete-form activity-delete", :method => :delete } ) do |f| -%>
5
+ <% if button_type == :image -%>
6
+ <%= image_submit_tag '/images/icons/delete.png', {:title => button_text, :width => '15', :height => '15', :alt => button_text } %>
7
+ <% else -%>
8
+ <%= submit_tag button_text, { :title => button_text } %>
9
+ <% end -%>
10
+ <% end -%>
11
+ <% end -%>
@@ -0,0 +1,35 @@
1
+ <div id="status-update">
2
+ <%= output_errors(t('muck.users.problem_with_status'), {:class => 'help-box'}, @activity) %>
3
+ <% remote_form_for(:activity,
4
+ :url => activities_path(:parent_id => activities_object, :parent_type => activities_object.type, :format => 'js'),
5
+ :html => { :id => 'status_update_form', :class => 'clear',
6
+ :action => activities_path(:parent_id => activities_object, :parent_type => activities_object.type) } ) do |f| -%>
7
+ <div id="progress-bar" style="display:none;">
8
+ <h3><%= t('muck.activities.updating_status_message') %></h3>
9
+ <img src="/images/loading.gif" alt="progress bar">
10
+ </div>
11
+ <div id="status-update-field" class="status-update-dim">
12
+ <%= t("muck.activities.status_update_prompt") %>
13
+ <%= f.text_field :content, :id => 'status_update' %>
14
+ <span id="status-update-button">
15
+ <%= f.submit t('muck.activities.post'), :id => 'submit_status', :class => "button" %>
16
+ </span>
17
+ </div>
18
+ <%= f.hidden_field :template, :value => 'status_update' %>
19
+ <%= f.hidden_field :is_status_update, :value => true %>
20
+ <% end %>
21
+ </div>
22
+ <% content_for :javascript do -%>
23
+ jQuery(document).ready(function() {
24
+ jQuery('#status_update').click(function(){
25
+ jQuery('#status-update-field').removeClass('status-update-dim');
26
+ jQuery('#status-update-field').addClass('status-update-lit');
27
+ });
28
+
29
+ jQuery("#status_update_form").submit(function() {
30
+ jQuery("#status-update-field").hide();
31
+ jQuery("#submit_status").hide();
32
+ jQuery("#progress-bar").show();
33
+ });
34
+ });
35
+ <% end -%>
@@ -0,0 +1,6 @@
1
+ <ul id="activity-filter">
2
+ <li class="all-activities <%=no_filter?%>"><a href="<%=all_activities_url%>"><%=t('muck.activities.all_activities')%></a></li>
3
+ <% activity_types.each do |type| -%>
4
+ <li class="<%= type.template%> <%=is_current_filter?(type.template)%>"><a href="?activity_filter=<%= type.template%>"><%= type.template.titleize.pluralize %></a></li>
5
+ <% end -%>
6
+ </ul>
@@ -0,0 +1,12 @@
1
+ <div class="activity activity-status-update delete-container" id="<%= activity.dom_id %>">
2
+ <div class="actor-icon"><%= icon activity.source %></div>
3
+ <div class="activity-content">
4
+ <p><span class="actor"><%= link_to activity.source.display_name, activity.source %></span> <%= activity.content %></p>
5
+ <span class="activity-time"><%= t("muck.activities.time_ago", :time_in_words => time_ago_in_words(activity.created_at)) %></span>
6
+ <% if !activity.has_comments? -%>
7
+ <span><a id="make_comment_<%=activity.dom_id%>" class="make-comment" href="#"><%=t('muck.activities.make_comment')%></a></span>
8
+ <% end -%>
9
+ <%= delete_activity(activity, :image) %>
10
+ </div>
11
+ <%= activity_comments(activity) %>
12
+ </div>
@@ -0,0 +1,3 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.resources :activities, :controller => 'muck/activities'
3
+ end
@@ -0,0 +1,36 @@
1
+ class AddMuckActivities < ActiveRecord::Migration
2
+
3
+ def self.up
4
+
5
+ create_table :activities, :force => true do |t|
6
+ t.integer :item_id
7
+ t.string :item_type
8
+ t.string :template
9
+ t.integer :source_id
10
+ t.string :source_type
11
+ t.text :content
12
+ t.string :title
13
+ t.boolean :is_status_update, :default => false
14
+ t.boolean :is_public, :default => true
15
+ t.timestamps
16
+ end
17
+
18
+ add_index :activities, ["item_id", "item_type"]
19
+
20
+ create_table :activity_feeds, :force => true do |t|
21
+ t.integer :activity_id
22
+ t.integer :ownable_id
23
+ t.string :ownable_type
24
+ end
25
+
26
+ add_index :activity_feeds, ["activity_id"]
27
+ add_index :activity_feeds, ["ownable_id", "ownable_type"]
28
+
29
+ end
30
+
31
+ def self.down
32
+ drop_table :activities
33
+ drop_table :activity_feeds
34
+ end
35
+
36
+ end
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,8 @@
1
+ class ActionController::Routing::RouteSet
2
+ def load_routes_with_muck_activities!
3
+ muck_activities_routes = File.join(File.dirname(__FILE__), *%w[.. .. config muck_activities_routes.rb])
4
+ add_configuration_file(muck_activities_routes) unless configuration_files.include? muck_activities_routes
5
+ load_routes_without_muck_activities!
6
+ end
7
+ alias_method_chain :load_routes!, :muck_activities
8
+ end