week_view_helper
1 2 require 'date' 3 4 # Author: Josh Adams 5 # This helper is based on CalendarHelper. 6 # WeekViewHelper allows you to draw a databound week view calendar with fine-grained CSS formatting 7 module WeekViewHelper 8 VERSION = '0.0.1' 9 10 # Returns an HTML week-view calendar. In its simplest form, this method generates a plain 11 # calendar (which can then be customized using CSS) for a given span of days. 12 # However, this may be customized in a variety of ways -- changing the default CSS 13 # classes, generating the individual day entries yourself, and so on. 14 # 15 # The following options are required: 16 # :start_date 17 # :end_date 18 # 19 # The following are optional, available for customizing the default behaviour: 20 # :table_class => "week-view" # The class for the <table> tag. 21 # :day_name_class => "dayName" # The class is for the names of the days, at the top. 22 # :day_class => "day" # The class for the individual day number cells. 23 # This may or may not be used if you specify a block (see below). 24 # :show_today => true # Highlights today on the calendar using the CSS class 'today'. 25 # # Defaults to true. 26 # :previous_span_text => nil # Displayed left if set 27 # :next_span_text => nil # Displayed right if set 28 # 29 # For more customization, you can pass a code block to this method, that will get two argument, both DateTime objects, 30 # and return a values for the individual table cells. The block can return an array, [cell_text, cell_attrs], 31 # cell_text being the text that is displayed and cell_attrs a hash containing the attributes for the <td> tag 32 # (this can be used to change the <td>'s class for customization with CSS). 33 # This block can also return the cell_text only, in which case the <td>'s class defaults to the value given in 34 # +:day_class+. If the block returns nil, the default options are used. 35 # 36 # Example usage: 37 # week_view(:start_date => (Date.today - 5), :end_date => Date.today) # This generates the simplest possible week-view. 38 # week_view(:start_date => (Date.today - 5), :end_date => Date.today, :table_class => "calendar_helper"}) # This generates a week-view, as 39 # # before, but the <table>'s class 40 # # is set to "calendar_helper". 41 # week_view(:start_date => (Date.today - 5), :end_date => Date.today) do |s| # This generates a simple week-view, but gives special spans 42 # if listOfSpecialSpans.include?(s) # (spans that are in the array listOfSpecialSpans) one CSS class, 43 # ["", {:class => "specialSpan"}] # "specialSpan", and gives the rest of the spans another CSS class, 44 # else # "normalSpan". You can also use this to highlight the current time differently 45 # ["", {:class => "normalSpan"}] # from the rest of the days, etc. 46 # end 47 # end 48 # 49 # For consistency with the themes provided in the calendar_styles generator, use "specialSpan" as the CSS class for marked days. 50 # 51 def week_view(options = {}, &block) 52 raise(ArgumentError, "No start date given") unless options.has_key?(:start_date) 53 raise(ArgumentError, "No end date given") unless options.has_key?(:end_date) 54 span = (options[:end_date] - options[:start_date]).to_i # Get the number of days represented by the span given 55 dates = (options[:start_date]..options[:end_date]) 56 start_time = 8 57 end_time = 17 58 time_range = (start_time..end_time).to_a 59 duration = 15 60 61 block ||= Proc.new {|d| nil} 62 defaults = { 63 :table_class => 'week-view', 64 :day_name_class => 'dayName', 65 :day_class => 'day', 66 :show_today => true, 67 :previous_span_text => nil, 68 :next_span_text => nil 69 } 70 options = defaults.merge options 71 72 if options[:url] 73 next_start_date = options[:end_date] + 1 74 next_end_date = next_start_date + 5 75 next_link = link_to('>>', url_for(options[:url].merge(:start_date => next_start_date, :end_date => next_end_date)) + options[:url_append]) 76 prev_start_date = options[:start_date] - span 77 prev_end_date = options[:start_date] - 1 78 prev_link = link_to('<<', url_for(options[:url].merge(:start_date => prev_start_date, :end_date => prev_end_date)) + options[:url_append]) 79 end 80 81 # TODO Use some kind of builder instead of straight HTML 82 cal = %(<table class="#{options[:table_class]}">\n) 83 cal << %(\t<thead>\n\t\t<tr>\n) 84 cal << %(\t\t\t<th>#{dates.first.strftime("%Y")}</th>\n) 85 dates.each do |d| 86 cal << "\t\t\t<th#{Date.today == d ? " class='today'" : ""}>#{d.strftime("%A")}<br />#{d.strftime("%m/%d")}</th>\n" 87 end 88 cal << "\t\t</tr>\n\t</thead>\n\t<tbody>\n" 89 time_range.each do |hour| 90 minutes = 0 91 print_hour = hour.to_s.rjust(2, '0') 92 4.times do |i| 93 print_minutes = minutes.to_s.rjust(2, '0') 94 cal << %(\t\t<tr class='m#{print_minutes} d#{duration}'>\n) 95 cal << %(\t\t\t<th rowspan="4"><h3>#{hour}</h3>AM</th>\n) if i==0 96 options[:start_date].upto(options[:end_date]) do |d| 97 the_minutes = minutes 98 print_start_minutes = the_minutes.to_s.ljust(2, '0') 99 start_datetime_string = %(#{d.to_s(:db)}T#{print_hour}:#{print_start_minutes}:00-06:00) 100 start_datetime = DateTime.parse(start_datetime_string).to_datetime 101 end_datetime = (start_datetime + duration.minutes).to_datetime 102 range = (start_datetime...end_datetime) 103 104 # cell_attrs should return a hash. 105 cell_text, cell_attrs = block.call(range) 106 cell_text ||= "" 107 cell_attrs ||= {} 108 cell_attrs[:class] = cell_attrs[:class].to_s + " today" if Date.today == d 109 cell_attrs = cell_attrs.map {|k, v| %(#{k}="#{v}") }.join(" ") 110 111 cal << "\t\t\t<td #{cell_attrs}>\n#{cell_text} \t\t\t</td>\n" 112 end 113 minutes += duration 114 cal << %(\t\t</tr>) 115 end 116 end 117 cal << "\n\t</tbody>\n</table>" 118 end 119 120 private 121 end 122
// Usage
1 2 <%= week_view :start_date => (Date.today - 2), :end_date => (Date.today + 2) do |range| 3 cell_text = "" 4 cell_attrs = {} 5 @events.each do |e| 6 #if range.first.to_date == e.starts_at.to_date#range.include?(e.starts_at.to_datetime) 7 if range.include?(e.starts_at.to_datetime) 8 cell_text << "<div class='event-container'>\n" 9 if e.work_order 10 work_order_text = "" 11 work_order_text << "<h3>" << e.work_order.ticket.summary + "</h3>\n" 12 work_order_text << e.work_order.description 13 14 klass = ["event"] 15 klass << "closed" if e.work_order.closed? 16 klass << "mm" + (e.work_order.hours * 60).to_i.to_s 17 18 work_order_text = "<div class='#{klass.join(" ")}'>\n#{work_order_text}\n</div>\n" 19 work_order_link = link_to(work_order_text, company_asset_ticket_work_order_path(e.work_order.company, e.work_order.asset, e.work_order.ticket, e.work_order)) 20 cell_text << work_order_link 21 end 22 cell_text << "</div>\n" 23 end 24 end 25 [cell_text, cell_attrs] 26 end 27 -%>
// Styles
1 2 table.week-view{ 3 width: 100%; 4 padding: 0; 5 border-collapse: collapse; 6 } 7 table.week-view tbody tr th{ 8 border-right: 1px solid black; 9 text-align: left; 10 padding-right: .5em; 11 } 12 table.week-view tbody tr th h3{ 13 display: inline; 14 font-size: 3em; 15 margin: 0; 16 padding: 0; 17 background: transparent; 18 border: none; 19 } 20 table.week-view th{ 21 background-color: #eee; 22 color: black; 23 } 24 table.week-view tr td{ 25 border-style: solid; 26 border-width: 1px 1px 0 0; 27 width: 19%; 28 padding: 0; 29 background-color: #ffffd5; 30 } 31 table.week-view tr.d15 td, 32 table.week-view tr.d15 th{ 33 font-size: 8px; 34 height: 1em; 35 border-color: #f3e4b1 #000; 36 } 37 table.week-view div.event-container{ 38 position: relative; 39 } 40 table.week-view tr td div.event{ 41 padding: 2px; 42 background-color: #fff; 43 height: 2em; 44 width: 90%; 45 position: absolute; 46 top: 0; 47 left: 0; 48 border-style: solid; 49 border-color: black black black #00f; 50 border-width: .0625em .0625em .0625em .5em; 51 margin-right: .5em; 52 color: #333; 53 overflow: hidden; 54 float: left; 55 } 56 table.week-view tr td div.event.mm60{ 57 height: 8em; 58 } 59 table.week-view tr td div.event.mm120{ 60 height: 16em; 61 } 62 table.week-view tr td div.event h3{ 63 margin: 0; 64 font-size: 9px; 65 color: black; 66 padding: 0; 67 border: 0; 68 background: transparent; 69 } 70 table.week-view tr.m00 td{ 71 border-top-color: #c2b68d; 72 } 73 table.week-view tr.m00 th{ 74 vertical-align: top; 75 }