cal_months_rails3 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +43 -0
- data/app/assets/javascripts/cal_months.js.coffee +19 -0
- data/app/assets/stylesheets/cal_months.css.sass +170 -0
- data/app/controllers/cal_months_controller.rb +10 -0
- data/app/helpers/cal_months_helper.rb +12 -0
- data/app/models/cal_event.rb +104 -0
- data/app/models/cal_month.rb +171 -0
- data/app/views/cal_months/_calendar.html.erb +6 -0
- data/app/views/cal_months/_month.html.erb +50 -0
- data/app/views/cal_months/_upcoming_events.html.erb +34 -0
- data/app/views/cal_months/show.js.erb +2 -0
- data/app/views/cal_months/show_current_event.js.erb +3 -0
- data/cal_months-1.0.0.gem +0 -0
- data/cal_months.gemspec +21 -0
- data/config/locales/cal_months_cs.yml +44 -0
- data/config/locales/cal_months_en.yml +44 -0
- data/db/migrate/create_cal_events.rb +13 -0
- data/db/migrate/create_cal_months.rb +11 -0
- data/lib/cal_months.rb +7 -0
- data/lib/generators/cal_months/install_generator.rb +50 -0
- metadata +79 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 28754ba3ac4c756df88b1f26b7162237e656df31
|
4
|
+
data.tar.gz: d19711faf88ad84aa2c59dcb46a14937f9ab6565
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: b3458225133f51c2fe63745e6577ff646bed3c40252080d64a1e8ef0a9fedcd4c4e22b17396a8edcf1bc9870b966517d9598e3c104edf92c224935cffe307f93
|
7
|
+
data.tar.gz: ccd96a735b0ad0250f8df4438659ed4655e70f6637876e8af89a526776691de7840beea873b231f98ff4ae2fd364068f1ce5c18c47b30d419a49984951689dc2
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2013 John Hager
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
*Rails 3*
|
2
|
+
# Cal Months
|
3
|
+
Allows for importing ical format calendars to the database with some default calendar views.
|
4
|
+
|
5
|
+
## Installing
|
6
|
+
|
7
|
+
Install the gem:
|
8
|
+
`gem cal_months`
|
9
|
+
|
10
|
+
Install the required files in your rails app:
|
11
|
+
`$ rails g cal_months:install`
|
12
|
+
|
13
|
+
Run migrations:
|
14
|
+
`$ rake db:migrate`
|
15
|
+
|
16
|
+
## Manually installing assets
|
17
|
+
|
18
|
+
Stylesheet:
|
19
|
+
`// require cal_month`
|
20
|
+
|
21
|
+
Javascript:
|
22
|
+
`//= require cal_month`
|
23
|
+
|
24
|
+
## Add Default Calendar Partial to a View
|
25
|
+
Add this to your view:
|
26
|
+
`render 'cal_months/calendar'`
|
27
|
+
|
28
|
+
Add this to your controller:
|
29
|
+
```
|
30
|
+
@cal_month = CalMonth.current_month
|
31
|
+
@current_event = CalMonth.upcoming_events.first
|
32
|
+
```
|
33
|
+
|
34
|
+
Note: `@cal_month` can be any `CalMonth`, and `@current_event` can be any item in the `CalMonth.upcoming_events` array.
|
35
|
+
|
36
|
+
## Importing icalendar
|
37
|
+
|
38
|
+
```
|
39
|
+
ical = File.open('path_to_ical.ics', 'r')
|
40
|
+
CalEvent.import_from_ical(ical)
|
41
|
+
```
|
42
|
+
|
43
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Place all the behaviors and hooks related to the matching controller here.
|
2
|
+
# All this logic will automatically be available in application.js.
|
3
|
+
# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
|
4
|
+
|
5
|
+
|
6
|
+
add_on_calendar_date_on_hover_event = ->
|
7
|
+
$('.day.circled').hover(
|
8
|
+
(->
|
9
|
+
events = $(this).data('event-names')
|
10
|
+
html = "<ul><li>" + events.join('</li><li>') + "</li></ul>"
|
11
|
+
$('.month .more-info').html(html)
|
12
|
+
),
|
13
|
+
(-> $('.month .more-info').html('')))
|
14
|
+
|
15
|
+
$(document).on 'ready page:load', ->
|
16
|
+
add_on_calendar_date_on_hover_event()
|
17
|
+
|
18
|
+
$(document).ajaxComplete ->
|
19
|
+
add_on_calendar_date_on_hover_event()
|
@@ -0,0 +1,170 @@
|
|
1
|
+
|
2
|
+
// Calendar Styles
|
3
|
+
$calendar-primary: #006BB3
|
4
|
+
$calendar-primary-light: #3084c0
|
5
|
+
$calendar-secondary: #a8a8a8
|
6
|
+
$calendar-secondary-light: #f1f1f1
|
7
|
+
$calendar-third: green
|
8
|
+
$calendar-fourth: red
|
9
|
+
|
10
|
+
$calendar-width: 550px
|
11
|
+
|
12
|
+
// Calulated
|
13
|
+
$calendar-height: $calendar-width * 375 / 550
|
14
|
+
|
15
|
+
$day-size: $calendar-width / 2 / 10 * 8 / 7 - 4
|
16
|
+
$date-size: $calendar-height * 56 / 100
|
17
|
+
|
18
|
+
$big-font-size: $calendar-height * 70 / 375
|
19
|
+
$large-font-size: $calendar-height * 24 / 375
|
20
|
+
$medium-font-size: $calendar-height * 20 / 375
|
21
|
+
$normal-font-size: $calendar-height * 16 / 375
|
22
|
+
$small-font-size: $calendar-height * 12 / 375
|
23
|
+
|
24
|
+
$large-vertical-padding: $calendar-height * 45 / 375
|
25
|
+
$medium-vertical-padding: $calendar-height * 15 / 375
|
26
|
+
$small-vertical-padding: $calendar-height * 5 / 375
|
27
|
+
|
28
|
+
$small-horizontal-padding: $calendar-width * 10 / 550
|
29
|
+
|
30
|
+
.calendar-container
|
31
|
+
div
|
32
|
+
box-sizing: border-box
|
33
|
+
.calendar
|
34
|
+
width: $calendar-width
|
35
|
+
height: $calendar-height
|
36
|
+
margin-top: 20px
|
37
|
+
display: inline-block
|
38
|
+
.upcoming-events
|
39
|
+
width: $calendar-width / 2
|
40
|
+
height: $calendar-height
|
41
|
+
background: $calendar-primary
|
42
|
+
padding: $small-vertical-padding $small-horizontal-padding $small-vertical-padding $small-horizontal-padding
|
43
|
+
display: inline-block
|
44
|
+
position: relative
|
45
|
+
color: white
|
46
|
+
.date
|
47
|
+
height: $date-size
|
48
|
+
font-size: $big-font-size
|
49
|
+
text-align: center
|
50
|
+
.block-left, .block-right
|
51
|
+
height: $date-size
|
52
|
+
.event-info
|
53
|
+
height: $calendar-height * 115 / 375
|
54
|
+
font-size: $normal-font-size
|
55
|
+
padding: $small-horizontal-padding $medium-vertical-padding 0 $medium-vertical-padding
|
56
|
+
text-align: center
|
57
|
+
.name
|
58
|
+
font-weight: bold
|
59
|
+
.more-info
|
60
|
+
position: relative
|
61
|
+
.time
|
62
|
+
display: none
|
63
|
+
&:hover
|
64
|
+
cursor: pointer
|
65
|
+
.time
|
66
|
+
font-size: $small-font-size
|
67
|
+
display: block
|
68
|
+
position: relative
|
69
|
+
font-weight: bold
|
70
|
+
.month
|
71
|
+
height: $calendar-height
|
72
|
+
width: $calendar-width / 2
|
73
|
+
border-top: 1px solid $calendar-secondary-light
|
74
|
+
border-bottom: 1px solid $calendar-secondary-light
|
75
|
+
border-right: 1px solid $calendar-secondary-light
|
76
|
+
padding: $small-vertical-padding $small-horizontal-padding $small-vertical-padding $small-horizontal-padding
|
77
|
+
position: relative
|
78
|
+
display: inline-block
|
79
|
+
background: white
|
80
|
+
a.navigation-left, a.navigation-right, .more-info a
|
81
|
+
color: $calendar-primary
|
82
|
+
&:hover, &:visited, &:focus
|
83
|
+
color: $calendar-primary
|
84
|
+
.calendar-grid
|
85
|
+
.block-left, .block-right
|
86
|
+
width: $calendar-width / 2 / 10
|
87
|
+
.grid
|
88
|
+
border-top: 1px solid $calendar-secondary
|
89
|
+
width: $calendar-width / 2 / 10 * 8
|
90
|
+
padding-top: $medium-vertical-padding
|
91
|
+
border-bottom-color: transparent
|
92
|
+
text-align: justify
|
93
|
+
.cal-head-row
|
94
|
+
height: $day-size
|
95
|
+
.day
|
96
|
+
width: $day-size
|
97
|
+
height: $day-size
|
98
|
+
cursor: auto
|
99
|
+
.weekend
|
100
|
+
color: $calendar-primary
|
101
|
+
.cal-row
|
102
|
+
position: relative
|
103
|
+
margin-top: $small-vertical-padding
|
104
|
+
height: $day-size
|
105
|
+
.day
|
106
|
+
width: $day-size
|
107
|
+
height: $day-size
|
108
|
+
font-size: $normal-font-size
|
109
|
+
cursor: pointer
|
110
|
+
display: inline-block
|
111
|
+
border-radius: 100%
|
112
|
+
text-align: center
|
113
|
+
&.null
|
114
|
+
border: 1px solid transparent
|
115
|
+
color: transparent
|
116
|
+
&.past
|
117
|
+
color: $calendar-secondary
|
118
|
+
&.circled
|
119
|
+
border: 1px solid $calendar-secondary
|
120
|
+
&.circled
|
121
|
+
border: 1px solid $calendar-primary
|
122
|
+
.more-info
|
123
|
+
width: $calendar-width / 2
|
124
|
+
font-size: $small-font-size
|
125
|
+
padding: $small-horizontal-padding $medium-vertical-padding 0 $medium-vertical-padding
|
126
|
+
text-align: left
|
127
|
+
font-weight: bold
|
128
|
+
|
129
|
+
.calendar-container
|
130
|
+
.navigation
|
131
|
+
padding-top: $calendar-height * 4 / 30 / 10
|
132
|
+
height: $calendar-height * 4 / 30
|
133
|
+
font-size: $medium-font-size
|
134
|
+
text-align: center
|
135
|
+
.text
|
136
|
+
top: $calendar-height * 4 / 30 / 10 / 5 * 8
|
137
|
+
position: relative
|
138
|
+
|
139
|
+
.block-left, .block-right
|
140
|
+
width: $calendar-width / 2 * 0.15
|
141
|
+
display: inline-block
|
142
|
+
position: absolute
|
143
|
+
|
144
|
+
.navigation-right, .navigation-left
|
145
|
+
font-size: $large-font-size
|
146
|
+
font-weight: bold
|
147
|
+
|
148
|
+
.block-left
|
149
|
+
left: 0
|
150
|
+
.block-right
|
151
|
+
right: 0
|
152
|
+
|
153
|
+
a.navigation-left, a.navigation-right, .more-info a
|
154
|
+
color: white
|
155
|
+
&:hover, &:visited, &:focus
|
156
|
+
text-decoration: none
|
157
|
+
color: white
|
158
|
+
|
159
|
+
|
160
|
+
.date .number, .calendar-grid .grid
|
161
|
+
height: $date-size
|
162
|
+
width: $calendar-width / 2 / 10 * 7
|
163
|
+
padding-top: $large-vertical-padding
|
164
|
+
position: relative
|
165
|
+
display: inline-block
|
166
|
+
border-bottom: 1px solid $calendar-primary-light
|
167
|
+
border-top: 1px solid $calendar-primary-light
|
168
|
+
// END Calendar Styles
|
169
|
+
|
170
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module CalMonthsHelper
|
2
|
+
def pretty_from_to(event)
|
3
|
+
dtstart, dtend = event[:start_datetime], event[:end_datetime]
|
4
|
+
if dtstart.to_date == dtend.to_date
|
5
|
+
"#{dtstart.strftime('%A, %d %b, %H:%M')} - " +
|
6
|
+
"#{dtend.strftime('%H:%M')}"
|
7
|
+
else
|
8
|
+
[dtstart, dtend].map { |dt| dt.strftime('%A, %d %b, %H:%M') }
|
9
|
+
.join(' - ')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'icalendar'
|
2
|
+
class CalEvent < ActiveRecord::Base
|
3
|
+
|
4
|
+
attr_accessible :name, :description, :rdate, :system_uid, :system_updated_at
|
5
|
+
|
6
|
+
validates_presence_of :system_uid, :system_updated_at
|
7
|
+
|
8
|
+
scope :for_month, ->(year, month) {
|
9
|
+
ids = all.map { |event|
|
10
|
+
event.id if event.months_affected.include?([year,month])
|
11
|
+
}.compact
|
12
|
+
where(id: ids)
|
13
|
+
}
|
14
|
+
|
15
|
+
def self.months_affected
|
16
|
+
all.flat_map(&:months_affected).uniq.sort
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.create_or_update(attributes = {})
|
20
|
+
new_event = CalEvent.new(attributes)
|
21
|
+
raise ActiveRecord::RecordInvalid unless new_event.valid?
|
22
|
+
|
23
|
+
found = CalEvent.find_by_system_uid(new_event.system_uid)
|
24
|
+
|
25
|
+
if found
|
26
|
+
if found.system_updated_at < new_event.system_updated_at
|
27
|
+
found.update_attributes(
|
28
|
+
name: new_event.name,
|
29
|
+
description: new_event.description,
|
30
|
+
system_updated_at: new_event.system_updated_at
|
31
|
+
)
|
32
|
+
end
|
33
|
+
found
|
34
|
+
else
|
35
|
+
new_event.save
|
36
|
+
new_event
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.import_from_ical(ical)
|
41
|
+
ids = []
|
42
|
+
cals = Icalendar.parse(ical)
|
43
|
+
cals.each do |cal|
|
44
|
+
cal.events.each do |event|
|
45
|
+
db_event = CalEvent.create_or_update(
|
46
|
+
name: event.summary.to_s,
|
47
|
+
description: event.description.to_s,
|
48
|
+
system_uid: event.uid.to_s,
|
49
|
+
system_updated_at: event.last_modified.to_datetime,
|
50
|
+
)
|
51
|
+
if event.rdate.empty?
|
52
|
+
db_event.rdate = [
|
53
|
+
[event.dtstart.to_datetime, event.dtend.to_datetime]
|
54
|
+
].to_json
|
55
|
+
else
|
56
|
+
db_event.rdate = event.rdate[0].to_json
|
57
|
+
end
|
58
|
+
db_event.save
|
59
|
+
ids << db_event.id
|
60
|
+
end
|
61
|
+
end
|
62
|
+
events = CalEvent.where(id: ids)
|
63
|
+
events.months_affected.each do |year, month|
|
64
|
+
data = events.for_month(year, month).to_event_data(year, month)
|
65
|
+
CalMonth.create_or_update(
|
66
|
+
year: year, month: month, event_data: data
|
67
|
+
)
|
68
|
+
end
|
69
|
+
events
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.to_event_data(year, month)
|
73
|
+
all.each_with_object(Hash.new {|h,k| h[k] = []}) { |event, data|
|
74
|
+
event.to_event_data[[year, month]].each do |day, event_data|
|
75
|
+
data[day] << event_data
|
76
|
+
end
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_event_data
|
81
|
+
data = Hash.new { |h,k| h[k] = {} }
|
82
|
+
datetimes.each {|start_datetime, end_datetime|
|
83
|
+
(start_datetime..end_datetime).each do |day|
|
84
|
+
data[[day.year, day.month]][day.day] = {
|
85
|
+
id: id,
|
86
|
+
name: name,
|
87
|
+
start_datetime: start_datetime,
|
88
|
+
end_datetime: end_datetime
|
89
|
+
}
|
90
|
+
end
|
91
|
+
}
|
92
|
+
data
|
93
|
+
end
|
94
|
+
|
95
|
+
# array of array [[start_datetime, end_datetime],...]
|
96
|
+
def datetimes
|
97
|
+
data = JSON.parse(rdate)
|
98
|
+
data.map { |pair| pair.map { |str| DateTime.parse(str) } }
|
99
|
+
end
|
100
|
+
|
101
|
+
def months_affected
|
102
|
+
datetimes.flatten.map { |date| [date.year, date.month] }.uniq.sort
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
class CalMonth < ActiveRecord::Base
|
2
|
+
|
3
|
+
attr_accessible :event_data, :month, :year
|
4
|
+
|
5
|
+
validates_presence_of :month, :year
|
6
|
+
validate :unique_month
|
7
|
+
|
8
|
+
def self.find_month(year, month)
|
9
|
+
CalMonth.where(year: year, month: month).limit(1).first
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.current_month
|
13
|
+
date = Date.today
|
14
|
+
fetch_month(date.year, date.month)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.fetch_month(year, month)
|
18
|
+
if found = find_month(year, month)
|
19
|
+
found
|
20
|
+
else
|
21
|
+
CalMonth.new(year: year, month: month)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.create_or_update(attributes = {})
|
26
|
+
month = find_month(attributes[:year], attributes[:month]) ||
|
27
|
+
CalMonth.new(year: attributes[:year], month: attributes[:month])
|
28
|
+
|
29
|
+
month.update_event_data(attributes[:event_data])
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns event data: array of hash, sorted by start datetime
|
33
|
+
# e.g. [{"id" => 1, "name" => "Next Event", "start_datetime" =>
|
34
|
+
def self.upcoming_events(date = nil)
|
35
|
+
date ||= Date.today
|
36
|
+
months = where('year >= ? AND month >= ?', date.year, date.month)
|
37
|
+
.order(:year).order(:month).limit(2)
|
38
|
+
|
39
|
+
unless months.empty?
|
40
|
+
events = months.first.events_after_day(date.day)
|
41
|
+
if events.empty?
|
42
|
+
months.last.events_after_day
|
43
|
+
else
|
44
|
+
events
|
45
|
+
end
|
46
|
+
else
|
47
|
+
[{
|
48
|
+
start_datetime: Date.today.to_datetime,
|
49
|
+
end_datetime: Date.today.to_datetime,
|
50
|
+
name: ''
|
51
|
+
}]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def events_after_day(day = 1)
|
56
|
+
eventful_day = date_events[(day-1)..-1].find { |day, data|
|
57
|
+
!data.empty? &&
|
58
|
+
data.any? { |event|
|
59
|
+
event[:end_datetime] > Time.zone.now
|
60
|
+
}
|
61
|
+
}
|
62
|
+
return [] unless eventful_day
|
63
|
+
|
64
|
+
events = eventful_day.last.sort_by {|event| event[:start_datetime]}
|
65
|
+
events.delete_if { |event| event[:end_datetime] < Time.zone.now }
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
def to_a
|
70
|
+
[year, month]
|
71
|
+
end
|
72
|
+
|
73
|
+
def next_month_array
|
74
|
+
n_year = year
|
75
|
+
n_month = month + 1
|
76
|
+
if n_month == 13
|
77
|
+
n_year += 1
|
78
|
+
n_month = 1
|
79
|
+
end
|
80
|
+
[n_year, n_month]
|
81
|
+
end
|
82
|
+
|
83
|
+
def prev_month_array
|
84
|
+
n_year = year
|
85
|
+
n_month = month - 1
|
86
|
+
if n_month == 0
|
87
|
+
n_year -= 1
|
88
|
+
n_month = 12
|
89
|
+
end
|
90
|
+
[n_year, n_month]
|
91
|
+
end
|
92
|
+
|
93
|
+
def to_date
|
94
|
+
Date.new(year, month)
|
95
|
+
end
|
96
|
+
|
97
|
+
def days
|
98
|
+
(1..to_date.end_of_month.day).to_a
|
99
|
+
end
|
100
|
+
|
101
|
+
def events_for_day?(day)
|
102
|
+
!events_for_day(day).empty?
|
103
|
+
end
|
104
|
+
|
105
|
+
def events_for_day(day)
|
106
|
+
date_events_hash[day.to_s]
|
107
|
+
end
|
108
|
+
|
109
|
+
def date_events
|
110
|
+
date_events_hash.sort_by { |date,_| date.to_i }
|
111
|
+
end
|
112
|
+
|
113
|
+
def update_event_data(new_data)
|
114
|
+
new_data.stringify_keys
|
115
|
+
old_data = JSON.parse(event_data || '{}')
|
116
|
+
data = merge_default_data(old_data).merge(new_data)
|
117
|
+
|
118
|
+
update_attribute(:event_data, data.to_json)
|
119
|
+
end
|
120
|
+
|
121
|
+
def each_week
|
122
|
+
date = to_date
|
123
|
+
data = date_events
|
124
|
+
day_of_week_offset = date.wday - 1
|
125
|
+
day_of_week_offset.times { data.unshift([nil, []]) }
|
126
|
+
|
127
|
+
if block_given?
|
128
|
+
data.each_slice(7) { |week| yield(week) }
|
129
|
+
else
|
130
|
+
data.each_slice(7)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
private
|
135
|
+
def merge_default_data(to_merge)
|
136
|
+
blank_days_hash.merge(to_merge)
|
137
|
+
end
|
138
|
+
|
139
|
+
def date_events_hash
|
140
|
+
@date_events_hash ||= merge_default_data(parsed_event_data)
|
141
|
+
end
|
142
|
+
|
143
|
+
def parsed_event_data
|
144
|
+
data = JSON.parse(event_data || '{}')
|
145
|
+
data = create_hash_with_indifferent_access(data)
|
146
|
+
data.each do |day, value|
|
147
|
+
value.each_with_index do |event, index|
|
148
|
+
[:start_datetime, :end_datetime].each do |key|
|
149
|
+
data[day][index][key] = DateTime.parse(data[day][index][key])
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def create_hash_with_indifferent_access(hash)
|
156
|
+
ActiveSupport::HashWithIndifferentAccess.new(hash)
|
157
|
+
end
|
158
|
+
|
159
|
+
def blank_days_hash
|
160
|
+
days.each_with_object({}) { |day, hash| hash[day] = [] }
|
161
|
+
.stringify_keys!
|
162
|
+
end
|
163
|
+
|
164
|
+
def unique_month
|
165
|
+
found = CalMonth.where(year: year, month: month)
|
166
|
+
.where('NOT(id = ?)', id)
|
167
|
+
if found.first
|
168
|
+
errors[:base] << "Unique month required. If you are reading this, there is a bug in the creation or updating of CalMonth models."
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
<div class="pull-left month">
|
2
|
+
<div class="navigation">
|
3
|
+
<div class="block-left">
|
4
|
+
<%= link_to cal_month_path(*@cal_month.prev_month_array, format: :js), class: 'navigation-left', remote: true do %>
|
5
|
+
<span class="glyphicon glyphicon-chevron-left"></span>
|
6
|
+
<% end %>
|
7
|
+
</div>
|
8
|
+
<% year, month = @cal_month.to_a %>
|
9
|
+
<span class="text"><%= "#{t(".month.#{month}")} '#{year.to_s[-2..-1]}" %></span>
|
10
|
+
<div class="block-right">
|
11
|
+
<%= link_to cal_month_path(*@cal_month.next_month_array, format: :js), class: 'navigation-right', remote: true do %>
|
12
|
+
<span class="glyphicon glyphicon-chevron-right"></span>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
<div class="calendar-grid">
|
17
|
+
<div class="block-left"></div>
|
18
|
+
<div class="grid">
|
19
|
+
<div class="cal-head-row">
|
20
|
+
<div class="day"><%=t('.day.short.1') %></div>
|
21
|
+
<div class="day"><%=t('.day.short.2') %></div>
|
22
|
+
<div class="day"><%=t('.day.short.3') %></div>
|
23
|
+
<div class="day"><%=t('.day.short.4') %></div>
|
24
|
+
<div class="day"><%=t('.day.short.5') %></div>
|
25
|
+
<div class="day weekend"><%=t('.day.short.6') %></div>
|
26
|
+
<div class="day weekend"><%=t('.day.short.7') %></div>
|
27
|
+
</div>
|
28
|
+
<% @cal_month.each_week do |week| %>
|
29
|
+
<div class="cal-row">
|
30
|
+
<% week.each do |day, events| %>
|
31
|
+
<% if @cal_month.to_date == Date.today.beginning_of_month %>
|
32
|
+
<% past = Date.today.day > day.to_i %>
|
33
|
+
<% else %>
|
34
|
+
<% past = Date.today > @cal_month.to_date %>
|
35
|
+
<% end %>
|
36
|
+
|
37
|
+
<% event_names = events.map {|event| truncate(event[:name], length: 34, omission: '...')} %>
|
38
|
+
<% if event_names.length > 5 %>
|
39
|
+
<% event_names = event_names[0..3] %>
|
40
|
+
<% event_names.push('<div class="text-center">...</div>') %>
|
41
|
+
<% end %>
|
42
|
+
<%= content_tag :div, day || '0', class: "day #{"null" unless day} #{"circled" unless events.empty?} #{"past" if past && day}", data: { event_names: event_names } %>
|
43
|
+
<% end %>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
46
|
+
</div>
|
47
|
+
<div class="block-right"></div>
|
48
|
+
</div>
|
49
|
+
<div class="more-info"></div>
|
50
|
+
</div>
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<div class="pull-left upcoming-events">
|
2
|
+
<div class="navigation">
|
3
|
+
<div class="block-left">
|
4
|
+
<% unless CalMonth.upcoming_events.first == @current_event %>
|
5
|
+
<%= link_to current_event_path(CalMonth.upcoming_events.index(@current_event) - 1, format: :js), class: 'navigation-left', remote: true do %>
|
6
|
+
<span class="glyphicon glyphicon-chevron-left"></span>
|
7
|
+
<% end %>
|
8
|
+
<% end %>
|
9
|
+
</div>
|
10
|
+
<span class="text"><%= t(".day.#{@current_event[:start_datetime].wday}") %></span>
|
11
|
+
<div class="block-right">
|
12
|
+
<% unless CalMonth.upcoming_events.last == @current_event %>
|
13
|
+
<%= link_to current_event_path(CalMonth.upcoming_events.index(@current_event) + 1, format: :js), class: 'navigation-right', remote: true do %>
|
14
|
+
<span class="glyphicon glyphicon-chevron-right"></span>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
<div class="date">
|
20
|
+
<div class="block-left"></div>
|
21
|
+
<div class="number">
|
22
|
+
<span class="text"><%= @current_event[:start_datetime].day %></span>
|
23
|
+
</div>
|
24
|
+
<div class="block-right"></div>
|
25
|
+
</div>
|
26
|
+
<div class="event-info">
|
27
|
+
<div class="name"><%= truncate(@current_event[:name], length: 45, omission: '...') %></div>
|
28
|
+
<div class="more-info">
|
29
|
+
<span><%= ". . ." %></span>
|
30
|
+
<div class="time"><%= pretty_from_to(@current_event) %></div>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
|
Binary file
|
data/cal_months.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
current_dir = File.expand_path('..', __FILE__)
|
2
|
+
#extensions = %w{ rb yml haml erb slim html js json jbuilder }
|
3
|
+
#files = Dir.glob(current_dir + "/**/*.{#{extensions.join(',')}}")
|
4
|
+
files = Dir.glob(current_dir + '/**/*')
|
5
|
+
files.collect! {|file| file.sub(current_dir + '/', '')}
|
6
|
+
files.push('LICENSE')
|
7
|
+
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = 'cal_months_rails3'
|
10
|
+
s.version = '1.0.1'
|
11
|
+
s.date = "#{Time.now.strftime("%Y-%m-%d")}"
|
12
|
+
s.homepage = 'https://github.com/jphager2/cal_months'
|
13
|
+
s.summary = 'icalendar integration'
|
14
|
+
s.description = 'A nice extension for quickly incorporating icalendar imports with default views (Rails 4)'
|
15
|
+
s.authors = ['jphager2']
|
16
|
+
s.email = 'jphager2@gmail.com'
|
17
|
+
s.files = files
|
18
|
+
s.license = 'MIT'
|
19
|
+
|
20
|
+
s.add_runtime_dependency 'icalendar', '~> 2.2'
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
cs:
|
2
|
+
cal_months:
|
3
|
+
calendar:
|
4
|
+
month:
|
5
|
+
month:
|
6
|
+
"1": Leden
|
7
|
+
"2": Únor
|
8
|
+
"3": Březen
|
9
|
+
"4": Duben
|
10
|
+
"5": Květen
|
11
|
+
"6": Červen
|
12
|
+
"7": Červenec
|
13
|
+
"8": Srpen
|
14
|
+
"9": Září
|
15
|
+
"10": Říjen
|
16
|
+
"11": Listopad
|
17
|
+
"12": Prosinec
|
18
|
+
day:
|
19
|
+
short:
|
20
|
+
"1": P
|
21
|
+
"2": Ú
|
22
|
+
"3": S
|
23
|
+
"4": Č
|
24
|
+
"5": P
|
25
|
+
"6": S
|
26
|
+
"7": N
|
27
|
+
long:
|
28
|
+
"1": Pondělí
|
29
|
+
"2": Úterý
|
30
|
+
"3": Středa
|
31
|
+
"4": Čtvrtek
|
32
|
+
"5": Pátek
|
33
|
+
"6": Sobota
|
34
|
+
"7": Neděle
|
35
|
+
upcoming_events:
|
36
|
+
day:
|
37
|
+
"1": Pondělí
|
38
|
+
"2": Úterý
|
39
|
+
"3": Středa
|
40
|
+
"4": Čtvrtek
|
41
|
+
"5": Pátek
|
42
|
+
"6": Sobota
|
43
|
+
"7": Neděle
|
44
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
en:
|
2
|
+
cal_months:
|
3
|
+
calendar:
|
4
|
+
month:
|
5
|
+
month:
|
6
|
+
"1": January
|
7
|
+
"2": February
|
8
|
+
"3": March
|
9
|
+
"4": April
|
10
|
+
"5": May
|
11
|
+
"6": June
|
12
|
+
"7": July
|
13
|
+
"8": August
|
14
|
+
"9": September
|
15
|
+
"10": October
|
16
|
+
"11": November
|
17
|
+
"12": December
|
18
|
+
day:
|
19
|
+
short:
|
20
|
+
"1": M
|
21
|
+
"2": T
|
22
|
+
"3": W
|
23
|
+
"4": T
|
24
|
+
"5": F
|
25
|
+
"6": S
|
26
|
+
"7": S
|
27
|
+
long:
|
28
|
+
"1": Monday
|
29
|
+
"2": Tuesday
|
30
|
+
"3": Wednesday
|
31
|
+
"4": Thursday
|
32
|
+
"5": Friday
|
33
|
+
"6": Saturday
|
34
|
+
"7": Sunday
|
35
|
+
upcoming_events:
|
36
|
+
day:
|
37
|
+
"1": Monday
|
38
|
+
"2": Tuesday
|
39
|
+
"3": Wednesday
|
40
|
+
"4": Thursday
|
41
|
+
"5": Friday
|
42
|
+
"6": Saturday
|
43
|
+
"7": Sunday
|
44
|
+
|
data/lib/cal_months.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
gem_app_path = File.expand_path('../..', __FILE__)
|
2
|
+
autoload :CalMonthsController, "#{gem_app_path}/app/controllers/cal_months_controller"
|
3
|
+
autoload :CalMonthsHelper, "#{gem_app_path}/app/helpers/cal_months_helper"
|
4
|
+
autoload :CalEvent, "#{gem_app_path}/app/models/cal_event"
|
5
|
+
autoload :CalMonth, "#{gem_app_path}/app/models/cal_month"
|
6
|
+
|
7
|
+
autoload :InstallGenerator, "#{gem_app_path}lib/generators/cal_months/install_generator"
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module CalMonths
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
|
8
|
+
def copy_locale
|
9
|
+
copy_file '../../../config/locales/cal_months_en.yml', 'config/locales/cal_months_en.yml'
|
10
|
+
copy_file '../../../config/locales/cal_months_cs.yml', 'config/locales/cal_months_cs.yml'
|
11
|
+
end
|
12
|
+
|
13
|
+
def copy_stylesheets
|
14
|
+
copy_file '../../../app/assets/javascripts/cal_months.js.coffee', 'app/assets/javascripts/cal_months.js.coffee'
|
15
|
+
copy_file '../../../app/assets/stylesheets/cal_months.css.sass', 'app/assets/stylesheets/cal_months.css.sass'
|
16
|
+
insert_into_file "app/assets/stylesheets/application#{detect_css_format[0]}", "\n#{detect_css_format[1]} require cal_months\n", :after => "require_self"
|
17
|
+
end
|
18
|
+
|
19
|
+
def detect_css_format
|
20
|
+
return ['.css', ' *='] if File.exist?('app/assets/stylesheets/application.css')
|
21
|
+
return ['.css.sass', ' //='] if File.exist?('app/assets/stylesheets/application.css.sass')
|
22
|
+
return ['.sass', ' //='] if File.exist?('app/assets/stylesheets/application.sass')
|
23
|
+
return ['.css.scss', ' //='] if File.exist?('app/assets/stylesheets/application.css.scss')
|
24
|
+
return ['.scss', ' //='] if File.exist?('app/assets/stylesheets/application.scss')
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_helper
|
28
|
+
insert_into_file "app/helpers/application_helper.rb", "\n include CalMonthsHelper\n", after: "module ApplicationHelper"
|
29
|
+
end
|
30
|
+
|
31
|
+
def copy_views
|
32
|
+
copy_file '../../../app/views/cal_months/_calendar.html.erb', 'app/views/cal_months/_calendar.html.erb'
|
33
|
+
copy_file '../../../app/views/cal_months/_month.html.erb', 'app/views/cal_months/_month.html.erb'
|
34
|
+
copy_file '../../../app/views/cal_months/_upcoming_events.html.erb', 'app/views/cal_months/_upcoming_events.html.erb'
|
35
|
+
copy_file '../../../app/views/cal_months/show.js.erb', 'app/views/cal_months/show.js.erb'
|
36
|
+
copy_file '../../../app/views/cal_months/show_current_event.js.erb', 'app/views/cal_months/show_current_event.js.erb'
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_routes
|
40
|
+
route "get '/cal_months/calendar/:year-:month', to: 'cal_months#show', as: :cal_month"
|
41
|
+
route "get '/cal_months/current-events/:id', to: 'cal_months#show_current_event', as: :current_event"
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_migrations
|
45
|
+
copy_file '../../../db/migrate/create_cal_events.rb', "db/migrate/#{Time.now.to_i}_create_cal_events.rb"
|
46
|
+
copy_file '../../../db/migrate/create_cal_months.rb', "db/migrate/#{Time.now.to_i + 1}_create_cal_months.rb"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
metadata
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cal_months_rails3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- jphager2
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-27 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: icalendar
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.2'
|
27
|
+
description: A nice extension for quickly incorporating icalendar imports with default
|
28
|
+
views (Rails 4)
|
29
|
+
email: jphager2@gmail.com
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- LICENSE
|
35
|
+
- README.md
|
36
|
+
- app/assets/javascripts/cal_months.js.coffee
|
37
|
+
- app/assets/stylesheets/cal_months.css.sass
|
38
|
+
- app/controllers/cal_months_controller.rb
|
39
|
+
- app/helpers/cal_months_helper.rb
|
40
|
+
- app/models/cal_event.rb
|
41
|
+
- app/models/cal_month.rb
|
42
|
+
- app/views/cal_months/_calendar.html.erb
|
43
|
+
- app/views/cal_months/_month.html.erb
|
44
|
+
- app/views/cal_months/_upcoming_events.html.erb
|
45
|
+
- app/views/cal_months/show.js.erb
|
46
|
+
- app/views/cal_months/show_current_event.js.erb
|
47
|
+
- cal_months-1.0.0.gem
|
48
|
+
- cal_months.gemspec
|
49
|
+
- config/locales/cal_months_cs.yml
|
50
|
+
- config/locales/cal_months_en.yml
|
51
|
+
- db/migrate/create_cal_events.rb
|
52
|
+
- db/migrate/create_cal_months.rb
|
53
|
+
- lib/cal_months.rb
|
54
|
+
- lib/generators/cal_months/install_generator.rb
|
55
|
+
homepage: https://github.com/jphager2/cal_months
|
56
|
+
licenses:
|
57
|
+
- MIT
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 2.2.2
|
76
|
+
signing_key:
|
77
|
+
specification_version: 4
|
78
|
+
summary: icalendar integration
|
79
|
+
test_files: []
|