conschedule 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +154 -0
- data/Rakefile +37 -0
- data/app/assets/config/conschedule_manifest.js +2 -0
- data/app/assets/fonts/icomoon.eot +0 -0
- data/app/assets/fonts/proxima_nova_100.eot +0 -0
- data/app/assets/fonts/proxima_nova_400.eot +0 -0
- data/app/assets/fonts/proxima_nova_700.eot +0 -0
- data/app/assets/images/conschedule/chosen-sprite-small.png +0 -0
- data/app/assets/images/conschedule/chosen-sprite.png +0 -0
- data/app/assets/images/conschedule/close.png +0 -0
- data/app/assets/images/conschedule/spinner-small.gif +0 -0
- data/app/assets/images/conschedule/spinner.gif +0 -0
- data/app/assets/javascripts/conschedule/application.js +22 -0
- data/app/assets/javascripts/conschedule/calendar.js +467 -0
- data/app/assets/javascripts/conschedule/date.js +104 -0
- data/app/assets/javascripts/conschedule/form.js +53 -0
- data/app/assets/javascripts/conschedule/home.js +149 -0
- data/app/assets/javascripts/conschedule/jquery-ui-datepicker.min.js +1674 -0
- data/app/assets/javascripts/conschedule/jquery.easing.min.js +44 -0
- data/app/assets/javascripts/conschedule/jquery.validate.js +1532 -0
- data/app/assets/javascripts/conschedule/js_time_zone.js +1433 -0
- data/app/assets/javascripts/conschedule/moment-timezone.js +1209 -0
- data/app/assets/javascripts/conschedule/moment.js +4195 -0
- data/app/assets/javascripts/conschedule/schedules.js +22 -0
- data/app/assets/javascripts/conschedule/time_zones_drop_down.js +609 -0
- data/app/assets/stylesheets/conschedule/application.css +4 -0
- data/app/assets/stylesheets/conschedule/common.css +816 -0
- data/app/assets/stylesheets/conschedule/home.css +2441 -0
- data/app/assets/stylesheets/conschedule/main.css +884 -0
- data/app/assets/stylesheets/conschedule/schedules.css +4 -0
- data/app/controllers/conschedule/application_controller.rb +49 -0
- data/app/controllers/conschedule/schedules_controller.rb +125 -0
- data/app/helpers/conschedule/application_helper.rb +15 -0
- data/app/helpers/conschedule/schedules_helper.rb +43 -0
- data/app/jobs/conschedule/application_job.rb +4 -0
- data/app/mailers/conschedule/schedules_mailer.rb +46 -0
- data/app/models/conschedule/application_record.rb +5 -0
- data/app/models/conschedule/schedule.rb +63 -0
- data/app/views/conschedule/schedules/_confirmation.html.erb +38 -0
- data/app/views/conschedule/schedules/_page_one.html.erb +75 -0
- data/app/views/conschedule/schedules/_page_three.html.erb +94 -0
- data/app/views/conschedule/schedules/_page_two.html.erb +22 -0
- data/app/views/conschedule/schedules/_schedules.html.erb +122 -0
- data/app/views/conschedule/schedules/create.js.erb +11 -0
- data/app/views/conschedule/schedules/index.html.erb +123 -0
- data/app/views/conschedule/schedules/index.js.erb +3 -0
- data/app/views/conschedule/schedules/new.html.erb +11 -0
- data/app/views/conschedule/schedules_mailer/send_cancel_email_owner.html.erb +61 -0
- data/app/views/conschedule/schedules_mailer/send_cancel_email_user.html.erb +29 -0
- data/app/views/conschedule/schedules_mailer/send_confirmation_email_owner.html.erb +77 -0
- data/app/views/conschedule/schedules_mailer/send_confirmation_email_user.html.erb +30 -0
- data/app/views/kaminari/custom_theme/_first_page.html.erb +3 -0
- data/app/views/kaminari/custom_theme/_gap.html.erb +1 -0
- data/app/views/kaminari/custom_theme/_last_page.html.erb +3 -0
- data/app/views/kaminari/custom_theme/_next_page.html.erb +1 -0
- data/app/views/kaminari/custom_theme/_page.html.erb +5 -0
- data/app/views/kaminari/custom_theme/_paginator.html.erb +23 -0
- data/app/views/kaminari/custom_theme/_prev_page.html.erb +1 -0
- data/app/views/layouts/conschedule/application.html.erb +14 -0
- data/app/views/layouts/conschedule/mailer.html.erb +11 -0
- data/app/views/layouts/conschedule/schedules.html.erb +14 -0
- data/config/initializers/assets.rb +11 -0
- data/config/routes.rb +11 -0
- data/db/migrate/20160812085505_create_conschedule_schedules.rb +27 -0
- data/lib/conschedule.rb +34 -0
- data/lib/conschedule/configuration.rb +25 -0
- data/lib/conschedule/engine.rb +5 -0
- data/lib/conschedule/gem_dependencies.rb +2 -0
- data/lib/conschedule/version.rb +3 -0
- data/lib/generators/conschedule/install_generator.rb +23 -0
- data/lib/generators/conschedule/views_generator.rb +45 -0
- data/lib/generators/templates/README +40 -0
- data/lib/generators/templates/initializer.rb +25 -0
- data/lib/tasks/conschedule_tasks.rake +4 -0
- metadata +182 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 93620dd4e9b1866e48c1b3d48271803f1429784c
|
4
|
+
data.tar.gz: a387a284eb4e5b8c0d00aadf9d89d7efb8dec04a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3051f2550ddb41658887a827d5bde6b8cab6542b9d148d50bb97f1908439b09bc54366bf955a33f12000e16d7c8bc2e4a1f9b46e24e50924f4d9c4ea0f74401b
|
7
|
+
data.tar.gz: c794bf2dd5cd43c9b8024e9319f8ac48b50c87cbb03a2d8e9cd6d199dcbbb1fa09c5363a802971995e8c51dca7dbe71a3ad072d210714435531d57a0e1f0788a
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2016 Sakilam Sandeep
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
# Conschedule
|
2
|
+
|
3
|
+
Conschedule library for Rails
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'conschedule'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install conschedule
|
20
|
+
|
21
|
+
## Embedding in a Rails app
|
22
|
+
|
23
|
+
Add the following to your routes.rb file:
|
24
|
+
|
25
|
+
``` ruby
|
26
|
+
mount Conschedule::Engine, at: "/"
|
27
|
+
```
|
28
|
+
|
29
|
+
(NOTE: You may mount the server at any path, not just "/")
|
30
|
+
|
31
|
+
You can then browse to your application path to view listing page, conschedule form page i.e.
|
32
|
+
|
33
|
+
* For listing page: http://127.0.0.1:3000
|
34
|
+
* For contact form page: http://127.0.0.1:3000/schedules/new
|
35
|
+
|
36
|
+
If you wish to authenticate listing page with Devise, it would look something like:
|
37
|
+
|
38
|
+
``` ruby
|
39
|
+
authenticate :admin do
|
40
|
+
get "/admin/schedules" => "conschedule/schedules#index"
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
## Configuration
|
45
|
+
|
46
|
+
Conschedule is extremely simple to setup. Just configure basic settings for Conschedule:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
Conschedule.configuration do |config|
|
50
|
+
config.main_heading = "Contact"
|
51
|
+
config.purpose = 'An introduction to our product'
|
52
|
+
config.instructions = 'Learn about our product'
|
53
|
+
config.location_details = 'Details will be provided on confirmation'
|
54
|
+
config.system_time_zone = "UTC"
|
55
|
+
config.start_date = "2016-01-01"
|
56
|
+
config.end_date = "2016-12-31"
|
57
|
+
config.available_days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
|
58
|
+
config.black_out_dates
|
59
|
+
config.sun_timings = ["09:00", "17:00"]
|
60
|
+
config.mon_timings = ["09:00", "17:00"]
|
61
|
+
config.tue_timings = ["09:00", "17:00"]
|
62
|
+
config.wed_timings = ["09:00", "17:00"]
|
63
|
+
config.thu_timings = ["09:00", "17:00"]
|
64
|
+
config.fri_timings = ["09:00", "17:00"]
|
65
|
+
config.sat_timings = ["09:00", "17:00"]
|
66
|
+
config.duration = 30
|
67
|
+
config.from_address = "PLEASE-CHANGE-ME@example.com"
|
68
|
+
config.send_confirmation_mail = false
|
69
|
+
config.send_cancel_mail = false
|
70
|
+
config.to_address = "PLEASE-CHANGE-ME@example.com"
|
71
|
+
config.contact_name = "PLEASE-CHANGE-ME"
|
72
|
+
config.enable_tz = true
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
The key options available are:
|
77
|
+
|
78
|
+
| Option | Description |
|
79
|
+
| ----------------- | ------------------------------- |
|
80
|
+
| `main_heading` | String to add page heading/title. |
|
81
|
+
| `instructions` | String to convey a message to user. |
|
82
|
+
| `location_details` | String to provide location details to user. |
|
83
|
+
| `system_time_zone` | TimeZone defines time zone of the application. |
|
84
|
+
| `start_date` | Date defines the start date of the calendar. |
|
85
|
+
| `end_date` | Date defines the end date of the calendar. |
|
86
|
+
| `available_days` | Array of abbreviated weekday name. |
|
87
|
+
| `black_out_dates` | Array of dates to mark unavailable dates in calendar. |
|
88
|
+
| `sun_timings` | Array of times defines start and end time of weekday Sunday. |
|
89
|
+
| `mon_timings` | Array of times defines start and end time of weekday Monday. |
|
90
|
+
| `tue_timings` | Array of times defines start and end time of weekday Tuesday. |
|
91
|
+
| `wed_timings` | Array of times defines start and end time of weekday Wednesday. |
|
92
|
+
| `thu_timings` | Array of times defines start and end time of weekday Thursday. |
|
93
|
+
| `fri_timings` | Array of times defines start and end time of weekday Friday. |
|
94
|
+
| `sat_timings` | Array of times defines start and end time of weekday Saturday. |
|
95
|
+
| `duration` | Integer defines duration of the slot in minutes. |
|
96
|
+
| `from_address` | String for sending confirmation and cancel mails. |
|
97
|
+
| `send_confirmation_mail` | Boolean defines wheather a copy of confirmation mail to be sent to the 'to_address'. |
|
98
|
+
| `send_cancel_mail` | Boolean defines wheather a copy of cancel mail to be sent to the 'to_address'. |
|
99
|
+
| `to_address` | String for receving confirmation and cancel mails. |
|
100
|
+
| `contact_name` | String used in confirmation and cancel mails. |
|
101
|
+
| `enable_tz` | Boolean defines wheather the time zone drop down should be active/inactive. |
|
102
|
+
|
103
|
+
Ensure you have set 'from_address' and 'contact_name' in config/initializers/conschedule.rb
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
config.from_address = "foo@example.com"
|
107
|
+
config.contact_name = "foo"
|
108
|
+
```
|
109
|
+
|
110
|
+
If you wish to receive confirmation and cancel mails, ensure you have set following config variables in config/initializers/conschedule.rb:
|
111
|
+
|
112
|
+
```ruby
|
113
|
+
config.send_confirmation_mail = true
|
114
|
+
config.send_cancel_mail = true
|
115
|
+
config.to_address = "foo@example.com"
|
116
|
+
```
|
117
|
+
|
118
|
+
## Customization
|
119
|
+
|
120
|
+
We built Conschedule to help you quickly integrate contact form in your application. However, we don't want to be in your way when you need to customize it.
|
121
|
+
|
122
|
+
Since Conschedule is an engine, all its views are packaged inside the gem. These views will help you get started, but after some time you may want to change them. If this is the case, you just need to invoke the following generator, and it will copy all views to your application:
|
123
|
+
|
124
|
+
```console
|
125
|
+
$ rails generate conschedule:views
|
126
|
+
```
|
127
|
+
|
128
|
+
If you would like to generate only a few sets of views, like the ones for the `form` and `listing`,
|
129
|
+
you can pass a list of names to the generator with the `-v` flag.
|
130
|
+
|
131
|
+
```console
|
132
|
+
$ rails generate conschedule:views -v form listing
|
133
|
+
```
|
134
|
+
|
135
|
+
## Contributing
|
136
|
+
|
137
|
+
1. Fork it ( https://github.com/rubyeffect/conschedule/fork )
|
138
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
139
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
140
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
141
|
+
5. Create a new Pull Request
|
142
|
+
|
143
|
+
## Links
|
144
|
+
|
145
|
+
* Code: `git clone git://github.com/rubyeffect/conschedule.git`
|
146
|
+
* Home: <http://github.com/rubyeffect/conschedule>
|
147
|
+
|
148
|
+
## About RubyEffect
|
149
|
+
|
150
|
+
![RubyEffect](http://blog.rubyeffect.com/wp-content/uploads/2015/05/cropped-re_original_logo.png)
|
151
|
+
|
152
|
+
RubyEffect builds intuitive, live and elegant software that solves real world problems. We love open source and it's community.
|
153
|
+
|
154
|
+
We would love to work on your ideas and see them grow. Say hello @ http://rubyeffect.com/contact
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Conschedule'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
require 'bundler/gem_tasks'
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
task default: :test
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,22 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require conschedule/jquery.easing.min
|
16
|
+
//= require conschedule/moment
|
17
|
+
//= require conschedule/moment-timezone
|
18
|
+
//= require conschedule/jquery.validate
|
19
|
+
//= require conschedule/js_time_zone
|
20
|
+
//= require conschedule/date
|
21
|
+
//= require conschedule/jquery-ui-datepicker.min
|
22
|
+
//= require conschedule/home
|
@@ -0,0 +1,467 @@
|
|
1
|
+
var page_info = gon.page_info;
|
2
|
+
if (page_info.enable_tz) {
|
3
|
+
var user_tz = jstz.determine().name();
|
4
|
+
}
|
5
|
+
else {
|
6
|
+
var user_tz = page_info.system_time_zone;
|
7
|
+
}
|
8
|
+
var calendar_data, selected_date, formatted_tz, slot_date, slot_start_time, slot_end_time;
|
9
|
+
|
10
|
+
function is_null_or_undef(variable) {
|
11
|
+
return (variable === null || variable === undefined);
|
12
|
+
}
|
13
|
+
|
14
|
+
function build_calendar(sequence) {
|
15
|
+
var date = start_date();
|
16
|
+
var no_of_days = 6;
|
17
|
+
var count = 0;
|
18
|
+
var dates_set = [];
|
19
|
+
while (dates_set.length <= no_of_days) {
|
20
|
+
if (!black_out_day(moment(date).format("ddd"))) {
|
21
|
+
dates_set.push(date);
|
22
|
+
count += 1;
|
23
|
+
}
|
24
|
+
date = sequence == "forward" ? tomorrow(date) : yesterday(date);
|
25
|
+
}
|
26
|
+
if ( sequence == "backward" ) {
|
27
|
+
dates_set = dates_set.reverse();
|
28
|
+
}
|
29
|
+
calendar_data = build_dates_set(dates_set);
|
30
|
+
generate_dates_template(calendar_data.days,calendar_data.today);
|
31
|
+
}
|
32
|
+
|
33
|
+
function start_date() {
|
34
|
+
return is_null_or_undef(page_info.start_date) ? user_cdt("YYYY-MM-DD") : moment.tz(page_info.start_date,page_info.system_time_zone).format("YYYY-MM-DD") < system_cdt("YYYY-MM-DD") ? system_cdt("YYYY-MM-DD") : moment.tz(page_info.start_date,page_info.system_time_zone).format("YYYY-MM-DD");
|
35
|
+
}
|
36
|
+
|
37
|
+
function end_date() {
|
38
|
+
return is_null_or_undef(page_info.end_date) ? null : moment.tz(page_info.end_date,page_info.system_time_zone).format("YYYY-MM-DD");
|
39
|
+
}
|
40
|
+
|
41
|
+
function user_cdt(pattern) {
|
42
|
+
return moment.tz(user_tz).format(pattern);
|
43
|
+
}
|
44
|
+
|
45
|
+
function system_cdt(pattern) {
|
46
|
+
return moment.tz(page_info.system_time_zone).format(pattern);
|
47
|
+
}
|
48
|
+
|
49
|
+
function black_out_day(weekday) {
|
50
|
+
return $.inArray(weekday, page_info.available_days) == -1
|
51
|
+
}
|
52
|
+
|
53
|
+
function tomorrow(date) {
|
54
|
+
return moment.tz(date,user_tz).add(1, 'days').format("YYYY-MM-DD");
|
55
|
+
}
|
56
|
+
|
57
|
+
function yesterday(date) {
|
58
|
+
return moment.tz(date,user_tz).add(-1, 'days').format("YYYY-MM-DD");
|
59
|
+
}
|
60
|
+
|
61
|
+
function build_dates_set(dates) {
|
62
|
+
if ( is_null_or_undef(page_info.calendar_start_date) ) {
|
63
|
+
page_info.calendar_start_date = dates[0];
|
64
|
+
}
|
65
|
+
data = {today: user_cdt("YYYY-MM-DD"), days: [], weeks: []};
|
66
|
+
var time_slots;
|
67
|
+
$.each(dates, function( index, date ) {
|
68
|
+
time_slots = get_time_slots(date);
|
69
|
+
day_set = {
|
70
|
+
date: date,
|
71
|
+
day_short: date_format(moment.tz(date,user_tz),"day_short"),
|
72
|
+
day_full: date_format(moment.tz(date,user_tz),"day_full"),
|
73
|
+
date_short: date_format(moment.tz(date,user_tz),"date_short"),
|
74
|
+
date_short_lz: date_format(moment.tz(date,user_tz),"date_short_lz"),
|
75
|
+
date_full: date_format(moment.tz(date,user_tz),"date_full"),
|
76
|
+
slots: time_slots,
|
77
|
+
status: get_day_status(date,end_date(),time_slots.availability),
|
78
|
+
separator: is_separator_point(date, dates[index + 1], index)
|
79
|
+
}
|
80
|
+
data.days.push(day_set);
|
81
|
+
if ( day_set.separator == "separator" || index == 6 ) {
|
82
|
+
data.weeks.push(build_labels_set(data.days,data.weeks,date));
|
83
|
+
}
|
84
|
+
});
|
85
|
+
return data;
|
86
|
+
}
|
87
|
+
|
88
|
+
function get_time_slots(date) {
|
89
|
+
var day = moment(date).format("ddd").toLowerCase();
|
90
|
+
var slots = {morning: [], noon: [], availability: true};
|
91
|
+
var slot_value;
|
92
|
+
if ( system_cdt("YYYY-MM-DD HH:mm") < day_end_time(day,date,false)) {
|
93
|
+
if ( date == system_cdt("YYYY-MM-DD") ) {
|
94
|
+
var computed_start_time = moment.tz(page_info.system_time_zone).tz(user_tz).format("YYYY-MM-DD HH:mm");
|
95
|
+
}
|
96
|
+
var start_time = day_start_time(day,date,true);
|
97
|
+
var end_time = day_end_time(day,date,true);
|
98
|
+
while (start_time < end_time) {
|
99
|
+
if ( is_null_or_undef(computed_start_time) ) {
|
100
|
+
slot_value = moment(start_time).format("hh:mma");
|
101
|
+
}
|
102
|
+
else {
|
103
|
+
if ( start_time > computed_start_time ) {
|
104
|
+
slot_value = moment(start_time).format("hh:mma");
|
105
|
+
}
|
106
|
+
}
|
107
|
+
if ( !is_null_or_undef(slot_value) ) {
|
108
|
+
if ( slot_value.search('am') != -1 ) {
|
109
|
+
slots.morning.push(slot_value);
|
110
|
+
}
|
111
|
+
else {
|
112
|
+
slots.noon.push(slot_value);
|
113
|
+
}
|
114
|
+
}
|
115
|
+
start_time = moment(start_time).add(page_info.duration, 'minutes').format("YYYY-MM-DD HH:mm");
|
116
|
+
}
|
117
|
+
}
|
118
|
+
if ( slots.morning.length == 0 && slots.noon.length == 0 ) {
|
119
|
+
slots.availability = false;
|
120
|
+
}
|
121
|
+
return slots;
|
122
|
+
}
|
123
|
+
|
124
|
+
function timings(day,position) {
|
125
|
+
var duration = day + "_timings";
|
126
|
+
return position == "start" ? page_info[duration][0] : page_info[duration][1];
|
127
|
+
}
|
128
|
+
|
129
|
+
function day_start_time(day,date,converted) {
|
130
|
+
var day_start_time = timings(day,'start');
|
131
|
+
var date_time = date + " " + day_start_time;
|
132
|
+
var dt_str;
|
133
|
+
if ( converted ) {
|
134
|
+
dt_str = moment.tz(date_time,page_info.system_time_zone).tz(user_tz).format("YYYY-MM-DD HH:mm");
|
135
|
+
}
|
136
|
+
else {
|
137
|
+
dt_str = moment.tz(date_time,page_info.system_time_zone).format("YYYY-MM-DD HH:mm");
|
138
|
+
}
|
139
|
+
return dt_str;
|
140
|
+
}
|
141
|
+
|
142
|
+
function day_end_time(day,date,converted) {
|
143
|
+
var day_end_time = timings(day,'end');
|
144
|
+
var date_time = date + " " + day_end_time;
|
145
|
+
var dt_str;
|
146
|
+
if ( converted ) {
|
147
|
+
dt_str = moment.tz(date_time,page_info.system_time_zone).tz(user_tz).format("YYYY-MM-DD HH:mm");
|
148
|
+
}
|
149
|
+
else {
|
150
|
+
dt_str = moment.tz(date_time,page_info.system_time_zone).format("YYYY-MM-DD HH:mm");
|
151
|
+
}
|
152
|
+
return dt_str;
|
153
|
+
}
|
154
|
+
|
155
|
+
function date_format(date, format) {
|
156
|
+
var date_str;
|
157
|
+
switch (format) {
|
158
|
+
case "day_short":
|
159
|
+
date_str = date.format("ddd");
|
160
|
+
break;
|
161
|
+
case "day_full":
|
162
|
+
date_str = date.format("dddd");
|
163
|
+
break;
|
164
|
+
case "date":
|
165
|
+
date_str = date.format("YYYY-MM-DD");
|
166
|
+
break;
|
167
|
+
case "date_time":
|
168
|
+
date_str = date.format("YYYY-MM-DD HH:mm");
|
169
|
+
break;
|
170
|
+
case "date_short":
|
171
|
+
date_str = date.format("MMM D");
|
172
|
+
break;
|
173
|
+
case "date_short_lz":
|
174
|
+
date_str = date.format("MMM DD");
|
175
|
+
break;
|
176
|
+
case "date_full":
|
177
|
+
date_str = date.format("MMMM D, YYYY");
|
178
|
+
break;
|
179
|
+
}
|
180
|
+
return date_str;
|
181
|
+
}
|
182
|
+
|
183
|
+
function get_day_status(date,finish_date,availability) {
|
184
|
+
return (date > finish_date || $.inArray(date, black_out_dates()) != -1 || availability == false) ? 'unavailable' : 'available'
|
185
|
+
}
|
186
|
+
|
187
|
+
function black_out_dates() {
|
188
|
+
dates = []
|
189
|
+
if ( !$.isEmptyObject(page_info.black_out_dates) ) {
|
190
|
+
$.each(page_info.black_out_dates, function( index, date ) {
|
191
|
+
dates.push(date_format(moment.tz(date,user_tz),"date"));
|
192
|
+
});
|
193
|
+
}
|
194
|
+
return dates;
|
195
|
+
}
|
196
|
+
|
197
|
+
function is_separator_point(date, next_date, count) {
|
198
|
+
return is_null_or_undef(next_date) ? "no-separator" : (week_number(date) != week_number(next_date) && count != 6) ? "separator" : "no-separator"
|
199
|
+
}
|
200
|
+
|
201
|
+
function week_number(date) {
|
202
|
+
return moment.tz(date,user_tz).isoWeek()
|
203
|
+
}
|
204
|
+
|
205
|
+
function build_labels_set(days,weeks,date) {
|
206
|
+
if ( $.isEmptyObject(weeks) ) {
|
207
|
+
var label = page_info.calendar_start_date == days[0].date ? "this week" : get_week_label(date);
|
208
|
+
var set = {label: label, "length": days.length};
|
209
|
+
}
|
210
|
+
else {
|
211
|
+
var total_length = 0;
|
212
|
+
$.each(weeks, function( index, week ) {
|
213
|
+
total_length += week.length;
|
214
|
+
});
|
215
|
+
var set = {label: get_week_label(date), "length": days.length - total_length};
|
216
|
+
}
|
217
|
+
return set;
|
218
|
+
}
|
219
|
+
|
220
|
+
function generate_dates_template(days,today_date) {
|
221
|
+
var ele = $('.js-days-body');
|
222
|
+
$.each(days, function( index, day ) {
|
223
|
+
var outer_html = '<div class="fraction js-day-wrapper ' + day.status + ' ' + day.separator + '"></div>';
|
224
|
+
if ( day.date === today_date ) {
|
225
|
+
var today_html = '<div class="today">– TODAY –</div>';
|
226
|
+
outer_html = $(outer_html).append(today_html);
|
227
|
+
}
|
228
|
+
var day_html = '<div class="day js-show-picker"></div>';
|
229
|
+
var day_full_html = '<div></div>';
|
230
|
+
var day_short_html = '<strong class="shorthand">' + day.day_short + '</strong><strong class="full">' + day.day_full + '</strong>';
|
231
|
+
day_full_html = $(day_full_html).append(day_short_html);
|
232
|
+
if ( day.date === today_date ) {
|
233
|
+
today_html = '<strong class="today-mobile">(TODAY)</strong>';
|
234
|
+
day_full_html = $(day_full_html).append(today_html);
|
235
|
+
}
|
236
|
+
day_html = $(day_html).append(day_full_html);
|
237
|
+
var date_html = '<div><div class="muted shorthand">' + day.date_short + '</div><div class="muted full">' + day.date_full + '</div></div>';
|
238
|
+
day_html = $(day_html).append(date_html);
|
239
|
+
var right_icon_html = '<i class="icon-arrow-right"></i>';
|
240
|
+
day_html = $(day_html).append(right_icon_html);
|
241
|
+
outer_html = $(outer_html).append(day_html);
|
242
|
+
if ( day.status === "unavailable" ) {
|
243
|
+
var status_html = '<span class="status">unavailable</span>';
|
244
|
+
outer_html = $(outer_html).append(status_html);
|
245
|
+
}
|
246
|
+
$('.js-spinner').addClass('hidden');
|
247
|
+
$('.js-navigation-prev').show();
|
248
|
+
$('.js-navigation-next').show();
|
249
|
+
$(ele).append(outer_html);
|
250
|
+
});
|
251
|
+
generate_labels_template(calendar_data.weeks);
|
252
|
+
}
|
253
|
+
|
254
|
+
function generate_labels_template(weeks) {
|
255
|
+
$(".js-weeks-region").html('<div><div class="scale"></div>');
|
256
|
+
var scale = $('.scale');
|
257
|
+
$.each(weeks, function( index, week ) {
|
258
|
+
var label_html = '<div class="division size' + week.length +'of7"><span class="label">' + week.label + '</span></div>';
|
259
|
+
scale.append(label_html);
|
260
|
+
});
|
261
|
+
load_calendar_navigation();
|
262
|
+
}
|
263
|
+
|
264
|
+
function calendar_date(order,format) {
|
265
|
+
var day = order == "start" ? calendar_data.days[0] : calendar_data.days[calendar_data.days.length - 1];
|
266
|
+
var date_str;
|
267
|
+
switch (format) {
|
268
|
+
case "date":
|
269
|
+
date_str = day.date;
|
270
|
+
break;
|
271
|
+
case "short_date_lz":
|
272
|
+
date_str = day.date_short_lz;
|
273
|
+
break;
|
274
|
+
}
|
275
|
+
return date_str;
|
276
|
+
}
|
277
|
+
|
278
|
+
function calendar_loader() {
|
279
|
+
$('.js-spinner').removeClass('hidden');
|
280
|
+
$('.js-navigation-prev').hide();
|
281
|
+
$('.js-navigation-next').hide();
|
282
|
+
$('.js-pagination-bar').empty();
|
283
|
+
$('.js-weeks-region').empty();
|
284
|
+
$('.js-days-body').empty();
|
285
|
+
}
|
286
|
+
|
287
|
+
function load_calendar_navigation() {
|
288
|
+
var left_navigation = '<strong class="left" data-nav="previous"><i class="icon-arrow-left-fill"></i>Before <span class="js-period-start-caption">' + calendar_date("start","short_date_lz") + '</span></strong>';
|
289
|
+
var right_navigation = '<strong class="right" data-nav="next">After <span class="js-period-end-caption">' + calendar_date("end","short_date_lz") + '</span><i class="icon-arrow-right-fill"></i></strong>';
|
290
|
+
$(".js-pagination-bar").append(left_navigation);
|
291
|
+
$(".js-pagination-bar").append(right_navigation);
|
292
|
+
if ( calendar_date("start","date") != page_info.calendar_start_date ) {
|
293
|
+
$('.js-navigation-prev').removeClass('disabled');
|
294
|
+
$('.left').removeClass('disabled');
|
295
|
+
}
|
296
|
+
else {
|
297
|
+
$('.js-navigation-prev').addClass('disabled');
|
298
|
+
$('.left').addClass('disabled');
|
299
|
+
}
|
300
|
+
calendar_bind_events();
|
301
|
+
}
|
302
|
+
|
303
|
+
function initialize_calendar(sequence) {
|
304
|
+
setTimeout(function() {
|
305
|
+
build_calendar(sequence);
|
306
|
+
}, 1000);
|
307
|
+
}
|
308
|
+
|
309
|
+
function get_week_label(date) {
|
310
|
+
var start_week_number = week_number(page_info.calendar_start_date);
|
311
|
+
var current_week_number = week_number(date);
|
312
|
+
var difference = current_week_number - start_week_number;
|
313
|
+
var week_str;
|
314
|
+
if ( difference == 1 ) {
|
315
|
+
week_str = "next week";
|
316
|
+
}
|
317
|
+
else {
|
318
|
+
week_str = difference + " weeks out";
|
319
|
+
}
|
320
|
+
return week_str;
|
321
|
+
}
|
322
|
+
|
323
|
+
function navigate(direction) {
|
324
|
+
calendar_loader();
|
325
|
+
page_info.start_date = direction == "forward" ? tomorrow(calendar_date("end","date")) : yesterday(calendar_date('start',"date"));
|
326
|
+
initialize_calendar(direction);
|
327
|
+
}
|
328
|
+
|
329
|
+
function load_calendar_tz(time_zone) {
|
330
|
+
user_tz = time_zone;
|
331
|
+
calendar_loader();
|
332
|
+
page_info.start_date = page_info.original_start_date;
|
333
|
+
initialize_calendar("forward");
|
334
|
+
}
|
335
|
+
|
336
|
+
function generate_date_slots_template(index) {
|
337
|
+
var time_slots = calendar_data.days[index].slots;
|
338
|
+
var am_template = $('<div class="js-am-spot-list"><ul class="spots"></ul></div>');
|
339
|
+
var pm_template = $('<div class="js-pm-spot-list"><ul class="spots"></ul></div>');
|
340
|
+
if ( time_slots.morning.length != 0 ) {
|
341
|
+
$.each(time_slots.morning, function( index, time ) {
|
342
|
+
am_template.find("ul.spots").append('<li class="spot available collapsed"><button class="time-button js-select">' + time + '<div class="status">available</div></button><button class="confirm-button hollow base js-confirm">Confirm</button></li>');
|
343
|
+
$('.js-spot-list').append(am_template);
|
344
|
+
});
|
345
|
+
}
|
346
|
+
if ( time_slots.morning.length != 0 && time_slots.noon.length != 0 ) {
|
347
|
+
$('.js-spot-list').append('<div class="js-meridiem meridiem" style="display: block;"><div class="text">noon</div></div>');
|
348
|
+
}
|
349
|
+
if ( time_slots.noon.length != 0 ) {
|
350
|
+
$.each(time_slots.noon, function( index, time ) {
|
351
|
+
pm_template.find("ul.spots").append('<li class="spot available collapsed"><button class="time-button js-select">' + time + '<div class="status">available</div></button><button class="confirm-button hollow base js-confirm">Confirm</button></li>');
|
352
|
+
$('.js-spot-list').append(pm_template);
|
353
|
+
});
|
354
|
+
}
|
355
|
+
time_slot_bind_events();
|
356
|
+
}
|
357
|
+
|
358
|
+
function calendar_bind_events() {
|
359
|
+
$('.right').on('click', function(){
|
360
|
+
navigate("forward");
|
361
|
+
});
|
362
|
+
$('.left').on('click', function(){
|
363
|
+
navigate("backward");
|
364
|
+
});
|
365
|
+
$(".js-day-wrapper").click(function() {
|
366
|
+
if ( !$(this).hasClass('unavailable') ) {
|
367
|
+
$(".js-spot-list").empty();
|
368
|
+
selected_date = moment($(this).find('div.full').html(),"MMMM DD, YYYY").format("YYYY-MM-DD");
|
369
|
+
$(".selected_day").html(date_format(moment(selected_date),"day_full"));
|
370
|
+
$(".selected_date").html(date_format(moment(selected_date),"date_full"));
|
371
|
+
$(".selected_tz").html(format_tz($(".chzn-single span").html()));
|
372
|
+
slot_date = date_format(moment(selected_date),"date");
|
373
|
+
generate_date_slots_template($(".js-day-wrapper").index($(this)));
|
374
|
+
reset_state($(".spot:first"));
|
375
|
+
wizard_next_step($(this));
|
376
|
+
}
|
377
|
+
});
|
378
|
+
}
|
379
|
+
|
380
|
+
function time_slot_bind_events() {
|
381
|
+
$(".spot").click(function(e) {
|
382
|
+
e.preventDefault();
|
383
|
+
reset_state($(this));
|
384
|
+
$(this).addClass("selected");
|
385
|
+
$(this).find(".time-button").addClass("neutral")
|
386
|
+
});
|
387
|
+
$(".confirm-button").click(function() {
|
388
|
+
var time = $(this).parent().find(".time-button").clone().children().remove().end().text();
|
389
|
+
$("div.slot-details").html('<i class="icon-clock"></i>' + " " + time + " - " + date_format(moment(selected_date),"day_full") + ", " + date_format(moment(selected_date),"date_full"));
|
390
|
+
$("div.tz-details").html('<i class="icon-globe"></i>' + " " + formatted_tz);
|
391
|
+
slot_start_time = moment(time,"HH:mma").format("HH:mm");
|
392
|
+
slot_end_time = moment(time,"HH:mma").add(page_info.duration,'minutes').format("HH:mm");
|
393
|
+
wizard_next_step($(this));
|
394
|
+
});
|
395
|
+
}
|
396
|
+
|
397
|
+
function reset_state(ele) {
|
398
|
+
var spots = ele.parent();
|
399
|
+
spots.find(".selected").removeClass("selected");
|
400
|
+
spots.find(".neutral").removeClass("neutral");
|
401
|
+
}
|
402
|
+
|
403
|
+
function format_tz(tz) {
|
404
|
+
formatted_tz = tz;
|
405
|
+
if ( tz.search('GMT') != -1 ) {
|
406
|
+
formatted_tz = tz.split(" ").slice(1).join(" ");
|
407
|
+
}
|
408
|
+
return formatted_tz;
|
409
|
+
}
|
410
|
+
|
411
|
+
function auto_detect_tz() {
|
412
|
+
if ( page_info.enable_tz ) {
|
413
|
+
var user_time_zone = jstz.determine().name();
|
414
|
+
$.each($('li.group-option'), function( index, li ) {
|
415
|
+
if ( $(li).data('timezone-identifier') == moment().tz_name(user_time_zone) ) {
|
416
|
+
$('#timezone_dropdown_chzn a span').html($(li).html());
|
417
|
+
$('.js-timezone-dropdown').val($(li).data('timezone-identifier'));
|
418
|
+
$("#schedule_user_tz_offset").val($(li).html());
|
419
|
+
}
|
420
|
+
if ( $(li).data('timezone-identifier') == page_info.system_time_zone ) {
|
421
|
+
$("#schedule_app_tz_offset").val($(li).html());
|
422
|
+
}
|
423
|
+
});
|
424
|
+
}
|
425
|
+
else {
|
426
|
+
$.each($('li.group-option'), function( index, li ) {
|
427
|
+
if ( $(li).data('timezone-identifier') == page_info.system_time_zone ) {
|
428
|
+
$('#timezone_dropdown_chzn a span').html($(li).html());
|
429
|
+
$('.js-timezone-dropdown').val($(li).data('timezone-identifier'));
|
430
|
+
$("#schedule_user_tz_offset").val($(li).html());
|
431
|
+
$("#schedule_app_tz_offset").val($(li).html());
|
432
|
+
}
|
433
|
+
});
|
434
|
+
}
|
435
|
+
}
|
436
|
+
|
437
|
+
$( document ).ready(function() {
|
438
|
+
|
439
|
+
$('#timezonesdropdown').timezonesdropdown();
|
440
|
+
|
441
|
+
auto_detect_tz();
|
442
|
+
|
443
|
+
if ( $('.js-timezone-dropdown').val() == "" ) {
|
444
|
+
$('.js-timezone-dropdown').val('UTC');
|
445
|
+
$("#timezone_dropdown_chzn a span").html("GMT+00:00 UTC Time");
|
446
|
+
}
|
447
|
+
|
448
|
+
load_calendar_tz(user_tz);
|
449
|
+
|
450
|
+
$(".js-navigation-next").click(function() {
|
451
|
+
if ( !$(this).hasClass("disabled") ) {
|
452
|
+
navigate("forward");
|
453
|
+
}
|
454
|
+
});
|
455
|
+
|
456
|
+
$(".js-navigation-prev").click(function() {
|
457
|
+
if ( !$(this).hasClass("disabled") ) {
|
458
|
+
navigate("backward");
|
459
|
+
}
|
460
|
+
});
|
461
|
+
|
462
|
+
$(".schedule-event").click(function() {
|
463
|
+
$("#schedule_slot_start_time").val(slot_date + " " + slot_start_time);
|
464
|
+
$("#schedule_slot_end_time").val(slot_date + " " + slot_end_time);
|
465
|
+
});
|
466
|
+
|
467
|
+
});
|