schedulable 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +174 -42
- data/Rakefile +3 -0
- data/config/locales/de.yml +29 -0
- data/{lib/generators/schedulable/templates/locale/schedulable.en.yml → config/locales/en.yml} +2 -2
- data/lib/generators/schedulable/locale_generator.rb +1 -1
- data/lib/generators/schedulable/templates/config/schedulable.rb +5 -2
- data/lib/generators/schedulable/templates/inputs/schedule_input.rb +81 -51
- data/lib/generators/schedulable/templates/migrations/create_schedules.rb +2 -2
- data/lib/generators/schedulable/templates/models/schedule.rb +1 -12
- data/lib/locales/en.yml +29 -0
- data/lib/{generators/schedulable/templates/locale → locales}/schedulable.de.yml +0 -0
- data/lib/schedulable.rb +7 -5
- data/lib/schedulable/acts_as_schedulable.rb +66 -59
- data/lib/schedulable/form_helper.rb +228 -0
- data/lib/schedulable/railtie.rb +21 -0
- data/lib/schedulable/schedule.rb +115 -0
- data/lib/schedulable/schedule_support.rb +1 -60
- data/lib/schedulable/version.rb +1 -1
- data/lib/tasks/schedulable_tasks.rake +1 -1
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf160baa485b91e6566ffb4a3d4914058237f634
|
4
|
+
data.tar.gz: edfc6d3c758cbdef642e633a1a32869f6a386327
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 555836580530752b1eecf9cf85cf9b8f7a44f5d12fb62254555930f895608d7a644a3f555a5c98e09b1fdb366466733952eea3afd31d053a4567406d074145c7
|
7
|
+
data.tar.gz: a47bd73ac68eeff77a1dcecbcebab3d32c4e41a04fe429efe13d862d54397475f08f50f8a51ab3a2a8755e343c1d65090d031ed95b3904ca7593ec4fd98741a4
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
schedulable
|
2
2
|
===========
|
3
3
|
|
4
|
-
Handling recurring events in rails.
|
4
|
+
> Handling recurring events in rails.
|
5
5
|
|
6
|
-
|
6
|
+
|
7
|
+
## Install
|
7
8
|
|
8
9
|
Put the following into your Gemfile and run `bundle install`
|
9
10
|
```cli
|
@@ -16,7 +17,7 @@ Install schedule migration and model
|
|
16
17
|
rails g schedulable:install
|
17
18
|
```
|
18
19
|
|
19
|
-
|
20
|
+
## Basic Usage
|
20
21
|
|
21
22
|
Create an event model
|
22
23
|
```cli
|
@@ -27,15 +28,13 @@ Configure your model to be schedulable:
|
|
27
28
|
```
|
28
29
|
# app/models/event.rb
|
29
30
|
class Event < ActiveRecord::Base
|
30
|
-
acts_as_schedulable
|
31
|
+
acts_as_schedulable :schedule
|
31
32
|
end
|
32
33
|
```
|
33
34
|
This will add an association to the model named 'schedule' which holds the schedule information.
|
34
35
|
|
35
|
-
|
36
|
-
|
37
|
-
### Attributes
|
38
|
-
The schedule object respects the following attributes:
|
36
|
+
### Schedule Model
|
37
|
+
The schedule-object respects the following attributes.
|
39
38
|
<table>
|
40
39
|
<tr>
|
41
40
|
<th>Name</th><th>Type</th><th>Description</th>
|
@@ -50,10 +49,10 @@ The schedule object respects the following attributes:
|
|
50
49
|
<td>time</td><td>Time</td><td>The time-attribute is used for singular events and also as starttime of the schedule</td>
|
51
50
|
</tr>
|
52
51
|
<tr>
|
53
|
-
<td>
|
52
|
+
<td>day</td><td>Array</td><td>Day of week. An array of weekday-names, i.e. ['monday', 'wednesday']</td>
|
54
53
|
</tr>
|
55
54
|
<tr>
|
56
|
-
<td>day_of_week</td><td>Hash</td><td>A hash of weekday-names, containing arrays with indices, i.e. {:monday => [1, -1]} ('every first and last monday in month')</td>
|
55
|
+
<td>day_of_week</td><td>Hash</td><td>Day of nth week. A hash of weekday-names, containing arrays with indices, i.e. {:monday => [1, -1]} ('every first and last monday in month')</td>
|
57
56
|
</tr>
|
58
57
|
<tr>
|
59
58
|
<td>interval</td><td>Integer</td><td>Specifies the interval of the recurring rule, i.e. every two weeks</td>
|
@@ -66,8 +65,83 @@ The schedule object respects the following attributes:
|
|
66
65
|
</tr>
|
67
66
|
</table>
|
68
67
|
|
69
|
-
|
70
|
-
|
68
|
+
## Forms
|
69
|
+
|
70
|
+
Use schedulable's built-in helpers to setup your form.
|
71
|
+
|
72
|
+
### FormBuilder
|
73
|
+
|
74
|
+
Schedulable extends FormBuilder with a 'schedule_select'-helper and should therefore seamlessly integrate it with your existing views:
|
75
|
+
|
76
|
+
```erb
|
77
|
+
<%# app/views/events/_form.html.erb %>
|
78
|
+
<%= form_for(@event) do |f| %>
|
79
|
+
|
80
|
+
<div class="field">
|
81
|
+
<%= f.label :name %><br>
|
82
|
+
<%= f.text_field :name %>
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<div class="field">
|
86
|
+
<%= f.label :schedule %><br>
|
87
|
+
<%= f.schedule_select :schedule %>
|
88
|
+
</div>
|
89
|
+
|
90
|
+
<div class="actions">
|
91
|
+
<%= f.submit %>
|
92
|
+
</div>
|
93
|
+
<% end %>
|
94
|
+
```
|
95
|
+
|
96
|
+
#### Customize markup
|
97
|
+
You can customize the generated markup by providing a hash of html-attributes as `style`-option. For wrappers, also provide a `tag`-attribute.
|
98
|
+
* field_html
|
99
|
+
* input_html
|
100
|
+
* input_wrapper
|
101
|
+
* label_html
|
102
|
+
* label_wrapper
|
103
|
+
* number_field_html
|
104
|
+
* number_field_wrapper
|
105
|
+
* date_select_html
|
106
|
+
* date_select_wrapper
|
107
|
+
* collection_select_html
|
108
|
+
* collection_select_wrapper
|
109
|
+
* collection_check_boxes_item_html
|
110
|
+
* collection_check_boxes_item_wrapper
|
111
|
+
|
112
|
+
#### Integrate with Bootstrap
|
113
|
+
|
114
|
+
The schedulable-formhelper has built-in-support for Bootstrap. Simply point the style-option of schedule_input to `bootstrap` or set it as default in config.
|
115
|
+
|
116
|
+
```erb
|
117
|
+
|
118
|
+
<%= f.schedule_select :schedule, style: :bootstrap %>
|
119
|
+
```
|
120
|
+
|
121
|
+
#### Options
|
122
|
+
|
123
|
+
<table>
|
124
|
+
<tr>
|
125
|
+
<th>Name</th><th>Type</th><th>Description</th>
|
126
|
+
</tr>
|
127
|
+
<tr>
|
128
|
+
<tr>
|
129
|
+
<td>count</td><td>Boolean</td><td>Specifies whether to show 'count'-field</td>
|
130
|
+
</tr>
|
131
|
+
<tr>
|
132
|
+
<td>interval</td><td>Boolean</td><td>Specifies whether to show 'interval'-field</td>
|
133
|
+
</tr>
|
134
|
+
<tr>
|
135
|
+
<td>style</td><td>Hash</td><td>Specifies a hash of options to customize markup. By providing a string, you can point to a prefined set of options. Built-in styles are :bootstrap and :default.
|
136
|
+
</tr>
|
137
|
+
<tr>
|
138
|
+
<td>until</td><td>Boolean</td><td>Specifies whether to show 'until'-field</td>
|
139
|
+
</tr>
|
140
|
+
</table>
|
141
|
+
|
142
|
+
### SimpleForm
|
143
|
+
Also provided with the plugin is a custom input for simple_form. Make sure, you installed [SimpleForm](https://github.com/plataformatec/simple_form) and executed `rails generate simple_form:install`.
|
144
|
+
|
71
145
|
|
72
146
|
```cli
|
73
147
|
rails g schedulable:simple_form
|
@@ -92,11 +166,57 @@ rails g schedulable:simple_form
|
|
92
166
|
</div>
|
93
167
|
|
94
168
|
<% end %>
|
169
|
+
```
|
95
170
|
|
171
|
+
#### Integrate with Bootstrap
|
172
|
+
|
173
|
+
Simple Form has built-in support for Bootstrap as of version 3.0.0.
|
174
|
+
At time of writing it requires some a little extra portion of configuration to make it look as expected:
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
# config/initializers/simple_form_bootstrap.rb
|
178
|
+
|
179
|
+
# Inline date_select-wrapper for Bootstrap
|
180
|
+
config.wrappers :horizontal_select_date, tag: 'div', class: 'form-group', error_class: 'has-error' do |b|
|
181
|
+
b.use :html5
|
182
|
+
b.optional :readonly
|
183
|
+
b.use :label, class: 'control-label'
|
184
|
+
b.wrapper tag: 'div', class: 'form-inline' do |ba|
|
185
|
+
ba.use :input, class: 'form-control'
|
186
|
+
ba.use :error, wrap_with: { tag: 'span', class: 'help-block' }
|
187
|
+
ba.use :hint, wrap_with: { tag: 'p', class: 'help-block' }
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Include date_select-wrapper in mappings
|
192
|
+
config.wrapper_mappings = {
|
193
|
+
datetime: :horizontal_select_date,
|
194
|
+
date: :horizontal_select_date,
|
195
|
+
time: :horizontal_select_date
|
196
|
+
}
|
96
197
|
```
|
97
198
|
|
98
|
-
####
|
199
|
+
#### Options
|
200
|
+
|
201
|
+
<table>
|
202
|
+
<tr>
|
203
|
+
<th>Name</th><th>Type</th><th>Description</th>
|
204
|
+
</tr>
|
205
|
+
<tr>
|
206
|
+
<tr>
|
207
|
+
<td>count</td><td>Boolean</td><td>Specifies whether to show 'count'-field</td>
|
208
|
+
</tr>
|
209
|
+
<tr>
|
210
|
+
<td>interval</td><td>Boolean</td><td>Specifies whether to show 'interval'-field</td>
|
211
|
+
</tr>
|
212
|
+
<tr>
|
213
|
+
<td>until</td><td>Boolean</td><td>Specifies whether to show 'until'-field</td>
|
214
|
+
</tr>
|
215
|
+
</table>
|
216
|
+
|
217
|
+
### Sanitize parameters
|
99
218
|
|
219
|
+
Add schedule-attributes to the list of strong parameters in your controller:
|
100
220
|
```
|
101
221
|
# app/controllers/event_controller.rb
|
102
222
|
def event_params
|
@@ -104,50 +224,52 @@ def event_params
|
|
104
224
|
end
|
105
225
|
```
|
106
226
|
|
107
|
-
|
108
|
-
|
109
|
-
You can access ice_cube-methods via the schedule association:
|
227
|
+
## Accessing IceCube
|
228
|
+
You can access ice_cube-methods directly via the schedule association:
|
110
229
|
|
111
230
|
```ruby
|
112
231
|
<%# app/views/events/show.html.erb %>
|
113
232
|
<p>
|
114
233
|
<strong>Schedule:</strong>
|
115
|
-
<%#
|
234
|
+
<%# Prints out a human-friendly description of the schedule, such as %>
|
116
235
|
<%= @event.schedule %>
|
117
236
|
</p>
|
118
237
|
```
|
119
238
|
|
120
239
|
```
|
121
|
-
#
|
240
|
+
# Prints all occurrences of the event until one year from now
|
122
241
|
puts @event.schedule.occurrences(Time.now + 1.year)
|
123
|
-
#
|
242
|
+
# Export to ical
|
124
243
|
puts @event.schedule.to_ical
|
125
244
|
```
|
126
245
|
See [IceCube](https://github.com/seejohnrun/ice_cube) for more information.
|
127
246
|
|
128
|
-
|
247
|
+
## Internationalization
|
129
248
|
|
130
|
-
|
131
|
-
|
249
|
+
Schedulable is bundled with translations in english and german which will be automatically initialized with your app.
|
250
|
+
You can customize these messages by running the locale generator and edit the created yml-files:
|
132
251
|
|
133
|
-
#### Localize Schedulable
|
134
|
-
Use the locale-generator to create a .yml-file containing schedulable messages in english:
|
135
252
|
```cli
|
136
|
-
rails g schedulable:locale
|
253
|
+
rails g schedulable:locale de
|
137
254
|
```
|
138
255
|
|
139
|
-
|
256
|
+
### Date- and Time-Messages
|
257
|
+
Appropriate datetime translations should be included.
|
258
|
+
Basic setup for many languages can be found here:
|
259
|
+
[https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale](https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale).
|
260
|
+
|
261
|
+
|
262
|
+
### IceCube-Messages
|
263
|
+
An internationalization-branch of ice_cube can be found here:
|
264
|
+
[https://github.com/joelmeyerhamme/ice_cube](https://github.com/joelmeyerhamme/ice_cube):
|
140
265
|
|
141
|
-
#### Localize Ice-Cube
|
142
|
-
Internationalization of ice-cube itself can be integrated by using [this fork](https://github.com/joelmeyerhamme/ice_cube):
|
143
266
|
```ruby
|
144
267
|
gem 'ice_cube', git: 'git://github.com/joelmeyerhamme/ice_cube.git', branch: 'international'
|
145
268
|
```
|
146
269
|
|
270
|
+
## Persist Occurrences
|
147
271
|
|
148
|
-
|
149
|
-
We need to have the occurrences persisted because we want to query the database for all occurrences of all instances of an event model or need to add additional attributes and functionality, such as allowing users to attend to a specific occurrence of an event.
|
150
|
-
The schedulable gem handles this for you.
|
272
|
+
Schedulable allows for persisting occurrences and associate them with your model.
|
151
273
|
Your occurrence model must include an attribute of type 'datetime' with name 'date' as well as a reference to your event model to setup up the association properly:
|
152
274
|
|
153
275
|
```ruby
|
@@ -161,19 +283,22 @@ class EventOccurrence < ActiveRecord::Base
|
|
161
283
|
end
|
162
284
|
```
|
163
285
|
|
164
|
-
|
286
|
+
Declare occurrence-model with the acts_as_schedule-method like this:
|
165
287
|
```
|
166
288
|
# app/models/event.rb
|
167
289
|
class Event < ActiveRecord::Base
|
168
|
-
acts_as_schedulable occurrences: :event_occurrences
|
290
|
+
acts_as_schedulable :schedule, occurrences: :event_occurrences
|
169
291
|
end
|
170
292
|
```
|
171
|
-
This will add a has_many-association with the name 'event_occurences' to your event-model.
|
172
|
-
Instances of remaining occurrences are built when the schedule is saved.
|
173
|
-
If the schedule has changed, the occurrences will be rebuilt if dates have also changed. Otherwise the time of the occurrence record will be adjusted to the new time.
|
174
|
-
As in real life, previous occurrences will always stay untouched.
|
175
293
|
|
176
|
-
|
294
|
+
This will add a `event_occurrences`-association to the model as well as `remaining_event_occurrences` and `previous_event_occurrences`-associations.
|
295
|
+
|
296
|
+
Instances of remaining occurrences are persisted when the parent-model is saved.
|
297
|
+
|
298
|
+
Occurrences records will be reused if their datetime matches the saved schedule.
|
299
|
+
Previous occurrences stay untouched.
|
300
|
+
|
301
|
+
### Terminating and non-terminating events
|
177
302
|
An event is terminating if an until- or count-attribute has been specified.
|
178
303
|
Since non-terminating events have infinite occurrences, we cannot build all occurrences at once ;-)
|
179
304
|
So we need to limit the number of occurrences in the database.
|
@@ -181,7 +306,7 @@ By default this will be one year from now.
|
|
181
306
|
This can be configured via the 'build_max_count' and 'build_max_period'-options.
|
182
307
|
See notes on configuration.
|
183
308
|
|
184
|
-
|
309
|
+
### Automate build of occurrences
|
185
310
|
Since we cannot build all occurrences at once, we will need a task that adds occurrences as time goes by.
|
186
311
|
Schedulable comes with a rake-task that performs an update on all scheduled occurrences.
|
187
312
|
|
@@ -191,7 +316,7 @@ rake schedulable:build_occurrences
|
|
191
316
|
|
192
317
|
You may add this task to crontab.
|
193
318
|
|
194
|
-
|
319
|
+
#### Using 'whenever' to schedule build of occurrences
|
195
320
|
|
196
321
|
With the 'whenever' gem this can be easily achieved.
|
197
322
|
|
@@ -222,18 +347,25 @@ Write to crontab:
|
|
222
347
|
whenever -w
|
223
348
|
```
|
224
349
|
|
225
|
-
|
350
|
+
## Configuration
|
226
351
|
Generate the configuration file
|
227
352
|
|
228
353
|
```cli
|
229
354
|
rails g schedulable:config
|
230
355
|
```
|
231
356
|
|
232
|
-
Open 'config/initializers/schedulable.rb' and edit options as
|
357
|
+
Open 'config/initializers/schedulable.rb' and edit options as needed:
|
233
358
|
|
234
359
|
```ruby
|
235
360
|
Schedulable.configure do |config|
|
236
361
|
config.max_build_count = 0
|
237
362
|
config.max_build_period = 1.year
|
363
|
+
config.form_helper = {
|
364
|
+
style: :default
|
365
|
+
}
|
238
366
|
end
|
239
367
|
```
|
368
|
+
|
369
|
+
|
370
|
+
## Changelog
|
371
|
+
See the [Changelog](CHANGELOG.md) for recent enhancements, bugfixes and deprecations.
|
data/Rakefile
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
de:
|
2
|
+
model:
|
3
|
+
schedule: 'Zeitplan'
|
4
|
+
|
5
|
+
activerecord:
|
6
|
+
attributes:
|
7
|
+
schedule:
|
8
|
+
name: Name
|
9
|
+
rule: Regel
|
10
|
+
time: Uhrzeit
|
11
|
+
date: Datum
|
12
|
+
day: Wochentage
|
13
|
+
day_of_week: "Wochentage im Monat"
|
14
|
+
interval: Intervall
|
15
|
+
until: Wiederholen bis
|
16
|
+
count: Anzahl Wiederholungen
|
17
|
+
|
18
|
+
schedulable:
|
19
|
+
monthly_week_names:
|
20
|
+
1st: '1.'
|
21
|
+
2nd: '2.'
|
22
|
+
3rd: '3.'
|
23
|
+
4th: '4.'
|
24
|
+
last: 'L'
|
25
|
+
rules:
|
26
|
+
singular: Einmalig
|
27
|
+
monthly: Monatlich
|
28
|
+
weekly: Wöchentlich
|
29
|
+
daily: Täglich
|
@@ -8,7 +8,7 @@ module Schedulable
|
|
8
8
|
|
9
9
|
def create_locale
|
10
10
|
puts 'install locale'
|
11
|
-
template "
|
11
|
+
template "../../../../config/locales/#{locale}.yml", "config/locales/schedulable.#{locale}.yml"
|
12
12
|
end
|
13
13
|
|
14
14
|
end
|
@@ -1,31 +1,52 @@
|
|
1
1
|
class ScheduleInput < SimpleForm::Inputs::Base
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
def input(wrapper_options)
|
4
|
+
|
5
|
+
|
6
|
+
# I18n
|
5
7
|
weekdays = Date::DAYNAMES.map(&:downcase)
|
6
|
-
daynames = I18n.t('date.day_names')
|
7
|
-
daylabels = Hash[weekdays.zip(daynames)]
|
8
8
|
weekdays = weekdays.slice(1..7) << weekdays.slice(0)
|
9
|
-
|
10
|
-
input_html_options[:type] ||= input_type if html5?
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
10
|
+
day_names = I18n.t('date.day_names', default: "")
|
11
|
+
day_names = day_names.blank? ? weekdays.map { |day| day.capitalize } : day_names.slice(1..7) << day_names.slice(0)
|
12
|
+
day_labels = Hash[weekdays.zip(day_names)]
|
13
|
+
|
14
|
+
# Pass in default month names when missing in translations
|
15
|
+
month_names = I18n.t('date.month_names', default: "")
|
16
|
+
month_names = month_names.blank? ? Date::MONTHNAMES : month_names
|
17
|
+
|
18
|
+
# Pass in default order when missing in translations
|
19
|
+
date_order = I18n.t('date.order', default: "")
|
20
|
+
date_order = date_order.blank? ? [:year, :month, :day] : date_order
|
21
|
+
|
22
|
+
date_options = {
|
23
|
+
order: date_order,
|
24
|
+
use_month_names: month_names
|
25
|
+
}
|
16
26
|
|
27
|
+
# Input html options
|
28
|
+
input_html_options[:type] ||= input_type if html5?
|
29
|
+
|
30
|
+
# Input options
|
31
|
+
input_options[:interval] = !input_options[:interval].nil? ? input_options[:interval] : false
|
32
|
+
input_options[:until] = !input_options[:until].nil? ? input_options[:until] : false
|
33
|
+
input_options[:count] = !input_options[:count].nil? ? input_options[:count] : false
|
34
|
+
|
17
35
|
@builder.simple_fields_for(:schedule, @builder.object.schedule || @builder.object.build_schedule) do |b|
|
36
|
+
|
37
|
+
# Javascript element id
|
38
|
+
field_id = b.object_name.to_s.gsub(/\]\[|[^-a-zA-Z0-9:.]/,"_").sub(/_$/,"")
|
18
39
|
|
19
|
-
b.template.content_tag("div", {id:
|
40
|
+
b.template.content_tag("div", {id: field_id}) do
|
20
41
|
|
21
|
-
b.input(:rule, collection: ['singular', 'daily', 'weekly', 'monthly'], label_method: lambda { |
|
42
|
+
b.input(:rule, collection: ['singular', 'daily', 'weekly', 'monthly'], label_method: lambda { |v| I18n.t("schedulable.rules.#{v}", default: v.capitalize) }, label: false, include_blank: false) <<
|
22
43
|
|
23
44
|
template.content_tag("div", {data: {group: 'singular'}}) do
|
24
|
-
b.input :date
|
45
|
+
b.input :date, date_options
|
25
46
|
end <<
|
26
47
|
|
27
48
|
template.content_tag("div", {data: {group: 'weekly'}}) do
|
28
|
-
b.input :
|
49
|
+
b.input :day, collection: weekdays, label_method: lambda { |v| (" " + day_labels[v]).html_safe}, boolean_style: :nested, as: :check_boxes
|
29
50
|
end <<
|
30
51
|
|
31
52
|
template.content_tag("div", {data: {group: 'monthly'}}) do
|
@@ -33,70 +54,79 @@ class ScheduleInput < SimpleForm::Inputs::Base
|
|
33
54
|
b.simple_fields_for :day_of_week, OpenStruct.new(b.object.day_of_week || {}) do |db|
|
34
55
|
template.content_tag("div", class: 'form-group' + (b.object.errors[:day_of_week].any? ? " has-error" : "")) do
|
35
56
|
b.label(:day_of_week, error: true) <<
|
36
|
-
template.content_tag("
|
37
|
-
template.content_tag("
|
38
|
-
template.content_tag("
|
39
|
-
['1st', '2nd', '3rd', '4th', 'last'].reduce(''.html_safe) { |
|
40
|
-
|
41
|
-
db.label(I18n.t("schedulable.monthly_week_names.#{item}") || item, required: false)
|
42
|
-
end
|
57
|
+
template.content_tag("div", nil, style: 'min-width: 280px; display: table') do
|
58
|
+
template.content_tag("div", nil, style: 'display: table-row') do
|
59
|
+
template.content_tag("span", nil, style: 'display: table-cell;') <<
|
60
|
+
['1st', '2nd', '3rd', '4th', 'last'].reduce(''.html_safe) { | content, item |
|
61
|
+
content << template.content_tag("span", I18n.t("schedulable.monthly_week_names.#{item}", default: item.to_s), style: 'display: table-cell; text-align: center')
|
43
62
|
}
|
44
63
|
end <<
|
45
|
-
weekdays.reduce(''.html_safe) do |
|
46
|
-
|
47
|
-
template.content_tag("
|
48
|
-
|
49
|
-
|
50
|
-
|
64
|
+
weekdays.reduce(''.html_safe) do | content, weekday |
|
65
|
+
content << template.content_tag("div", nil, style: 'display: table-row') do
|
66
|
+
template.content_tag("span", day_labels[weekday] || weekday, style: 'display: table-cell') <<
|
67
|
+
db.collection_check_boxes(weekday.to_sym, [1, 2, 3, 4, -1], lambda { |i| i} , lambda { |i| " ".html_safe}, checked: db.object.send(weekday), item_wrapper_tag: nil) do |cb|
|
68
|
+
template.content_tag("span", cb.check_box(), style: 'display: table-cell; text-align: center')
|
69
|
+
end
|
51
70
|
end
|
52
71
|
end
|
53
|
-
end <<
|
72
|
+
end <<
|
54
73
|
b.error(:day_of_week)
|
55
74
|
end
|
56
75
|
end
|
57
76
|
end <<
|
58
77
|
|
59
|
-
template.content_tag("div",
|
60
|
-
b.input :time
|
78
|
+
template.content_tag("div", data: {group: 'singular,daily,weekly,monthly'}) do
|
79
|
+
b.input :time, date_options
|
61
80
|
end <<
|
62
81
|
|
63
|
-
(
|
64
|
-
|
65
|
-
|
82
|
+
(if input_options[:interval]
|
83
|
+
template.content_tag("div", data: {group: 'daily,weekly,monthly'}) do
|
84
|
+
b.input :interval
|
85
|
+
end
|
86
|
+
else
|
87
|
+
b.input(:interval, as: :hidden, input_html: {value: 1})
|
88
|
+
end) <<
|
66
89
|
|
67
|
-
(
|
68
|
-
|
69
|
-
|
90
|
+
(if input_options[:until]
|
91
|
+
template.content_tag("div", data: {group: 'daily,weekly,monthly'}) do
|
92
|
+
b.input :until, date_options
|
93
|
+
end
|
94
|
+
else
|
95
|
+
b.input(:until, as: :hidden, input_html: {value: nil})
|
96
|
+
end) <<
|
70
97
|
|
71
|
-
|
72
|
-
|
73
|
-
|
98
|
+
if input_options[:count]
|
99
|
+
template.content_tag("div", data: {group: 'daily,weekly,monthly'}) do
|
100
|
+
b.input :count
|
101
|
+
end
|
102
|
+
else
|
103
|
+
b.input(:count, as: :hidden, input_html: {value: 0})
|
104
|
+
end
|
74
105
|
|
75
106
|
|
76
107
|
|
77
108
|
end <<
|
78
109
|
|
79
110
|
template.javascript_tag(
|
80
|
-
"
|
81
|
-
" var container =
|
82
|
-
" var select = container.
|
111
|
+
"(function() {" <<
|
112
|
+
" var container = document.querySelectorAll('##{field_id}'); container = container[container.length - 1]; " <<
|
113
|
+
" var select = container.querySelector(\"select[name*='rule']\"); " <<
|
83
114
|
" function update() {" <<
|
84
115
|
" var value = this.value;" <<
|
85
|
-
" container.
|
86
|
-
" var groups =
|
87
|
-
" if (
|
88
|
-
"
|
116
|
+
" [].slice.call(container.querySelectorAll(\"*[data-group]\")).forEach(function(elem) { " <<
|
117
|
+
" var groups = elem.getAttribute('data-group').split(',');" <<
|
118
|
+
" if (groups.indexOf(value) >= 0) {" <<
|
119
|
+
" elem.style.display = ''" <<
|
89
120
|
" } else {" <<
|
90
|
-
"
|
121
|
+
" elem.style.display = 'none'" <<
|
91
122
|
" }" <<
|
92
123
|
" });" <<
|
93
124
|
" }" <<
|
94
|
-
" select.on('change', update);" <<
|
95
|
-
" update.call(select
|
96
|
-
"})"
|
125
|
+
" if (jQuery) { jQuery(select).on('change', update); } else { select.addEventListener('change', update); }" <<
|
126
|
+
" update.call(select);" <<
|
127
|
+
"})()"
|
97
128
|
)
|
98
129
|
|
99
|
-
|
100
130
|
end
|
101
131
|
|
102
132
|
|