diff options
34 files changed, 924 insertions, 35 deletions
| @@ -7,3 +7,8 @@ coverage | |||
| 7 | coverage.data | 7 | coverage.data |
| 8 | .project | 8 | .project |
| 9 | db/updates/ | 9 | db/updates/ |
| 10 | lib/chaos_calendar/Makefile | ||
| 11 | lib/chaos_calendar/ical_occurrences.bundle | ||
| 12 | lib/chaos_calendar/ical_occurrences.o | ||
| 13 | lib/chaos_calendar/ical_occurrences_wrap.c | ||
| 14 | lib/chaos_calendar/ical_occurrences_wrap.o \ No newline at end of file | ||
diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb new file mode 100644 index 0000000..c25c73f --- /dev/null +++ b/app/controllers/events_controller.rb | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | class EventsController < ApplicationController | ||
| 2 | # GET /events | ||
| 3 | # GET /events.xml | ||
| 4 | def index | ||
| 5 | @events = Event.all | ||
| 6 | |||
| 7 | respond_to do |format| | ||
| 8 | format.html # index.html.erb | ||
| 9 | format.xml { render :xml => @events } | ||
| 10 | end | ||
| 11 | end | ||
| 12 | |||
| 13 | # GET /events/1 | ||
| 14 | # GET /events/1.xml | ||
| 15 | def show | ||
| 16 | @event = Event.find(params[:id]) | ||
| 17 | |||
| 18 | respond_to do |format| | ||
| 19 | format.html # show.html.erb | ||
| 20 | format.xml { render :xml => @event } | ||
| 21 | end | ||
| 22 | end | ||
| 23 | |||
| 24 | # GET /events/new | ||
| 25 | # GET /events/new.xml | ||
| 26 | def new | ||
| 27 | @event = Event.new | ||
| 28 | |||
| 29 | respond_to do |format| | ||
| 30 | format.html # new.html.erb | ||
| 31 | format.xml { render :xml => @event } | ||
| 32 | end | ||
| 33 | end | ||
| 34 | |||
| 35 | # GET /events/1/edit | ||
| 36 | def edit | ||
| 37 | @event = Event.find(params[:id]) | ||
| 38 | end | ||
| 39 | |||
| 40 | # POST /events | ||
| 41 | # POST /events.xml | ||
| 42 | def create | ||
| 43 | @event = Event.new(params[:event]) | ||
| 44 | |||
| 45 | respond_to do |format| | ||
| 46 | if @event.save | ||
| 47 | flash[:notice] = 'Event was successfully created.' | ||
| 48 | format.html { redirect_to(@event) } | ||
| 49 | format.xml { render :xml => @event, :status => :created, :location => @event } | ||
| 50 | else | ||
| 51 | format.html { render :action => "new" } | ||
| 52 | format.xml { render :xml => @event.errors, :status => :unprocessable_entity } | ||
| 53 | end | ||
| 54 | end | ||
| 55 | end | ||
| 56 | |||
| 57 | # PUT /events/1 | ||
| 58 | # PUT /events/1.xml | ||
| 59 | def update | ||
| 60 | @event = Event.find(params[:id]) | ||
| 61 | |||
| 62 | respond_to do |format| | ||
| 63 | if @event.update_attributes(params[:event]) | ||
| 64 | flash[:notice] = 'Event was successfully updated.' | ||
| 65 | format.html { redirect_to(@event) } | ||
| 66 | format.xml { head :ok } | ||
| 67 | else | ||
| 68 | format.html { render :action => "edit" } | ||
| 69 | format.xml { render :xml => @event.errors, :status => :unprocessable_entity } | ||
| 70 | end | ||
| 71 | end | ||
| 72 | end | ||
| 73 | |||
| 74 | # DELETE /events/1 | ||
| 75 | # DELETE /events/1.xml | ||
| 76 | def destroy | ||
| 77 | @event = Event.find(params[:id]) | ||
| 78 | @event.destroy | ||
| 79 | |||
| 80 | respond_to do |format| | ||
| 81 | format.html { redirect_to(events_url) } | ||
| 82 | format.xml { head :ok } | ||
| 83 | end | ||
| 84 | end | ||
| 85 | end | ||
diff --git a/app/controllers/occurrences_controller.rb b/app/controllers/occurrences_controller.rb new file mode 100644 index 0000000..e3f1cdd --- /dev/null +++ b/app/controllers/occurrences_controller.rb | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | class OccurrencesController < ApplicationController | ||
| 2 | # GET /occurrences | ||
| 3 | # GET /occurrences.xml | ||
| 4 | def index | ||
| 5 | @occurrences = Occurrence.all | ||
| 6 | |||
| 7 | respond_to do |format| | ||
| 8 | format.html # index.html.erb | ||
| 9 | format.xml { render :xml => @occurrences } | ||
| 10 | end | ||
| 11 | end | ||
| 12 | |||
| 13 | # GET /occurrences/1 | ||
| 14 | # GET /occurrences/1.xml | ||
| 15 | def show | ||
| 16 | @occurrence = Occurrence.find(params[:id]) | ||
| 17 | |||
| 18 | respond_to do |format| | ||
| 19 | format.html # show.html.erb | ||
| 20 | format.xml { render :xml => @occurrence } | ||
| 21 | end | ||
| 22 | end | ||
| 23 | |||
| 24 | # GET /occurrences/new | ||
| 25 | # GET /occurrences/new.xml | ||
| 26 | def new | ||
| 27 | @occurrence = Occurrence.new | ||
| 28 | |||
| 29 | respond_to do |format| | ||
| 30 | format.html # new.html.erb | ||
| 31 | format.xml { render :xml => @occurrence } | ||
| 32 | end | ||
| 33 | end | ||
| 34 | |||
| 35 | # GET /occurrences/1/edit | ||
| 36 | def edit | ||
| 37 | @occurrence = Occurrence.find(params[:id]) | ||
| 38 | end | ||
| 39 | |||
| 40 | # POST /occurrences | ||
| 41 | # POST /occurrences.xml | ||
| 42 | def create | ||
| 43 | @occurrence = Occurrence.new(params[:occurrence]) | ||
| 44 | |||
| 45 | respond_to do |format| | ||
| 46 | if @occurrence.save | ||
| 47 | flash[:notice] = 'Occurrence was successfully created.' | ||
| 48 | format.html { redirect_to(@occurrence) } | ||
| 49 | format.xml { render :xml => @occurrence, :status => :created, :location => @occurrence } | ||
| 50 | else | ||
| 51 | format.html { render :action => "new" } | ||
| 52 | format.xml { render :xml => @occurrence.errors, :status => :unprocessable_entity } | ||
| 53 | end | ||
| 54 | end | ||
| 55 | end | ||
| 56 | |||
| 57 | # PUT /occurrences/1 | ||
| 58 | # PUT /occurrences/1.xml | ||
| 59 | def update | ||
| 60 | @occurrence = Occurrence.find(params[:id]) | ||
| 61 | |||
| 62 | respond_to do |format| | ||
| 63 | if @occurrence.update_attributes(params[:occurrence]) | ||
| 64 | flash[:notice] = 'Occurrence was successfully updated.' | ||
| 65 | format.html { redirect_to(@occurrence) } | ||
| 66 | format.xml { head :ok } | ||
| 67 | else | ||
| 68 | format.html { render :action => "edit" } | ||
| 69 | format.xml { render :xml => @occurrence.errors, :status => :unprocessable_entity } | ||
| 70 | end | ||
| 71 | end | ||
| 72 | end | ||
| 73 | |||
| 74 | # DELETE /occurrences/1 | ||
| 75 | # DELETE /occurrences/1.xml | ||
| 76 | def destroy | ||
| 77 | @occurrence = Occurrence.find(params[:id]) | ||
| 78 | @occurrence.destroy | ||
| 79 | |||
| 80 | respond_to do |format| | ||
| 81 | format.html { redirect_to(occurrences_url) } | ||
| 82 | format.xml { head :ok } | ||
| 83 | end | ||
| 84 | end | ||
| 85 | end | ||
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb new file mode 100644 index 0000000..8a9a878 --- /dev/null +++ b/app/helpers/events_helper.rb | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | module EventsHelper | ||
| 2 | end | ||
diff --git a/app/helpers/occurrences_helper.rb b/app/helpers/occurrences_helper.rb new file mode 100644 index 0000000..8cba881 --- /dev/null +++ b/app/helpers/occurrences_helper.rb | |||
| @@ -0,0 +1,2 @@ | |||
| 1 | module OccurrencesHelper | ||
| 2 | end | ||
diff --git a/app/models/event.rb b/app/models/event.rb new file mode 100644 index 0000000..60b8521 --- /dev/null +++ b/app/models/event.rb | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | class Event < ActiveRecord::Base | ||
| 2 | |||
| 3 | # Associations | ||
| 4 | |||
| 5 | has_many :occurrences | ||
| 6 | belongs_to :node | ||
| 7 | |||
| 8 | # Callbacks | ||
| 9 | |||
| 10 | after_save :generate_occurences | ||
| 11 | |||
| 12 | # Instance Methods | ||
| 13 | |||
| 14 | def occurrences_in_range start_time, end_time | ||
| 15 | self.occurrences.find( | ||
| 16 | :all, :conditions => [ | ||
| 17 | "start_time > ? AND end_time < ?", | ||
| 18 | start_time, end_time | ||
| 19 | ] | ||
| 20 | ) | ||
| 21 | end | ||
| 22 | |||
| 23 | private | ||
| 24 | def generate_occurences | ||
| 25 | Occurrence.generate self | ||
| 26 | end | ||
| 27 | end | ||
diff --git a/app/models/node.rb b/app/models/node.rb index d2db4ba..da26164 100644 --- a/app/models/node.rb +++ b/app/models/node.rb | |||
| @@ -7,6 +7,7 @@ class Node < ActiveRecord::Base | |||
| 7 | belongs_to :head, :class_name => "Page", :foreign_key => :head_id | 7 | belongs_to :head, :class_name => "Page", :foreign_key => :head_id |
| 8 | belongs_to :draft, :class_name => "Page", :foreign_key => :draft_id | 8 | belongs_to :draft, :class_name => "Page", :foreign_key => :draft_id |
| 9 | has_many :permissions | 9 | has_many :permissions |
| 10 | has_one :event | ||
| 10 | 11 | ||
| 11 | # Callbacks | 12 | # Callbacks |
| 12 | after_create :initialize_empty_page | 13 | after_create :initialize_empty_page |
diff --git a/app/models/occurrence.rb b/app/models/occurrence.rb new file mode 100644 index 0000000..6205618 --- /dev/null +++ b/app/models/occurrence.rb | |||
| @@ -0,0 +1,60 @@ | |||
| 1 | # TODO Make a gem out of the c wrapper | ||
| 2 | require 'lib/chaos_calendar/ical_occurrences' | ||
| 3 | |||
| 4 | class Occurrence < ActiveRecord::Base | ||
| 5 | |||
| 6 | # Associations | ||
| 7 | |||
| 8 | belongs_to :node | ||
| 9 | belongs_to :event | ||
| 10 | |||
| 11 | # Class Methods | ||
| 12 | |||
| 13 | def self.find_in_range start_time, end_time | ||
| 14 | find( | ||
| 15 | :all, :conditions => [ | ||
| 16 | "start_time > ? AND end_time < ?", start_time, end_time | ||
| 17 | ] | ||
| 18 | ) | ||
| 19 | end | ||
| 20 | |||
| 21 | # Deletes all Occurrences which belong to the given event. Afterwards a few | ||
| 22 | # variables are set to save repetitive queries. The occurrences of the given | ||
| 23 | # event are then calculated and created. | ||
| 24 | def self.generate event | ||
| 25 | self.delete_all(:event_id => event.id) | ||
| 26 | |||
| 27 | node = event.node | ||
| 28 | summary = node.head.title | ||
| 29 | duration = (event.end_time - event.start_time) | ||
| 30 | occurrences = self.generate_dates(event) | ||
| 31 | |||
| 32 | occurrences.each do |occurrence| | ||
| 33 | self.create( | ||
| 34 | :summary => summary, | ||
| 35 | :start_time => occurrence, | ||
| 36 | :end_time => (occurrence + duration), | ||
| 37 | :node_id => node.id, | ||
| 38 | :event_id => event.id | ||
| 39 | ) | ||
| 40 | end | ||
| 41 | end | ||
| 42 | |||
| 43 | # Calculates the start_time of all occurrences for a given event if a proper | ||
| 44 | # RRule is provided. An ArgumentError is thrown from within the libical | ||
| 45 | # wrapper if the RRule is malformed. If the rrule attribute of an event is | ||
| 46 | # nil, it simply returns the event start_time as only occurrence. | ||
| 47 | # Return value is always an array of Time objects. | ||
| 48 | def self.generate_dates event | ||
| 49 | if event.rrule | ||
| 50 | Ical_occurrences::occurrences( | ||
| 51 | event.start_time.utc.iso8601, | ||
| 52 | (Time.now + 5.years).utc.iso8601, | ||
| 53 | event.rrule | ||
| 54 | ) | ||
| 55 | else | ||
| 56 | [event.start_time] | ||
| 57 | end | ||
| 58 | |||
| 59 | end | ||
| 60 | end | ||
diff --git a/app/views/events/edit.html.erb b/app/views/events/edit.html.erb new file mode 100644 index 0000000..e40ac55 --- /dev/null +++ b/app/views/events/edit.html.erb | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | <h1>Editing event</h1> | ||
| 2 | |||
| 3 | <% form_for(@event) do |f| %> | ||
| 4 | <%= f.error_messages %> | ||
| 5 | |||
| 6 | <p> | ||
| 7 | <%= f.label :start_time %><br /> | ||
| 8 | <%= f.datetime_select :start_time %> | ||
| 9 | </p> | ||
| 10 | <p> | ||
| 11 | <%= f.label :end_time %><br /> | ||
| 12 | <%= f.datetime_select :end_time %> | ||
| 13 | </p> | ||
| 14 | <p> | ||
| 15 | <%= f.label :rrule %><br /> | ||
| 16 | <%= f.text_field :rrule %> | ||
| 17 | </p> | ||
| 18 | <p> | ||
| 19 | <%= f.label :custom_rrule %><br /> | ||
| 20 | <%= f.check_box :custom_rrule %> | ||
| 21 | </p> | ||
| 22 | <p> | ||
| 23 | <%= f.label :allday %><br /> | ||
| 24 | <%= f.check_box :allday %> | ||
| 25 | </p> | ||
| 26 | <p> | ||
| 27 | <%= f.label :url %><br /> | ||
| 28 | <%= f.text_field :url %> | ||
| 29 | </p> | ||
| 30 | <p> | ||
| 31 | <%= f.label :latitude %><br /> | ||
| 32 | <%= f.text_field :latitude %> | ||
| 33 | </p> | ||
| 34 | <p> | ||
| 35 | <%= f.label :longitude %><br /> | ||
| 36 | <%= f.text_field :longitude %> | ||
| 37 | </p> | ||
| 38 | <p> | ||
| 39 | <%= f.label :node_id %><br /> | ||
| 40 | <%= f.text_field :node_id %> | ||
| 41 | </p> | ||
| 42 | <p> | ||
| 43 | <%= f.submit 'Update' %> | ||
| 44 | </p> | ||
| 45 | <% end %> | ||
| 46 | |||
| 47 | <%= link_to 'Show', @event %> | | ||
| 48 | <%= link_to 'Back', events_path %> \ No newline at end of file | ||
diff --git a/app/views/events/index.html.erb b/app/views/events/index.html.erb new file mode 100644 index 0000000..c1b5b48 --- /dev/null +++ b/app/views/events/index.html.erb | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | <h1>Listing events</h1> | ||
| 2 | |||
| 3 | <table> | ||
| 4 | <tr> | ||
| 5 | <th>Start time</th> | ||
| 6 | <th>End time</th> | ||
| 7 | <th>Rrule</th> | ||
| 8 | <th>Custom rrule</th> | ||
| 9 | <th>Allday</th> | ||
| 10 | <th>Url</th> | ||
| 11 | <th>Latitude</th> | ||
| 12 | <th>Longitude</th> | ||
| 13 | <th>Node</th> | ||
| 14 | </tr> | ||
| 15 | |||
| 16 | <% @events.each do |event| %> | ||
| 17 | <tr> | ||
| 18 | <td><%=h event.start_time %></td> | ||
| 19 | <td><%=h event.end_time %></td> | ||
| 20 | <td><%=h event.rrule %></td> | ||
| 21 | <td><%=h event.custom_rrule %></td> | ||
| 22 | <td><%=h event.allday %></td> | ||
| 23 | <td><%=h event.url %></td> | ||
| 24 | <td><%=h event.latitude %></td> | ||
| 25 | <td><%=h event.longitude %></td> | ||
| 26 | <td><%=h event.node_id %></td> | ||
| 27 | <td><%= link_to 'Show', event %></td> | ||
| 28 | <td><%= link_to 'Edit', edit_event_path(event) %></td> | ||
| 29 | <td><%= link_to 'Destroy', event, :confirm => 'Are you sure?', :method => :delete %></td> | ||
| 30 | </tr> | ||
| 31 | <% end %> | ||
| 32 | </table> | ||
| 33 | |||
| 34 | <br /> | ||
| 35 | |||
| 36 | <%= link_to 'New event', new_event_path %> \ No newline at end of file | ||
diff --git a/app/views/events/new.html.erb b/app/views/events/new.html.erb new file mode 100644 index 0000000..0182b07 --- /dev/null +++ b/app/views/events/new.html.erb | |||
| @@ -0,0 +1,47 @@ | |||
| 1 | <h1>New event</h1> | ||
| 2 | |||
| 3 | <% form_for(@event) do |f| %> | ||
| 4 | <%= f.error_messages %> | ||
| 5 | |||
| 6 | <p> | ||
| 7 | <%= f.label :start_time %><br /> | ||
| 8 | <%= f.datetime_select :start_time %> | ||
| 9 | </p> | ||
| 10 | <p> | ||
| 11 | <%= f.label :end_time %><br /> | ||
| 12 | <%= f.datetime_select :end_time %> | ||
| 13 | </p> | ||
| 14 | <p> | ||
| 15 | <%= f.label :rrule %><br /> | ||
| 16 | <%= f.text_field :rrule %> | ||
| 17 | </p> | ||
| 18 | <p> | ||
| 19 | <%= f.label :custom_rrule %><br /> | ||
| 20 | <%= f.check_box :custom_rrule %> | ||
| 21 | </p> | ||
| 22 | <p> | ||
| 23 | <%= f.label :allday %><br /> | ||
| 24 | <%= f.check_box :allday %> | ||
| 25 | </p> | ||
| 26 | <p> | ||
| 27 | <%= f.label :url %><br /> | ||
| 28 | <%= f.text_field :url %> | ||
| 29 | </p> | ||
| 30 | <p> | ||
| 31 | <%= f.label :latitude %><br /> | ||
| 32 | <%= f.text_field :latitude %> | ||
| 33 | </p> | ||
| 34 | <p> | ||
| 35 | <%= f.label :longitude %><br /> | ||
| 36 | <%= f.text_field :longitude %> | ||
| 37 | </p> | ||
| 38 | <p> | ||
| 39 | <%= f.label :node_id %><br /> | ||
| 40 | <%= f.text_field :node_id %> | ||
| 41 | </p> | ||
| 42 | <p> | ||
| 43 | <%= f.submit 'Create' %> | ||
| 44 | </p> | ||
| 45 | <% end %> | ||
| 46 | |||
| 47 | <%= link_to 'Back', events_path %> \ No newline at end of file | ||
diff --git a/app/views/events/show.html.erb b/app/views/events/show.html.erb new file mode 100644 index 0000000..699765d --- /dev/null +++ b/app/views/events/show.html.erb | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | <p> | ||
| 2 | <b>Start time:</b> | ||
| 3 | <%=h @event.start_time %> | ||
| 4 | </p> | ||
| 5 | |||
| 6 | <p> | ||
| 7 | <b>End time:</b> | ||
| 8 | <%=h @event.end_time %> | ||
| 9 | </p> | ||
| 10 | |||
| 11 | <p> | ||
| 12 | <b>Rrule:</b> | ||
| 13 | <%=h @event.rrule %> | ||
| 14 | </p> | ||
| 15 | |||
| 16 | <p> | ||
| 17 | <b>Custom rrule:</b> | ||
| 18 | <%=h @event.custom_rrule %> | ||
| 19 | </p> | ||
| 20 | |||
| 21 | <p> | ||
| 22 | <b>Allday:</b> | ||
| 23 | <%=h @event.allday %> | ||
| 24 | </p> | ||
| 25 | |||
| 26 | <p> | ||
| 27 | <b>Url:</b> | ||
| 28 | <%=h @event.url %> | ||
| 29 | </p> | ||
| 30 | |||
| 31 | <p> | ||
| 32 | <b>Latitude:</b> | ||
| 33 | <%=h @event.latitude %> | ||
| 34 | </p> | ||
| 35 | |||
| 36 | <p> | ||
| 37 | <b>Longitude:</b> | ||
| 38 | <%=h @event.longitude %> | ||
| 39 | </p> | ||
| 40 | |||
| 41 | <p> | ||
| 42 | <b>Node:</b> | ||
| 43 | <%=h @event.node_id %> | ||
| 44 | </p> | ||
| 45 | |||
| 46 | |||
| 47 | <%= link_to 'Edit', edit_event_path(@event) %> | | ||
| 48 | <%= link_to 'Back', events_path %> \ No newline at end of file | ||
diff --git a/app/views/layouts/events.html.erb b/app/views/layouts/events.html.erb new file mode 100644 index 0000000..93a6c0c --- /dev/null +++ b/app/views/layouts/events.html.erb | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | ||
| 2 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
| 3 | |||
| 4 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | ||
| 5 | <head> | ||
| 6 | <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> | ||
| 7 | <title>Events: <%= controller.action_name %></title> | ||
| 8 | <%= stylesheet_link_tag 'scaffold' %> | ||
| 9 | </head> | ||
| 10 | <body> | ||
| 11 | |||
| 12 | <p style="color: green"><%= flash[:notice] %></p> | ||
| 13 | |||
| 14 | <%= yield %> | ||
| 15 | |||
| 16 | </body> | ||
| 17 | </html> | ||
diff --git a/app/views/layouts/occurrences.html.erb b/app/views/layouts/occurrences.html.erb new file mode 100644 index 0000000..ab4aca6 --- /dev/null +++ b/app/views/layouts/occurrences.html.erb | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" | ||
| 2 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> | ||
| 3 | |||
| 4 | <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | ||
| 5 | <head> | ||
| 6 | <meta http-equiv="content-type" content="text/html;charset=UTF-8" /> | ||
| 7 | <title>Occurrences: <%= controller.action_name %></title> | ||
| 8 | <%= stylesheet_link_tag 'scaffold' %> | ||
| 9 | </head> | ||
| 10 | <body> | ||
| 11 | |||
| 12 | <p style="color: green"><%= flash[:notice] %></p> | ||
| 13 | |||
| 14 | <%= yield %> | ||
| 15 | |||
| 16 | </body> | ||
| 17 | </html> | ||
diff --git a/app/views/occurrences/edit.html.erb b/app/views/occurrences/edit.html.erb new file mode 100644 index 0000000..6a81188 --- /dev/null +++ b/app/views/occurrences/edit.html.erb | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | <h1>Editing occurrence</h1> | ||
| 2 | |||
| 3 | <% form_for(@occurrence) do |f| %> | ||
| 4 | <%= f.error_messages %> | ||
| 5 | |||
| 6 | <p> | ||
| 7 | <%= f.label :summary %><br /> | ||
| 8 | <%= f.text_field :summary %> | ||
| 9 | </p> | ||
| 10 | <p> | ||
| 11 | <%= f.label :start_time %><br /> | ||
| 12 | <%= f.datetime_select :start_time %> | ||
| 13 | </p> | ||
| 14 | <p> | ||
| 15 | <%= f.label :end_time %><br /> | ||
| 16 | <%= f.datetime_select :end_time %> | ||
| 17 | </p> | ||
| 18 | <p> | ||
| 19 | <%= f.label :node_id %><br /> | ||
| 20 | <%= f.text_field :node_id %> | ||
| 21 | </p> | ||
| 22 | <p> | ||
| 23 | <%= f.label :event_id %><br /> | ||
| 24 | <%= f.text_field :event_id %> | ||
| 25 | </p> | ||
| 26 | <p> | ||
| 27 | <%= f.submit 'Update' %> | ||
| 28 | </p> | ||
| 29 | <% end %> | ||
| 30 | |||
| 31 | <%= link_to 'Show', @occurrence %> | | ||
| 32 | <%= link_to 'Back', occurrences_path %> \ No newline at end of file | ||
diff --git a/app/views/occurrences/index.html.erb b/app/views/occurrences/index.html.erb new file mode 100644 index 0000000..06dbf07 --- /dev/null +++ b/app/views/occurrences/index.html.erb | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | <h1>Listing occurrences</h1> | ||
| 2 | |||
| 3 | <table> | ||
| 4 | <tr> | ||
| 5 | <th>Summary</th> | ||
| 6 | <th>Start time</th> | ||
| 7 | <th>End time</th> | ||
| 8 | <th>Node</th> | ||
| 9 | <th>Event</th> | ||
| 10 | </tr> | ||
| 11 | |||
| 12 | <% @occurrences.each do |occurrence| %> | ||
| 13 | <tr> | ||
| 14 | <td><%=h occurrence.summary %></td> | ||
| 15 | <td><%=h occurrence.start_time %></td> | ||
| 16 | <td><%=h occurrence.end_time %></td> | ||
| 17 | <td><%=h occurrence.node_id %></td> | ||
| 18 | <td><%=h occurrence.event_id %></td> | ||
| 19 | <td><%= link_to 'Show', occurrence %></td> | ||
| 20 | <td><%= link_to 'Edit', edit_occurrence_path(occurrence) %></td> | ||
| 21 | <td><%= link_to 'Destroy', occurrence, :confirm => 'Are you sure?', :method => :delete %></td> | ||
| 22 | </tr> | ||
| 23 | <% end %> | ||
| 24 | </table> | ||
| 25 | |||
| 26 | <br /> | ||
| 27 | |||
| 28 | <%= link_to 'New occurrence', new_occurrence_path %> \ No newline at end of file | ||
diff --git a/app/views/occurrences/new.html.erb b/app/views/occurrences/new.html.erb new file mode 100644 index 0000000..0a77af1 --- /dev/null +++ b/app/views/occurrences/new.html.erb | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | <h1>New occurrence</h1> | ||
| 2 | |||
| 3 | <% form_for(@occurrence) do |f| %> | ||
| 4 | <%= f.error_messages %> | ||
| 5 | |||
| 6 | <p> | ||
| 7 | <%= f.label :summary %><br /> | ||
| 8 | <%= f.text_field :summary %> | ||
| 9 | </p> | ||
| 10 | <p> | ||
| 11 | <%= f.label :start_time %><br /> | ||
| 12 | <%= f.datetime_select :start_time %> | ||
| 13 | </p> | ||
| 14 | <p> | ||
| 15 | <%= f.label :end_time %><br /> | ||
| 16 | <%= f.datetime_select :end_time %> | ||
| 17 | </p> | ||
| 18 | <p> | ||
| 19 | <%= f.label :node_id %><br /> | ||
| 20 | <%= f.text_field :node_id %> | ||
| 21 | </p> | ||
| 22 | <p> | ||
| 23 | <%= f.label :event_id %><br /> | ||
| 24 | <%= f.text_field :event_id %> | ||
| 25 | </p> | ||
| 26 | <p> | ||
| 27 | <%= f.submit 'Create' %> | ||
| 28 | </p> | ||
| 29 | <% end %> | ||
| 30 | |||
| 31 | <%= link_to 'Back', occurrences_path %> \ No newline at end of file | ||
diff --git a/app/views/occurrences/show.html.erb b/app/views/occurrences/show.html.erb new file mode 100644 index 0000000..9e831cf --- /dev/null +++ b/app/views/occurrences/show.html.erb | |||
| @@ -0,0 +1,28 @@ | |||
| 1 | <p> | ||
| 2 | <b>Summary:</b> | ||
| 3 | <%=h @occurrence.summary %> | ||
| 4 | </p> | ||
| 5 | |||
| 6 | <p> | ||
| 7 | <b>Start time:</b> | ||
| 8 | <%=h @occurrence.start_time %> | ||
| 9 | </p> | ||
| 10 | |||
| 11 | <p> | ||
| 12 | <b>End time:</b> | ||
| 13 | <%=h @occurrence.end_time %> | ||
| 14 | </p> | ||
| 15 | |||
| 16 | <p> | ||
| 17 | <b>Node:</b> | ||
| 18 | <%=h @occurrence.node_id %> | ||
| 19 | </p> | ||
| 20 | |||
| 21 | <p> | ||
| 22 | <b>Event:</b> | ||
| 23 | <%=h @occurrence.event_id %> | ||
| 24 | </p> | ||
| 25 | |||
| 26 | |||
| 27 | <%= link_to 'Edit', edit_occurrence_path(@occurrence) %> | | ||
| 28 | <%= link_to 'Back', occurrences_path %> \ No newline at end of file | ||
diff --git a/config/routes.rb b/config/routes.rb index 24735b5..11ca34c 100644 --- a/config/routes.rb +++ b/config/routes.rb | |||
| @@ -1,4 +1,8 @@ | |||
| 1 | ActionController::Routing::Routes.draw do |map| | 1 | ActionController::Routing::Routes.draw do |map| |
| 2 | map.resources :occurrences | ||
| 3 | |||
| 4 | map.resources :events | ||
| 5 | |||
| 2 | map.root( | 6 | map.root( |
| 3 | :locale => 'de', | 7 | :locale => 'de', |
| 4 | :controller => 'content', | 8 | :controller => 'content', |
diff --git a/db/migrate/20090316194152_create_events.rb b/db/migrate/20090316194152_create_events.rb new file mode 100644 index 0000000..7f44fdf --- /dev/null +++ b/db/migrate/20090316194152_create_events.rb | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | class CreateEvents < ActiveRecord::Migration | ||
| 2 | def self.up | ||
| 3 | create_table :events do |t| | ||
| 4 | t.datetime :start_time | ||
| 5 | t.datetime :end_time | ||
| 6 | t.string :rrule | ||
| 7 | t.boolean :custom_rrule | ||
| 8 | t.boolean :allday | ||
| 9 | t.string :url | ||
| 10 | t.float :latitude | ||
| 11 | t.float :longitude | ||
| 12 | t.integer :node_id | ||
| 13 | |||
| 14 | t.timestamps | ||
| 15 | end | ||
| 16 | end | ||
| 17 | |||
| 18 | def self.down | ||
| 19 | drop_table :events | ||
| 20 | end | ||
| 21 | end | ||
diff --git a/db/migrate/20090316195143_create_occurrences.rb b/db/migrate/20090316195143_create_occurrences.rb new file mode 100644 index 0000000..e0df07b --- /dev/null +++ b/db/migrate/20090316195143_create_occurrences.rb | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | class CreateOccurrences < ActiveRecord::Migration | ||
| 2 | def self.up | ||
| 3 | create_table :occurrences do |t| | ||
| 4 | t.string :summary | ||
| 5 | t.datetime :start_time | ||
| 6 | t.datetime :end_time | ||
| 7 | t.integer :node_id | ||
| 8 | t.integer :event_id | ||
| 9 | |||
| 10 | t.timestamps | ||
| 11 | end | ||
| 12 | end | ||
| 13 | |||
| 14 | def self.down | ||
| 15 | drop_table :occurrences | ||
| 16 | end | ||
| 17 | end | ||
diff --git a/doc/cccms_model.graffle b/doc/cccms_model.graffle index 8303a0b..98ab2c7 100644 --- a/doc/cccms_model.graffle +++ b/doc/cccms_model.graffle | |||
| Binary files differ | |||
diff --git a/lib/chaos_calendar.rb b/lib/chaos_calendar.rb deleted file mode 100644 index b363ccb..0000000 --- a/lib/chaos_calendar.rb +++ /dev/null | |||
| @@ -1,35 +0,0 @@ | |||
| 1 | require 'vpim' | ||
| 2 | |||
| 3 | class Occurrence | ||
| 4 | def initialize start, event, node | ||
| 5 | @dtstart = start | ||
| 6 | @event = event | ||
| 7 | @node = node | ||
| 8 | end | ||
| 9 | attr_reader :dtstart, :event, :node | ||
| 10 | end | ||
| 11 | |||
| 12 | class ChaosCalendar | ||
| 13 | attr_reader :calendar | ||
| 14 | def initialize | ||
| 15 | @calendar = {} | ||
| 16 | end | ||
| 17 | |||
| 18 | def push cal, node | ||
| 19 | Vpim::Icalendar.decode( cal ).each { |c| c.events.each { |e| @calendar[e] = node } } | ||
| 20 | end | ||
| 21 | |||
| 22 | def occurrences start_time, end_time | ||
| 23 | occurr = [] | ||
| 24 | @calendar.each { |e, node| | ||
| 25 | if e.occurs_in?( start_time, end_time ) | ||
| 26 | e.occurences( end_time ) { |t| | ||
| 27 | occurr << Occurrence.new(t,e,node) if (t + (e.duration || 0)) >= start_time | ||
| 28 | } | ||
| 29 | end | ||
| 30 | } | ||
| 31 | |||
| 32 | return occurr.sort { |lhs, rhs| lhs.dtstart <=> rhs.dtstart } | ||
| 33 | end | ||
| 34 | |||
| 35 | end | ||
diff --git a/lib/chaos_calendar/gen.sh b/lib/chaos_calendar/gen.sh index 2f5351a..2f5351a 100644..100755 --- a/lib/chaos_calendar/gen.sh +++ b/lib/chaos_calendar/gen.sh | |||
diff --git a/public/stylesheets/scaffold.css b/public/stylesheets/scaffold.css new file mode 100644 index 0000000..093c209 --- /dev/null +++ b/public/stylesheets/scaffold.css | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | body { background-color: #fff; color: #333; } | ||
| 2 | |||
| 3 | body, p, ol, ul, td { | ||
| 4 | font-family: verdana, arial, helvetica, sans-serif; | ||
| 5 | font-size: 13px; | ||
| 6 | line-height: 18px; | ||
| 7 | } | ||
| 8 | |||
| 9 | pre { | ||
| 10 | background-color: #eee; | ||
| 11 | padding: 10px; | ||
| 12 | font-size: 11px; | ||
| 13 | } | ||
| 14 | |||
| 15 | a { color: #000; } | ||
| 16 | a:visited { color: #666; } | ||
| 17 | a:hover { color: #fff; background-color:#000; } | ||
| 18 | |||
| 19 | .fieldWithErrors { | ||
| 20 | padding: 2px; | ||
| 21 | background-color: red; | ||
| 22 | display: table; | ||
| 23 | } | ||
| 24 | |||
| 25 | #errorExplanation { | ||
| 26 | width: 400px; | ||
| 27 | border: 2px solid red; | ||
| 28 | padding: 7px; | ||
| 29 | padding-bottom: 12px; | ||
| 30 | margin-bottom: 20px; | ||
| 31 | background-color: #f0f0f0; | ||
| 32 | } | ||
| 33 | |||
| 34 | #errorExplanation h2 { | ||
| 35 | text-align: left; | ||
| 36 | font-weight: bold; | ||
| 37 | padding: 5px 5px 5px 15px; | ||
| 38 | font-size: 12px; | ||
| 39 | margin: -7px; | ||
| 40 | background-color: #c00; | ||
| 41 | color: #fff; | ||
| 42 | } | ||
| 43 | |||
| 44 | #errorExplanation p { | ||
| 45 | color: #333; | ||
| 46 | margin-bottom: 0; | ||
| 47 | padding: 5px; | ||
| 48 | } | ||
| 49 | |||
| 50 | #errorExplanation ul li { | ||
| 51 | font-size: 12px; | ||
| 52 | list-style: square; | ||
| 53 | } | ||
| 54 | |||
diff --git a/test/fixtures/events.yml b/test/fixtures/events.yml new file mode 100644 index 0000000..bd73671 --- /dev/null +++ b/test/fixtures/events.yml | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html | ||
| 2 | |||
| 3 | |||
diff --git a/test/fixtures/occurrences.yml b/test/fixtures/occurrences.yml new file mode 100644 index 0000000..a56c164 --- /dev/null +++ b/test/fixtures/occurrences.yml | |||
| @@ -0,0 +1 @@ | |||
| # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html | |||
diff --git a/test/functional/events_controller_test.rb b/test/functional/events_controller_test.rb new file mode 100644 index 0000000..5698c7b --- /dev/null +++ b/test/functional/events_controller_test.rb | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | require 'test_helper' | ||
| 2 | |||
| 3 | class EventsControllerTest < ActionController::TestCase | ||
| 4 | # test "should get index" do | ||
| 5 | # get :index | ||
| 6 | # assert_response :success | ||
| 7 | # assert_not_nil assigns(:events) | ||
| 8 | # end | ||
| 9 | # | ||
| 10 | # test "should get new" do | ||
| 11 | # get :new | ||
| 12 | # assert_response :success | ||
| 13 | # end | ||
| 14 | # | ||
| 15 | # test "should create event" do | ||
| 16 | # assert_difference('Event.count') do | ||
| 17 | # post :create, :event => { } | ||
| 18 | # end | ||
| 19 | # | ||
| 20 | # assert_redirected_to event_path(assigns(:event)) | ||
| 21 | # end | ||
| 22 | # | ||
| 23 | # test "should show event" do | ||
| 24 | # get :show, :id => events(:one).to_param | ||
| 25 | # assert_response :success | ||
| 26 | # end | ||
| 27 | # | ||
| 28 | # test "should get edit" do | ||
| 29 | # get :edit, :id => events(:one).to_param | ||
| 30 | # assert_response :success | ||
| 31 | # end | ||
| 32 | # | ||
| 33 | # test "should update event" do | ||
| 34 | # put :update, :id => events(:one).to_param, :event => { } | ||
| 35 | # assert_redirected_to event_path(assigns(:event)) | ||
| 36 | # end | ||
| 37 | # | ||
| 38 | # test "should destroy event" do | ||
| 39 | # assert_difference('Event.count', -1) do | ||
| 40 | # delete :destroy, :id => events(:one).to_param | ||
| 41 | # end | ||
| 42 | # | ||
| 43 | # assert_redirected_to events_path | ||
| 44 | # end | ||
| 45 | end | ||
diff --git a/test/functional/occurrences_controller_test.rb b/test/functional/occurrences_controller_test.rb new file mode 100644 index 0000000..0b00e0e --- /dev/null +++ b/test/functional/occurrences_controller_test.rb | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | require 'test_helper' | ||
| 2 | |||
| 3 | class OccurrencesControllerTest < ActionController::TestCase | ||
| 4 | # test "should get index" do | ||
| 5 | # get :index | ||
| 6 | # assert_response :success | ||
| 7 | # assert_not_nil assigns(:occurrences) | ||
| 8 | # end | ||
| 9 | # | ||
| 10 | # test "should get new" do | ||
| 11 | # get :new | ||
| 12 | # assert_response :success | ||
| 13 | # end | ||
| 14 | # | ||
| 15 | # test "should create occurrence" do | ||
| 16 | # assert_difference('Occurrence.count') do | ||
| 17 | # post :create, :occurrence => { } | ||
| 18 | # end | ||
| 19 | # | ||
| 20 | # assert_redirected_to occurrence_path(assigns(:occurrence)) | ||
| 21 | # end | ||
| 22 | # | ||
| 23 | # test "should show occurrence" do | ||
| 24 | # get :show, :id => occurrences(:one).to_param | ||
| 25 | # assert_response :success | ||
| 26 | # end | ||
| 27 | # | ||
| 28 | # test "should get edit" do | ||
| 29 | # get :edit, :id => occurrences(:one).to_param | ||
| 30 | # assert_response :success | ||
| 31 | # end | ||
| 32 | # | ||
| 33 | # test "should update occurrence" do | ||
| 34 | # put :update, :id => occurrences(:one).to_param, :occurrence => { } | ||
| 35 | # assert_redirected_to occurrence_path(assigns(:occurrence)) | ||
| 36 | # end | ||
| 37 | # | ||
| 38 | # test "should destroy occurrence" do | ||
| 39 | # assert_difference('Occurrence.count', -1) do | ||
| 40 | # delete :destroy, :id => occurrences(:one).to_param | ||
| 41 | # end | ||
| 42 | # | ||
| 43 | # assert_redirected_to occurrences_path | ||
| 44 | # end | ||
| 45 | end | ||
diff --git a/test/unit/event_test.rb b/test/unit/event_test.rb new file mode 100644 index 0000000..8d51b1a --- /dev/null +++ b/test/unit/event_test.rb | |||
| @@ -0,0 +1,119 @@ | |||
| 1 | require 'test_helper' | ||
| 2 | |||
| 3 | class EventTest < ActiveSupport::TestCase | ||
| 4 | |||
| 5 | def setup | ||
| 6 | Page.delete_all | ||
| 7 | @cal_node = Node.create :slug => "calendar" | ||
| 8 | @cal_node.move_to_child_of Node.root | ||
| 9 | @draft = @cal_node.find_or_create_draft User.first | ||
| 10 | @draft.title = "99C3" | ||
| 11 | @draft.abstract = "The 99th Chaos Comunication Congress" | ||
| 12 | @draft.body = "Its totally freakin awesome" | ||
| 13 | @draft.save | ||
| 14 | @cal_node.publish_draft! | ||
| 15 | @cal_node.head.reload | ||
| 16 | end | ||
| 17 | |||
| 18 | test 'verfy setup data' do | ||
| 19 | assert_not_nil @cal_node | ||
| 20 | assert_not_nil @cal_node.head | ||
| 21 | end | ||
| 22 | |||
| 23 | test 'creating an event with malformed rrule raises exception' do | ||
| 24 | assert_raise(ArgumentError) do | ||
| 25 | Event.create!( | ||
| 26 | :start_time => "2009-01-01T15:23:42".to_time, | ||
| 27 | :end_time => "2009-01-01T20:05:23".to_time, | ||
| 28 | :url => "http://events.ccc.de/congress/2082", | ||
| 29 | :latitude => 52.525308, | ||
| 30 | :longitude => 13.378944, | ||
| 31 | :rrule => "FOOBAR", | ||
| 32 | :allday => false, | ||
| 33 | :custom_rrule => false, | ||
| 34 | :node_id => @cal_node.id | ||
| 35 | ) | ||
| 36 | end | ||
| 37 | end | ||
| 38 | |||
| 39 | test 'create day event for node with one occurrence' do | ||
| 40 | assert_not_nil event = Event.create!( | ||
| 41 | :start_time => "2009-01-01T15:23:42".to_time, | ||
| 42 | :end_time => "2009-01-01T20:05:23".to_time, | ||
| 43 | :url => "http://events.ccc.de/congress/2082", | ||
| 44 | :latitude => 52.525308, | ||
| 45 | :longitude => 13.378944, | ||
| 46 | :rrule => nil, | ||
| 47 | :allday => false, | ||
| 48 | :custom_rrule => false, | ||
| 49 | :node_id => @cal_node.id | ||
| 50 | ) | ||
| 51 | |||
| 52 | assert_equal 1, Occurrence.count | ||
| 53 | assert_equal event.start_time, Occurrence.first.start_time | ||
| 54 | assert_equal event.end_time, Occurrence.first.end_time | ||
| 55 | assert_equal @cal_node.head.title, Occurrence.first.summary | ||
| 56 | end | ||
| 57 | |||
| 58 | test 'create day event with weekly reoccurrence and checking data' do | ||
| 59 | assert_not_nil event = Event.create!( | ||
| 60 | :start_time => "2009-01-01T15:23:42".to_time, | ||
| 61 | :end_time => "2009-01-01T20:05:23".to_time, | ||
| 62 | :url => "http://events.ccc.de/congress/2082", | ||
| 63 | :latitude => 52.525308, | ||
| 64 | :longitude => 13.378944, | ||
| 65 | :rrule => "FREQ=WEEKLY;INTERVAL=1", | ||
| 66 | :allday => false, | ||
| 67 | :custom_rrule => false, | ||
| 68 | :node_id => @cal_node.id | ||
| 69 | ) | ||
| 70 | |||
| 71 | assert_not_nil scoped_occurrences = event.occurrences_in_range( | ||
| 72 | "2009-01-01".to_time, "2009-12-31".to_time | ||
| 73 | ) | ||
| 74 | |||
| 75 | assert_equal 52, scoped_occurrences.length | ||
| 76 | |||
| 77 | assert_equal "2009-12-24T15:23:42".to_time, scoped_occurrences[51].start_time | ||
| 78 | assert_equal "2009-12-24T20:05:23".to_time, scoped_occurrences[51].end_time | ||
| 79 | assert_equal "99C3", scoped_occurrences[51].summary | ||
| 80 | assert_equal @cal_node.event, scoped_occurrences[51].event | ||
| 81 | assert_equal @cal_node, scoped_occurrences[51].node | ||
| 82 | |||
| 83 | assert_equal "2009-03-19T15:23:42".to_time, scoped_occurrences[11].start_time | ||
| 84 | assert_equal "2009-03-19T20:05:23".to_time, scoped_occurrences[11].end_time | ||
| 85 | assert_equal "99C3", scoped_occurrences[11].summary | ||
| 86 | assert_equal @cal_node.event, scoped_occurrences[11].event | ||
| 87 | assert_equal @cal_node, scoped_occurrences[11].node | ||
| 88 | |||
| 89 | assert_equal "2009-01-01T15:23:42".to_time, scoped_occurrences[0].start_time | ||
| 90 | assert_equal "2009-01-01T20:05:23".to_time, scoped_occurrences[0].end_time | ||
| 91 | assert_equal "99C3", scoped_occurrences[0].summary | ||
| 92 | assert_equal @cal_node.event, scoped_occurrences[11].event | ||
| 93 | assert_equal @cal_node, scoped_occurrences[11].node | ||
| 94 | end | ||
| 95 | |||
| 96 | test 'create chaosradio event with custom rrule and interval' do | ||
| 97 | assert_not_nil event = Event.create!( | ||
| 98 | :start_time => "2009-01-28T21:00:00".to_time, | ||
| 99 | :end_time => "2009-01-28T23:00:00".to_time, | ||
| 100 | :url => "http://chaosradio.ccc.de", | ||
| 101 | :latitude => 52.525308, | ||
| 102 | :longitude => 13.378944, | ||
| 103 | :rrule => "FREQ=MONTHLY;INTERVAL=1;BYDAY=-1WE", | ||
| 104 | :allday => false, | ||
| 105 | :custom_rrule => true, | ||
| 106 | :node_id => @cal_node.id | ||
| 107 | ) | ||
| 108 | |||
| 109 | assert_not_nil scoped_occurrences = event.occurrences_in_range( | ||
| 110 | "2009-01-01".to_time, "2009-12-31".to_time | ||
| 111 | ) | ||
| 112 | |||
| 113 | assert_equal 12, scoped_occurrences.length | ||
| 114 | |||
| 115 | expected_days = [28, 25, 25, 29, 27, 24, 29, 26, 30, 28, 25, 30] | ||
| 116 | chaosradio_days = scoped_occurrences.map {|x| x.start_time.day} | ||
| 117 | assert_equal expected_days, chaosradio_days | ||
| 118 | end | ||
| 119 | end \ No newline at end of file | ||
diff --git a/test/unit/helpers/events_helper_test.rb b/test/unit/helpers/events_helper_test.rb new file mode 100644 index 0000000..2e7567e --- /dev/null +++ b/test/unit/helpers/events_helper_test.rb | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | require 'test_helper' | ||
| 2 | |||
| 3 | class EventsHelperTest < ActionView::TestCase | ||
| 4 | end | ||
diff --git a/test/unit/helpers/occurrences_helper_test.rb b/test/unit/helpers/occurrences_helper_test.rb new file mode 100644 index 0000000..0692926 --- /dev/null +++ b/test/unit/helpers/occurrences_helper_test.rb | |||
| @@ -0,0 +1,4 @@ | |||
| 1 | require 'test_helper' | ||
| 2 | |||
| 3 | class OccurrencesHelperTest < ActionView::TestCase | ||
| 4 | end | ||
diff --git a/test/unit/occurrence_test.rb b/test/unit/occurrence_test.rb new file mode 100644 index 0000000..91a78ec --- /dev/null +++ b/test/unit/occurrence_test.rb | |||
| @@ -0,0 +1,8 @@ | |||
| 1 | require 'test_helper' | ||
| 2 | |||
| 3 | class OccurrenceTest < ActiveSupport::TestCase | ||
| 4 | # Replace this with your real tests. | ||
| 5 | test "the truth" do | ||
| 6 | assert true | ||
| 7 | end | ||
| 8 | end | ||
diff --git a/vendor/rails b/vendor/rails | |||
| Subproject bc5c984c3e2dd3ae63cb89216e581a24cd76bd0 | Subproject 40e813cbf83ff0258c7549211aa7a0e1c7ddb4c | ||
