fullcalendar_engine 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/Rakefile +34 -0
  3. data/app/assets/javascripts/fullcalendar_engine/application.js +13 -0
  4. data/app/assets/javascripts/fullcalendar_engine/events.js +197 -0
  5. data/app/assets/javascripts/fullcalendar_engine/fullcalendar.js +6110 -0
  6. data/app/assets/javascripts/fullcalendar_engine/gcal.js +107 -0
  7. data/app/assets/javascripts/fullcalendar_engine/jquery-ui-1.10.3.custom.min.js +7 -0
  8. data/app/assets/stylesheets/fullcalendar_engine/application.css +13 -0
  9. data/app/assets/stylesheets/fullcalendar_engine/fullcalendar.css +589 -0
  10. data/app/assets/stylesheets/fullcalendar_engine/images/animated-overlay.gif +0 -0
  11. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  12. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  13. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_flat_10_000000_40x100.png +0 -0
  14. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  15. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  16. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  17. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  18. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  19. data/app/assets/stylesheets/fullcalendar_engine/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  20. data/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_222222_256x240.png +0 -0
  21. data/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_228ef1_256x240.png +0 -0
  22. data/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ef8c08_256x240.png +0 -0
  23. data/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ffd27a_256x240.png +0 -0
  24. data/app/assets/stylesheets/fullcalendar_engine/images/ui-icons_ffffff_256x240.png +0 -0
  25. data/app/assets/stylesheets/fullcalendar_engine/jquery-ui-1.10.3.custom.css +1177 -0
  26. data/app/assets/stylesheets/fullcalendar_engine/style.css +23 -0
  27. data/app/controllers/fullcalendar_engine/application_controller.rb +4 -0
  28. data/app/controllers/fullcalendar_engine/events_controller.rb +106 -0
  29. data/app/models/fullcalendar_engine/event.rb +56 -0
  30. data/app/models/fullcalendar_engine/event_series.rb +50 -0
  31. data/app/views/fullcalendar_engine/events/_edit_form.html.erb +40 -0
  32. data/app/views/fullcalendar_engine/events/_form.html.erb +38 -0
  33. data/app/views/fullcalendar_engine/events/index.html.erb +27 -0
  34. data/app/views/fullcalendar_engine/events/new.js.erb +1 -0
  35. data/config/full-calendar.yml.dummy +57 -0
  36. data/config/initializers/configuration.rb +17 -0
  37. data/config/initializers/constants.rb +1 -0
  38. data/config/routes.rb +12 -0
  39. data/db/migrate/20131203105320_create_fullcalendar_engine_events.rb +13 -0
  40. data/db/migrate/20131203105529_create_fullcalendar_engine_event_series.rb +12 -0
  41. data/lib/fullcalendar_engine.rb +4 -0
  42. data/lib/fullcalendar_engine/engine.rb +5 -0
  43. data/lib/fullcalendar_engine/version.rb +3 -0
  44. data/lib/generators/fullcalendar_engine/install/install_generator.rb +29 -0
  45. data/lib/tasks/fullcalendar_engine_tasks.rake +4 -0
  46. data/test/controllers/fullcalendar_engine/events_controller_test.rb +9 -0
  47. data/test/fixtures/fullcalendar_engine/event_series.yml +11 -0
  48. data/test/fixtures/fullcalendar_engine/events.yml +11 -0
  49. data/test/fullcalendar_engine_test.rb +7 -0
  50. data/test/helpers/fullcalendar_engine/events_helper_test.rb +6 -0
  51. data/test/integration/navigation_test.rb +10 -0
  52. data/test/models/fullcalendar_engine/event_series_test.rb +9 -0
  53. data/test/models/fullcalendar_engine/event_test.rb +9 -0
  54. data/test/test_helper.rb +15 -0
  55. metadata +127 -0
@@ -0,0 +1,23 @@
1
+ body{
2
+ font-size: 12px;
3
+ font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
4
+ }
5
+
6
+ #loading{
7
+ position: absolute;
8
+ right: 0px;
9
+ top: 0px;
10
+ background-color: #dd0000;
11
+ font-weight:bold;
12
+ color: white;
13
+ margin: 5px;
14
+ padding: 3px;
15
+ }
16
+
17
+ span > div#loading {
18
+ position: fixed;
19
+ }
20
+
21
+ h1{
22
+ font-size: 16px;
23
+ }
@@ -0,0 +1,4 @@
1
+ module FullcalendarEngine
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,106 @@
1
+ require_dependency "fullcalendar_engine/application_controller"
2
+
3
+ module FullcalendarEngine
4
+ class EventsController < ApplicationController
5
+
6
+ layout FullcalendarEngine::Configuration['layout'] || "application"
7
+
8
+ before_filter :load_event, :only => [:edit, :update, :destroy, :move, :resize]
9
+ before_filter :determine_event_type, :only => :create
10
+
11
+ def create
12
+ if @event.save
13
+ render :nothing => true
14
+ else
15
+ render :text => event.errors.full_messages.to_sentence, :status => 422
16
+ end
17
+ end
18
+
19
+ def new
20
+ respond_to do |format|
21
+ format.js
22
+ end
23
+ end
24
+
25
+ def get_events
26
+ @events = Event.where("starttime >= '#{Time.at(params['start'].to_i).to_formatted_s(:db)}' and endtime <= '#{Time.at(params['end'].to_i).to_formatted_s(:db)}'")
27
+ events = []
28
+ @events.each do |event|
29
+ events << {:id => event.id, :title => event.title, :description => event.description || "Some cool description here...", :start => "#{event.starttime.iso8601}", :end => "#{event.endtime.iso8601}", :allDay => event.all_day, :recurring => (event.event_series_id)? true: false}
30
+ end
31
+ render :json => events.to_json
32
+ end
33
+
34
+ def move
35
+ if @event
36
+ @event.starttime = (params[:minute_delta].to_i).minutes.from_now((params[:day_delta].to_i).days.from_now(@event.starttime))
37
+ @event.endtime = (params[:minute_delta].to_i).minutes.from_now((params[:day_delta].to_i).days.from_now(@event.endtime))
38
+ @event.all_day = params[:all_day]
39
+ @event.save
40
+ end
41
+ render :nothing => true
42
+ end
43
+
44
+ def resize
45
+ if @event
46
+ @event.endtime = (params[:minute_delta].to_i).minutes.from_now((params[:day_delta].to_i).days.from_now(@event.endtime))
47
+ @event.save
48
+ end
49
+ render :nothing => true
50
+ end
51
+
52
+ def edit
53
+ render :json => { :form => render_to_string(:partial => 'edit_form') }
54
+ end
55
+
56
+ def update
57
+ case params[:event][:commit_button]
58
+ when "Update All Occurrence"
59
+ @events = @event.event_series.events #.find(:all, :conditions => ["starttime > '#{@event.starttime.to_formatted_s(:db)}' "])
60
+ @event.update_events(@events, event_params)
61
+ when "Update All Following Occurrence"
62
+ @events = @event.event_series.events.find(:all, :conditions => ["starttime > '#{@event.starttime.to_formatted_s(:db)}' "])
63
+ @event.update_events(@events, event_params)
64
+ else
65
+ @event.attributes = event_params
66
+ @event.save
67
+ end
68
+ render :nothing => true
69
+ end
70
+
71
+ def destroy
72
+ case params[:delete_all]
73
+ when "true"
74
+ @event.event_series.destroy
75
+ when "future"
76
+ @events = @event.event_series.events.find(:all, :conditions => ["starttime > '#{@event.starttime.to_formatted_s(:db)}' "])
77
+ @event.event_series.events.delete(@events)
78
+ else
79
+ @event.destroy
80
+ end
81
+ render :nothing => true
82
+ end
83
+
84
+ private
85
+
86
+ def load_event
87
+ @event = Event.where(:id => params[:id]).first
88
+ unless @event
89
+ render :json => {:message => "Event Not Found.."}, :status => 404 and return
90
+ end
91
+ end
92
+
93
+ def event_params
94
+ params.require(:event).permit('title', 'description', 'starttime(1i)', 'starttime(2i)', 'starttime(3i)', 'starttime(4i)', 'starttime(5i)', 'endtime(1i)', 'endtime(2i)', 'endtime(3i)', 'endtime(4i)', 'endtime(5i)', 'all_day', 'period', 'frequency', 'commit_button')
95
+ end
96
+
97
+ def determine_event_type
98
+ if params[:event][:period] == "Does not repeat"
99
+ @event = Event.new(event_params)
100
+ else
101
+ @event = EventSeries.new(event_params)
102
+ end
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,56 @@
1
+ module FullcalendarEngine
2
+ class Event < ActiveRecord::Base
3
+
4
+ attr_accessor :period, :frequency, :commit_button
5
+
6
+ validates :title, :description, :presence => true
7
+ validate :validate_timings
8
+
9
+ belongs_to :event_series
10
+
11
+ REPEATS = {
12
+ :no_repeat => "Does not repeat",
13
+ :days => "Daily",
14
+ :weeks => "Weekly",
15
+ :months => "Monthly",
16
+ :years => "Yearly"
17
+ }
18
+
19
+ def validate_timings
20
+ if (starttime >= endtime) and !all_day
21
+ errors[:base] << "Start Time must be less than End Time"
22
+ end
23
+ end
24
+
25
+ def update_events(events, event)
26
+ events.each do |e|
27
+ begin
28
+ old_start_time, old_end_time = e.starttime, e.endtime
29
+ e.attributes = event
30
+ if event_series.period.downcase == 'monthly' or event_series.period.downcase == 'yearly'
31
+ new_start_time = make_date_time(e.starttime, old_start_time)
32
+ new_end_time = make_date_time(e.starttime, old_end_time, e.endtime)
33
+ else
34
+ new_start_time = make_date_time(e.starttime, old_end_time)
35
+ new_end_time = make_date_time(e.endtime, old_end_time)
36
+ end
37
+ rescue
38
+ new_start_time = new_end_time = nil
39
+ end
40
+ if new_start_time and new_end_time
41
+ e.starttime, e.endtime = new_start_time, new_end_time
42
+ e.save
43
+ end
44
+ end
45
+
46
+ event_series.attributes = event
47
+ event_series.save
48
+ end
49
+
50
+ private
51
+
52
+ def make_date_time(original_time, difference_time, event_time = nil)
53
+ DateTime.parse("#{original_time.hour}:#{original_time.min}:#{original_time.sec}, #{event_time.try(:day) || difference_time.day}-#{difference_time.month}-#{difference_time.year}")
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,50 @@
1
+ module FullcalendarEngine
2
+ class EventSeries < ActiveRecord::Base
3
+
4
+ attr_accessor :title, :description, :commit_button
5
+
6
+ validates :frequency, :period, :starttime, :endtime, :title, :description, :presence => true
7
+
8
+ has_many :events, :dependent => :destroy
9
+
10
+ after_create :create_events_until_end_time
11
+
12
+ def create_events_until_end_time(end_time=RECURRING_EVENTS_UPTO)
13
+ old_start_time = starttime
14
+ old_end_time = endtime
15
+ frequency_period = recurring_period(period)
16
+ new_start_time, new_end_time = old_start_time, old_end_time
17
+
18
+ while frequency.send(frequency_period).from_now(old_start_time) <= end_time
19
+ self.events.create(
20
+ :title => title,
21
+ :description => description,
22
+ :all_day => all_day,
23
+ :starttime => new_start_time,
24
+ :endtime => new_end_time
25
+ )
26
+ new_start_time = old_start_time = frequency.send(frequency_period).from_now(old_start_time)
27
+ new_end_time = old_end_time = frequency.send(frequency_period).from_now(old_end_time)
28
+
29
+ if period.downcase == 'monthly' or period.downcase == 'yearly'
30
+ begin
31
+ new_start_time = make_date_time(starttime, old_start_time)
32
+ new_end_time = make_date_time(endtime, old_end_time)
33
+ rescue
34
+ new_start_time = new_end_time = nil
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def recurring_period(period)
41
+ Event::REPEATS.key(period).to_s.downcase
42
+ end
43
+
44
+ private
45
+
46
+ def make_date_time(original_time, difference_time)
47
+ DateTime.parse("#{original_time.hour}:#{original_time.min}:#{original_time.sec}, #{original_time.day}-#{difference_time.month}-#{difference_time.year}")
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,40 @@
1
+ <%= form_for @event, :html => { :id => 'event_form' } do |f| %>
2
+ <p>
3
+ <%=f.label :title %>
4
+ <br/>
5
+ <%=f.text_field :title %>
6
+ </p>
7
+ <p>
8
+ <%=f.label :description %>
9
+ <br/>
10
+ <%=f.text_area :description, :rows => 4, :cols => 30 %>
11
+ </p>
12
+ <p>
13
+ <%=f.label :starttime, 'Start Time' %>
14
+ <br/>
15
+ <%=f.datetime_select :starttime %>
16
+ </p>
17
+ <p>
18
+ <%=f.label :endtime, 'End Time' %>
19
+ <br/>
20
+ <%=f.datetime_select :endtime %>
21
+ </p>
22
+ <p>
23
+ <%=f.label :all_day %>
24
+ <%=f.check_box :all_day %>
25
+ </p>
26
+
27
+ <%=f.hidden_field :id, :value => @event.id%>
28
+ <%=f.hidden_field :commit_button, :value => ""%>
29
+ <p>
30
+ <%if @event.event_series -%>
31
+ <%=f.submit 'Update Only This Occurrence', :onclick => "document.getElementById('event_commit_button').value = this.value"%>
32
+ <%=f.submit 'Update All Occurrence', :onclick => "document.getElementById('event_commit_button').value = this.value"%>
33
+ <%=f.submit 'Update All Following Occurrence', :onclick => "document.getElementById('event_commit_button').value = this.value"%>
34
+ <%else-%>
35
+ <%=f.submit 'Update', :onclick => "document.getElementById('event_commit_button').value = this.value"%>
36
+ <%end-%>
37
+
38
+ <span id = "updating_events" class="spinner" style = "display:none;">Updating, Please wait...</span>
39
+ </p>
40
+ <%end %>
@@ -0,0 +1,38 @@
1
+ <%= form_for @event ||= FullcalendarEngine::Event.new, :html => { :id => 'event_form' } do |f| %>
2
+ <p>
3
+ <%=f.label :title %>
4
+ <br/>
5
+ <%=f.text_field :title %>
6
+ </p>
7
+ <p>
8
+ <%=f.label :description %>
9
+ <br/>
10
+ <%=f.text_area :description, :rows => 4, :cols => 30 %>
11
+ </p>
12
+ <p>
13
+ <%=f.label :starttime, 'Start Time' %>
14
+ <br/>
15
+ <%=f.datetime_select :starttime %>
16
+ </p>
17
+ <p>
18
+ <%=f.label :endtime, 'End Time' %>
19
+ <br/>
20
+ <%=f.datetime_select :endtime %>
21
+ </p>
22
+ <p>
23
+ <%=f.label :all_day %>
24
+ <%=f.check_box :all_day %>
25
+ </p>
26
+ <p>
27
+ <%=f.label :period, "Repeats" %>
28
+ <%=f.select :period, FullcalendarEngine::Event::REPEATS.values,{}, :onchange => "FullcalendarEngine.Events.showPeriodAndFrequency(this.value);" %>
29
+ </p>
30
+ <p id = "frequency" style = "display:none;">
31
+ <%=f.label :frequency, "Repeat every" %>
32
+ <%=f.select :frequency, (1..30).to_a %> <span id = "period"></span>
33
+ </p>
34
+ <%=f.hidden_field :id, :value => @event.id %>
35
+ <p>
36
+ <%=f.submit 'Create' %> <span id = "creating_events" class="spinner" style = "display:none;">Creating, Please wait...</span>
37
+ </p>
38
+ <%end %>
@@ -0,0 +1,27 @@
1
+ <p>
2
+ <%= link_to 'Create Event', 'javascript:void()', :id => 'new_event' %>
3
+ </p>
4
+
5
+ <%= content_tag :script do %>
6
+ full_calendar_options = <%= FullcalendarEngine::Configuration.to_json.html_safe %>
7
+ app_path = full_calendar_options["mount_path"]
8
+ <% end %>
9
+
10
+ <div>
11
+ <div id='calendar'></div>
12
+ </div>
13
+ <div id="event_desc_dialog" class="dialog" style="display:none;"></div>
14
+ <div id="create_event_dialog" class="dialog" style ="display:none;">
15
+ <%= render 'form' %>
16
+ </div>
17
+
18
+ <script>
19
+ $(document).ready(function(){
20
+ $('#calendar').fullCalendar(full_calendar_options);
21
+ // page is now ready, initialize the calendar...
22
+ $('#new_event').click(function(event) {
23
+ FullcalendarEngine.Form.display()
24
+ event.preventDefault();
25
+ });
26
+ });
27
+ </script>
@@ -0,0 +1 @@
1
+ $("#create_event_dialog").html("<%= escape_javascript( render partial: 'form') %>")
@@ -0,0 +1,57 @@
1
+ # Refer to the http://arshaw.com/fullcalendar/docs/ to know more about the following options in greater depth
2
+ # defaultView: 'agendaWeek'
3
+ # aspectRatio: 1.35
4
+ # header:
5
+ # left: 'prev,next today'
6
+ # center: 'title'
7
+ # right: 'month,agendaWeek,agendaDay'
8
+ # weekends: true
9
+ # weekNumbers: false
10
+ # weekNumberCalculation: 'iso'
11
+ # weekNumberTitle: 'W'
12
+
13
+ # editable: true
14
+ # disableDragging: false
15
+ # disableResizing: false
16
+ # allDayDefault: true
17
+ # ignoreTimezone: true
18
+
19
+ # lazyFetching: true
20
+ # startParam: 'start'
21
+ # endParam: 'end'
22
+
23
+ # titleFormat:
24
+ # month: 'MMMM yyyy'
25
+ # week: "MMM d[ yyyy]{ '&#8212;'[ MMM] d yyyy}"
26
+ # day: 'dddd, MMM d, yyyy'
27
+ # columnFormat:
28
+ # month: 'ddd'
29
+ # week: 'ddd M/d'
30
+ # day: 'dddd M/d'
31
+ # timeFormat:
32
+ # '': 'h(:mm)t' # default
33
+
34
+ # isRTL: false
35
+ # firstDay: 0
36
+ # monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December']
37
+ # monthNamesShort: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
38
+ # dayNames: ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
39
+ # dayNamesShort: ['Sun','Mon','Tue','Wed','Thu','Fri','Sat']
40
+ # buttonText:
41
+ # prev: "<span class='fc-text-arrow'>prev..</span>"
42
+ # next: "<span class='fc-text-arrow'>next..</span>"
43
+ # prevYear: "<span class='fc-text-arrow'>&laquo;</span>"
44
+ # nextYear: "<span class='fc-text-arrow'>&raquo;</span>"
45
+ # today: 'today'
46
+ # month: 'month'
47
+ # week: 'week'
48
+ # day: 'day'
49
+
50
+ # theme: false
51
+ # buttonIcons:
52
+ # prev: 'circle-triangle-w'
53
+ # next: 'circle-triangle-e'
54
+ # selectable: true
55
+ # unselectAuto: true
56
+ # dropAccept: '*'
57
+ # handleWindowResize: true
@@ -0,0 +1,17 @@
1
+ config = File.exists?('config/fullcalendar.yml') ? YAML.load_file("config/fullcalendar.yml") || {} : {}
2
+ FullcalendarEngine::Configuration = {
3
+ 'editable' => true,
4
+ 'header' => {
5
+ left: 'prev,next today',
6
+ center: 'title',
7
+ right: 'month,agendaWeek,agendaDay'
8
+ },
9
+ 'defaultView' => 'agendaWeek',
10
+ 'height' => 500,
11
+ 'slotMinutes' => 15,
12
+ 'dragOpacity' => 0.5,
13
+ 'selectable' => true,
14
+ 'timeFormat' => "h:mm t{ - h:mm t}"
15
+ }
16
+ FullcalendarEngine::Configuration.merge!(config)
17
+ FullcalendarEngine::Configuration['events'] = "#{FullcalendarEngine::Configuration['mount_path']}/events/get_events"
@@ -0,0 +1 @@
1
+ RECURRING_EVENTS_UPTO = (Date.today.beginning_of_year + 5.years).to_time
data/config/routes.rb ADDED
@@ -0,0 +1,12 @@
1
+ FullcalendarEngine::Engine.routes.draw do
2
+ root :to => 'events#index'
3
+ resources :events do
4
+ collection do
5
+ get :get_events
6
+ end
7
+ member do
8
+ post :move
9
+ post :resize
10
+ end
11
+ end
12
+ end