simple_calendar-timeslot 0.3.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/Gemfile.lock +3 -1
- data/README.md +55 -3
- data/app/assets/stylesheets/simple_calendar-timeslot.css +6 -0
- data/app/views/simple_calendar/timeslot/_timeslot_calendar.html.erb +2 -2
- data/lib/simple_calendar/timeslot/timeslot_calendar.rb +52 -45
- data/lib/simple_calendar/timeslot/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e642f680ea5441076624a829e2e672a1cbb57f8b2ffffcf161dd658ae8b5b17c
|
4
|
+
data.tar.gz: 39caf7b4c9a72da1e11e8b21c12fb2fd8c7928ef86d18a572afaa6a0d9709d0c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae67297856bc7d27e71ab6740c9b73b7e033d24a5cd7f3b5d9d3f4cc032fa0e7f36f1b5f63375529aa954af4f6a34be0385cbdf5d2d8abeabfe997aaff44bbf2
|
7
|
+
data.tar.gz: 05126f7fe63a2027f731f56138bffd965aebf46e0943da182b2d35cb337f6df860a0e097bc1293522ce4256706ae429fd944071aa0543516ed16641ca7ecba26
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.6.0] - 2021-11-15
|
4
|
+
### Added
|
5
|
+
- Added option horizontal_scroll_split to view helper, which defaults to false. This option affects
|
6
|
+
horizontal orientation only. If set to false, the
|
7
|
+
different days of the calendar scroll together horizontally, which is more consistent with the
|
8
|
+
behaviour of the vertical layout. If set to true, the days scroll independently.
|
9
|
+
|
10
|
+
## [0.5.1] - 2021-11-15
|
11
|
+
### Fixed
|
12
|
+
- Fixed reliance of calendar on legacy function to
|
13
|
+
calculate event height
|
14
|
+
|
15
|
+
## [0.5.0] - 2021-11-14
|
16
|
+
- Removed images for the README from the gem, sry :(
|
17
|
+
|
18
|
+
## [0.4.0] - 2021-11-14
|
19
|
+
### Added
|
20
|
+
- Added compatibilty with the attribute and end_attribute options in the view helper
|
21
|
+
- Added documentation to README
|
22
|
+
|
3
23
|
## [0.3.0] - 2021-11-14
|
4
24
|
### Fixed
|
5
25
|
- Fix issue with css styles when including style of this gem and simple_calendar
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
simple_calendar-timeslot (0.
|
4
|
+
simple_calendar-timeslot (0.6.0)
|
5
5
|
simple_calendar (~> 2.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -90,6 +90,8 @@ GEM
|
|
90
90
|
nokogiri (1.12.5)
|
91
91
|
mini_portile2 (~> 2.6.1)
|
92
92
|
racc (~> 1.4)
|
93
|
+
nokogiri (1.12.5-x86_64-darwin)
|
94
|
+
racc (~> 1.4)
|
93
95
|
parallel (1.21.0)
|
94
96
|
parser (3.0.2.0)
|
95
97
|
ast (~> 2.4.1)
|
data/README.md
CHANGED
@@ -2,10 +2,18 @@
|
|
2
2
|
|
3
3
|
This is an extension of the rubygem `simple_calendar` by Chris Oliver aka excid3. It allows
|
4
4
|
for simple calendar creation in a Ruby on Rails app with an timeslot representation of events
|
5
|
-
in a 24h day.
|
5
|
+
in a 24h day.
|
6
|
+
|
7
|
+
This helps to visually grasps the length of events and the time between them. In case of overlapping, the respective events are shown side-by-side. It is also possible to categorise events in buckets according to some function, then they will be shown next to one another in the 24h timeline.
|
8
|
+
|
6
9
|
Horizontal and vertical layout is selectable via options, just like many other ones.
|
7
10
|
|
8
|
-
|
11
|
+
Horizontal example
|
12
|
+

|
13
|
+
|
14
|
+
Vertical example
|
15
|
+

|
16
|
+
|
9
17
|
|
10
18
|
## Installation
|
11
19
|
|
@@ -23,12 +31,56 @@ Or install it yourself as:
|
|
23
31
|
|
24
32
|
$ gem install simple_calendar-timeslot
|
25
33
|
|
26
|
-
|
34
|
+
|
35
|
+
**Important** Then include the stylesheet in your rails app.
|
36
|
+
|
37
|
+
If you have an `application.css` file, include the following:
|
38
|
+
```ruby
|
39
|
+
*= require simple_calendar-timeslot
|
40
|
+
```
|
41
|
+
If you use an SCSS file (`application.scss`), add the following line instead:
|
42
|
+
```ruby
|
43
|
+
@import 'simple_calendar-timeslot';
|
44
|
+
```
|
27
45
|
|
28
46
|
## Usage
|
29
47
|
|
30
48
|
TODO: Write usage instructions here
|
31
49
|
|
50
|
+
Your model must implement a `start_time` and `end_time` function,
|
51
|
+
or you can specify alternatives as options to the call below
|
52
|
+
as `attribute: :my_start_time` and `end_attribute: :my_end_time`.
|
53
|
+
|
54
|
+
```erb
|
55
|
+
<%= timeslot_calendar(events: @events,
|
56
|
+
number_of_days: 2,
|
57
|
+
px_per_minute: 1.5,
|
58
|
+
orientation: :horizontal,
|
59
|
+
horizontal_height_px: 250,
|
60
|
+
# attribute: :my_start_time,
|
61
|
+
# display_grid: false,
|
62
|
+
# display_bucket_title: :event_type,
|
63
|
+
# bucket_title_size: 30,
|
64
|
+
# grid_width: "20px",
|
65
|
+
# split_by_type: :event_type
|
66
|
+
) do |event| %>
|
67
|
+
<div class="timeslot-event">
|
68
|
+
<%= event.title %>
|
69
|
+
</div>
|
70
|
+
<% end %>
|
71
|
+
|
72
|
+
```
|
73
|
+
|
74
|
+
Shortversion in the meantime:
|
75
|
+
- orientation (:vertical, :horizontal, default: :vertical)
|
76
|
+
- horizontal_height_px default: 300
|
77
|
+
- split_by_type (model function to call in case of bucketung f.ex.`:event_type`, default: false)
|
78
|
+
- px_per_minute default: 0.65
|
79
|
+
- display_bucket_title (model function to call in case of bucketung f.ex.`:event_type_name`, default: false)
|
80
|
+
- bucket_title_size default: 20
|
81
|
+
- grid_width default: 20px
|
82
|
+
- display_grid default: true
|
83
|
+
|
32
84
|
## Development
|
33
85
|
|
34
86
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -9,6 +9,10 @@
|
|
9
9
|
display: flex;
|
10
10
|
flex-direction: column;
|
11
11
|
}
|
12
|
+
.timeslot-calendar .days-wrapper-horizontal.scroll-link {
|
13
|
+
overflow-x: auto;
|
14
|
+
overflow-y: hidden;
|
15
|
+
}
|
12
16
|
.timeslot-calendar .day-wrapper {
|
13
17
|
flex: 1 1 0;
|
14
18
|
}
|
@@ -21,6 +25,8 @@
|
|
21
25
|
display: flex;
|
22
26
|
flex-direction: column;
|
23
27
|
position: relative;
|
28
|
+
}
|
29
|
+
.timeslot-calendar .day-content-horizontal.scroll-split {
|
24
30
|
overflow-x: auto;
|
25
31
|
overflow-y: hidden;
|
26
32
|
}
|
@@ -66,7 +66,7 @@
|
|
66
66
|
<% end %>
|
67
67
|
</div>
|
68
68
|
<% elsif calendar.orientation == :horizontal %>
|
69
|
-
<div class="days-wrapper-horizontal">
|
69
|
+
<div class="days-wrapper-horizontal <%= calendar.horizontal_scroll_split ? "" : "scroll-link" %>">
|
70
70
|
<% date_range.slice(0, 7).each do |day| %>
|
71
71
|
<div class="day-wrapper">
|
72
72
|
<div class="day-title-row">
|
@@ -78,7 +78,7 @@
|
|
78
78
|
</span>
|
79
79
|
</div>
|
80
80
|
<%= content_tag :div, class: calendar.td_classes_for(day) do %>
|
81
|
-
<div class="day-content-horizontal">
|
81
|
+
<div class="day-content-horizontal <%= calendar.horizontal_scroll_split ? "scroll-split" : "" %>">
|
82
82
|
<div class="day-content-horizontal-inner" style="width:<%=calendar.height%>px;height:<%=calendar.horizontal_height_px%>px">
|
83
83
|
<% if calendar.display_grid %>
|
84
84
|
<div class="hour-indicator-col-horizontal" style="z-index:-10;">
|
@@ -1,53 +1,31 @@
|
|
1
1
|
require "simple_calendar"
|
2
2
|
|
3
3
|
module SimpleCalendar
|
4
|
-
module Timeslot
|
4
|
+
module Timeslot
|
5
5
|
class TimeslotCalendar < SimpleCalendar::Calendar
|
6
6
|
MINUTE_HEIGHT_PX = 0.65
|
7
7
|
FIRST_HOUR_SLOT = 0
|
8
|
-
|
9
|
-
def height
|
10
|
-
h = (24 - TimeslotCalendar::FIRST_HOUR_SLOT) * 60 * px_per_minute
|
11
|
-
h = h+bucket_title_size if display_bucket_title
|
12
|
-
h
|
13
|
-
end
|
14
|
-
|
15
|
-
def event_height(event, day)
|
16
|
-
minutes = if event.start_time.to_date != day
|
17
|
-
(event.end_time - event.end_time.midnight)/60
|
18
|
-
elsif event.start_time.to_date < event.end_time.to_date
|
19
|
-
(event.end_time.midnight - 60 - event.start_time)/60
|
20
|
-
else
|
21
|
-
event.duration
|
22
|
-
end
|
23
|
-
minutes * px_per_minute
|
24
|
-
end
|
25
|
-
|
26
|
-
def event_top_distance(event, day)
|
27
|
-
return 0 if event.start_time.to_date != day
|
28
|
-
(event.start_time.hour - TimeslotCalendar::FIRST_HOUR_SLOT) * 60 * px_per_minute + event.start_time.min * px_per_minute
|
29
|
-
end
|
30
|
-
|
8
|
+
|
31
9
|
def orientation
|
32
10
|
@options.fetch(:orientation, :vertical)
|
33
11
|
end
|
34
|
-
|
12
|
+
|
35
13
|
def horizontal_height_px
|
36
14
|
@options.fetch(:horizontal_height_px, 300)
|
37
15
|
end
|
38
|
-
|
16
|
+
|
39
17
|
def split_by_type
|
40
18
|
@options.fetch(:split_by_type, false)
|
41
19
|
end
|
42
|
-
|
20
|
+
|
43
21
|
def px_per_minute
|
44
22
|
@options.fetch(:px_per_minute, TimeslotCalendar::MINUTE_HEIGHT_PX)
|
45
23
|
end
|
46
|
-
|
24
|
+
|
47
25
|
def display_bucket_title
|
48
26
|
@options.fetch(:display_bucket_title, false)
|
49
27
|
end
|
50
|
-
|
28
|
+
|
51
29
|
def bucket_title_size
|
52
30
|
if display_bucket_title
|
53
31
|
@options.fetch(:bucket_title_size, 20)
|
@@ -55,11 +33,11 @@ module SimpleCalendar
|
|
55
33
|
0
|
56
34
|
end
|
57
35
|
end
|
58
|
-
|
36
|
+
|
59
37
|
def grid_top_offset(hour)
|
60
38
|
4.16666667 * hour
|
61
39
|
end
|
62
|
-
|
40
|
+
|
63
41
|
def grid_width
|
64
42
|
if display_grid
|
65
43
|
@options.fetch(:grid_width, "20px")
|
@@ -67,11 +45,39 @@ module SimpleCalendar
|
|
67
45
|
0
|
68
46
|
end
|
69
47
|
end
|
70
|
-
|
48
|
+
|
71
49
|
def display_grid
|
72
50
|
@options.fetch(:display_grid, true)
|
73
51
|
end
|
74
|
-
|
52
|
+
|
53
|
+
def horizontal_scroll_split
|
54
|
+
@options.fetch(:horizontal_scroll_split, false)
|
55
|
+
end
|
56
|
+
|
57
|
+
def height
|
58
|
+
#h = (24 - TimeslotCalendar::FIRST_HOUR_SLOT) * 60 * px_per_minute
|
59
|
+
h = 24 * 60 * px_per_minute
|
60
|
+
h = h+bucket_title_size if display_bucket_title
|
61
|
+
h
|
62
|
+
end
|
63
|
+
|
64
|
+
def event_height(event, day)
|
65
|
+
minutes = if event.send(attribute).to_date != day
|
66
|
+
(event.send(end_attribute) - event.send(end_attribute).midnight)/60
|
67
|
+
elsif event.send(attribute).to_date < event.send(end_attribute).to_date
|
68
|
+
(event.send(end_attribute).midnight - 60 - event.send(attribute))/60
|
69
|
+
else
|
70
|
+
(event.send(end_attribute) - event.send(attribute))/60
|
71
|
+
end
|
72
|
+
minutes * px_per_minute
|
73
|
+
end
|
74
|
+
|
75
|
+
def event_top_distance(event, day)
|
76
|
+
return 0 if event.send(attribute).to_date != day
|
77
|
+
#(event.send(attribute).hour - TimeslotCalendar::FIRST_HOUR_SLOT) * 60 * px_per_minute + event.send(attribute).min * px_per_minute
|
78
|
+
event.send(attribute).hour * 60 * px_per_minute + event.send(attribute).min * px_per_minute
|
79
|
+
end
|
80
|
+
|
75
81
|
def split_into_buckets(events)
|
76
82
|
if split_by_type
|
77
83
|
events.group_by{|e| e.send split_by_type}.values
|
@@ -79,33 +85,34 @@ module SimpleCalendar
|
|
79
85
|
[events]
|
80
86
|
end
|
81
87
|
end
|
82
|
-
|
88
|
+
|
83
89
|
def slot_events(events, day)
|
84
90
|
r = {}
|
85
91
|
events.each do |event|
|
86
92
|
r[event] = [0, 0, event_height(event, day), event_top_distance(event, day)]
|
87
93
|
end
|
88
|
-
#
|
94
|
+
# Credit: https://stackoverflow.com/questions/11311410/visualization-of-calendar-events-algorithm-to-layout-events-with-maximum-width
|
95
|
+
# Author: Markus Jarderot (https://stackoverflow.com/users/22364/markus-jarderot)
|
89
96
|
columns = [[]]
|
90
97
|
last_event_ending = nil
|
91
98
|
events.each do |event|
|
92
|
-
if
|
99
|
+
if !last_event_ending.nil? && event.send(attribute) > last_event_ending
|
93
100
|
pack_events(r, columns)
|
94
|
-
|
101
|
+
columns = [[]]
|
95
102
|
last_event_ending = nil
|
96
103
|
end
|
97
104
|
placed = false
|
98
105
|
columns.each do |col|
|
99
|
-
|
106
|
+
unless events_collide(r, col.last, event)
|
100
107
|
col << event
|
101
108
|
placed = true
|
102
109
|
break
|
103
110
|
end
|
104
111
|
end
|
105
|
-
|
112
|
+
unless placed
|
106
113
|
columns << [event]
|
107
114
|
end
|
108
|
-
event_end_time = event.
|
115
|
+
event_end_time = event.send(end_attribute)
|
109
116
|
if last_event_ending.nil? || event_end_time > last_event_ending
|
110
117
|
last_event_ending = event_end_time
|
111
118
|
end
|
@@ -115,7 +122,9 @@ module SimpleCalendar
|
|
115
122
|
end
|
116
123
|
r
|
117
124
|
end
|
118
|
-
|
125
|
+
|
126
|
+
private
|
127
|
+
|
119
128
|
def pack_events(r, columns)
|
120
129
|
num_columns = columns.size.to_f
|
121
130
|
columns.each_with_index do |col, iter_col|
|
@@ -126,14 +135,14 @@ module SimpleCalendar
|
|
126
135
|
end
|
127
136
|
end
|
128
137
|
end
|
129
|
-
|
138
|
+
|
130
139
|
def events_collide(r, event1, event2)
|
131
140
|
return false if event1.nil? || event2.nil?
|
132
141
|
event1_bottom = r[event1][3] + r[event1][2]
|
133
142
|
event2_bottom = r[event2][3] + r[event2][2]
|
134
143
|
event1_bottom > r[event2][3] && r[event1][3] < event2_bottom
|
135
144
|
end
|
136
|
-
|
145
|
+
|
137
146
|
def expand_event(r, event, iter_col, columns)
|
138
147
|
col_span = 1
|
139
148
|
columns.each_with_index do |column, index|
|
@@ -146,8 +155,6 @@ module SimpleCalendar
|
|
146
155
|
end
|
147
156
|
col_span
|
148
157
|
end
|
149
|
-
|
150
|
-
private
|
151
158
|
end
|
152
159
|
end
|
153
160
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simple_calendar-timeslot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kim Laplume
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-11-
|
11
|
+
date: 2021-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: simple_calendar
|