cal_months 0.0.2
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 +42 -0
- data/app/assets/javascripts/cal_months.js.coffee +19 -0
- data/app/assets/stylesheets/cal_months.css.sass +167 -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 +148 -0
- data/app/views/cal_months/_calendar.html.haml +4 -0
- data/app/views/cal_months/_month.html.haml +38 -0
- data/app/views/cal_months/_upcoming_events.html.haml +22 -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.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 +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6d6bf2409ba5107e46504b869e0f87d06e1c4acb
|
4
|
+
data.tar.gz: 3ba1fcea89d3975be4f0a4fe38efc30d22f2c354
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 136d8ab98695e48ccbd81e426ac2e399195f95bf8437546186a2afe2935a10091c09e2f1ec0fbc8cbdaff4acdf91cfe21eb8bae1ad218387a67adc561e5626e5
|
7
|
+
data.tar.gz: 994afdf999e8b949cd973f9f1ece93ac0b7b206f98261045827ac9174ecd81d617a5a2072a5092e40eb5d639cfc7cf8b5b8598649903bbc77baabcab6c6f611e
|
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,42 @@
|
|
1
|
+
# Cal Months
|
2
|
+
Allows for importing ical format calendars to the database with some default calendar views.
|
3
|
+
|
4
|
+
## Installing
|
5
|
+
|
6
|
+
Install the gem:
|
7
|
+
`gem cal_months`
|
8
|
+
|
9
|
+
Install the required files in your rails app:
|
10
|
+
`$ rails g cal_months:install`
|
11
|
+
|
12
|
+
Run migrations:
|
13
|
+
`$ rake db:migrate`
|
14
|
+
|
15
|
+
## Manually installing assets
|
16
|
+
|
17
|
+
Stylesheet:
|
18
|
+
`// require cal_month`
|
19
|
+
|
20
|
+
Javascript:
|
21
|
+
`//= require cal_month`
|
22
|
+
|
23
|
+
## Add Default Calendar Partial to a View
|
24
|
+
Add this to your view:
|
25
|
+
`render 'cal_months/calendar'`
|
26
|
+
|
27
|
+
Add this to your controller:
|
28
|
+
```
|
29
|
+
@cal_month = CalMonth.current_month
|
30
|
+
@current_event = CalMonth.upcoming_events.first
|
31
|
+
```
|
32
|
+
|
33
|
+
Note: `@cal_month` can be any `CalMonth`, and `@current_event` can be any item in the `CalMonth.upcoming_events` array.
|
34
|
+
|
35
|
+
## Importing icalendar
|
36
|
+
|
37
|
+
```
|
38
|
+
ical = File.open('path_to_ical.ics', 'r')
|
39
|
+
CalEvent.import_from_ical(ical)
|
40
|
+
```
|
41
|
+
|
42
|
+
|
@@ -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,167 @@
|
|
1
|
+
// Calendar Styles
|
2
|
+
$calendar-primary: #006BB3
|
3
|
+
$calendar-primary-light: #3084c0
|
4
|
+
$calendar-secondary: #a8a8a8
|
5
|
+
$calendar-secondary-light: #f1f1f1
|
6
|
+
$calendar-third: green
|
7
|
+
$calendar-fourth: red
|
8
|
+
|
9
|
+
$calendar-width: 550px
|
10
|
+
|
11
|
+
// Calulated
|
12
|
+
$calendar-height: $calendar-width * 375 / 550
|
13
|
+
|
14
|
+
$day-size: $calendar-width / 2 / 10 * 8 / 7 - 4
|
15
|
+
$date-size: $calendar-height * 56 / 100
|
16
|
+
|
17
|
+
$big-font-size: $calendar-height * 70 / 375
|
18
|
+
$large-font-size: $calendar-height * 24 / 375
|
19
|
+
$medium-font-size: $calendar-height * 20 / 375
|
20
|
+
$normal-font-size: $calendar-height * 16 / 375
|
21
|
+
$small-font-size: $calendar-height * 12 / 375
|
22
|
+
|
23
|
+
$large-vertical-padding: $calendar-height * 45 / 375
|
24
|
+
$medium-vertical-padding: $calendar-height * 15 / 375
|
25
|
+
$small-vertical-padding: $calendar-height * 5 / 375
|
26
|
+
|
27
|
+
$small-horizontal-padding: $calendar-width * 10 / 550
|
28
|
+
|
29
|
+
.calendar-container
|
30
|
+
.calendar
|
31
|
+
width: $calendar-width
|
32
|
+
height: $calendar-height
|
33
|
+
margin-top: 20px
|
34
|
+
display: inline-block
|
35
|
+
.upcoming-events
|
36
|
+
width: $calendar-width / 2
|
37
|
+
height: $calendar-height
|
38
|
+
background: $calendar-primary
|
39
|
+
padding: $small-vertical-padding $small-horizontal-padding $small-vertical-padding $small-horizontal-padding
|
40
|
+
display: inline-block
|
41
|
+
position: relative
|
42
|
+
color: white
|
43
|
+
.date
|
44
|
+
height: $date-size
|
45
|
+
font-size: $big-font-size
|
46
|
+
text-align: center
|
47
|
+
.block-left, .block-right
|
48
|
+
height: $date-size
|
49
|
+
.event-info
|
50
|
+
height: $calendar-height * 115 / 375
|
51
|
+
font-size: $normal-font-size
|
52
|
+
padding: $small-horizontal-padding $medium-vertical-padding 0 $medium-vertical-padding
|
53
|
+
text-align: center
|
54
|
+
.name
|
55
|
+
font-weight: bold
|
56
|
+
.more-info
|
57
|
+
position: relative
|
58
|
+
.time
|
59
|
+
display: none
|
60
|
+
&:hover
|
61
|
+
cursor: pointer
|
62
|
+
.time
|
63
|
+
font-size: $small-font-size
|
64
|
+
display: block
|
65
|
+
position: relative
|
66
|
+
font-weight: bold
|
67
|
+
.month
|
68
|
+
height: $calendar-height
|
69
|
+
width: $calendar-width / 2
|
70
|
+
border-top: 1px solid $calendar-secondary-light
|
71
|
+
border-bottom: 1px solid $calendar-secondary-light
|
72
|
+
border-right: 1px solid $calendar-secondary-light
|
73
|
+
padding: $small-vertical-padding $small-horizontal-padding $small-vertical-padding $small-horizontal-padding
|
74
|
+
position: relative
|
75
|
+
display: inline-block
|
76
|
+
background: white
|
77
|
+
a.navigation-left, a.navigation-right, .more-info a
|
78
|
+
color: $calendar-primary
|
79
|
+
&:hover, &:visited, &:focus
|
80
|
+
color: $calendar-primary
|
81
|
+
.calendar-grid
|
82
|
+
.block-left, .block-right
|
83
|
+
width: $calendar-width / 2 / 10
|
84
|
+
.grid
|
85
|
+
border-top: 1px solid $calendar-secondary
|
86
|
+
width: $calendar-width / 2 / 10 * 8
|
87
|
+
padding-top: $medium-vertical-padding
|
88
|
+
border-bottom-color: transparent
|
89
|
+
text-align: justify
|
90
|
+
.cal-head-row
|
91
|
+
height: $day-size
|
92
|
+
.day
|
93
|
+
width: $day-size
|
94
|
+
height: $day-size
|
95
|
+
cursor: auto
|
96
|
+
.weekend
|
97
|
+
color: $calendar-primary
|
98
|
+
.cal-row
|
99
|
+
position: relative
|
100
|
+
margin-top: $small-vertical-padding
|
101
|
+
height: $day-size
|
102
|
+
.day
|
103
|
+
width: $day-size
|
104
|
+
height: $day-size
|
105
|
+
font-size: $normal-font-size
|
106
|
+
cursor: pointer
|
107
|
+
display: inline-block
|
108
|
+
border-radius: 100%
|
109
|
+
text-align: center
|
110
|
+
&.null
|
111
|
+
border: 1px solid transparent
|
112
|
+
color: transparent
|
113
|
+
&.past
|
114
|
+
color: $calendar-secondary
|
115
|
+
&.circled
|
116
|
+
border: 1px solid $calendar-secondary
|
117
|
+
&.circled
|
118
|
+
border: 1px solid $calendar-primary
|
119
|
+
.more-info
|
120
|
+
width: $calendar-width / 2
|
121
|
+
font-size: $small-font-size
|
122
|
+
padding: $small-horizontal-padding $medium-vertical-padding 0 $medium-vertical-padding
|
123
|
+
text-align: left
|
124
|
+
font-weight: bold
|
125
|
+
|
126
|
+
.calendar-container
|
127
|
+
.navigation
|
128
|
+
padding-top: $calendar-height * 4 / 30 / 10
|
129
|
+
height: $calendar-height * 4 / 30
|
130
|
+
font-size: $medium-font-size
|
131
|
+
text-align: center
|
132
|
+
.text
|
133
|
+
top: $calendar-height * 4 / 30 / 10 / 5 * 8
|
134
|
+
position: relative
|
135
|
+
|
136
|
+
.block-left, .block-right
|
137
|
+
width: $calendar-width / 2 * 0.15
|
138
|
+
display: inline-block
|
139
|
+
position: absolute
|
140
|
+
|
141
|
+
.navigation-right, .navigation-left
|
142
|
+
font-size: $large-font-size
|
143
|
+
font-weight: bold
|
144
|
+
|
145
|
+
.block-left
|
146
|
+
left: 0
|
147
|
+
.block-right
|
148
|
+
right: 0
|
149
|
+
|
150
|
+
a.navigation-left, a.navigation-right, .more-info a
|
151
|
+
color: white
|
152
|
+
&:hover, &:visited, &:focus
|
153
|
+
text-decoration: none
|
154
|
+
color: white
|
155
|
+
|
156
|
+
|
157
|
+
.date .number, .calendar-grid .grid
|
158
|
+
height: $date-size
|
159
|
+
width: $calendar-width / 2 / 10 * 7
|
160
|
+
padding-top: $large-vertical-padding
|
161
|
+
position: relative
|
162
|
+
display: inline-block
|
163
|
+
border-bottom: 1px solid $calendar-primary-light
|
164
|
+
border-top: 1px solid $calendar-primary-light
|
165
|
+
// END Calendar Styles
|
166
|
+
|
167
|
+
|
@@ -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,148 @@
|
|
1
|
+
class CalMonth < ActiveRecord::Base
|
2
|
+
attr_accessible :event_data, :month, :year
|
3
|
+
|
4
|
+
validates_presence_of :month, :year
|
5
|
+
validate :unique_month
|
6
|
+
|
7
|
+
def self.find_month(year, month)
|
8
|
+
CalMonth.where(year: year, month: month).limit(1).first
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.current_month
|
12
|
+
date = Date.today
|
13
|
+
fetch_month(date.year, date.month)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.fetch_month(year, month)
|
17
|
+
if found = find_month(year, month)
|
18
|
+
found
|
19
|
+
else
|
20
|
+
CalMonth.new(year: year, month: month)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.create_or_update(attributes = {})
|
25
|
+
month = find_month(attributes[:year], attributes[:month]) ||
|
26
|
+
CalMonth.new(year: attributes[:year], month: attributes[:month])
|
27
|
+
|
28
|
+
month.update_event_data(attributes[:event_data])
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns event data: array of hash, sorted by start datetime
|
32
|
+
# e.g. [{"id" => 1, "name" => "Next Event", "start_datetime" =>
|
33
|
+
def self.upcoming_events(date = nil)
|
34
|
+
date ||= Date.today
|
35
|
+
month = where('year >= ? AND month >= ?', date.year, date.month)
|
36
|
+
.order(:year).order(:month).limit(1).first
|
37
|
+
events = month.date_events[(date.day-1)..-1].find { |day, data|
|
38
|
+
!data.empty? &&
|
39
|
+
data.any? { |event|
|
40
|
+
event[:end_datetime] > Time.zone.now
|
41
|
+
}
|
42
|
+
}.last.sort_by { |event| event[:start_datetime] }
|
43
|
+
events.delete_if { |event| event[:end_datetime] < Time.zone.now }
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_a
|
47
|
+
[year, month]
|
48
|
+
end
|
49
|
+
|
50
|
+
def next_month_array
|
51
|
+
n_year = year
|
52
|
+
n_month = month + 1
|
53
|
+
if n_month == 13
|
54
|
+
n_year += 1
|
55
|
+
n_month = 1
|
56
|
+
end
|
57
|
+
[n_year, n_month]
|
58
|
+
end
|
59
|
+
|
60
|
+
def prev_month_array
|
61
|
+
n_year = year
|
62
|
+
n_month = month - 1
|
63
|
+
if n_month == 0
|
64
|
+
n_year -= 1
|
65
|
+
n_month = 12
|
66
|
+
end
|
67
|
+
[n_year, n_month]
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_date
|
71
|
+
Date.new(year, month)
|
72
|
+
end
|
73
|
+
|
74
|
+
def days
|
75
|
+
(1..to_date.end_of_month.day).to_a
|
76
|
+
end
|
77
|
+
|
78
|
+
def events_for_day?(day)
|
79
|
+
!events_for_day(day).empty?
|
80
|
+
end
|
81
|
+
|
82
|
+
def events_for_day(day)
|
83
|
+
date_events_hash[day.to_s]
|
84
|
+
end
|
85
|
+
|
86
|
+
def date_events
|
87
|
+
date_events_hash.sort_by { |date,_| date.to_i }
|
88
|
+
end
|
89
|
+
|
90
|
+
def update_event_data(new_data)
|
91
|
+
new_data.stringify_keys
|
92
|
+
old_data = JSON.parse(event_data || '{}')
|
93
|
+
data = merge_default_data(old_data).merge(new_data)
|
94
|
+
|
95
|
+
update_attribute(:event_data, data.to_json)
|
96
|
+
end
|
97
|
+
|
98
|
+
def each_week
|
99
|
+
date = to_date
|
100
|
+
data = date_events
|
101
|
+
day_of_week_offset = date.wday - 1
|
102
|
+
day_of_week_offset.times { data.unshift([nil, []]) }
|
103
|
+
|
104
|
+
if block_given?
|
105
|
+
data.each_slice(7) { |week| yield(week) }
|
106
|
+
else
|
107
|
+
data.each_slice(7)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def merge_default_data(to_merge)
|
113
|
+
blank_days_hash.merge(to_merge)
|
114
|
+
end
|
115
|
+
|
116
|
+
def date_events_hash
|
117
|
+
@date_events_hash ||= merge_default_data(parsed_event_data)
|
118
|
+
end
|
119
|
+
|
120
|
+
def parsed_event_data
|
121
|
+
data = JSON.parse(event_data || '{}')
|
122
|
+
data = create_hash_with_indifferent_access(data)
|
123
|
+
data.each do |day, value|
|
124
|
+
value.each_with_index do |event, index|
|
125
|
+
[:start_datetime, :end_datetime].each do |key|
|
126
|
+
data[day][index][key] = DateTime.parse(data[day][index][key])
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def create_hash_with_indifferent_access(hash)
|
133
|
+
ActiveSupport::HashWithIndifferentAccess.new(hash)
|
134
|
+
end
|
135
|
+
|
136
|
+
def blank_days_hash
|
137
|
+
days.each_with_object({}) { |day, hash| hash[day] = [] }
|
138
|
+
.stringify_keys!
|
139
|
+
end
|
140
|
+
|
141
|
+
def unique_month
|
142
|
+
found = CalMonth.where(year: year, month: month)
|
143
|
+
.where('NOT(id = ?)', id)
|
144
|
+
if found.first
|
145
|
+
errors[:base] << "Unique month required. If you are reading this, there is a bug in the creation or updating of CalMonth models."
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
.pull-left.month
|
2
|
+
.navigation
|
3
|
+
.block-left
|
4
|
+
= link_to cal_month_path(*@cal_month.prev_month_array, format: :js), class: 'navigation-left', remote: true do
|
5
|
+
%span.glyphicon.glyphicon-chevron-left
|
6
|
+
|
7
|
+
- year, month = @cal_month.to_a
|
8
|
+
%span.text= "#{t(".month.#{month}")} '#{year.to_s[-2..-1]}"
|
9
|
+
.block-right
|
10
|
+
= link_to cal_month_path(*@cal_month.next_month_array, format: :js), class: 'navigation-right', remote: true do
|
11
|
+
%span.glyphicon.glyphicon-chevron-right
|
12
|
+
.calendar-grid
|
13
|
+
.block-left
|
14
|
+
.grid
|
15
|
+
.cal-head-row
|
16
|
+
.day=t('.day.short.1')
|
17
|
+
.day=t('.day.short.2')
|
18
|
+
.day=t('.day.short.3')
|
19
|
+
.day=t('.day.short.4')
|
20
|
+
.day=t('.day.short.5')
|
21
|
+
.day.weekend=t('.day.short.6')
|
22
|
+
.day.weekend=t('.day.short.7')
|
23
|
+
- @cal_month.each_week do |week|
|
24
|
+
.cal-row
|
25
|
+
- week.each do |day, events|
|
26
|
+
- if @cal_month.to_date == Date.today.beginning_of_month
|
27
|
+
- past = Date.today.day > day.to_i
|
28
|
+
- else
|
29
|
+
- past = Date.today > @cal_month.to_date
|
30
|
+
|
31
|
+
- event_names = events.map {|event| truncate(event[:name], length: 34, omission: '...')}
|
32
|
+
- if event_names.length > 5
|
33
|
+
- event_names = event_names[0..3]
|
34
|
+
- event_names.push('<div class="text-center">...</div>')
|
35
|
+
%div{ class: "day #{"null" unless day} #{"circled" unless events.empty?} #{"past" if past && day}", data: { event_names: event_names } }="#{day || '0'}"
|
36
|
+
|
37
|
+
.block-right
|
38
|
+
.more-info
|
@@ -0,0 +1,22 @@
|
|
1
|
+
.pull-left.upcoming-events
|
2
|
+
.navigation
|
3
|
+
.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.glyphicon.glyphicon-chevron-left
|
7
|
+
%span.text= t(".day.#{@current_event[:start_datetime].wday}")
|
8
|
+
.block-right
|
9
|
+
- unless CalMonth.upcoming_events.last == @current_event
|
10
|
+
= link_to current_event_path(CalMonth.upcoming_events.index(@current_event) + 1, format: :js), class: 'navigation-right', remote: true do
|
11
|
+
%span.glyphicon.glyphicon-chevron-right
|
12
|
+
.date
|
13
|
+
.block-left
|
14
|
+
.number
|
15
|
+
%span.text=@current_event[:start_datetime].day
|
16
|
+
.block-right
|
17
|
+
.event-info
|
18
|
+
.name= truncate(@current_event[:name], length: 45, omission: '...')
|
19
|
+
.more-info
|
20
|
+
%span=". . ."
|
21
|
+
.time=pretty_from_to(@current_event)
|
22
|
+
|
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'
|
10
|
+
s.version = '0.0.2'
|
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'
|
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", "include CalMonthsHelper", after: "module ApplicationHelper\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
def copy_views
|
32
|
+
copy_file '../../../app/views/cal_months/_calendar.html.haml', 'app/views/cal_months/_calendar.html.haml'
|
33
|
+
copy_file '../../../app/views/cal_months/_month.html.haml', 'app/views/cal_months/_month.html.haml'
|
34
|
+
copy_file '../../../app/views/cal_months/_upcoming_events.html.haml', 'app/views/cal_months/_upcoming_events.html.haml'
|
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,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cal_months
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
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
|
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.haml
|
43
|
+
- app/views/cal_months/_month.html.haml
|
44
|
+
- app/views/cal_months/_upcoming_events.html.haml
|
45
|
+
- app/views/cal_months/show.js.erb
|
46
|
+
- app/views/cal_months/show_current_event.js.erb
|
47
|
+
- cal_months.gemspec
|
48
|
+
- config/locales/cal_months_cs.yml
|
49
|
+
- config/locales/cal_months_en.yml
|
50
|
+
- db/migrate/create_cal_events.rb
|
51
|
+
- db/migrate/create_cal_months.rb
|
52
|
+
- lib/cal_months.rb
|
53
|
+
- lib/generators/cal_months/install_generator.rb
|
54
|
+
homepage: https://github.com/jphager2/cal_months
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
metadata: {}
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options: []
|
60
|
+
require_paths:
|
61
|
+
- lib
|
62
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ">="
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
requirements: []
|
73
|
+
rubyforge_project:
|
74
|
+
rubygems_version: 2.2.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: icalendar integration
|
78
|
+
test_files: []
|