particle-calendar 0.1.2 → 0.1.3
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/README.md +6 -0
- data/config/availability.example.yml +3 -0
- data/lib/availability/application.rb +2 -1
- data/lib/availability/config.rb +5 -12
- data/lib/availability/config_value_parser.rb +18 -0
- data/lib/availability/renderer.rb +12 -6
- data/lib/availability/version.rb +1 -1
- data/templates/index.html.erb +5 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f9f0c170b7f8d695d6c4fb1e46c8469870536a9d551eb13a5ef19b2b48929db2
|
|
4
|
+
data.tar.gz: 464aa7b98a03dfaf87f8f7a60db717dc83e87c49a336733f2f2ffcc626b1dfc5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9fd923f8052c1d844203a7b76601e16dfc181b75f2492c451a208e16deae106d916cd122a7422b37e17883b72de90b6fd89fbb86bd5f045189d9e68f0f8accf6
|
|
7
|
+
data.tar.gz: 105bba2a9405df074f8e634e88a59abd6407487ae5ddf76e0ddc7933ae8406388ca2da91869b5b6c32f2177eccea9d9989011bd3426a426b8b12bb6a49a1625a
|
data/README.md
CHANGED
|
@@ -151,6 +151,12 @@ availability:
|
|
|
151
151
|
first_day_of_week: sunday
|
|
152
152
|
```
|
|
153
153
|
|
|
154
|
+
`weekend_days` controls which weekday labels appear red in the desktop calendar header. Date headings keep their normal color. It defaults to Saturday and Sunday, regardless of `first_day_of_week` or availability windows. Use distinct lowercase weekday names; an empty list disables weekend highlighting:
|
|
155
|
+
|
|
156
|
+
```yaml
|
|
157
|
+
weekend_days: [friday, saturday]
|
|
158
|
+
```
|
|
159
|
+
|
|
154
160
|
### Minimum slots and event buffers
|
|
155
161
|
|
|
156
162
|
`minimum_slot_minutes` removes shorter free fragments after subtraction. The default is `0`.
|
|
@@ -13,6 +13,9 @@ minimum_slot_minutes: 60
|
|
|
13
13
|
# The calendar grid starts on Monday by default. Any lowercase weekday is accepted.
|
|
14
14
|
first_day_of_week: monday
|
|
15
15
|
|
|
16
|
+
# Weekday labels in the desktop header appear red. Defaults to Saturday and Sunday.
|
|
17
|
+
weekend_days: [saturday, sunday]
|
|
18
|
+
|
|
16
19
|
event_buffer:
|
|
17
20
|
before_minutes: 0
|
|
18
21
|
after_minutes: 0
|
data/lib/availability/config.rb
CHANGED
|
@@ -14,7 +14,8 @@ module Availability
|
|
|
14
14
|
include ConfigValueParser
|
|
15
15
|
|
|
16
16
|
TOP_LEVEL_KEYS = %w[
|
|
17
|
-
enabled timezone calendar_urls days_to_show minimum_slot_minutes event_buffer
|
|
17
|
+
enabled timezone calendar_urls days_to_show minimum_slot_minutes event_buffer
|
|
18
|
+
availability first_day_of_week weekend_days
|
|
18
19
|
].freeze
|
|
19
20
|
EVENT_BUFFER_KEYS = %w[before_minutes after_minutes].freeze
|
|
20
21
|
WEEKDAYS = %w[sunday monday tuesday wednesday thursday friday saturday].freeze
|
|
@@ -24,7 +25,7 @@ module Availability
|
|
|
24
25
|
MAX_CALENDAR_URLS = 20
|
|
25
26
|
|
|
26
27
|
attr_reader :enabled, :timezone, :calendar_urls, :days_to_show,
|
|
27
|
-
:minimum_slot_minutes, :buffer_before_minutes, :buffer_after_minutes, :first_day_of_week
|
|
28
|
+
:minimum_slot_minutes, :buffer_before_minutes, :buffer_after_minutes, :first_day_of_week, :weekend_days
|
|
28
29
|
|
|
29
30
|
def self.load(path, env: ENV)
|
|
30
31
|
raise ConfigError, "configuration file not found: #{path}" unless File.file?(path)
|
|
@@ -58,7 +59,8 @@ module Availability
|
|
|
58
59
|
@timezone = parse_timezone
|
|
59
60
|
@days_to_show = bounded_positive_integer('days_to_show', default: 28, maximum: MAX_DAYS_TO_SHOW)
|
|
60
61
|
@minimum_slot_minutes = nonnegative_integer('minimum_slot_minutes', default: 0)
|
|
61
|
-
@first_day_of_week =
|
|
62
|
+
@first_day_of_week = weekday('first_day_of_week', default: 'monday', allowed: WEEKDAYS)
|
|
63
|
+
@weekend_days = weekday_list('weekend_days', default: %w[saturday sunday], allowed: WEEKDAYS)
|
|
62
64
|
end
|
|
63
65
|
|
|
64
66
|
def stringify_keys(value)
|
|
@@ -81,15 +83,6 @@ module Availability
|
|
|
81
83
|
raise ConfigError, "timezone is unknown: #{name}"
|
|
82
84
|
end
|
|
83
85
|
|
|
84
|
-
def parse_first_day_of_week
|
|
85
|
-
day = @raw.fetch('first_day_of_week', 'monday')
|
|
86
|
-
unless day.is_a?(String) && WEEKDAYS.include?(day)
|
|
87
|
-
raise ConfigError, "first_day_of_week must be one of: #{WEEKDAYS.join(', ')}"
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
day
|
|
91
|
-
end
|
|
92
|
-
|
|
93
86
|
def parse_buffers
|
|
94
87
|
buffer = @raw.fetch('event_buffer', {})
|
|
95
88
|
raise ConfigError, 'event_buffer must be a mapping' unless buffer.is_a?(Hash)
|
|
@@ -44,5 +44,23 @@ module Availability
|
|
|
44
44
|
|
|
45
45
|
raise ConfigError, "#{label} must be a non-negative integer"
|
|
46
46
|
end
|
|
47
|
+
|
|
48
|
+
def weekday_list(key, default:, allowed:)
|
|
49
|
+
days = @raw.fetch(key, default)
|
|
50
|
+
raise ConfigError, "#{key} must be an array" unless days.is_a?(Array)
|
|
51
|
+
unless days.all? { |day| day.is_a?(String) && allowed.include?(day) }
|
|
52
|
+
raise ConfigError, "#{key} must contain only: #{allowed.join(', ')}"
|
|
53
|
+
end
|
|
54
|
+
raise ConfigError, "#{key} must not contain duplicates" unless days.uniq.length == days.length
|
|
55
|
+
|
|
56
|
+
days.dup.freeze
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def weekday(key, default:, allowed:)
|
|
60
|
+
day = @raw.fetch(key, default)
|
|
61
|
+
return day if day.is_a?(String) && allowed.include?(day)
|
|
62
|
+
|
|
63
|
+
raise ConfigError, "#{key} must be one of: #{allowed.join(', ')}"
|
|
64
|
+
end
|
|
47
65
|
end
|
|
48
66
|
end
|
|
@@ -13,17 +13,17 @@ module Availability
|
|
|
13
13
|
@template = ERB.new(File.read(template_path), trim_mode: '-')
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
def render(days:, generated_at:, timezone:, enabled:, today:, days_to_show:, first_day_of_week:)
|
|
17
|
-
|
|
16
|
+
def render(days:, generated_at:, timezone:, enabled:, today:, days_to_show:, first_day_of_week:, weekend_days:)
|
|
17
|
+
@template.result(View.new(
|
|
18
18
|
days: days,
|
|
19
19
|
generated_at: generated_at,
|
|
20
20
|
timezone: timezone,
|
|
21
21
|
enabled: enabled,
|
|
22
22
|
today: today,
|
|
23
23
|
days_to_show: days_to_show,
|
|
24
|
-
first_day_of_week: first_day_of_week
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
first_day_of_week: first_day_of_week,
|
|
25
|
+
weekend_days: weekend_days
|
|
26
|
+
).template_binding)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
# Exposes only display-safe availability values and formatting helpers to ERB.
|
|
@@ -32,7 +32,8 @@ module Availability
|
|
|
32
32
|
|
|
33
33
|
attr_reader :enabled, :today
|
|
34
34
|
|
|
35
|
-
def initialize(days:, generated_at:, timezone:, enabled:, today:, days_to_show:, first_day_of_week
|
|
35
|
+
def initialize(days:, generated_at:, timezone:, enabled:, today:, days_to_show:, first_day_of_week:,
|
|
36
|
+
weekend_days:)
|
|
36
37
|
@days = days
|
|
37
38
|
@generated_at = generated_at
|
|
38
39
|
@timezone = timezone
|
|
@@ -40,6 +41,7 @@ module Availability
|
|
|
40
41
|
@today = today
|
|
41
42
|
@days_to_show = days_to_show
|
|
42
43
|
@first_day_of_week = first_day_of_week
|
|
44
|
+
@weekend_days = weekend_days
|
|
43
45
|
end
|
|
44
46
|
|
|
45
47
|
def template_binding
|
|
@@ -80,6 +82,10 @@ module Availability
|
|
|
80
82
|
WEEKDAYS.rotate(WEEKDAYS.index(@first_day_of_week))
|
|
81
83
|
end
|
|
82
84
|
|
|
85
|
+
def weekend_day?(weekday)
|
|
86
|
+
@weekend_days.include?(weekday)
|
|
87
|
+
end
|
|
88
|
+
|
|
83
89
|
def updated_at
|
|
84
90
|
@timezone.to_local(@generated_at.getutc).strftime('%-d %b %Y, %H:%M %Z')
|
|
85
91
|
end
|
data/lib/availability/version.rb
CHANGED
data/templates/index.html.erb
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
--today-label-background: #e0f2fe;
|
|
28
28
|
--today-label-text: #075985;
|
|
29
29
|
--empty: #526175;
|
|
30
|
+
--weekend: #b91c1c;
|
|
30
31
|
--shadow: 0 1px 2px rgb(15 23 42 / 0.04), 0 8px 24px rgb(15 23 42 / 0.04);
|
|
31
32
|
font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
32
33
|
}
|
|
@@ -148,6 +149,8 @@
|
|
|
148
149
|
text-transform: uppercase;
|
|
149
150
|
}
|
|
150
151
|
|
|
152
|
+
.weekday-header span.weekend { color: var(--weekend); }
|
|
153
|
+
|
|
151
154
|
.days {
|
|
152
155
|
display: grid;
|
|
153
156
|
grid-template-columns: repeat(7, minmax(0, 1fr));
|
|
@@ -358,6 +361,7 @@
|
|
|
358
361
|
--today-label-background: #0c4a6e;
|
|
359
362
|
--today-label-text: #bae6fd;
|
|
360
363
|
--empty: #a3aec0;
|
|
364
|
+
--weekend: #fca5a5;
|
|
361
365
|
--shadow: 0 1px 2px rgb(0 0 0 / 0.2), 0 10px 28px rgb(0 0 0 / 0.16);
|
|
362
366
|
}
|
|
363
367
|
}
|
|
@@ -394,7 +398,7 @@
|
|
|
394
398
|
<% if enabled -%>
|
|
395
399
|
<div class="calendar">
|
|
396
400
|
<div class="weekday-header" aria-hidden="true">
|
|
397
|
-
<% weekdays.each do |weekday| -%><span
|
|
401
|
+
<% weekdays.each do |weekday| -%><span<%= ' class="weekend"' if weekend_day?(weekday) %>><%= h weekday[0, 3] %></span><% end -%>
|
|
398
402
|
</div>
|
|
399
403
|
<% weeks.each_with_index do |week, index| -%>
|
|
400
404
|
<section class="week" aria-labelledby="week-<%= index + 1 %>-heading">
|