event_calendar_engine 0.1.11 → 0.2.0

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 (45) hide show
  1. data/Gemfile.lock +39 -35
  2. data/VERSION +1 -1
  3. data/app/controllers/event_revisions_controller.rb +1 -1
  4. data/app/controllers/events_controller.rb +21 -36
  5. data/app/controllers/links_controller.rb +62 -0
  6. data/app/helpers/event_calendar/application_helper.rb +73 -4
  7. data/app/models/event.rb +21 -43
  8. data/app/models/event_instance_methods.rb +40 -9
  9. data/app/models/link.rb +19 -0
  10. data/app/views/event_revisions/_list_group.html.erb +1 -1
  11. data/app/views/events/_details.html.erb +2 -1
  12. data/app/views/events/_event.html.erb +2 -0
  13. data/app/views/events/_event_details.html.erb +22 -17
  14. data/app/views/events/_form.html.erb +47 -3
  15. data/app/views/events/_list_group.html.erb +1 -1
  16. data/app/views/events/_one_day_list_event.html.erb +1 -1
  17. data/app/views/events/edit.html.erb +1 -1
  18. data/app/views/links/_form.html.erb +18 -0
  19. data/app/views/links/_link.html.erb +6 -0
  20. data/app/views/links/_links.html.erb +6 -0
  21. data/app/views/links/create.js.rjs +14 -0
  22. data/app/views/links/edit.html.erb +3 -0
  23. data/app/views/links/new.html.erb +3 -0
  24. data/app/views/links/show.html.erb +3 -0
  25. data/app/views/links/update.js.rjs +15 -0
  26. data/config/routes.rb +1 -56
  27. data/db/migrate/20110204223256_add_presenters_facilitators_to_events.rb +11 -0
  28. data/db/migrate/20110206000427_create_event_calendar_links.rb +23 -0
  29. data/db/schema.rb +18 -1
  30. data/public/javascripts/event_calendar/event_calendar.js +7 -0
  31. data/public/javascripts/event_calendar/event_calendar_behaviors.js +92 -23
  32. data/public/stylesheets/event_calendar/blueprint/screen.css +1 -0
  33. data/spec/controllers/events_controller_spec.rb +4 -2
  34. data/spec/controllers/links_controller_spec.rb +140 -0
  35. data/spec/fixtures/event_calendar_events.yml +12 -2
  36. data/spec/fixtures/event_calendar_events_links.yml +3 -0
  37. data/spec/fixtures/event_calendar_links.yml +4 -0
  38. data/spec/helpers/event_calendar/application_helper_spec.rb +4 -4
  39. data/spec/models/event_instance_methods_spec.rb +58 -0
  40. data/spec/models/event_revision_spec.rb +11 -10
  41. data/spec/models/event_spec.rb +31 -65
  42. data/spec/models/link_spec.rb +31 -0
  43. data/spec/spec_helpers/helpers.rb +15 -0
  44. metadata +29 -6
  45. data/app/views/events/_times.html.erb +0 -5
data/db/schema.rb CHANGED
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended to check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(:version => 20101223233354) do
13
+ ActiveRecord::Schema.define(:version => 20110206000427) do
14
14
 
15
15
  create_table "event_calendar_attendees", :force => true do |t|
16
16
  t.integer "event_id"
@@ -41,6 +41,23 @@ ActiveRecord::Schema.define(:version => 20101223233354) do
41
41
  t.datetime "revisable_deleted_at"
42
42
  t.boolean "revisable_is_current", :default => true
43
43
  t.string "timezone"
44
+ t.text "presenters"
45
+ t.text "facilitators"
46
+ end
47
+
48
+ create_table "event_calendar_events_links", :id => false, :force => true do |t|
49
+ t.integer "event_id"
50
+ t.integer "link_id"
51
+ end
52
+
53
+ add_index "event_calendar_events_links", ["event_id", "link_id"], :name => "index_event_calendar_events_links_on_event_id_and_link_id"
54
+
55
+ create_table "event_calendar_links", :force => true do |t|
56
+ t.string "name"
57
+ t.string "url"
58
+ t.text "description"
59
+ t.datetime "created_at"
60
+ t.datetime "updated_at"
44
61
  end
45
62
 
46
63
  end
@@ -14,6 +14,13 @@ jQuery(function($) {
14
14
  $('ul.events').attach(Collapsible);
15
15
  $('a.show_hide_link').attach(ShowHideLink);
16
16
  $('a.view_events').attach(EventView);
17
+ $('div.links').attach(MagicButtons);
18
+ $('div.links').attach(QuickZoom);
19
+ $('div.event').attach(QuickZoom);
20
+ $('ul.events').attach(QuickZoom);
21
+ $('div.links').attach(DynamicForm, {
22
+ formElement: $('#link_dynamic_form')
23
+ });
17
24
  });
18
25
 
19
26
  /*
@@ -132,32 +132,63 @@ ShowHideLink = $.klass({
132
132
 
133
133
  DynamicForm = $.klass({
134
134
  initialize: function(options) {
135
- this.formId = options.formId; // new_description
136
- this.formContainer = options.formContainer; // blank_description_form
137
- this.targetIdName = options.targetIdName; // file_attachment_id
138
- this.targetContentName = options.targetContentName; // file_attachment[description]
139
- this.targetContentType = options.targetContentType;
140
- this.actionPrefix = options.actionPrefix; // /file_attachments
135
+ this.formElement = options.formElement;
136
+ this.resourceType = this.formElement.attr('id').replace('_dynamic_form', '');
137
+ this.resourceInputs = this.formElement.find(':input[id^="'+this.resourceType+'"]');
138
+ this.resourcePlural = this.element.attr('id');
139
+ this.originalAction = this.formElement.attr('action');
140
+ this.formElement.remove();
141
141
  },
142
- onclick: function(e) {
143
- e.preventDefault();
144
-
145
- var targetIdValue = this.element.attr(this.targetIdName);
146
- var targetContentValue = this.element.attr(this.targetContentName);
147
-
148
- $('#' + this.formId).attr("action", this.actionPrefix + "/" + targetIdValue);
149
-
150
- $('#' + this.formId).clearForm();
151
-
152
- $('#' + this.formContainer).insertBefore(this.element);
153
-
154
- $(this.targetContentType + '[name='+ this.targetContentName +']').val(targetContentValue);
155
-
156
- $('#' + this.formContainer).show();
157
- }
142
+ onclick: $.delegate({
143
+ '.new': function(clickedElement, event) {
144
+ event.preventDefault();
145
+ $('#'+this.formElement.attr('id')).remove();
146
+ this.formElement.clearForm();
147
+ this.formElement.attr('action', this.originalAction);
148
+ this.formElement.find(':input[name="_method"]').attr('value', 'post');
149
+ this.formElement.insertAfter(clickedElement);
150
+ this.formElement.attach(Remote.Form);
151
+ this.formElement.show();
152
+ },
153
+ '.cancel': function(clickedElement, event) {
154
+ event.preventDefault();
155
+ this.formElement.clearForm();
156
+ this.formElement.attr('action', this.originalAction);
157
+ this.formElement.find(':input[name="_method"]').attr('value', 'post');
158
+ $('#'+this.formElement.attr('id')).remove();
159
+ },
160
+ '.edit': function(clickedElement, event) {
161
+ event.preventDefault();
162
+ $('#'+this.formElement.attr('id')).remove();
163
+
164
+ var resourceContainer = clickedElement.parents('.' + this.resourceType);
165
+ var resourceId = /\d+/.exec(resourceContainer.attr('id'))[0];
166
+
167
+ // append resourceId to current form action
168
+ this.formElement.attr("action", this.originalAction + "/" + resourceId);
169
+ this.formElement.find(':input[name="_method"]').attr('value', 'put');
170
+
171
+ // clear form input values
172
+ this.formElement.clearForm();
173
+ // move form to resource
174
+ this.formElement.insertBefore(clickedElement);
175
+
176
+ this.resourceInputs.each(function() {
177
+ if( this.type != 'submit' ) {
178
+ // get resource attr names from form input ids
179
+ var resourceAttrContainer = resourceContainer.find('.'+this.id);
180
+ // get resource attr vals from w/in resource container
181
+ this.value = $.trim(resourceAttrContainer.text());
182
+ }
183
+ });
184
+
185
+ this.formElement.attach(Remote.Form);
186
+ this.formElement.show();
187
+ }
188
+ })
158
189
  });
159
190
 
160
- EventView = $.klass({
191
+ var EventView = $.klass({
161
192
  onclick: function(e) {
162
193
  if( this.element.hasClass('calendar') ) {
163
194
  $('#event_list').hide();
@@ -169,6 +200,40 @@ EventView = $.klass({
169
200
  }
170
201
  });
171
202
 
203
+ var MagicButtons = $.klass({
204
+ initialize: function() {
205
+ if( this.element.find('.magic').size() > 0 ) {
206
+ this.element.find('.magic').hide();
207
+ }
208
+ },
209
+ onmouseover: $.delegate({
210
+ 'p': function(mousedElement, event) {
211
+ if( mousedElement.find('.magic').size() > 0 ) {
212
+ mousedElement.find('.magic').show();
213
+ }
214
+ }
215
+ }),
216
+ onmouseout: $.delegate({
217
+ 'p': function(mousedElement, event) {
218
+ if( mousedElement.find('.magic').size() > 0 ) {
219
+ mousedElement.find('.magic').hide();
220
+ }
221
+ }
222
+ })
223
+ });
224
+ var QuickZoom = $.klass({
225
+ onmouseover: $.delegate({
226
+ '.zoom': function(mousedElement, event) {
227
+ mousedElement.addClass('enlarge');
228
+ }
229
+ }),
230
+ onmouseout: $.delegate({
231
+ '.enlarge': function(mousedElement, event) {
232
+ mousedElement.removeClass('enlarge');
233
+ }
234
+ })
235
+ });
236
+
172
237
  var Collapsible = $.klass({
173
238
  initialize: function() {
174
239
  this.element.find('.open').each(function(i, e) {
@@ -180,6 +245,10 @@ var Collapsible = $.klass({
180
245
  },
181
246
  onclick: $.delegate({
182
247
  '.collapsible': function(clickedElement, event) {
248
+ expanded = clickedElement.siblings().find(':visible').size();
249
+ if( expanded < 1 ) {
250
+ event.preventDefault();
251
+ }
183
252
  clickedElement.siblings().toggle();
184
253
  }
185
254
  })
@@ -389,6 +389,7 @@ div.select_popper_box ul li:hover {background:#EEE;}
389
389
  ;}
390
390
  #event_end_on {width:50%
391
391
  ;}
392
+ .enlarge {font-size:115%;}
392
393
 
393
394
  /* fancy-type */
394
395
  p + p {text-indent:2em;margin-top:-1.5em;}
@@ -5,11 +5,13 @@ describe EventsController do
5
5
  let(:event) do
6
6
  mock_model(Event, {
7
7
  :name => 'Some Event',
8
- :start_on => Date.yesterday,
8
+ :start_on => 4.hours.from_now,
9
+ :start_time= => 4.hours.from_now,
9
10
  :end_on => Date.tomorrow,
10
11
  :timezone => 'Pacific Time (US & Canada)',
11
12
  :description => 'Some Description',
12
- :location => 'Some City'
13
+ :location => 'Some City',
14
+ :links => mock('Relation', :build => mock_model(Link))
13
15
  })
14
16
  end
15
17
  let(:params) do
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+
3
+ describe LinksController do
4
+ subject{ Event }
5
+ let(:stub_link) do
6
+ stub_model(Link)
7
+ end
8
+ let(:link) do
9
+ mock_model(Link)
10
+ end
11
+ let(:event) do
12
+ mock_model(Event, {
13
+ :save! => nil,
14
+ :links => mock('Relation', {
15
+ :build => stub_link
16
+ })
17
+ })
18
+ end
19
+ before(:each) do
20
+ subject.stub(:find).and_return(event)
21
+ end
22
+ describe "GET :edit, :event_id => int, :id => int" do
23
+ let(:params) do
24
+ {:event_id => event.id, :id => link.id}
25
+ end
26
+ before(:each) do
27
+ Link.should_receive(:find){ link }
28
+ end
29
+ it "loads an @event and @link" do
30
+ get :edit, params
31
+ assigns(:event).should eq event
32
+ assigns(:link).should eq link
33
+ end
34
+ it "renders the edit template" do
35
+ get :edit, params
36
+ response.should render_template('links/edit')
37
+ end
38
+ end
39
+ describe "PUT :update, :event_id => int, :id => int, :link => {}" do
40
+ let(:params) do
41
+ {:event_id => event.id, :id => link.id}
42
+ end
43
+ let(:link_params) do
44
+ {:name => 'Updated', :url => 'example.com/updated.html'}
45
+ end
46
+ before(:each) do
47
+ link.stub(:update_attributes){ nil }
48
+ Link.should_receive(:find){ link }
49
+ end
50
+ it "loads an @event and @link" do
51
+ put :update, params
52
+ assigns(:event).should eq event
53
+ assigns(:link).should eq link
54
+ end
55
+ it "updates the @link" do
56
+ link.should_receive(:update_attributes).with(link_params.stringify_keys)
57
+ put :update, params.merge!({:link => link_params})
58
+ end
59
+ context "update succeeds :)" do
60
+ before(:each) do
61
+ link.stub(:update_attributes){ true }
62
+ end
63
+ it "sets flash[:notice]" do
64
+ put :update, params
65
+ flash[:notice].should_not be_nil
66
+ end
67
+ it "as http: redirects to @event" do
68
+ put :update, params
69
+ response.should redirect_to event_path(event)
70
+ end
71
+ end
72
+ context "update fails :(" do
73
+ before(:each) do
74
+ link.stub(:update_attributes){ false }
75
+ end
76
+ it "as http: renders the edit template" do
77
+ put :update, params
78
+ response.should render_template('links/edit')
79
+ end
80
+ end
81
+ it "as xhr: renders update.rjs" do
82
+ xhr :put, :update, params
83
+ response.should render_template('links/update')
84
+ end
85
+ end
86
+ describe "POST :create, :event_id => int, :link => {}" do
87
+ let(:params) do
88
+ {:event_id => event.id}
89
+ end
90
+ let(:link_params) do
91
+ {:name => 'Created', :url => 'http://test.com'}
92
+ end
93
+ it "loads an @event" do
94
+ post :create, params
95
+ assigns(:event).should eq event
96
+ end
97
+ it "builds a new link" do
98
+ event.links.should_receive(:build).with(link_params.stringify_keys)
99
+ post :create, params.merge!({:link => link_params})
100
+ end
101
+ it "saves! the @event, without triggering a revision" do
102
+ event.should_receive(:save!).with(:without_revision => true)
103
+ post :create, params
104
+ end
105
+ it "as http: renders events/show if an ActiveRecord::RecordInvalid exception is raised" do
106
+ event.stub(:save!){ raise ActiveRecord::RecordInvalid.new(event) }
107
+ post :create, params
108
+ response.should render_template('events/show')
109
+ end
110
+ it "sets a flash[:notice]" do
111
+ post :create, params
112
+ flash[:notice].should_not be_nil
113
+ end
114
+ it "as http: redirects to the event" do
115
+ post :create, params
116
+ response.should redirect_to event_path(event)
117
+ end
118
+ it "as xhr: renders create.rjs" do
119
+ xhr :post, :create, params
120
+ response.should render_template('links/create')
121
+ end
122
+ end
123
+ describe "DELETE :destroy, :event_id => int, :id => int" do
124
+ let(:params) do
125
+ {:event_id => event.id, :id => link.id}
126
+ end
127
+ before(:each) do
128
+ link.stub(:destroy){ nil }
129
+ Link.should_receive(:find){ link }
130
+ end
131
+ it "destroys a link" do
132
+ link.should_receive(:destroy)
133
+ delete :destroy, params
134
+ end
135
+ it "as http: redirects to :event_id" do
136
+ delete :destroy, params
137
+ response.should redirect_to event_path event.id
138
+ end
139
+ end
140
+ end
@@ -4,5 +4,15 @@ editable_event:
4
4
  event_type: Conference
5
5
  location: "Eugene, Oregon"
6
6
  description: "Will be great! Lots of good info, food and drinks!"
7
- start_on: "10/14/2010"
8
- end_on: "10/15/2010"
7
+ start_on: "2010-10-14"
8
+ end_on: "2010-10-15"
9
+ timezone: 'Pacific Time (US & Canada)'
10
+
11
+ restorable_event:
12
+ id: <%= Fixtures.identify :restorable_event %>
13
+ name: Restorable Event
14
+ event_type: Meeting
15
+ location: "Portland, Oregon"
16
+ start_on: 2011-02-04 14:00:00.000000
17
+ end_on: 2011-02-04 15:00:00.000000
18
+ timezone: 'Pacific Time (US & Canada)'
@@ -0,0 +1,3 @@
1
+ editable_event_editable_link:
2
+ event_id: <%= Fixtures.identify :editable_event %>
3
+ link_id: <%= Fixtures.identify :editable_link %>
@@ -0,0 +1,4 @@
1
+ editable_link:
2
+ id: <%= Fixtures.identify :editable_link %>
3
+ name: Editable Link
4
+ url: http://test.com/
@@ -5,10 +5,10 @@ describe EventCalendar::ApplicationHelper do
5
5
  it "returns times" do
6
6
  time = Time.now
7
7
  helper.time_with_zones(time).should eq [
8
- ["EST", time.in_time_zone("Eastern Time (US & Canada)").strftime(TIME_BASE)],
9
- ["CST", time.in_time_zone("Central Time (US & Canada)").strftime(TIME_BASE)],
10
- ["MST", time.in_time_zone("Mountain Time (US & Canada)").strftime(TIME_BASE)],
11
- ["PST", time.in_time_zone("Pacific Time (US & Canada)").strftime(TIME_BASE)]
8
+ ["Eastern", time.in_time_zone("Eastern Time (US & Canada)").strftime(TIME_BASE)],
9
+ ["Central", time.in_time_zone("Central Time (US & Canada)").strftime(TIME_BASE)],
10
+ ["Mountain", time.in_time_zone("Mountain Time (US & Canada)").strftime(TIME_BASE)],
11
+ ["Pacific", time.in_time_zone("Pacific Time (US & Canada)").strftime(TIME_BASE)]
12
12
  ]
13
13
  end
14
14
  end
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+ require 'acts_as_fu'
3
+ RSpec.configure do |config|
4
+ config.include ActsAsFu
5
+ end
6
+
7
+ describe EventInstanceMethods do
8
+ before(:each) do
9
+ build_model :fake_event do
10
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[Rails.env.to_sym])
11
+ string :name
12
+ datetime :start_on
13
+ datetime :end_on
14
+ string :timezone
15
+
16
+ include EventInstanceMethods
17
+ end
18
+ end
19
+ let(:event) do
20
+ FakeEvent.new({
21
+ :name => 'One Day',
22
+ :start_on => Time.now,
23
+ :end_on => Time.now,
24
+ :timezone => "Pacific Time (US & Canada)"
25
+ })
26
+ end
27
+
28
+ context "distinguishing one day events from the rest" do
29
+ it "given a start_on & end_on, compare day, month and year" do
30
+ event.one_day?.should be_true
31
+ event.end_on = 1.day.from_now
32
+ event.one_day?.should be_false
33
+ end
34
+ it "given only a start_on, return true" do
35
+ event.end_on = nil
36
+ event.one_day?.should be_true
37
+ end
38
+ it "given only a end_on, ... return true" do
39
+ event.start_on = nil
40
+ event.one_day?.should be_true
41
+ end
42
+ end
43
+
44
+ it "knows start|end_day" do
45
+ event.start_day.should eq Date.today.day
46
+ event.end_day.should eq Date.today.day
47
+ end
48
+
49
+ it "knows start|end_month" do
50
+ event.start_month.should eq Date.today.strftime('%B')
51
+ event.end_month.should eq Date.today.strftime("%B")
52
+ end
53
+
54
+ it "knows start|end_year" do
55
+ event.start_year.should eq Date.today.year
56
+ event.end_year.should eq Date.today.year
57
+ end
58
+ end