muck-activities 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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