From d2bfbfd2810fbee673e43b2515db8bac527b3441 Mon Sep 17 00:00:00 2001 From: hukl Date: Mon, 16 Mar 2009 20:58:49 +0100 Subject: Refactored Chaos Calendar by wrapping libical and introducing event and occurrence model. More improvements to come. Enables us to create events with reoccurrence and intervals etc. --- app/controllers/events_controller.rb | 85 +++++++++++++++++++++++++++++++ app/controllers/occurrences_controller.rb | 85 +++++++++++++++++++++++++++++++ app/helpers/events_helper.rb | 2 + app/helpers/occurrences_helper.rb | 2 + app/models/event.rb | 27 ++++++++++ app/models/node.rb | 1 + app/models/occurrence.rb | 60 ++++++++++++++++++++++ app/views/events/edit.html.erb | 48 +++++++++++++++++ app/views/events/index.html.erb | 36 +++++++++++++ app/views/events/new.html.erb | 47 +++++++++++++++++ app/views/events/show.html.erb | 48 +++++++++++++++++ app/views/layouts/events.html.erb | 17 +++++++ app/views/layouts/occurrences.html.erb | 17 +++++++ app/views/occurrences/edit.html.erb | 32 ++++++++++++ app/views/occurrences/index.html.erb | 28 ++++++++++ app/views/occurrences/new.html.erb | 31 +++++++++++ app/views/occurrences/show.html.erb | 28 ++++++++++ 17 files changed, 594 insertions(+) create mode 100644 app/controllers/events_controller.rb create mode 100644 app/controllers/occurrences_controller.rb create mode 100644 app/helpers/events_helper.rb create mode 100644 app/helpers/occurrences_helper.rb create mode 100644 app/models/event.rb create mode 100644 app/models/occurrence.rb create mode 100644 app/views/events/edit.html.erb create mode 100644 app/views/events/index.html.erb create mode 100644 app/views/events/new.html.erb create mode 100644 app/views/events/show.html.erb create mode 100644 app/views/layouts/events.html.erb create mode 100644 app/views/layouts/occurrences.html.erb create mode 100644 app/views/occurrences/edit.html.erb create mode 100644 app/views/occurrences/index.html.erb create mode 100644 app/views/occurrences/new.html.erb create mode 100644 app/views/occurrences/show.html.erb (limited to 'app') 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 @@ +class EventsController < ApplicationController + # GET /events + # GET /events.xml + def index + @events = Event.all + + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @events } + end + end + + # GET /events/1 + # GET /events/1.xml + def show + @event = Event.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.xml { render :xml => @event } + end + end + + # GET /events/new + # GET /events/new.xml + def new + @event = Event.new + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @event } + end + end + + # GET /events/1/edit + def edit + @event = Event.find(params[:id]) + end + + # POST /events + # POST /events.xml + def create + @event = Event.new(params[:event]) + + respond_to do |format| + if @event.save + flash[:notice] = 'Event was successfully created.' + format.html { redirect_to(@event) } + format.xml { render :xml => @event, :status => :created, :location => @event } + else + format.html { render :action => "new" } + format.xml { render :xml => @event.errors, :status => :unprocessable_entity } + end + end + end + + # PUT /events/1 + # PUT /events/1.xml + def update + @event = Event.find(params[:id]) + + respond_to do |format| + if @event.update_attributes(params[:event]) + flash[:notice] = 'Event was successfully updated.' + format.html { redirect_to(@event) } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @event.errors, :status => :unprocessable_entity } + end + end + end + + # DELETE /events/1 + # DELETE /events/1.xml + def destroy + @event = Event.find(params[:id]) + @event.destroy + + respond_to do |format| + format.html { redirect_to(events_url) } + format.xml { head :ok } + end + end +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 @@ +class OccurrencesController < ApplicationController + # GET /occurrences + # GET /occurrences.xml + def index + @occurrences = Occurrence.all + + respond_to do |format| + format.html # index.html.erb + format.xml { render :xml => @occurrences } + end + end + + # GET /occurrences/1 + # GET /occurrences/1.xml + def show + @occurrence = Occurrence.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.xml { render :xml => @occurrence } + end + end + + # GET /occurrences/new + # GET /occurrences/new.xml + def new + @occurrence = Occurrence.new + + respond_to do |format| + format.html # new.html.erb + format.xml { render :xml => @occurrence } + end + end + + # GET /occurrences/1/edit + def edit + @occurrence = Occurrence.find(params[:id]) + end + + # POST /occurrences + # POST /occurrences.xml + def create + @occurrence = Occurrence.new(params[:occurrence]) + + respond_to do |format| + if @occurrence.save + flash[:notice] = 'Occurrence was successfully created.' + format.html { redirect_to(@occurrence) } + format.xml { render :xml => @occurrence, :status => :created, :location => @occurrence } + else + format.html { render :action => "new" } + format.xml { render :xml => @occurrence.errors, :status => :unprocessable_entity } + end + end + end + + # PUT /occurrences/1 + # PUT /occurrences/1.xml + def update + @occurrence = Occurrence.find(params[:id]) + + respond_to do |format| + if @occurrence.update_attributes(params[:occurrence]) + flash[:notice] = 'Occurrence was successfully updated.' + format.html { redirect_to(@occurrence) } + format.xml { head :ok } + else + format.html { render :action => "edit" } + format.xml { render :xml => @occurrence.errors, :status => :unprocessable_entity } + end + end + end + + # DELETE /occurrences/1 + # DELETE /occurrences/1.xml + def destroy + @occurrence = Occurrence.find(params[:id]) + @occurrence.destroy + + respond_to do |format| + format.html { redirect_to(occurrences_url) } + format.xml { head :ok } + end + end +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 @@ +module EventsHelper +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 @@ +module OccurrencesHelper +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 @@ +class Event < ActiveRecord::Base + + # Associations + + has_many :occurrences + belongs_to :node + + # Callbacks + + after_save :generate_occurences + + # Instance Methods + + def occurrences_in_range start_time, end_time + self.occurrences.find( + :all, :conditions => [ + "start_time > ? AND end_time < ?", + start_time, end_time + ] + ) + end + + private + def generate_occurences + Occurrence.generate self + end +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 belongs_to :head, :class_name => "Page", :foreign_key => :head_id belongs_to :draft, :class_name => "Page", :foreign_key => :draft_id has_many :permissions + has_one :event # Callbacks 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 @@ +# TODO Make a gem out of the c wrapper +require 'lib/chaos_calendar/ical_occurrences' + +class Occurrence < ActiveRecord::Base + + # Associations + + belongs_to :node + belongs_to :event + + # Class Methods + + def self.find_in_range start_time, end_time + find( + :all, :conditions => [ + "start_time > ? AND end_time < ?", start_time, end_time + ] + ) + end + + # Deletes all Occurrences which belong to the given event. Afterwards a few + # variables are set to save repetitive queries. The occurrences of the given + # event are then calculated and created. + def self.generate event + self.delete_all(:event_id => event.id) + + node = event.node + summary = node.head.title + duration = (event.end_time - event.start_time) + occurrences = self.generate_dates(event) + + occurrences.each do |occurrence| + self.create( + :summary => summary, + :start_time => occurrence, + :end_time => (occurrence + duration), + :node_id => node.id, + :event_id => event.id + ) + end + end + + # Calculates the start_time of all occurrences for a given event if a proper + # RRule is provided. An ArgumentError is thrown from within the libical + # wrapper if the RRule is malformed. If the rrule attribute of an event is + # nil, it simply returns the event start_time as only occurrence. + # Return value is always an array of Time objects. + def self.generate_dates event + if event.rrule + Ical_occurrences::occurrences( + event.start_time.utc.iso8601, + (Time.now + 5.years).utc.iso8601, + event.rrule + ) + else + [event.start_time] + end + + end +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 @@ +

Editing event

+ +<% form_for(@event) do |f| %> + <%= f.error_messages %> + +

+ <%= f.label :start_time %>
+ <%= f.datetime_select :start_time %> +

+

+ <%= f.label :end_time %>
+ <%= f.datetime_select :end_time %> +

+

+ <%= f.label :rrule %>
+ <%= f.text_field :rrule %> +

+

+ <%= f.label :custom_rrule %>
+ <%= f.check_box :custom_rrule %> +

+

+ <%= f.label :allday %>
+ <%= f.check_box :allday %> +

+

+ <%= f.label :url %>
+ <%= f.text_field :url %> +

+

+ <%= f.label :latitude %>
+ <%= f.text_field :latitude %> +

+

+ <%= f.label :longitude %>
+ <%= f.text_field :longitude %> +

+

+ <%= f.label :node_id %>
+ <%= f.text_field :node_id %> +

+

+ <%= f.submit 'Update' %> +

+<% end %> + +<%= link_to 'Show', @event %> | +<%= 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 @@ +

Listing events

+ + + + + + + + + + + + + + +<% @events.each do |event| %> + + + + + + + + + + + + + + +<% end %> +
Start timeEnd timeRruleCustom rruleAlldayUrlLatitudeLongitudeNode
<%=h event.start_time %><%=h event.end_time %><%=h event.rrule %><%=h event.custom_rrule %><%=h event.allday %><%=h event.url %><%=h event.latitude %><%=h event.longitude %><%=h event.node_id %><%= link_to 'Show', event %><%= link_to 'Edit', edit_event_path(event) %><%= link_to 'Destroy', event, :confirm => 'Are you sure?', :method => :delete %>
+ +
+ +<%= 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 @@ +

New event

+ +<% form_for(@event) do |f| %> + <%= f.error_messages %> + +

+ <%= f.label :start_time %>
+ <%= f.datetime_select :start_time %> +

+

+ <%= f.label :end_time %>
+ <%= f.datetime_select :end_time %> +

+

+ <%= f.label :rrule %>
+ <%= f.text_field :rrule %> +

+

+ <%= f.label :custom_rrule %>
+ <%= f.check_box :custom_rrule %> +

+

+ <%= f.label :allday %>
+ <%= f.check_box :allday %> +

+

+ <%= f.label :url %>
+ <%= f.text_field :url %> +

+

+ <%= f.label :latitude %>
+ <%= f.text_field :latitude %> +

+

+ <%= f.label :longitude %>
+ <%= f.text_field :longitude %> +

+

+ <%= f.label :node_id %>
+ <%= f.text_field :node_id %> +

+

+ <%= f.submit 'Create' %> +

+<% end %> + +<%= 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 @@ +

+ Start time: + <%=h @event.start_time %> +

+ +

+ End time: + <%=h @event.end_time %> +

+ +

+ Rrule: + <%=h @event.rrule %> +

+ +

+ Custom rrule: + <%=h @event.custom_rrule %> +

+ +

+ Allday: + <%=h @event.allday %> +

+ +

+ Url: + <%=h @event.url %> +

+ +

+ Latitude: + <%=h @event.latitude %> +

+ +

+ Longitude: + <%=h @event.longitude %> +

+ +

+ Node: + <%=h @event.node_id %> +

+ + +<%= link_to 'Edit', edit_event_path(@event) %> | +<%= 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 @@ + + + + + + Events: <%= controller.action_name %> + <%= stylesheet_link_tag 'scaffold' %> + + + +

<%= flash[:notice] %>

+ +<%= yield %> + + + 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 @@ + + + + + + Occurrences: <%= controller.action_name %> + <%= stylesheet_link_tag 'scaffold' %> + + + +

<%= flash[:notice] %>

+ +<%= yield %> + + + 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 @@ +

Editing occurrence

+ +<% form_for(@occurrence) do |f| %> + <%= f.error_messages %> + +

+ <%= f.label :summary %>
+ <%= f.text_field :summary %> +

+

+ <%= f.label :start_time %>
+ <%= f.datetime_select :start_time %> +

+

+ <%= f.label :end_time %>
+ <%= f.datetime_select :end_time %> +

+

+ <%= f.label :node_id %>
+ <%= f.text_field :node_id %> +

+

+ <%= f.label :event_id %>
+ <%= f.text_field :event_id %> +

+

+ <%= f.submit 'Update' %> +

+<% end %> + +<%= link_to 'Show', @occurrence %> | +<%= 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 @@ +

Listing occurrences

+ + + + + + + + + + +<% @occurrences.each do |occurrence| %> + + + + + + + + + + +<% end %> +
SummaryStart timeEnd timeNodeEvent
<%=h occurrence.summary %><%=h occurrence.start_time %><%=h occurrence.end_time %><%=h occurrence.node_id %><%=h occurrence.event_id %><%= link_to 'Show', occurrence %><%= link_to 'Edit', edit_occurrence_path(occurrence) %><%= link_to 'Destroy', occurrence, :confirm => 'Are you sure?', :method => :delete %>
+ +
+ +<%= 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 @@ +

New occurrence

+ +<% form_for(@occurrence) do |f| %> + <%= f.error_messages %> + +

+ <%= f.label :summary %>
+ <%= f.text_field :summary %> +

+

+ <%= f.label :start_time %>
+ <%= f.datetime_select :start_time %> +

+

+ <%= f.label :end_time %>
+ <%= f.datetime_select :end_time %> +

+

+ <%= f.label :node_id %>
+ <%= f.text_field :node_id %> +

+

+ <%= f.label :event_id %>
+ <%= f.text_field :event_id %> +

+

+ <%= f.submit 'Create' %> +

+<% end %> + +<%= 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 @@ +

+ Summary: + <%=h @occurrence.summary %> +

+ +

+ Start time: + <%=h @occurrence.start_time %> +

+ +

+ End time: + <%=h @occurrence.end_time %> +

+ +

+ Node: + <%=h @occurrence.node_id %> +

+ +

+ Event: + <%=h @occurrence.event_id %> +

+ + +<%= link_to 'Edit', edit_occurrence_path(@occurrence) %> | +<%= link_to 'Back', occurrences_path %> \ No newline at end of file -- cgit v1.3