spud_events 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +57 -0
  3. data/Rakefile +28 -0
  4. data/app/assets/images/spud/admin/events_thumb.png +0 -0
  5. data/app/assets/javascripts/calendar_events.js +2 -0
  6. data/app/assets/javascripts/calendars.js +2 -0
  7. data/app/assets/javascripts/spud/admin/calendar_events.js +2 -0
  8. data/app/assets/javascripts/spud/admin/calendars.js +0 -0
  9. data/app/assets/javascripts/spud/admin/events.js +51 -0
  10. data/app/assets/javascripts/spud/events.js +0 -0
  11. data/app/assets/lib/colorpicker/colorpicker.css +161 -0
  12. data/app/assets/lib/colorpicker/colorpicker.js +484 -0
  13. data/app/assets/lib/colorpicker/images/blank.gif +0 -0
  14. data/app/assets/lib/colorpicker/images/colorpicker_background.png +0 -0
  15. data/app/assets/lib/colorpicker/images/colorpicker_hex.png +0 -0
  16. data/app/assets/lib/colorpicker/images/colorpicker_hsb_b.png +0 -0
  17. data/app/assets/lib/colorpicker/images/colorpicker_hsb_h.png +0 -0
  18. data/app/assets/lib/colorpicker/images/colorpicker_hsb_s.png +0 -0
  19. data/app/assets/lib/colorpicker/images/colorpicker_indic.gif +0 -0
  20. data/app/assets/lib/colorpicker/images/colorpicker_overlay.png +0 -0
  21. data/app/assets/lib/colorpicker/images/colorpicker_rgb_b.png +0 -0
  22. data/app/assets/lib/colorpicker/images/colorpicker_rgb_g.png +0 -0
  23. data/app/assets/lib/colorpicker/images/colorpicker_rgb_r.png +0 -0
  24. data/app/assets/lib/colorpicker/images/colorpicker_select.gif +0 -0
  25. data/app/assets/lib/colorpicker/images/colorpicker_submit.png +0 -0
  26. data/app/assets/lib/colorpicker/images/custom_background.png +0 -0
  27. data/app/assets/lib/colorpicker/images/custom_hex.png +0 -0
  28. data/app/assets/lib/colorpicker/images/custom_hsb_b.png +0 -0
  29. data/app/assets/lib/colorpicker/images/custom_hsb_h.png +0 -0
  30. data/app/assets/lib/colorpicker/images/custom_hsb_s.png +0 -0
  31. data/app/assets/lib/colorpicker/images/custom_indic.gif +0 -0
  32. data/app/assets/lib/colorpicker/images/custom_rgb_b.png +0 -0
  33. data/app/assets/lib/colorpicker/images/custom_rgb_g.png +0 -0
  34. data/app/assets/lib/colorpicker/images/custom_rgb_r.png +0 -0
  35. data/app/assets/lib/colorpicker/images/custom_submit.png +0 -0
  36. data/app/assets/lib/colorpicker/images/select.png +0 -0
  37. data/app/assets/lib/colorpicker/images/select2.png +0 -0
  38. data/app/assets/lib/colorpicker/images/slider.png +0 -0
  39. data/app/assets/stylesheets/spud/admin/events.css +16 -0
  40. data/app/assets/stylesheets/spud/calendar_events.css +18 -0
  41. data/app/assets/stylesheets/spud/calendars.css +136 -0
  42. data/app/assets/stylesheets/spud/events.css +4 -0
  43. data/app/controllers/calendar_events_controller.rb +8 -0
  44. data/app/controllers/calendars_controller.rb +30 -0
  45. data/app/controllers/spud/admin/calendar_events_controller.rb +64 -0
  46. data/app/controllers/spud/admin/calendars_controller.rb +52 -0
  47. data/app/helpers/calendars_helper.rb +49 -0
  48. data/app/helpers/spud/admin/calendar_events_helper.rb +2 -0
  49. data/app/helpers/spud/admin/calendars_helper.rb +13 -0
  50. data/app/models/spud_calendar.rb +7 -0
  51. data/app/models/spud_calendar_event.rb +11 -0
  52. data/app/views/calendar_events/show.html.erb +5 -0
  53. data/app/views/calendars/_calendar.html.erb +26 -0
  54. data/app/views/calendars/_calendar_options.html.erb +4 -0
  55. data/app/views/calendars/show.html.erb +4 -0
  56. data/app/views/spud/admin/calendar_events/_calendar.html.erb +14 -0
  57. data/app/views/spud/admin/calendar_events/_form.html.erb +98 -0
  58. data/app/views/spud/admin/calendar_events/edit.html.erb +1 -0
  59. data/app/views/spud/admin/calendar_events/index.html.erb +20 -0
  60. data/app/views/spud/admin/calendar_events/new.html.erb +1 -0
  61. data/app/views/spud/admin/calendars/_calendar_legend.html.erb +7 -0
  62. data/app/views/spud/admin/calendars/_form.html.erb +20 -0
  63. data/app/views/spud/admin/calendars/edit.html.erb +1 -0
  64. data/app/views/spud/admin/calendars/new.html.erb +1 -0
  65. data/config/application.rb +50 -0
  66. data/config/boot.rb +6 -0
  67. data/config/routes.rb +17 -0
  68. data/db/migrate/20120216191833_create_spud_calendars.rb +12 -0
  69. data/db/migrate/20120216192531_create_spud_calendar_events.rb +15 -0
  70. data/db/migrate/20130214131628_add_location_to_spud_calendar_event.rb +10 -0
  71. data/lib/spud_events.rb +8 -0
  72. data/lib/spud_events/calendar_builder.rb +133 -0
  73. data/lib/spud_events/configuration.rb +10 -0
  74. data/lib/spud_events/engine.rb +30 -0
  75. data/lib/spud_events/table_builder.rb +88 -0
  76. data/lib/spud_events/version.rb +5 -0
  77. metadata +258 -0
@@ -0,0 +1,2 @@
1
+ module Spud::Admin::CalendarEventsHelper
2
+ end
@@ -0,0 +1,13 @@
1
+ module Spud::Admin::CalendarsHelper
2
+ def link_to_admin_previous_calendar_month(date, url_for_options)
3
+ date = date.advance(:months => -1)
4
+ calendar = params[:calendar] ? params[:calendar] : nil
5
+ link_to('« Previous Month'.html_safe, spud_admin_list_spud_calendar_events_path(:month => date.month, :year => date.year, :calendar => calendar), :class => 'spud_events_calendar_link previous_calendar btn').html_safe
6
+ end
7
+
8
+ def link_to_admin_next_calendar_month(date, url_for_options)
9
+ date = date.advance(:months => 1)
10
+ calendar = params[:calendar] ? params[:calendar] : nil
11
+ link_to('Next Month »'.html_safe, spud_admin_list_spud_calendar_events_path(:month => date.month, :year => date.year, :calendar => calendar), :class => 'spud_events_calendar_link next_calendar btn').html_safe
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ class SpudCalendar < ActiveRecord::Base
2
+ has_many :spud_calendar_events, :dependent => :destroy
3
+ validates_presence_of :title, :color
4
+
5
+ attr_accessible :title, :color
6
+
7
+ end
@@ -0,0 +1,11 @@
1
+ class SpudCalendarEvent < ActiveRecord::Base
2
+ belongs_to :spud_calendar
3
+ validates_presence_of :title, :start_at, :end_at, :spud_calendar_id
4
+
5
+ attr_accessible :title, :description, :start_at, :end_at, :all_day, :spud_calendar_id, :spud_calendar, :location, :address, :address_2, :city, :state, :zip
6
+
7
+ def self.in_month_of(month)
8
+ where(["spud_calendar_events.start_at <= ? AND spud_calendar_events.start_at >= ?", month.end_of_month, month.beginning_of_month])
9
+ end
10
+
11
+ end
@@ -0,0 +1,5 @@
1
+ <h2><%= @event.title %></h2>
2
+ <h4 class="spud_calendar_event_date">
3
+ <%= @event.start_at.strftime('%B %d, %Y') %>
4
+ </h4>
5
+ <p><%= @event.description %></p>
@@ -0,0 +1,26 @@
1
+ <div>
2
+ <h2><%= date.strftime("%B %Y") %></h2>
3
+ <% build_calendar_for @events, :year => date.year, :month => date.month do |t| %>
4
+ <%= raw t.head('S', 'M', 'T', 'W', 'T', 'F', 'S') %>
5
+ <% t.day do |day, tasks| %>
6
+ <%= content_tag :span, day.day, :class => (tasks.count > 0 ? "spud_events_calendar_date spud_events_calendar_date_active" : "spud_events_calendar_date") %>
7
+ <% end %>
8
+ <% end %>
9
+ </div>
10
+
11
+ <nav id="spud_events_calendar_nav">
12
+ <%= link_to_previous_calendar_month(@calendar_date, {:controller => 'spud/events/calendars', :action => :show}) %>
13
+ <%= link_to_next_calendar_month(@calendar_date, {:controller => 'spud/events/calendars', :action => :show}) %>
14
+ </nav>
15
+
16
+ <%= build_calendar_for @events, :year => date.year, :month => date.month do |t| %>
17
+ <%= raw t.head('S', 'M', 'T', 'W', 'T', 'F', 'S') %>
18
+ <%= t.day do |day, tasks| %>
19
+ <div class="spud_events_calendar_date_container">
20
+ <%= content_tag :span, day.day, :class => (tasks.count > 0 ? "spud_events_calendar_date spud_events_calendar_date_active" : "spud_events_calendar_date") %>
21
+ <% tasks.each do |task| %>
22
+ <%= link_to task.title[0,25], "#", :class => "spud_events_calendar_event_marker spud_events_calendar_event_#{task.spud_calendar_id}", :style => "background-color: \##{task.spud_calendar.color}; color:\##{calendar_fore_color(task.spud_calendar.color)};" %>
23
+ <% end %>
24
+ </div>
25
+ <% end %>
26
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <%= form_tag calendar_path(@calendar_date.strftime("%b").downcase, @calendar_date.strftime("%Y")), :method => 'post', :id => "spud_events_calendar_for" do %>
2
+ <%= select_tag 'calendar', get_calendar_options('All Calendars') %>
3
+ <%= submit_tag 'Go' %>
4
+ <% end %>
@@ -0,0 +1,4 @@
1
+ <%= render :partial => 'calendar_options' %>
2
+ <div id="spud_events_calendar">
3
+ <%= render :partial => 'calendar', :locals => {:date => @calendar_date} %>
4
+ </div>
@@ -0,0 +1,14 @@
1
+ <p><%= link_to_admin_next_calendar_month(@calendar_date, :class => "btn") %></p>
2
+ <p><%= link_to_admin_previous_calendar_month(@calendar_date, :class => "btn") %></p>
3
+
4
+ <%= build_calendar_for @calendar_events, :year => @calendar_date.year, :month => @calendar_date.month do |t| %>
5
+ <%= raw t.head('S', 'M', 'T', 'W', 'T', 'F', 'S') %>
6
+ <%= t.day do |day, tasks| %>
7
+ <div class="spud_events_admin_calendar_date_container">
8
+ <%= content_tag :span, day.day, :class => (tasks.count > 0 ? "spud_events_admin_calendar_date spud_events_admin_calendar_date_active" : "spud_events_admin_calendar_date") %>
9
+ <% tasks.each do |task| %>
10
+ <%= link_to task.title[0,25], edit_spud_admin_calendar_event_path(task.id), :class => "spud_events_admin_calendar_event_marker spud_events_calendar_event_#{task.spud_calendar_id}", :style => "background-color: \##{task.spud_calendar.color}; color:\##{calendar_fore_color(task.spud_calendar.color)}" %>
11
+ <% end %>
12
+ </div>
13
+ <% end %>
14
+ <% end %>
@@ -0,0 +1,98 @@
1
+ <%= form_for @calendar_event, :url => path,:html=>{:class=>"form-horizontal"} do |f| %>
2
+ <%= error_messages_for(f.object) %>
3
+ <fieldset>
4
+ <legend>Details</legend>
5
+ <div class="control-group">
6
+ <%= f.label :spud_calender_id, "Calendar",:class => "control-label" %>
7
+ <div class="controls">
8
+ <%= f.select(:spud_calendar_id, options_from_collection_for_select(SpudCalendar.all, :id, :title, @calendar_event.spud_calendar_id)) %>
9
+ </div>
10
+ </div>
11
+ <div class="control-group">
12
+ <%= f.label :title,:class => "control-label" %>
13
+ <div class="controls">
14
+ <%= f.text_field :title %>
15
+ </div>
16
+ </div>
17
+ <div class="control-group">
18
+ <%= f.label :description,:class => "control-label" %>
19
+ <div class="controls">
20
+ <%= f.text_area :description, :rows => 5 %>
21
+ </div>
22
+ </div>
23
+ </fieldset>
24
+
25
+ <fieldset>
26
+ <legend>Event Time</legend>
27
+
28
+ <div class="control-group">
29
+ <%= f.label :start_at, "Starts",:class => "control-label" %>
30
+ <div class="controls">
31
+ <%= f.text_field :start_at,:value => f.object.start_at.blank? ? Time.now.strftime("%Y-%m-%d %H:%M") : f.object.start_at.strftime("%Y-%m-%d %H:%M") , :class => 'spud_form_date_picker' %>
32
+ <span class="time_select">
33
+ <%= f.time_select :start_at, :ignore_date => true,:ampm => true%>
34
+ </span>
35
+ </div>
36
+ </div>
37
+ <div class="control-group">
38
+ <%= f.label :end_at, "Ends",:class => "control-label" %>
39
+
40
+ <div class="controls">
41
+ <%= f.text_field :end_at,:value => f.object.end_at.blank? ? Time.now.strftime("%Y-%m-%d %H:%M") : f.object.end_at.strftime("%Y-%m-%d %H:%M") , :class => 'spud_form_date_picker' %>
42
+ <span class="time_select">
43
+ <%= f.time_select :end_at, :ignore_date => true,:ampm => true%>
44
+ </span>
45
+ </div>
46
+ </div>
47
+ </fieldset>
48
+ <fieldset>
49
+ <legend>Location</legend>
50
+ <div class="control-group">
51
+ <%= f.label :location,:class => "control-label" %>
52
+ <div class="controls">
53
+ <%= f.text_field :location %>
54
+ </div>
55
+ </div>
56
+ <div class="control-group">
57
+ <%= f.label :address,:class => "control-label" %>
58
+ <div class="controls">
59
+ <%= f.text_field :address %>
60
+ </div>
61
+ </div>
62
+ <div class="control-group">
63
+ <%= f.label :address_2,:class => "control-label" %>
64
+ <div class="controls">
65
+ <%= f.text_field :address_2 %>
66
+ </div>
67
+ </div>
68
+ <div class="control-group">
69
+ <%= f.label :city,:class => "control-label" %>
70
+ <div class="controls">
71
+ <%= f.text_field :city %>
72
+ </div>
73
+ </div>
74
+ <div class="control-group">
75
+ <%= f.label :state,:class => "control-label" %>
76
+ <div class="controls">
77
+ <%= f.text_field :state %>
78
+ </div>
79
+ </div>
80
+ <div class="control-group">
81
+ <%= f.label :zip,:class => "control-label" %>
82
+ <div class="controls">
83
+ <%= f.text_field :zip %>
84
+ </div>
85
+ </div>
86
+ </fieldset>
87
+
88
+ <div class="form-actions">
89
+ <%=f.submit "Create Event", :class=>"btn btn-primary"%> <%= link_to "Delete", spud_admin_calendar_event_path(@calendar_event), :method=>:delete,:class => "btn btn-danger", :confirm=>"Are you sure you want delete this event?" if !@calendar_event.new_record? %> or <%=link_to "cancel",spud_admin_list_spud_calendar_events_path,:class => "btn"%>
90
+ </div>
91
+
92
+ <% end %>
93
+ <br class="clear" />
94
+ <script type="text/javascript">
95
+ $(document).ready(function(){
96
+ spud.admin.date_picker.init();
97
+ });
98
+ </script>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form', :locals => {:path => spud_admin_calendar_event_path(@calendar_event)} %>
@@ -0,0 +1,20 @@
1
+ <%=content_for :data_controls do%>
2
+ <%= link_to "New Event", new_spud_admin_calendar_event_path, :class => "btn btn-primary right" %>
3
+ <%end%>
4
+ <%=content_for :detail do%>
5
+ <h3>Calendar Events - <%= @calendar_date.strftime('%B %Y') %></h3>
6
+
7
+ <div id="spud_events_admin_calendar">
8
+ <%= render :partial => 'calendar' %>
9
+ </div>
10
+
11
+ <ul id="spud_events_admin_calendar_legend">
12
+ <%= render :partial => 'spud/admin/calendars/calendar_legend', :collection => @calendars, :as => :calendar %>
13
+ <li>
14
+ <%= link_to("New Calendar", new_spud_admin_calendar_path, :class => "btn btn-primary btn-small pull-right") %>
15
+ <br style="clear:right;"/>
16
+ </li>
17
+ </ul>
18
+
19
+
20
+ <%end%>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form', :locals => {:path => spud_admin_calendar_events_path} %>
@@ -0,0 +1,7 @@
1
+ <li id="spud_events_admin_calendar_legend_<%= calendar.id %>" class="spud_events_admin_calendar_legend_item">
2
+ <%= content_tag :span, calendar.title, :style => "background-color: \##{calendar.color};color:\##{calendar_fore_color(calendar.color)}"%>
3
+ <div class="spud_events_admin_calendar_actions">
4
+ <%= link_to 'edit', edit_spud_admin_calendar_path(calendar), :class => "btn btn-mini" %>
5
+ <%= link_to 'delete', spud_admin_calendar_path(calendar), :remote => true, :confirm => "This action can't be undone. Would you like to remove the calendar \"#{calendar.title}\"?", :method => :delete, :class => 'js-spud-calendar-delete-action btn btn-mini btn-danger' %>
6
+ </div>
7
+ </li>
@@ -0,0 +1,20 @@
1
+ <%= form_for @calendar, :url => (@calendar.new_record? ? spud_admin_calendars_path : spud_admin_calendar_path(@calendar)),:html=>{:class=>"form-horizontal"} do |f| %>
2
+ <%= error_messages_for(f.object) %>
3
+ <div class="control-group">
4
+ <%= f.label :title,:class => "control-label" %>
5
+ <div class="controls">
6
+ <%= f.text_field :title %>
7
+ </div>
8
+ </div>
9
+ <div class="control-group">
10
+ <%= f.label :color,:class => "control-label" %>
11
+ <div class="controls">
12
+ <%= f.hidden_field :color %>
13
+ <div class="spud_events_admin_color_picker"></div>
14
+ </div>
15
+ </div>
16
+ <div class="form-actions">
17
+ <%=f.submit "Save", :class=>"btn btn-primary"%> or <%=link_to "cancel",spud_admin_list_spud_calendar_events_path,:class => "btn"%>
18
+ </div>
19
+
20
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,50 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ if defined?(Bundler)
6
+ # If you precompile assets before deploying to production, use this line
7
+ Bundler.require *Rails.groups(:assets => %w(development test))
8
+ # If you want your assets lazily compiled in production, use this line
9
+ # Bundler.require(:default, :assets, Rails.env)
10
+ end
11
+
12
+ module Spud
13
+ module Events
14
+ class Application < Rails::Application
15
+ # Settings in config/environments/* take precedence over those specified here.
16
+ # Application configuration should go into files in config/initializers
17
+ # -- all .rb files in that directory are automatically loaded.
18
+
19
+ # Custom directories with classes and modules you want to be autoloadable.
20
+ # config.autoload_paths += %W(#{config.root}/extras)
21
+
22
+ # Only load the plugins named here, in the order given (default is alphabetical).
23
+ # :all can be used as a placeholder for all plugins not explicitly named.
24
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
25
+
26
+ # Activate observers that should always be running.
27
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
28
+
29
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
30
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
31
+ # config.time_zone = 'Central Time (US & Canada)'
32
+
33
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
34
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
35
+ # config.i18n.default_locale = :de
36
+
37
+ # Configure the default encoding used in templates for Ruby 1.9.
38
+ config.encoding = "utf-8"
39
+
40
+ # Configure sensitive parameters which will be filtered from the log file.
41
+ config.filter_parameters += [:password]
42
+
43
+ # Enable the asset pipeline
44
+ config.assets.enabled = true
45
+
46
+ # Version of your assets, change this if you want to expire all your assets
47
+ config.assets.version = '1.0'
48
+ end
49
+ end
50
+ end
data/config/boot.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rubygems'
2
+
3
+ # Set up gems listed in the Gemfile.
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
5
+
6
+ require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
data/config/routes.rb ADDED
@@ -0,0 +1,17 @@
1
+ Rails.application.routes.draw do
2
+
3
+ # Calendar
4
+ match 'calendar(/:month(/:year(/:calendar)))' => "calendars#show", :as => "calendar"
5
+ match 'calendar_event/:id' => "calendar_events#show", :as => "event"
6
+ namespace :spud do
7
+ namespace :admin do
8
+ # Events
9
+ resources :calendar_events, :except => [:index]
10
+ resources :calendars, :except => [:index]
11
+ match 'events(/:month(/:year(/:calendar)))' => "calendar_events#index", :as => "list_spud_calendar_events"
12
+ end
13
+ end
14
+
15
+
16
+ end
17
+
@@ -0,0 +1,12 @@
1
+ class CreateSpudCalendars < ActiveRecord::Migration
2
+ def change
3
+ create_table :spud_calendars do |t|
4
+ t.string :title
5
+ t.column :color, 'binary(6)'
6
+
7
+ t.timestamps
8
+ end
9
+
10
+ add_index :spud_calendars, :title
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ class CreateSpudCalendarEvents < ActiveRecord::Migration
2
+ def change
3
+ create_table :spud_calendar_events do |t|
4
+ t.references :spud_calendar
5
+ t.string :title
6
+ t.text :description
7
+ t.datetime :start_at
8
+ t.datetime :end_at
9
+ t.boolean :all_day
10
+
11
+ t.timestamps
12
+ end
13
+ add_index :spud_calendar_events, :spud_calendar_id
14
+ end
15
+ end
@@ -0,0 +1,10 @@
1
+ class AddLocationToSpudCalendarEvent < ActiveRecord::Migration
2
+ def change
3
+ add_column :spud_calendar_events, :location, :string
4
+ add_column :spud_calendar_events, :address, :string
5
+ add_column :spud_calendar_events, :address_2, :string
6
+ add_column :spud_calendar_events, :city, :string
7
+ add_column :spud_calendar_events, :state, :string
8
+ add_column :spud_calendar_events, :zip, :string
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ module Spud
2
+ module Events
3
+ require 'spud_events/configuration'
4
+ require 'spud_events/engine' if defined?(Rails)
5
+ require 'spud_events/table_builder'
6
+ require 'spud_events/calendar_builder'
7
+ end
8
+ end
@@ -0,0 +1,133 @@
1
+ module Spud
2
+ module Events
3
+ class CalendarBuilder < Spud::Events::TableBuilder
4
+ def initialize(objects, template, calendar, options)
5
+ super(objects, template, options)
6
+ @calendar = calendar.new(options)
7
+ @today = options[:today] || Time.now
8
+ end
9
+
10
+ def day(*args,&block)
11
+ raise ArgumentError, "Missing block" unless block_given?
12
+ options = options_from_hash(args)
13
+ day_method = options.delete(:day_method) || :start_at
14
+ id_pattern = options.delete(:id)
15
+ activity_class = options.delete(:activity)
16
+ output = ""
17
+ @calendar.objects_for_days(@objects, day_method).to_a.sort{|a1, a2| a1.first <=> a2.first }.each do |o|
18
+ key, array = o
19
+ day, objects = array
20
+
21
+ output << @template.tag(:tr,options,true) if (day.wday == @calendar.first_weekday)
22
+ output << @template.tag(:td,td_options(day, id_pattern, (objects.empty? ? nil: activity_class)), true)
23
+ output << @template.with_output_buffer{block.call(day, objects)}
24
+ output << '</td>'
25
+ output << '</tr>' if (day.wday == @calendar.last_weekday)
26
+ end
27
+ @template.content_tag(:tbody, output.html_safe, {}, false)
28
+ end
29
+
30
+ private
31
+
32
+ def objects_for_days
33
+ @calendar.objects_for_days(@objects)
34
+ end
35
+
36
+ def td_options(day, id_pattern, activity_class)
37
+ options = {}
38
+ if(day.strftime("%Y-%m-%d") == @today.strftime("%Y-%m-%d"))
39
+ options[:class] = 'today'
40
+ elsif(day.month != @calendar.month)
41
+ options[:class] = 'notmonth'
42
+ elsif(day.wday == 0 or day.wday == 6)
43
+ options[:class] = 'weekend'
44
+ elsif activity_class
45
+ options[:class] = activity_class
46
+ end
47
+ if id_pattern
48
+ options[:id] = day.strftime(id_pattern)
49
+ end
50
+
51
+ options
52
+ end
53
+
54
+ end
55
+
56
+ class Calendar
57
+ attr_accessor :first_weekday, :last_weekday, :month
58
+ def initialize(options={})
59
+ @year = options[:year] || Time.now.year
60
+ @month = options[:month] || Time.now.month
61
+ @first_day_of_week = options[:first_day_of_week] || 0
62
+ @first_weekday = first_day_of_week(@first_day_of_week)
63
+ @last_weekday = last_day_of_week(@first_day_of_week)
64
+ @first = Date.civil(@year, @month, 1)
65
+ @last = Date.civil(@year, @month, -1)
66
+ end
67
+
68
+ def each_day
69
+ first_day.upto(last_day) do |day|
70
+ yield(day)
71
+ end
72
+ end
73
+
74
+ def last_day
75
+ last = @last
76
+ while(last.wday % 7 != @last_weekday % 7)
77
+ last = last.next
78
+ end
79
+ last
80
+ end
81
+
82
+ def first_day
83
+ first = @first - 6
84
+ while(first.wday % 7 != (@first_weekday) % 7)
85
+ first = first.next
86
+ end
87
+ first
88
+ end
89
+
90
+ def objects_for_days(objects, day_method)
91
+ unless @objects_for_days
92
+ @objects_for_days = {}
93
+ days.each{|day| @objects_for_days[day.strftime("%Y-%m-%d")] = [day, []]}
94
+ objects.each do |o|
95
+ date = o.send(day_method.to_sym).strftime("%Y-%m-%d")
96
+ if @objects_for_days[date]
97
+ @objects_for_days[date][1] << o
98
+ end
99
+ end
100
+ end
101
+ @objects_for_days
102
+ end
103
+
104
+ def days
105
+ unless @days
106
+ @days = []
107
+ each_day{|day| @days << day}
108
+ end
109
+ @days
110
+ end
111
+
112
+ def mjdays
113
+ unless @mjdays
114
+ @mdays = []
115
+ each_day{|day| @days << day}
116
+ end
117
+ @days
118
+ end
119
+
120
+ def first_day_of_week(day)
121
+ day
122
+ end
123
+
124
+ def last_day_of_week(day)
125
+ if day > 0
126
+ day - 1
127
+ else
128
+ 6
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end