simple_calendar-timeslot 0.5.1 → 0.90.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 +34 -0
- data/Gemfile.lock +2 -2
- data/README.md +118 -31
- data/app/assets/stylesheets/simple_calendar-timeslot.css +92 -61
- data/app/views/simple_calendar/timeslot/_timeslot_calendar.html.erb +150 -111
- data/lib/simple_calendar/timeslot/timeslot_calendar.rb +56 -28
- 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: c69834a6c0289a7d3679c45911fd5feb363201a4ae250efe96ec5b9b3e610bdf
|
4
|
+
data.tar.gz: 382ed150f3b8cc79e6e8fabd9e2280c320f4963babbf287a9df7a32526c24262
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 03410faac3f8c01a01505583b0cb7676496181f8eda96b8687774dcaaa32006b60d0b760f45f88ba9d20efd3b67545f8790b71ed28d3e8d3d064d3770cf9b778
|
7
|
+
data.tar.gz: b901a9dcd48841e85687a528892d9f8cf79c509e7fbaf7d3f22c59d00f7d489eb0d22b30e5a520b3d73497cfd91b1a63e4160aadda6f375f4f8ac72196215cd4
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [0.90.0] - 2021-11-17
|
4
|
+
### Changed
|
5
|
+
- **Mayor changes** to complete html layout
|
6
|
+
- **Option arguments changed**:
|
7
|
+
- `orientation` has been removed for `layout`
|
8
|
+
- `split_by_type` has been renamed to `bucket_by`
|
9
|
+
- `horizontal_height_px` has been renamed to `day_height_px`
|
10
|
+
- `horizontal_scroll_split` is now possible with a separate layout
|
11
|
+
- `bucket_title_size` has been removed, the size is determined by the size of the DOM-elements
|
12
|
+
### Added
|
13
|
+
- New Layout `horizontal_date_on_top`
|
14
|
+
- New option `body_size_px` that limits the calendar body height if set and makes it scrollable.
|
15
|
+
- New option `date_format_string`, that applies the format string before displaying the date above each day
|
16
|
+
- New option `date_header_format_string`, that applies the format string before displaying the `start_date` url parameter in the heading of the calendar (between previos and next links)
|
17
|
+
|
18
|
+
|
19
|
+
## [0.8.0] - 2021-11-15
|
20
|
+
### Changed
|
21
|
+
- Shuffle html layout around a bit for easier css styling like sticky
|
22
|
+
|
23
|
+
## [0.7.0] - 2021-11-15
|
24
|
+
### Added
|
25
|
+
- new option to display a current time indicator line (based on Time.zone.now), that is invisible unless styled, the css-class is
|
26
|
+
`current_time_indicator`
|
27
|
+
### Fixed
|
28
|
+
- minor z-index inconsistencies for event rendering
|
29
|
+
|
30
|
+
## [0.6.0] - 2021-11-15
|
31
|
+
### Added
|
32
|
+
- Added option horizontal_scroll_split to view helper, which defaults to false. This option affects
|
33
|
+
horizontal orientation only. If set to false, the
|
34
|
+
different days of the calendar scroll together horizontally, which is more consistent with the
|
35
|
+
behaviour of the vertical layout. If set to true, the days scroll independently.
|
36
|
+
|
3
37
|
## [0.5.1] - 2021-11-15
|
4
38
|
### Fixed
|
5
39
|
- Fixed reliance of calendar on legacy function to
|
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.90.0)
|
5
5
|
simple_calendar (~> 2.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -159,7 +159,7 @@ GEM
|
|
159
159
|
sprockets (4.0.2)
|
160
160
|
concurrent-ruby (~> 1.0)
|
161
161
|
rack (> 1, < 3)
|
162
|
-
sprockets-rails (3.
|
162
|
+
sprockets-rails (3.4.0)
|
163
163
|
actionpack (>= 5.2)
|
164
164
|
activesupport (>= 5.2)
|
165
165
|
sprockets (>= 3.0.0)
|
data/README.md
CHANGED
@@ -1,18 +1,96 @@
|
|
1
1
|
# SimpleCalendar::Timeslot
|
2
2
|
|
3
|
-
This is an extension of the rubygem `simple_calendar` by Chris Oliver aka excid3. It allows
|
3
|
+
This gem 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
5
|
in a 24h day.
|
6
6
|
|
7
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
8
|
|
9
|
-
|
9
|
+
Different layouts are selectable via options, just like many other ones.
|
10
|
+
|
11
|
+
All layouts support the following options:
|
12
|
+
- event rendering can be completely controlled, the calendar provides a wrapping div around with the correct dimensions at the right place
|
13
|
+
- responsive design which can (and should) be styled to your liking
|
14
|
+
- turn hour grid on/off
|
15
|
+
- set the width of the grid in `px` or `%`
|
16
|
+
- adjust the pixel-size corresponding to one minute
|
17
|
+
- limit the overall size of day, making part of it scroll
|
18
|
+
- for horizontal layouts: determine the breadth of one day
|
19
|
+
- "bucketing" of events by same value, any event function can be provided (see colums "Me" and "Mom" in image below and symbol `:event_type_name` in code)
|
20
|
+
- displaying of bucket label by provided function on event
|
21
|
+
- formating of date above day
|
22
|
+
- formating of date in heading
|
23
|
+
- turn current time indicator on/off, this is an invisible css-stylable div with class `tscal-current-time-indicator` (can be seen in examples below)
|
24
|
+
- by default, the 24h-grid hides any overflow which is recommended not to overwrite, otherwise there might be 2-directional scrolling
|
25
|
+
|
26
|
+
**Note:** events are styled in the examples with the following minimalistic styles to show their outline. This is not the case when the gem is used out of the box, because it would make the style hard to overwrite because of css-predence rules.
|
27
|
+
```css
|
28
|
+
.event-wrapper {
|
29
|
+
border: solid 1px black;
|
30
|
+
}
|
31
|
+
```
|
32
|
+
|
33
|
+
### Vertical layout
|
34
|
+
This layout grows vertically, and can be limited in height by option `body_size_px` and will then scroll.
|
35
|
+
The horizontal direction is responsive.
|
36
|
+

|
37
|
+
|
38
|
+
Code
|
39
|
+
```erb
|
40
|
+
<%= timeslot_calendar(events: @events,
|
41
|
+
layout: :vertical,
|
42
|
+
number_of_days: 2,
|
43
|
+
px_per_minute: 1.3,
|
44
|
+
#display_grid: true,
|
45
|
+
grid_width: "30px",
|
46
|
+
body_size_px: 600,
|
47
|
+
bucket_by: :event_type,
|
48
|
+
date_format_string: "%d.%m.%Y",
|
49
|
+
#date_heading_format_string: "%d.%m.%Y",
|
50
|
+
display_bucket_title: :event_type_name,
|
51
|
+
display_current_time_indicator: true
|
52
|
+
) do |event| %>
|
53
|
+
<div class="timeslot-event">
|
54
|
+
<%= event.title %>
|
55
|
+
</div>
|
56
|
+
<% end %>
|
57
|
+
```
|
58
|
+
|
59
|
+
### Horizontal layout
|
60
|
+
This layout is basicall the vertical one toppled over. The days grows horizontally, if it has not enough space (which is likely this direction) the day will scroll with the day and bucket headings staying fixed. Multiple days scroll together. The height per day can be adjusted as option, the events scale responsively.
|
61
|
+
|
62
|
+
One advantage over vertical layout is that the horizontal scrolling works better for mobile devices, combined with vertical scroll to scroll further down.
|
63
|
+

|
64
|
+
|
65
|
+
Code:
|
66
|
+
```erb
|
67
|
+
<%= timeslot_calendar(events: @events,
|
68
|
+
layout: :horizontal,
|
69
|
+
day_height_px: 100,
|
70
|
+
#...
|
71
|
+
) do |event| %>
|
72
|
+
<div class="timeslot-event">
|
73
|
+
<%= event.title %>
|
74
|
+
</div>
|
75
|
+
<% end %>
|
76
|
+
```
|
77
|
+
|
78
|
+
### Horizontal - Date on top
|
79
|
+
My personal favorite: like horizontal layout, but the date is moved above the scrolling day, freeing up space. Forcibly, the scroll between days is separated (this could be restored with a javascript scroll-lock).
|
80
|
+

|
10
81
|
|
11
|
-
|
12
|
-
|
82
|
+
Code:
|
83
|
+
```erb
|
84
|
+
<%= timeslot_calendar(events: @events,
|
85
|
+
layout: :horizontal_date_on_top,
|
86
|
+
#...
|
87
|
+
) do |event| %>
|
88
|
+
<div class="timeslot-event">
|
89
|
+
<%= event.title %>
|
90
|
+
</div>
|
91
|
+
<% end %>
|
92
|
+
```
|
13
93
|
|
14
|
-
Vertical example
|
15
|
-

|
16
94
|
|
17
95
|
|
18
96
|
## Installation
|
@@ -34,7 +112,7 @@ Or install it yourself as:
|
|
34
112
|
|
35
113
|
**Important** Then include the stylesheet in your rails app.
|
36
114
|
|
37
|
-
If you have an `application.css` file, include the following:
|
115
|
+
If you have an `application.css` file, include the following (before `*= require_tree .` and `*= require_self` if you want to overwrite styles with equal specificity):
|
38
116
|
```ruby
|
39
117
|
*= require simple_calendar-timeslot
|
40
118
|
```
|
@@ -45,41 +123,49 @@ If you use an SCSS file (`application.scss`), add the following line instead:
|
|
45
123
|
|
46
124
|
## Usage
|
47
125
|
|
48
|
-
|
126
|
+
Include a code snipped like the one below anywhere in your `.html.erb` file, set `@events` in your calling controller to be a collection of your model object to be displayed. You can refer to the documentation on [simple_calendar/Rendering_Events](https://github.com/excid3/simple_calendar#rendering-events) (thats from the gem on which this one is built on top of), the complete paragraph applies to this gem as well.
|
49
127
|
|
50
|
-
|
51
|
-
|
52
|
-
|
128
|
+
All options are optional, below you see all possible values commented out with their default value behind the colon and a short description afterwards.
|
129
|
+
|
130
|
+
Your model must implement a `start_time` and `end_time` function that returns a datetime, or you can specify alternatives as options to the call below
|
131
|
+
as `attribute: :my_start_time` and `end_attribute: :my_end_time` (without the `#` of course).
|
53
132
|
|
54
133
|
```erb
|
55
134
|
<%= timeslot_calendar(events: @events,
|
56
|
-
number_of_days:
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
#
|
61
|
-
#
|
62
|
-
#
|
63
|
-
#
|
64
|
-
#
|
65
|
-
#
|
135
|
+
# number_of_days: 4,
|
136
|
+
# layout: :vertical, # possible values: :vertical, :horizontal, :horizontal_date_on_top
|
137
|
+
# px_per_minute: 0.65, # define size of one minute
|
138
|
+
# display_grid: true,
|
139
|
+
# grid_width: "20px", # can be any valid css size px, %, em
|
140
|
+
# display_current_time_indicator: false, # draw a line to show the current time, stylable class: tscal-current-time-indicator
|
141
|
+
# body_size_px: false, # only vertical layout: set integer if your want to limit the height
|
142
|
+
# day_height_px: 200, # only horizontal and horizontal_date_on_top layout: set height for a day
|
143
|
+
# bucket_by: false, # give model function as symbol if you want to bucket events by this function (f.ex. :event_type)
|
144
|
+
# display_bucket_title: false,
|
145
|
+
# date_format_string: false,
|
146
|
+
# date_heading_format_string: "%B %Y",
|
147
|
+
# attribute: :my_start_time, # provide alternative to :start_time model function
|
148
|
+
# end_attribute: :my_end_time, # provide alternative to :end_time model function
|
66
149
|
) do |event| %>
|
67
150
|
<div class="timeslot-event">
|
68
151
|
<%= event.title %>
|
69
152
|
</div>
|
70
153
|
<% end %>
|
71
|
-
|
72
154
|
```
|
73
155
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
-
|
79
|
-
-
|
80
|
-
-
|
81
|
-
|
82
|
-
-
|
156
|
+
## Customization
|
157
|
+
|
158
|
+
Style away as much as you want. This gem is mainly concerned to move the right pieces to the right place, how they look is up to you. Have a look
|
159
|
+
at the generated HTML or start with these classes
|
160
|
+
- `.tscal-event-wrapper`
|
161
|
+
- `.tscal-current-time-indicator`
|
162
|
+
- `.tscal-hour-cell`
|
163
|
+
|
164
|
+
Some words of caution: overflow is hidden for the scrolling part of the calendar, that is a div with class `.buckets-wrapper`. If you see your box-shadows clipped, that is probably causing it. You can of course overwrite clipping (with `.timeslot-calendar .buckets-wrapper { overflow: visible; }`), but then I recommend setting `overflow: hidden;` on `.tscal-event-wrapper`, otherwise you risk to see scrolling where you don't want to, when to content of the event is overflowing.
|
165
|
+
|
166
|
+
Here is an example with some basic styling
|
167
|
+
|
168
|
+

|
83
169
|
|
84
170
|
## Development
|
85
171
|
|
@@ -89,4 +175,5 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
89
175
|
|
90
176
|
## Contributing
|
91
177
|
|
178
|
+
I could use some help with the test suite.
|
92
179
|
Bug reports and pull requests are welcome on GitHub at https://github.com/1klap/simple_calendar-timeslot.
|
@@ -1,99 +1,130 @@
|
|
1
|
+
/******* Default styling, overwrite me! *******/
|
2
|
+
.tscal-event-wrapper {
|
3
|
+
border: solid 1px black;
|
4
|
+
/*
|
5
|
+
overflow: hidden;
|
6
|
+
background-color: #fff;
|
7
|
+
z-index: 5;
|
8
|
+
*/
|
9
|
+
}
|
10
|
+
.tscal-current-time-indicator {
|
11
|
+
border: solid 1px rgba(219, 187, 187, 0.5);;
|
12
|
+
}
|
13
|
+
.tscal-hour-cell {
|
14
|
+
border-style: solid;
|
15
|
+
border-color: rgba(229, 231, 235, 0.5);
|
16
|
+
}
|
17
|
+
.tscal-vertical {
|
18
|
+
border-width: 2px 0 0;
|
19
|
+
}
|
20
|
+
.tscal-horizontal {
|
21
|
+
border-width: 0 0 0 2px;
|
22
|
+
}
|
23
|
+
/******* Layout: Base (==Vertical) *******/
|
1
24
|
.timeslot-calendar div {
|
2
25
|
box-sizing: border-box;
|
3
26
|
}
|
4
|
-
.timeslot-calendar .
|
27
|
+
.timeslot-calendar .titles-heading {
|
5
28
|
display: flex;
|
6
29
|
flex-direction: row;
|
7
30
|
}
|
8
|
-
.timeslot-calendar .
|
31
|
+
.timeslot-calendar .title-heading {
|
32
|
+
flex: 1;
|
33
|
+
}
|
34
|
+
.timeslot-calendar .buckets-heading {
|
9
35
|
display: flex;
|
10
|
-
flex-direction:
|
36
|
+
flex-direction: row;
|
11
37
|
}
|
12
|
-
.timeslot-calendar .
|
13
|
-
flex: 1
|
38
|
+
.timeslot-calendar .bucket-heading {
|
39
|
+
flex: 1;
|
14
40
|
}
|
15
|
-
.timeslot-calendar .
|
41
|
+
.timeslot-calendar .calendar-body {
|
16
42
|
display: flex;
|
17
|
-
flex-direction:
|
43
|
+
flex-direction: row;
|
44
|
+
overflow-y: scroll;
|
45
|
+
}
|
46
|
+
.timeslot-calendar .day-wrapper {
|
47
|
+
flex: 1;
|
48
|
+
}
|
49
|
+
.timeslot-calendar .day-body {
|
18
50
|
position: relative;
|
19
51
|
}
|
20
|
-
.timeslot-calendar .
|
52
|
+
.timeslot-calendar .hour-indicator-wrapper {
|
21
53
|
display: flex;
|
22
54
|
flex-direction: column;
|
55
|
+
height: 100%;
|
23
56
|
position: relative;
|
24
|
-
overflow-x: auto;
|
25
|
-
overflow-y: hidden;
|
26
57
|
}
|
27
|
-
.timeslot-calendar .
|
28
|
-
|
58
|
+
.timeslot-calendar .hour-indicator-cell {
|
59
|
+
min-height: 0;
|
60
|
+
flex: 1;
|
29
61
|
}
|
30
|
-
|
31
|
-
|
32
|
-
display: flex;
|
33
|
-
flex: 1 1 0;
|
34
|
-
flex-direction: column;
|
35
|
-
z-index: 0;
|
62
|
+
.timeslot-calendar .tscal-current-time-indicator {
|
63
|
+
position: absolute;
|
36
64
|
}
|
37
|
-
.timeslot-calendar .
|
65
|
+
.timeslot-calendar .buckets-wrapper {
|
66
|
+
position: absolute;
|
38
67
|
display: flex;
|
39
|
-
flex: 1 1 0;
|
40
68
|
flex-direction: row;
|
41
|
-
|
42
|
-
z-index: 0;
|
69
|
+
overflow: hidden;
|
43
70
|
}
|
44
|
-
.timeslot-calendar .
|
45
|
-
|
46
|
-
|
47
|
-
border-width: 2px 0 0;
|
48
|
-
border-color: rgba(229, 231, 235, 0.5);
|
49
|
-
box-sizing: border-box;
|
50
|
-
}
|
51
|
-
.timeslot-calendar .hour-indicator-horizontal {
|
52
|
-
border-style: solid;
|
53
|
-
flex: 1 1 0;
|
54
|
-
border-width: 0 0 0 2px;
|
55
|
-
border-color: rgba(229, 231, 235, 0.5);
|
56
|
-
box-sizing: border-box;
|
71
|
+
.timeslot-calendar .bucket {
|
72
|
+
flex: 1;
|
73
|
+
position: relative;
|
57
74
|
}
|
58
|
-
.timeslot-calendar .
|
75
|
+
.timeslot-calendar .event-wrapper {
|
59
76
|
position: absolute;
|
60
|
-
|
61
77
|
}
|
62
|
-
|
78
|
+
/******* Layout: Vertical specific *******/
|
79
|
+
.timeslot-calendar .orientation-wrapper.vertical .hour-indicator {
|
80
|
+
text-align: center;
|
81
|
+
}
|
82
|
+
/******* Layout: Horizontal *******/
|
83
|
+
.timeslot-calendar .orientation-wrapper.horizontal {
|
63
84
|
display: flex;
|
64
85
|
flex-direction: row;
|
65
86
|
}
|
66
|
-
.timeslot-calendar .
|
67
|
-
|
87
|
+
.timeslot-calendar .orientation-wrapper.horizontal .titles-heading {
|
88
|
+
flex-direction: column;
|
89
|
+
}
|
90
|
+
.timeslot-calendar .orientation-wrapper.horizontal .title-heading {
|
91
|
+
flex: none;
|
68
92
|
display: flex;
|
93
|
+
flex-direction: row;
|
94
|
+
}
|
95
|
+
.timeslot-calendar .orientation-wrapper.horizontal .day-heading {
|
96
|
+
flex: 1;
|
97
|
+
}
|
98
|
+
.timeslot-calendar .orientation-wrapper.horizontal .buckets-heading {
|
69
99
|
flex-direction: column;
|
70
100
|
}
|
71
|
-
.timeslot-calendar .
|
72
|
-
flex: 1
|
101
|
+
.timeslot-calendar .orientation-wrapper.horizontal .calendar-body {
|
102
|
+
flex: 1;
|
103
|
+
flex-direction: column;
|
104
|
+
overflow-x: scroll;
|
73
105
|
}
|
74
|
-
.timeslot-calendar .
|
75
|
-
flex:
|
106
|
+
.timeslot-calendar .orientation-wrapper.horizontal .buckets-wrapper {
|
107
|
+
flex-direction: column;
|
108
|
+
}
|
109
|
+
.timeslot-calendar .orientation-wrapper.horizontal .hour-indicator-wrapper {
|
110
|
+
flex-direction: row;
|
111
|
+
}
|
112
|
+
/******* Layout: Horizontal - Date On Top *******/
|
113
|
+
.timeslot-calendar .orientation-wrapper.horizontal_date_on_top .body-wrapper {
|
76
114
|
display: flex;
|
77
115
|
flex-direction: row;
|
78
116
|
}
|
79
|
-
.timeslot-calendar .
|
80
|
-
|
117
|
+
.timeslot-calendar .orientation-wrapper.horizontal_date_on_top .buckets-heading {
|
118
|
+
flex-direction: column;
|
81
119
|
}
|
82
|
-
.timeslot-calendar .
|
83
|
-
|
120
|
+
.timeslot-calendar .orientation-wrapper.horizontal_date_on_top .calendar-body {
|
121
|
+
flex: 1;
|
122
|
+
flex-direction: column;
|
123
|
+
overflow-x: scroll;
|
84
124
|
}
|
85
|
-
.timeslot-calendar .
|
86
|
-
|
87
|
-
z-index: 1;
|
88
|
-
box-sizing: border-box;
|
125
|
+
.timeslot-calendar .orientation-wrapper.horizontal_date_on_top .buckets-wrapper {
|
126
|
+
flex-direction: column;
|
89
127
|
}
|
90
|
-
|
91
|
-
|
92
|
-
width: 100%;
|
93
|
-
height: 100%;
|
94
|
-
border-width: 2px;
|
95
|
-
border-style: solid;
|
96
|
-
border-color: rgba(0, 0, 0, 0.5);
|
97
|
-
border-radius: 0.25rem;
|
98
|
-
background-color: white;
|
128
|
+
.timeslot-calendar .orientation-wrapper.horizontal_date_on_top .hour-indicator-wrapper {
|
129
|
+
flex-direction: row;
|
99
130
|
}
|
@@ -1,139 +1,178 @@
|
|
1
1
|
<div class="timeslot-calendar">
|
2
2
|
<div class="calendar-heading">
|
3
3
|
<%= link_to t('simple_calendar.previous', default: 'Previous'), calendar.url_for_previous_view %>
|
4
|
-
<span class="calendar-title"
|
4
|
+
<span class="calendar-title">
|
5
|
+
<%= start_date.strftime(calendar.date_heading_format_string) %>
|
6
|
+
</span>
|
5
7
|
<%= link_to t('simple_calendar.next', default: 'Next'), calendar.url_for_next_view %>
|
6
8
|
</div>
|
7
|
-
|
8
|
-
|
9
|
-
<div class="
|
10
|
-
|
11
|
-
|
12
|
-
|
9
|
+
<% if calendar.layout == :vertical || calendar.layout == :horizontal %>
|
10
|
+
<div class="orientation-wrapper <%=calendar.layout%>">
|
11
|
+
<div class="titles-heading">
|
12
|
+
<% event_map = date_range.map { |day| calendar.split_into_buckets(sorted_events.fetch(day, [])) } %>
|
13
|
+
<% date_range.each_with_index do |day, index| %>
|
14
|
+
<div class="title-heading <%=calendar.td_classes_for(day).join(' ')%>" style="<%=calendar.day_height_style%>">
|
15
|
+
<div class="day-heading">
|
16
|
+
<div class="day-heading-inner">
|
13
17
|
<span class="day-weekday">
|
14
18
|
<%= t('date.abbr_day_names')[day.wday] %>
|
15
19
|
</span>
|
16
20
|
<span class="day-date">
|
17
|
-
<%= day %>
|
21
|
+
<%= calendar.date_format_string ? day.strftime(calendar.date_format_string) : day %>
|
18
22
|
</span>
|
19
23
|
</div>
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
</div>
|
25
|
+
<% if calendar.display_bucket_title %>
|
26
|
+
<div class="buckets-heading">
|
27
|
+
<% if calendar.layout == :vertical %>
|
28
|
+
<div style="width:<%=calendar.grid_width%>"></div>
|
29
|
+
<% else %>
|
30
|
+
<div style="height:<%=calendar.grid_width%>"></div>
|
31
|
+
<% end %>
|
32
|
+
<% event_map[index].each do |bucket| %>
|
33
|
+
<div class="bucket-heading">
|
34
|
+
<%= bucket&.first&.send calendar.display_bucket_title %>
|
35
|
+
</div>
|
36
|
+
<% end %>
|
37
|
+
</div>
|
38
|
+
<% end %>
|
39
|
+
</div>
|
40
|
+
<% end %>
|
41
|
+
</div>
|
42
|
+
<div class="calendar-body" style="<%=calendar.body_style%>" >
|
43
|
+
<% event_map.each_with_index do |buckets, index| %>
|
44
|
+
<div class="day-wrapper">
|
45
|
+
<% if calendar.layout == :vertical %>
|
46
|
+
<div class="day-body <%=calendar.td_classes_for(date_range[index]).join(' ')%>" style="height:<%=calendar.day_size%>px">
|
47
|
+
<% else %>
|
48
|
+
<div class="day-body <%=calendar.td_classes_for(date_range[index]).join(' ')%>" style="width:<%=calendar.day_size%>px;height:<%=calendar.day_height_px%>px">
|
49
|
+
<% end %>
|
50
|
+
<% if calendar.display_grid %>
|
51
|
+
<div class="hour-indicator-wrapper">
|
52
|
+
<% (0..23).each do |hour| %>
|
53
|
+
<% if calendar.layout == :vertical %>
|
54
|
+
<div class="hour-indicator-cell tscal-vertical tscal-hour-cell" id="hour-<%=hour %>">
|
55
|
+
<div class="hour-indicator" style="width:<%=calendar.grid_width%>">
|
56
|
+
<% else %>
|
57
|
+
<div class="hour-indicator-cell tscal-horizontal tscal-hour-cell" id="hour-<%=hour %>">
|
58
|
+
<div class="hour-indicator" style="height:<%=calendar.grid_width%>">
|
59
|
+
<% end %>
|
60
|
+
<%=hour%>
|
61
|
+
</div>
|
62
|
+
</div>
|
63
|
+
<% end %>
|
64
|
+
</div>
|
65
|
+
<% end %>
|
66
|
+
<% if calendar.display_current_time_indicator %>
|
67
|
+
<% if calendar.layout == :vertical %>
|
68
|
+
<div class="tscal-current-time-indicator" style="top:<%=calendar.current_time_offset %>px;left:0;right:0;height:0;"></div>
|
69
|
+
<% else %>
|
70
|
+
<div class="tscal-current-time-indicator" style="left:<%=calendar.current_time_offset %>px;top:0;bottom:0;width:0;"></div>
|
71
|
+
<% end %>
|
72
|
+
<% end %>
|
73
|
+
<% if calendar.layout == :vertical %>
|
74
|
+
<div class="buckets-wrapper" style="left:<%=calendar.grid_width%>;right:0;top:0;bottom:0;">
|
75
|
+
<% else %>
|
76
|
+
<div class="buckets-wrapper" style="top:<%=calendar.grid_width%>;right:0;left:0;bottom:0;">
|
77
|
+
<% end %>
|
78
|
+
<% buckets.each do |bucket| %>
|
79
|
+
<div class="bucket">
|
80
|
+
<% events_size = calendar.slot_events(bucket, date_range[index]) %>
|
81
|
+
<% bucket.each do |event| %>
|
82
|
+
<% if calendar.layout == :vertical %>
|
83
|
+
<div class="event-wrapper tscal-event-wrapper" style="width:<%=events_size[event][0]%>%;top:<%=events_size[event][3]%>px;left:<%=events_size[event][1]%>%;height:<%=events_size[event][2]%>px">
|
84
|
+
<% else %>
|
85
|
+
<div class="event-wrapper tscal-event-wrapper" style="height:<%=events_size[event][0]%>%;left:<%=events_size[event][3]%>px;top:<%=events_size[event][1]%>%;width:<%=events_size[event][2]%>px">
|
33
86
|
<% end %>
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
<div class="bucket-wrapper">
|
40
|
-
<div class="bucket-vertical">
|
41
|
-
<% if calendar.display_bucket_title %>
|
42
|
-
<div class="bucket-title" style="height:<%=calendar.bucket_title_size%>px">
|
43
|
-
<%= bucket&.first&.send calendar.display_bucket_title %>
|
44
|
-
</div>
|
45
|
-
<% end %>
|
46
|
-
<div class="events-wrapper">
|
47
|
-
<% events_size = calendar.slot_events(bucket, day) %>
|
48
|
-
<% bucket.each do |event| %>
|
49
|
-
<div class="event-wrapper" style="z-index:20;width:<%=events_size[event][0]%>%;top:<%=events_size[event][3]%>px;left:<%=events_size[event][1]%>%;height:<%=events_size[event][2]%>px">
|
50
|
-
<% if defined?(Haml) && respond_to?(:block_is_haml?) && block_is_haml?(passed_block) %>
|
51
|
-
<% capture_haml(event, &passed_block) %>
|
52
|
-
<% else %>
|
53
|
-
<% passed_block.call event %>
|
54
|
-
<% end %>
|
55
|
-
</div>
|
56
|
-
<% end %>
|
57
|
-
</div>
|
58
|
-
</div>
|
59
|
-
</div>
|
60
|
-
<% end %>
|
61
|
-
</div>
|
87
|
+
<% if defined?(Haml) && respond_to?(:block_is_haml?) && block_is_haml?(passed_block) %>
|
88
|
+
<% capture_haml(event, &passed_block) %>
|
89
|
+
<% else %>
|
90
|
+
<% passed_block.call event %>
|
91
|
+
<% end %>
|
62
92
|
</div>
|
93
|
+
<% end %>
|
63
94
|
</div>
|
64
95
|
<% end %>
|
96
|
+
</div>
|
65
97
|
</div>
|
66
|
-
|
98
|
+
</div>
|
99
|
+
<% end %>
|
67
100
|
</div>
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
101
|
+
</div>
|
102
|
+
<% elsif calendar.layout == :horizontal_date_on_top %>
|
103
|
+
<div class="orientation-wrapper <%=calendar.layout%>">
|
104
|
+
<% event_map = date_range.map { |day| calendar.split_into_buckets(sorted_events.fetch(day, [])) } %>
|
105
|
+
<% date_range.each_with_index do |day, index| %>
|
106
|
+
<div class="outer-day-wrapper <%=calendar.td_classes_for(day).join(' ')%>">
|
107
|
+
<div class="day-heading">
|
108
|
+
<div class="day-heading-inner">
|
109
|
+
<span class="day-weekday">
|
110
|
+
<%= t('date.abbr_day_names')[day.wday] %>
|
111
|
+
</span>
|
112
|
+
<span class="day-date">
|
113
|
+
<%= calendar.date_format_string ? day.strftime(calendar.date_format_string) : day %>
|
114
|
+
</span>
|
115
|
+
</div>
|
116
|
+
</div>
|
117
|
+
<div class="body-wrapper">
|
118
|
+
<% if calendar.display_bucket_title %>
|
119
|
+
<div class="buckets-heading">
|
120
|
+
<% if calendar.layout == :vertical %>
|
121
|
+
<div style="width:<%=calendar.grid_width%>"></div>
|
122
|
+
<% else %>
|
123
|
+
<div style="height:<%=calendar.grid_width%>"></div>
|
124
|
+
<% end %>
|
125
|
+
<% event_map[index].each do |bucket| %>
|
126
|
+
<div class="bucket-heading">
|
127
|
+
<%= bucket&.first&.send calendar.display_bucket_title %>
|
79
128
|
</div>
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
<% end %>
|
129
|
+
<% end %>
|
130
|
+
</div>
|
131
|
+
<% end %>
|
132
|
+
|
133
|
+
<div class="calendar-body" style="<%=calendar.body_style%>" >
|
134
|
+
<% buckets = event_map[index] %>
|
135
|
+
<div class="day-wrapper">
|
136
|
+
<div class="day-body <%=calendar.td_classes_for(date_range[index]).join(' ')%>" style="width:<%=calendar.day_size%>px;height:<%=calendar.day_height_px%>px">
|
137
|
+
<% if calendar.display_grid %>
|
138
|
+
<div class="hour-indicator-wrapper">
|
139
|
+
<% (0..23).each do |hour| %>
|
140
|
+
<div class="hour-indicator-cell tscal-horizontal tscal-hour-cell" id="hour-<%=hour %>">
|
141
|
+
<div class="hour-indicator" style="height:<%=calendar.grid_width%>">
|
142
|
+
<%=hour%>
|
95
143
|
</div>
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
<div class="events-inner-horizontal">
|
114
|
-
<% events_size = calendar.slot_events(bucket, day) %>
|
115
|
-
<% bucket.each do |event| %>
|
116
|
-
<div class="event-wrapper" style="height:<%=events_size[event][0]%>%;left:<%=events_size[event][3]%>px;top:<%=events_size[event][1]%>%;width:<%=events_size[event][2]%>px">
|
117
|
-
<% if defined?(Haml) && respond_to?(:block_is_haml?) && block_is_haml?(passed_block) %>
|
118
|
-
<% capture_haml(event, &passed_block) %>
|
119
|
-
<% else %>
|
120
|
-
<% passed_block.call event %>
|
121
|
-
<% end %>
|
122
|
-
</div>
|
123
|
-
<% end %>
|
124
|
-
</div>
|
125
|
-
</div>
|
126
|
-
</div>
|
144
|
+
</div>
|
145
|
+
<% end %>
|
146
|
+
</div>
|
147
|
+
<% end %>
|
148
|
+
<% if calendar.display_current_time_indicator %>
|
149
|
+
<div class="tscal-current-time-indicator" style="left:<%=calendar.current_time_offset %>px;top:0;bottom:0;width:0;"></div>
|
150
|
+
<% end %>
|
151
|
+
<div class="buckets-wrapper" style="top:<%=calendar.grid_width%>;right:0;left:0;bottom:0;">
|
152
|
+
<% buckets.each do |bucket| %>
|
153
|
+
<div class="bucket">
|
154
|
+
<% events_size = calendar.slot_events(bucket, date_range[index]) %>
|
155
|
+
<% bucket.each do |event| %>
|
156
|
+
<div class="event-wrapper tscal-event-wrapper" style="height:<%=events_size[event][0]%>%;left:<%=events_size[event][3]%>px;top:<%=events_size[event][1]%>%;width:<%=events_size[event][2]%>px">
|
157
|
+
<% if defined?(Haml) && respond_to?(:block_is_haml?) && block_is_haml?(passed_block) %>
|
158
|
+
<% capture_haml(event, &passed_block) %>
|
159
|
+
<% else %>
|
160
|
+
<% passed_block.call event %>
|
127
161
|
<% end %>
|
128
162
|
</div>
|
163
|
+
<% end %>
|
129
164
|
</div>
|
165
|
+
<% end %>
|
130
166
|
</div>
|
131
167
|
</div>
|
132
|
-
|
168
|
+
</div>
|
133
169
|
</div>
|
134
|
-
|
170
|
+
</div>
|
135
171
|
</div>
|
172
|
+
|
173
|
+
<% end %>
|
174
|
+
</div>
|
136
175
|
<% else %>
|
137
|
-
<div>Unsupported
|
176
|
+
<div>Unsupported layout for timeslot_calendar, please contact your webdeveloper</div>
|
138
177
|
<% end %>
|
139
|
-
</div>
|
178
|
+
</div>
|
@@ -3,27 +3,29 @@ require "simple_calendar"
|
|
3
3
|
module SimpleCalendar
|
4
4
|
module Timeslot
|
5
5
|
class TimeslotCalendar < SimpleCalendar::Calendar
|
6
|
-
MINUTE_HEIGHT_PX = 0.65
|
7
|
-
FIRST_HOUR_SLOT = 0
|
8
6
|
|
9
|
-
def
|
10
|
-
@options.fetch(:
|
7
|
+
def layout
|
8
|
+
@options.fetch(:layout, :vertical)
|
11
9
|
end
|
12
10
|
|
13
|
-
def
|
14
|
-
@options.fetch(:
|
11
|
+
def px_per_minute
|
12
|
+
@options.fetch(:px_per_minute, 0.65)
|
15
13
|
end
|
16
14
|
|
17
|
-
def
|
18
|
-
@options.fetch(:
|
15
|
+
def display_grid
|
16
|
+
@options.fetch(:display_grid, true)
|
19
17
|
end
|
20
|
-
|
21
|
-
def
|
22
|
-
|
18
|
+
|
19
|
+
def grid_width
|
20
|
+
if display_grid
|
21
|
+
@options.fetch(:grid_width, "20px")
|
22
|
+
else
|
23
|
+
0
|
24
|
+
end
|
23
25
|
end
|
24
26
|
|
25
|
-
def
|
26
|
-
@options.fetch(:
|
27
|
+
def display_current_time_indicator
|
28
|
+
@options.fetch(:display_current_time_indicator, false)
|
27
29
|
end
|
28
30
|
|
29
31
|
def bucket_title_size
|
@@ -34,27 +36,46 @@ module SimpleCalendar
|
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
37
|
-
def
|
38
|
-
|
39
|
+
def body_size_px
|
40
|
+
@options.fetch(:body_size_px, false)
|
39
41
|
end
|
40
42
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
43
|
+
def day_height_px
|
44
|
+
@options.fetch(:day_height_px, 200)
|
45
|
+
end
|
46
|
+
|
47
|
+
def bucket_by
|
48
|
+
@options.fetch(:bucket_by, false)
|
49
|
+
end
|
50
|
+
|
51
|
+
def display_bucket_title
|
52
|
+
@options.fetch(:display_bucket_title, false)
|
53
|
+
end
|
54
|
+
|
55
|
+
def date_format_string
|
56
|
+
@options.fetch(:date_format_string, false)
|
57
|
+
end
|
58
|
+
|
59
|
+
def date_heading_format_string
|
60
|
+
@options.fetch(:date_heading_format_string, "%B %Y")
|
61
|
+
end
|
62
|
+
|
63
|
+
def body_style
|
64
|
+
if layout == :vertical
|
65
|
+
body_size_px ? "height:#{body_size_px}px" : ''
|
66
|
+
elsif layout == :horizontal
|
67
|
+
'height:100%'
|
44
68
|
else
|
45
|
-
|
69
|
+
''
|
46
70
|
end
|
47
71
|
end
|
48
72
|
|
49
|
-
def
|
50
|
-
|
73
|
+
def day_height_style
|
74
|
+
layout == :horizontal ? "height:#{day_height_px}px;" : ""
|
51
75
|
end
|
52
76
|
|
53
|
-
def
|
54
|
-
|
55
|
-
h = 24 * 60 * px_per_minute
|
56
|
-
h = h+bucket_title_size if display_bucket_title
|
57
|
-
h
|
77
|
+
def day_size
|
78
|
+
24 * 60 * px_per_minute
|
58
79
|
end
|
59
80
|
|
60
81
|
def event_height(event, day)
|
@@ -75,8 +96,9 @@ module SimpleCalendar
|
|
75
96
|
end
|
76
97
|
|
77
98
|
def split_into_buckets(events)
|
78
|
-
if
|
79
|
-
events.
|
99
|
+
if bucket_by
|
100
|
+
return [[]] if events.size == 0
|
101
|
+
events.group_by{|e| e.send bucket_by}.values
|
80
102
|
else
|
81
103
|
[events]
|
82
104
|
end
|
@@ -119,6 +141,12 @@ module SimpleCalendar
|
|
119
141
|
r
|
120
142
|
end
|
121
143
|
|
144
|
+
def current_time_offset
|
145
|
+
now = Time.zone.now
|
146
|
+
offset = (now.hour * 60 + now.min) * px_per_minute
|
147
|
+
offset
|
148
|
+
end
|
149
|
+
|
122
150
|
private
|
123
151
|
|
124
152
|
def pack_events(r, columns)
|
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.90.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-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: simple_calendar
|