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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43966203ce48c4c965bfb74fb242a926ecc9b5cb34aa0b56426d85410b3f08aa
4
- data.tar.gz: 848c5d0c11a76c476e99c9376f81b8b708619bbf1ba1aafe93ad9dc87ec41267
3
+ metadata.gz: c69834a6c0289a7d3679c45911fd5feb363201a4ae250efe96ec5b9b3e610bdf
4
+ data.tar.gz: 382ed150f3b8cc79e6e8fabd9e2280c320f4963babbf287a9df7a32526c24262
5
5
  SHA512:
6
- metadata.gz: 849481225d905b3b962d6f90965324c0645db136c7e2bb5e350b26bca496ba9edf8a5f7409c37cfc4d53e3f3e3bf23d1f0d2716a7d0b25c27ceabcd004ba4369
7
- data.tar.gz: 7ab1c262be43bc58ad0d3d184c76cf1fa927c58d1156d0c9e110098429f37b2c517b4d636d6c40263cecf4f2663119d284dd3bb3c212582e67cd4487906bd8ce
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.5.1)
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.3.0)
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
- Horizontal and vertical layout is selectable via options, just like many other ones.
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
+ ![Vertical Layout](https://raw.githubusercontent.com/1klap/simple_calendar-timeslot/90a0c2b72b172a113105412ef34dd00f728e50e4/img/simple_calendar-timeslot_vertical-v2.png)
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
+ ![Horizontal Layout](https://raw.githubusercontent.com/1klap/simple_calendar-timeslot/90a0c2b72b172a113105412ef34dd00f728e50e4/img/simple_calendar-timeslot_horizontal-v2.png)
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
+ ![Horizontal Layout](https://raw.githubusercontent.com/1klap/simple_calendar-timeslot/90a0c2b72b172a113105412ef34dd00f728e50e4/img/simple_calendar-timeslot_horizontal2-v2.png)
10
81
 
11
- Horizontal example
12
- ![Horizontal Calendar](https://github.com/1klap/simple_calendar-timeslot/blob/96475bf7c354b7e0318a9421e155588d96517fc3/img/simple_calendar-timeslot_horizontal.png?raw=true)
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
- ![Vertical Calendar](https://github.com/1klap/simple_calendar-timeslot/blob/96475bf7c354b7e0318a9421e155588d96517fc3/img/simple_calendar-timeslot_vertical.png?raw=true)
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
- TODO: Write usage instructions here
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
- 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`.
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: 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
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
- 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
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
+ ![Styled calendar](https://raw.githubusercontent.com/1klap/simple_calendar-timeslot/c844c11f99c51f1b44bab825943615c295acde29/img/simple_calendar-timeslot_styled.png)
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 .days-wrapper-vertical {
27
+ .timeslot-calendar .titles-heading {
5
28
  display: flex;
6
29
  flex-direction: row;
7
30
  }
8
- .timeslot-calendar .days-wrapper-horizontal {
31
+ .timeslot-calendar .title-heading {
32
+ flex: 1;
33
+ }
34
+ .timeslot-calendar .buckets-heading {
9
35
  display: flex;
10
- flex-direction: column;
36
+ flex-direction: row;
11
37
  }
12
- .timeslot-calendar .day-wrapper {
13
- flex: 1 1 0;
38
+ .timeslot-calendar .bucket-heading {
39
+ flex: 1;
14
40
  }
15
- .timeslot-calendar .day-content-vertical {
41
+ .timeslot-calendar .calendar-body {
16
42
  display: flex;
17
- flex-direction: column;
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 .day-content-horizontal {
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 .day-content-horizontal-inner {
28
- position: relative;
58
+ .timeslot-calendar .hour-indicator-cell {
59
+ min-height: 0;
60
+ flex: 1;
29
61
  }
30
-
31
- .timeslot-calendar .hour-indicator-col-vertical {
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 .hour-indicator-col-horizontal {
65
+ .timeslot-calendar .buckets-wrapper {
66
+ position: absolute;
38
67
  display: flex;
39
- flex: 1 1 0;
40
68
  flex-direction: row;
41
- height: 100%;
42
- z-index: 0;
69
+ overflow: hidden;
43
70
  }
44
- .timeslot-calendar .hour-indicator-vertical {
45
- border-style: solid;
46
- flex: 1 1 0;
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 .buckets-wrapper {
75
+ .timeslot-calendar .event-wrapper {
59
76
  position: absolute;
60
-
61
77
  }
62
- .timeslot-calendar .buckets-vertical {
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 .buckets-horizontal {
67
- position: absolute;
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 .bucket-wrapper {
72
- flex: 1 1 0;
101
+ .timeslot-calendar .orientation-wrapper.horizontal .calendar-body {
102
+ flex: 1;
103
+ flex-direction: column;
104
+ overflow-x: scroll;
73
105
  }
74
- .timeslot-calendar .bucket-horizontal {
75
- flex: 1 1 0;
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 .bucket-inner-horizontal {
80
- position: relative;
117
+ .timeslot-calendar .orientation-wrapper.horizontal_date_on_top .buckets-heading {
118
+ flex-direction: column;
81
119
  }
82
- .timeslot-calendar .events-wrapper {
83
- position: relative;
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 .event-wrapper {
86
- position: absolute;
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
- /*--- Event example style ----*/
91
- .timeslot-event {
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"><%= t('date.month_names')[start_date.month] %> <%= start_date.year %></span>
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
- <% if calendar.orientation == :vertical %>
9
- <div class="days-wrapper-vertical">
10
- <% date_range.slice(0, 7).each do |day| %>
11
- <div class="day-wrapper">
12
- <div class="day-title-row">
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
- <%= content_tag :div, class: calendar.td_classes_for(day) do %>
21
- <div class="day-content-vertical" style="height:<%=calendar.height%>px;">
22
- <% if calendar.display_grid %>
23
- <div class="hour-indicator-col-vertical">
24
- <% if calendar.display_bucket_title %>
25
- <div class="bucket-title" style="height:<%=calendar.bucket_title_size%>px"></div>
26
- <% end %>
27
- <% (0..23).each do |hour| %>
28
- <div class="hour-indicator-vertical" id="hour-<%=hour %>">
29
- <%=hour%>
30
- </div>
31
- <% end %>
32
- </div>
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
- <% events = sorted_events.fetch(day, []) %>
35
- <% buckets = calendar.split_into_buckets(events) %>
36
- <div class="buckets-wrapper" style="left:<%=calendar.grid_width%>;right:0">
37
- <div class="buckets-vertical">
38
- <% buckets.each do |bucket| %>
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
- <% end %>
98
+ </div>
99
+ <% end %>
67
100
  </div>
68
- <% elsif calendar.orientation == :horizontal %>
69
- <div class="days-wrapper-horizontal">
70
- <% date_range.slice(0, 7).each do |day| %>
71
- <div class="day-wrapper">
72
- <div class="day-title-row">
73
- <span class="day-weekday">
74
- <%= t('date.abbr_day_names')[day.wday] %>
75
- </span>
76
- <span class="day-date">
77
- <%= day %>
78
- </span>
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
- <%= content_tag :div, class: calendar.td_classes_for(day) do %>
81
- <div class="day-content-horizontal">
82
- <div class="day-content-horizontal-inner" style="width:<%=calendar.height%>px;height:<%=calendar.horizontal_height_px%>px">
83
- <% if calendar.display_grid %>
84
- <div class="hour-indicator-col-horizontal" style="z-index:-10;">
85
- <% if calendar.display_bucket_title %>
86
- <div class="bucket-title" style="width:<%=calendar.bucket_title_size%>px;"></div>
87
- <% end %>
88
- <% (0..23).each do |hour| %>
89
- <div class="hour-indicator-horizontal" id="hour-<%=hour %>">
90
- <div style="height:20px">
91
- <%=hour%>
92
- </div>
93
- </div>
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
- <% end %>
97
- <% events = sorted_events.fetch(day, []) %>
98
- <% buckets = calendar.split_into_buckets(events) %>
99
- <div class="buckets-wrapper" style="top:<%=calendar.grid_width%>;bottom:0">
100
- <div class="buckets" >
101
- <% buckets.each do |bucket| %>
102
- <div class="bucket-horizontal">
103
- <% if calendar.display_bucket_title %>
104
- <div class="bucket-title-size-wrap" style="width:<%=calendar.bucket_title_size%>px;">
105
- <div class="bucket-title-text-wrapper">
106
- <div class="bucket-title-text">
107
- <%= bucket&.first&.send calendar.display_bucket_title %>
108
- </div>
109
- </div>
110
- </div>
111
- <% end %>
112
- <div class="events-wrapper" style="height:<%=(calendar.horizontal_height_px-(calendar.display_grid ? 20 : 0)) / buckets.size%>px;">
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
- <% end %>
168
+ </div>
133
169
  </div>
134
- <% end %>
170
+ </div>
135
171
  </div>
172
+
173
+ <% end %>
174
+ </div>
136
175
  <% else %>
137
- <div>Unsupported orientation: <%= calendar.orientation %></div>
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 orientation
10
- @options.fetch(:orientation, :vertical)
7
+ def layout
8
+ @options.fetch(:layout, :vertical)
11
9
  end
12
10
 
13
- def horizontal_height_px
14
- @options.fetch(:horizontal_height_px, 300)
11
+ def px_per_minute
12
+ @options.fetch(:px_per_minute, 0.65)
15
13
  end
16
14
 
17
- def split_by_type
18
- @options.fetch(:split_by_type, false)
15
+ def display_grid
16
+ @options.fetch(:display_grid, true)
19
17
  end
20
-
21
- def px_per_minute
22
- @options.fetch(:px_per_minute, TimeslotCalendar::MINUTE_HEIGHT_PX)
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 display_bucket_title
26
- @options.fetch(:display_bucket_title, false)
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 grid_top_offset(hour)
38
- 4.16666667 * hour
39
+ def body_size_px
40
+ @options.fetch(:body_size_px, false)
39
41
  end
40
42
 
41
- def grid_width
42
- if display_grid
43
- @options.fetch(:grid_width, "20px")
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
- 0
69
+ ''
46
70
  end
47
71
  end
48
72
 
49
- def display_grid
50
- @options.fetch(:display_grid, true)
73
+ def day_height_style
74
+ layout == :horizontal ? "height:#{day_height_px}px;" : ""
51
75
  end
52
76
 
53
- def height
54
- #h = (24 - TimeslotCalendar::FIRST_HOUR_SLOT) * 60 * px_per_minute
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 split_by_type
79
- events.group_by{|e| e.send split_by_type}.values
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)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SimpleCalendar
4
4
  module Timeslot
5
- VERSION = "0.5.1"
5
+ VERSION = "0.90.0"
6
6
  end
7
7
  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.5.1
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-15 00:00:00.000000000 Z
11
+ date: 2021-11-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: simple_calendar