Version Description
- Added support for Recurring Appointments (Add-on)
- Added new status Rejected for appointments
- Added ability to send notifications for deleted appointments
- Added buttons for quick access to Bookly documentation and support team
Download this release
Release Info
Developer | Ladela |
Plugin | WordPress Online Booking and Scheduling Plugin – Bookly |
Version | 13.0 |
Comparing to | |
See all releases |
Code changes from version 11.3.1 to 13.0
- autoload.php +18 -18
- backend/Backend.php +120 -130
- backend/modules/appearance/Controller.php +193 -201
- backend/modules/appearance/lib/Helper.php +58 -0
- backend/modules/appearance/resources/js/appearance.js +598 -583
- backend/modules/appearance/templates/_1_service.php +178 -194
- backend/modules/appearance/templates/_3_time.php +165 -165
- backend/modules/appearance/templates/_4_cart.php +0 -132
- backend/modules/appearance/templates/_5_cart.php +135 -0
- backend/modules/appearance/templates/_5_details.php +0 -63
- backend/modules/appearance/templates/_6_details.php +44 -0
- backend/modules/appearance/templates/_6_payment.php +0 -67
- backend/modules/appearance/templates/_7_done.php +0 -7
- backend/modules/appearance/templates/_7_payment.php +69 -0
- backend/modules/appearance/templates/_8_complete.php +7 -0
- backend/modules/appearance/templates/_card_payment.php +37 -37
- backend/modules/appearance/templates/_codes.php +25 -25
- backend/modules/appearance/templates/_progress_tracker.php +18 -12
- backend/modules/appearance/templates/index.php +127 -125
- backend/modules/appointments/Controller.php +255 -245
- backend/modules/appointments/resources/js/appointments.js +57 -33
- backend/modules/appointments/templates/_export_dialog.php +39 -39
- backend/modules/appointments/templates/_print_dialog.php +33 -1
- backend/modules/appointments/templates/index.php +121 -118
- backend/modules/calendar/Components.php +30 -4
- backend/modules/calendar/Controller.php +747 -583
- backend/modules/calendar/resources/css/fullcalendar.min.css +4 -4
- backend/modules/calendar/resources/js/calendar.js +400 -370
- backend/modules/calendar/resources/js/delete_dialog.js +9 -0
- backend/modules/calendar/resources/js/fullcalendar.min.js +8 -8
- backend/modules/calendar/resources/js/ng-appointment_dialog.js +981 -728
- backend/modules/calendar/templates/_appointment_dialog.php +14 -14
- backend/modules/calendar/templates/_customer_details_dialog.php +98 -97
- backend/modules/calendar/templates/_delete_dialog.php +32 -0
- backend/modules/calendar/templates/calendar.php +93 -91
- backend/modules/coupons/Controller.php +65 -63
- backend/modules/coupons/forms/Coupon.php +18 -18
- backend/modules/coupons/resources/js/coupons.js +63 -64
- backend/modules/coupons/templates/_modal.php +66 -1
- backend/modules/coupons/templates/index.php +43 -44
- backend/modules/custom_fields/Controller.php +89 -87
- backend/modules/custom_fields/resources/js/custom_fields.js +2 -2
- backend/modules/custom_fields/templates/_services.php +31 -31
- backend/modules/custom_fields/templates/index.php +2 -7
- backend/modules/customers/Components.php +7 -7
- backend/modules/customers/Controller.php +234 -234
- backend/modules/customers/forms/Customer.php +25 -25
- backend/modules/customers/resources/js/customers.js +7 -7
- backend/modules/customers/resources/js/ng-customer_dialog.js +121 -121
- backend/modules/customers/templates/_customer_dialog.php +2 -6
- backend/modules/customers/templates/_import.php +35 -35
- backend/modules/customers/templates/index.php +11 -11
- backend/modules/debug/Controller.php +172 -51
- backend/modules/debug/resources/css/style.css +22 -0
- backend/modules/debug/resources/js/debug.js +6 -0
- backend/modules/debug/templates/index.php +28 -0
- backend/modules/notifications/Controller.php +109 -107
- backend/modules/notifications/forms/Notifications.php +214 -212
- backend/modules/notifications/resources/js/ng-app.js +8 -8
- backend/modules/notifications/resources/js/notification.js +33 -33
- backend/modules/notifications/templates/_codes.php +2 -1
- backend/modules/notifications/templates/_codes_cart.php +16 -16
- backend/modules/notifications/templates/_test_email_notifications_modal.php +19 -14
- backend/modules/notifications/templates/index.php +142 -150
- backend/modules/payments/Components.php +1 -1
- backend/modules/payments/Controller.php +265 -262
- backend/modules/payments/resources/js/ng-payment_details_dialog.js +3 -3
- backend/modules/payments/resources/js/payments.js +183 -183
- backend/modules/payments/templates/_payment_details_dialog.php +18 -20
- backend/modules/payments/templates/details.php +131 -131
- backend/modules/payments/templates/index.php +90 -89
- backend/modules/services/Controller.php +292 -287
- backend/modules/services/forms/Category.php +22 -22
- backend/modules/services/forms/Service.php +74 -51
- backend/modules/services/resources/js/service.js +511 -511
- backend/modules/services/templates/_list.php +258 -310
autoload.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
/**
|
4 |
-
*
|
5 |
-
* @param $class
|
6 |
-
*/
|
7 |
-
function bookly_lite_loader( $class )
|
8 |
-
{
|
9 |
-
if ( preg_match( '/^BooklyLite\\\\(.+)?([^\\\\]+)$/U', ltrim( $class, '\\' ), $match ) ) {
|
10 |
-
$file = __DIR__ . DIRECTORY_SEPARATOR
|
11 |
-
. strtolower( str_replace( '\\', DIRECTORY_SEPARATOR, preg_replace( '/([a-z])([A-Z])/', '$1_$2', $match[1] ) ) )
|
12 |
-
. $match[2]
|
13 |
-
. '.php';
|
14 |
-
if ( is_readable( $file ) ) {
|
15 |
-
require_once $file;
|
16 |
-
}
|
17 |
-
}
|
18 |
-
}
|
19 |
spl_autoload_register( 'bookly_lite_loader', true, true );
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
|
3 |
+
/**
|
4 |
+
* BooklyLite autoload.
|
5 |
+
* @param $class
|
6 |
+
*/
|
7 |
+
function bookly_lite_loader( $class )
|
8 |
+
{
|
9 |
+
if ( preg_match( '/^BooklyLite\\\\(.+)?([^\\\\]+)$/U', ltrim( $class, '\\' ), $match ) ) {
|
10 |
+
$file = __DIR__ . DIRECTORY_SEPARATOR
|
11 |
+
. strtolower( str_replace( '\\', DIRECTORY_SEPARATOR, preg_replace( '/([a-z])([A-Z])/', '$1_$2', $match[1] ) ) )
|
12 |
+
. $match[2]
|
13 |
+
. '.php';
|
14 |
+
if ( is_readable( $file ) ) {
|
15 |
+
require_once $file;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
}
|
19 |
spl_autoload_register( 'bookly_lite_loader', true, true );
|
backend/Backend.php
CHANGED
@@ -1,131 +1,121 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend;
|
3 |
-
|
4 |
-
use BooklyLite\Backend\Modules;
|
5 |
-
use BooklyLite\Frontend;
|
6 |
-
use BooklyLite\Lib;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class Backend
|
10 |
-
* @package BooklyLite\Backend
|
11 |
-
*/
|
12 |
-
class Backend
|
13 |
-
{
|
14 |
-
public function __construct()
|
15 |
-
{
|
16 |
-
// Backend controllers.
|
17 |
-
$this->apearanceController = Modules\Appearance\Controller::getInstance();
|
18 |
-
$this->appointmentsController = Modules\Appointments\Controller::getInstance();
|
19 |
-
$this->calendarController = Modules\Calendar\Controller::getInstance();
|
20 |
-
$this->couponsController = Modules\Coupons\Controller::getInstance();
|
21 |
-
$this->customerController = Modules\Customers\Controller::getInstance();
|
22 |
-
$this->customFieldsController = Modules\CustomFields\Controller::getInstance();
|
23 |
-
$this->debugController = Modules\Debug\Controller::getInstance();
|
24 |
-
$this->notificationsController = Modules\Notifications\Controller::getInstance();
|
25 |
-
$this->paymentController = Modules\Payments\Controller::getInstance();
|
26 |
-
$this->serviceController = Modules\Services\Controller::getInstance();
|
27 |
-
$this->settingsController = Modules\Settings\Controller::getInstance();
|
28 |
-
$this->
|
29 |
-
$this->
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
$this->
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
if (
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
array( $this->debugController, 'index' ) );
|
122 |
-
}
|
123 |
-
|
124 |
-
global $submenu;
|
125 |
-
do_action( 'bookly_admin_menu', 'ab-system' );
|
126 |
-
unset ( $submenu['ab-system'][0] );
|
127 |
-
}
|
128 |
-
}
|
129 |
-
}
|
130 |
-
|
131 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend;
|
3 |
+
|
4 |
+
use BooklyLite\Backend\Modules;
|
5 |
+
use BooklyLite\Frontend;
|
6 |
+
use BooklyLite\Lib;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Backend
|
10 |
+
* @package BooklyLite\Backend
|
11 |
+
*/
|
12 |
+
class Backend
|
13 |
+
{
|
14 |
+
public function __construct()
|
15 |
+
{
|
16 |
+
// Backend controllers.
|
17 |
+
$this->apearanceController = Modules\Appearance\Controller::getInstance();
|
18 |
+
$this->appointmentsController = Modules\Appointments\Controller::getInstance();
|
19 |
+
$this->calendarController = Modules\Calendar\Controller::getInstance();
|
20 |
+
$this->couponsController = Modules\Coupons\Controller::getInstance();
|
21 |
+
$this->customerController = Modules\Customers\Controller::getInstance();
|
22 |
+
$this->customFieldsController = Modules\CustomFields\Controller::getInstance();
|
23 |
+
$this->debugController = Modules\Debug\Controller::getInstance();
|
24 |
+
$this->notificationsController = Modules\Notifications\Controller::getInstance();
|
25 |
+
$this->paymentController = Modules\Payments\Controller::getInstance();
|
26 |
+
$this->serviceController = Modules\Services\Controller::getInstance();
|
27 |
+
$this->settingsController = Modules\Settings\Controller::getInstance();
|
28 |
+
$this->supportController = Modules\Support\Controller::getInstance();
|
29 |
+
$this->smsController = Modules\Sms\Controller::getInstance();
|
30 |
+
$this->staffController = Modules\Staff\Controller::getInstance();
|
31 |
+
|
32 |
+
// Frontend controllers that work via admin-ajax.php.
|
33 |
+
$this->bookingController = Frontend\Modules\Booking\Controller::getInstance();
|
34 |
+
$this->customerProfileController = Frontend\Modules\CustomerProfile\Controller::getInstance();
|
35 |
+
|
36 |
+
add_action( 'admin_menu', array( $this, 'addAdminMenu' ) );
|
37 |
+
add_action( 'wp_loaded', array( $this, 'init' ) );
|
38 |
+
add_action( 'admin_init', array( $this, 'addTinyMCEPlugin' ) );
|
39 |
+
}
|
40 |
+
|
41 |
+
public function init()
|
42 |
+
{
|
43 |
+
if ( ! session_id() ) {
|
44 |
+
@session_start();
|
45 |
+
}
|
46 |
+
}
|
47 |
+
|
48 |
+
public function addTinyMCEPlugin()
|
49 |
+
{
|
50 |
+
new Modules\TinyMce\Plugin();
|
51 |
+
}
|
52 |
+
|
53 |
+
public function addAdminMenu()
|
54 |
+
{
|
55 |
+
/** @var \WP_User $current_user */
|
56 |
+
global $current_user;
|
57 |
+
|
58 |
+
if ( $current_user->has_cap( 'administrator' ) || Lib\Entities\Staff::query()->where( 'wp_user_id', $current_user->ID )->count() ) {
|
59 |
+
$dynamic_position = '80.0000001' . mt_rand( 1, 1000 ); // position always is under `Settings`
|
60 |
+
add_menu_page( 'Bookly', 'Bookly', 'read', 'bookly-menu', '',
|
61 |
+
plugins_url( 'resources/images/menu.png', __FILE__ ), $dynamic_position );
|
62 |
+
|
63 |
+
// Translated submenu pages.
|
64 |
+
$calendar = __( 'Calendar', 'bookly' );
|
65 |
+
$appointments = __( 'Appointments', 'bookly' );
|
66 |
+
$staff_members = __( 'Staff Members', 'bookly' );
|
67 |
+
$services = __( 'Services', 'bookly' );
|
68 |
+
$sms = __( 'SMS Notifications', 'bookly' );
|
69 |
+
$notifications = __( 'Email Notifications', 'bookly' );
|
70 |
+
$customers = __( 'Customers', 'bookly' );
|
71 |
+
$payments = __( 'Payments', 'bookly' );
|
72 |
+
$appearance = __( 'Appearance', 'bookly' );
|
73 |
+
$settings = __( 'Settings', 'bookly' );
|
74 |
+
$coupons = __( 'Coupons', 'bookly' );
|
75 |
+
$custom_fields = __( 'Custom Fields', 'bookly' );
|
76 |
+
|
77 |
+
add_submenu_page( 'bookly-menu', $calendar, $calendar, 'read',
|
78 |
+
Modules\Calendar\Controller::page_slug, array( $this->calendarController, 'index' ) );
|
79 |
+
add_submenu_page( 'bookly-menu', $appointments, $appointments, 'manage_options',
|
80 |
+
Modules\Appointments\Controller::page_slug, array( $this->appointmentsController, 'index' ) );
|
81 |
+
do_action( 'bookly_render_menu_after_appointments' );
|
82 |
+
if ( $current_user->has_cap( 'administrator' ) ) {
|
83 |
+
add_submenu_page( 'bookly-menu', $staff_members, $staff_members, 'manage_options',
|
84 |
+
Modules\Staff\Controller::page_slug, array( $this->staffController, 'index' ) );
|
85 |
+
} else {
|
86 |
+
if ( get_option( 'bookly_gen_allow_staff_edit_profile' ) == 1 ) {
|
87 |
+
add_submenu_page( 'bookly-menu', __( 'Profile', 'bookly' ), __( 'Profile', 'bookly' ), 'read',
|
88 |
+
Modules\Staff\Controller::page_slug, array( $this->staffController, 'index' ) );
|
89 |
+
}
|
90 |
+
}
|
91 |
+
add_submenu_page( 'bookly-menu', $services, $services, 'manage_options',
|
92 |
+
Modules\Services\Controller::page_slug, array( $this->serviceController, 'index' ) );
|
93 |
+
add_submenu_page( 'bookly-menu', $customers, $customers, 'manage_options',
|
94 |
+
Modules\Customers\Controller::page_slug, array( $this->customerController, 'index' ) );
|
95 |
+
add_submenu_page( 'bookly-menu', $notifications, $notifications, 'manage_options',
|
96 |
+
Modules\Notifications\Controller::page_slug, array( $this->notificationsController, 'index' ) );
|
97 |
+
add_submenu_page( 'bookly-menu', $sms, $sms, 'manage_options',
|
98 |
+
Modules\Sms\Controller::page_slug, array( $this->smsController, 'index' ) );
|
99 |
+
add_submenu_page( 'bookly-menu', $payments, $payments, 'manage_options',
|
100 |
+
Modules\Payments\Controller::page_slug, array( $this->paymentController, 'index' ) );
|
101 |
+
add_submenu_page( 'bookly-menu', $appearance, $appearance, 'manage_options',
|
102 |
+
Modules\Appearance\Controller::page_slug, array( $this->apearanceController, 'index' ) );
|
103 |
+
add_submenu_page( 'bookly-menu', $custom_fields, $custom_fields, 'manage_options',
|
104 |
+
Modules\CustomFields\Controller::page_slug, array( $this->customFieldsController, 'index' ) );
|
105 |
+
add_submenu_page( 'bookly-menu', $coupons, $coupons, 'manage_options',
|
106 |
+
Modules\Coupons\Controller::page_slug, array( $this->couponsController, 'index' ) );
|
107 |
+
add_submenu_page( 'bookly-menu', $settings, $settings, 'manage_options',
|
108 |
+
Modules\Settings\Controller::page_slug, array( $this->settingsController, 'index' ) );
|
109 |
+
|
110 |
+
if ( isset ( $_GET['page'] ) && $_GET['page'] == 'bookly-debug' ) {
|
111 |
+
add_submenu_page( 'bookly-menu', 'Debug', 'Debug', 'manage_options',
|
112 |
+
Modules\Debug\Controller::page_slug, array( $this->debugController, 'index' ) );
|
113 |
+
}
|
114 |
+
|
115 |
+
global $submenu;
|
116 |
+
do_action( 'bookly_admin_menu', 'bookly-menu' );
|
117 |
+
unset ( $submenu['bookly-menu'][0] );
|
118 |
+
}
|
119 |
+
}
|
120 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
}
|
backend/modules/appearance/Controller.php
CHANGED
@@ -1,202 +1,194 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Appearance;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Appearance
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
$
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
'css/
|
27 |
-
|
28 |
-
'css/
|
29 |
-
'css/
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
'js/
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
'js/
|
50 |
-
'js/
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
'
|
64 |
-
'
|
65 |
-
'
|
66 |
-
'
|
67 |
-
'
|
68 |
-
'
|
69 |
-
'
|
70 |
-
|
71 |
-
|
72 |
-
'
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
get_option( '
|
81 |
-
get_option( '
|
82 |
-
get_option( '
|
83 |
-
get_option( '
|
84 |
-
get_option( '
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
'
|
104 |
-
'
|
105 |
-
'
|
106 |
-
'
|
107 |
-
'
|
108 |
-
|
109 |
-
'
|
110 |
-
|
111 |
-
|
112 |
-
'
|
113 |
-
'
|
114 |
-
'
|
115 |
-
'
|
116 |
-
'
|
117 |
-
'
|
118 |
-
'
|
119 |
-
'
|
120 |
-
'
|
121 |
-
'
|
122 |
-
'
|
123 |
-
'
|
124 |
-
'
|
125 |
-
'
|
126 |
-
'
|
127 |
-
'
|
128 |
-
'
|
129 |
-
'
|
130 |
-
'
|
131 |
-
'
|
132 |
-
'
|
133 |
-
'
|
134 |
-
'
|
135 |
-
'
|
136 |
-
'
|
137 |
-
'
|
138 |
-
'
|
139 |
-
'
|
140 |
-
'
|
141 |
-
'
|
142 |
-
|
143 |
-
|
144 |
-
'
|
145 |
-
'
|
146 |
-
'
|
147 |
-
'
|
148 |
-
|
149 |
-
|
150 |
-
'
|
151 |
-
|
152 |
-
'
|
153 |
-
'
|
154 |
-
'
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
$
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
}
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
}
|
182 |
-
|
183 |
-
/**
|
184 |
-
*
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
*
|
195 |
-
* @param string $prefix
|
196 |
-
*/
|
197 |
-
protected function registerWpActions( $prefix = '' )
|
198 |
-
{
|
199 |
-
parent::registerWpActions( 'wp_ajax_ab_' );
|
200 |
-
}
|
201 |
-
|
202 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Appearance;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Appearance
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-appearance';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Default Action
|
16 |
+
*/
|
17 |
+
public function index()
|
18 |
+
{
|
19 |
+
/** @var \WP_Locale $wp_locale */
|
20 |
+
global $wp_locale;
|
21 |
+
|
22 |
+
$this->enqueueStyles( array(
|
23 |
+
'frontend' => array_merge(
|
24 |
+
( get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
25 |
+
? array()
|
26 |
+
: array( 'css/intlTelInput.css' ) ),
|
27 |
+
array(
|
28 |
+
'css/ladda.min.css',
|
29 |
+
'css/picker.classic.css',
|
30 |
+
'css/picker.classic.date.css',
|
31 |
+
'css/bookly-main.css',
|
32 |
+
)
|
33 |
+
),
|
34 |
+
'backend' => array(
|
35 |
+
'bootstrap/css/bootstrap-theme.min.css',
|
36 |
+
'css/bootstrap-editable.css',
|
37 |
+
),
|
38 |
+
'wp' => array( 'wp-color-picker' ),
|
39 |
+
) );
|
40 |
+
|
41 |
+
$this->enqueueScripts( array(
|
42 |
+
'backend' => array(
|
43 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
44 |
+
'js/bootstrap-editable.min.js' => array( 'jquery' ),
|
45 |
+
'js/alert.js' => array( 'jquery' ),
|
46 |
+
),
|
47 |
+
'frontend' => array_merge(
|
48 |
+
array(
|
49 |
+
'js/picker.js' => array( 'jquery' ),
|
50 |
+
'js/picker.date.js' => array( 'jquery' ),
|
51 |
+
'js/spin.min.js' => array( 'jquery' ),
|
52 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
53 |
+
),
|
54 |
+
get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
55 |
+
? array()
|
56 |
+
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
57 |
+
),
|
58 |
+
'wp' => array( 'wp-color-picker' ),
|
59 |
+
'module' => array( 'js/appearance.js' => array( 'jquery' ) )
|
60 |
+
) );
|
61 |
+
|
62 |
+
wp_localize_script( 'bookly-picker.date.js', 'BooklyL10n', array(
|
63 |
+
'today' => __( 'Today', 'bookly' ),
|
64 |
+
'months' => array_values( $wp_locale->month ),
|
65 |
+
'days' => array_values( $wp_locale->weekday_abbrev ),
|
66 |
+
'nextMonth' => __( 'Next month', 'bookly' ),
|
67 |
+
'prevMonth' => __( 'Previous month', 'bookly' ),
|
68 |
+
'date_format' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_PICKADATE ),
|
69 |
+
'start_of_week' => (int) get_option( 'start_of_week' ),
|
70 |
+
'saved' => __( 'Settings saved.', 'bookly' ),
|
71 |
+
'intlTelInput' => array(
|
72 |
+
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
73 |
+
'utils' => plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
74 |
+
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
75 |
+
)
|
76 |
+
) );
|
77 |
+
|
78 |
+
// Initialize steps (tabs).
|
79 |
+
$this->steps = array(
|
80 |
+
1 => get_option( 'bookly_l10n_step_service' ),
|
81 |
+
get_option( 'bookly_l10n_step_extras' ),
|
82 |
+
get_option( 'bookly_l10n_step_time' ),
|
83 |
+
get_option( 'bookly_l10n_step_repeat' ),
|
84 |
+
get_option( 'bookly_l10n_step_cart' ),
|
85 |
+
get_option( 'bookly_l10n_step_details' ),
|
86 |
+
get_option( 'bookly_l10n_step_payment' ),
|
87 |
+
get_option( 'bookly_l10n_step_done' )
|
88 |
+
);
|
89 |
+
|
90 |
+
// Render general layout.
|
91 |
+
$this->render( 'index' );
|
92 |
+
}
|
93 |
+
|
94 |
+
/**
|
95 |
+
* Update options
|
96 |
+
*/
|
97 |
+
public function executeUpdateAppearanceOptions()
|
98 |
+
{
|
99 |
+
if ( $this->hasParameter( 'options' ) ) {
|
100 |
+
$get_option = $this->getParameter( 'options' );
|
101 |
+
$options = array(
|
102 |
+
// Info text.
|
103 |
+
'bookly_l10n_info_cart_step' => $get_option['text_info_cart_step'],
|
104 |
+
'bookly_l10n_info_complete_step' => $get_option['text_info_complete_step'],
|
105 |
+
'bookly_l10n_info_coupon' => $get_option['text_info_coupon'],
|
106 |
+
'bookly_l10n_info_details_step' => $get_option['text_info_details_step'],
|
107 |
+
'bookly_l10n_info_details_step_guest' => $get_option['text_info_details_step_guest'],
|
108 |
+
'bookly_l10n_info_payment_step' => $get_option['text_info_payment_step'],
|
109 |
+
'bookly_l10n_info_service_step' => $get_option['text_info_service_step'],
|
110 |
+
'bookly_l10n_info_time_step' => $get_option['text_info_time_step'],
|
111 |
+
// Step, label and option texts.
|
112 |
+
'bookly_l10n_button_apply' => $get_option['text_button_apply'],
|
113 |
+
'bookly_l10n_button_back' => $get_option['text_button_back'],
|
114 |
+
'bookly_l10n_button_book_more' => $get_option['text_button_book_more'],
|
115 |
+
'bookly_l10n_button_next' => $get_option['text_button_next'],
|
116 |
+
'bookly_l10n_label_category' => $get_option['text_label_category'],
|
117 |
+
'bookly_l10n_label_ccard_code' => $get_option['text_label_ccard_code'],
|
118 |
+
'bookly_l10n_label_ccard_expire' => $get_option['text_label_ccard_expire'],
|
119 |
+
'bookly_l10n_label_ccard_number' => $get_option['text_label_ccard_number'],
|
120 |
+
'bookly_l10n_label_coupon' => $get_option['text_label_coupon'],
|
121 |
+
'bookly_l10n_label_email' => $get_option['text_label_email'],
|
122 |
+
'bookly_l10n_label_employee' => $get_option['text_label_employee'],
|
123 |
+
'bookly_l10n_label_finish_by' => $get_option['text_label_finish_by'],
|
124 |
+
'bookly_l10n_label_name' => $get_option['text_label_name'],
|
125 |
+
'bookly_l10n_label_number_of_persons' => $get_option['text_label_number_of_persons'],
|
126 |
+
'bookly_l10n_label_pay_ccard' => $get_option['text_label_pay_ccard'],
|
127 |
+
'bookly_l10n_label_pay_locally' => $get_option['text_label_pay_locally'],
|
128 |
+
'bookly_l10n_label_pay_mollie' => $get_option['text_label_pay_mollie'],
|
129 |
+
'bookly_l10n_label_pay_paypal' => $get_option['text_label_pay_paypal'],
|
130 |
+
'bookly_l10n_label_phone' => $get_option['text_label_phone'],
|
131 |
+
'bookly_l10n_label_select_date' => $get_option['text_label_select_date'],
|
132 |
+
'bookly_l10n_label_service' => $get_option['text_label_service'],
|
133 |
+
'bookly_l10n_label_start_from' => $get_option['text_label_start_from'],
|
134 |
+
'bookly_l10n_option_category' => $get_option['text_option_category'],
|
135 |
+
'bookly_l10n_option_employee' => $get_option['text_option_employee'],
|
136 |
+
'bookly_l10n_option_service' => $get_option['text_option_service'],
|
137 |
+
'bookly_l10n_step_cart' => $get_option['text_step_cart'],
|
138 |
+
'bookly_l10n_step_details' => $get_option['text_step_details'],
|
139 |
+
'bookly_l10n_step_done' => $get_option['text_step_done'],
|
140 |
+
'bookly_l10n_step_payment' => $get_option['text_step_payment'],
|
141 |
+
'bookly_l10n_step_service' => $get_option['text_step_service'],
|
142 |
+
'bookly_l10n_step_time' => $get_option['text_step_time'],
|
143 |
+
// Validator errors.
|
144 |
+
'bookly_l10n_required_email' => $get_option['text_required_email'],
|
145 |
+
'bookly_l10n_required_employee' => $get_option['text_required_employee'],
|
146 |
+
'bookly_l10n_required_name' => $get_option['text_required_name'],
|
147 |
+
'bookly_l10n_required_phone' => $get_option['text_required_phone'],
|
148 |
+
'bookly_l10n_required_service' => $get_option['text_required_service'],
|
149 |
+
// Color.
|
150 |
+
'bookly_app_color' => $get_option['color'],
|
151 |
+
// Checkboxes.
|
152 |
+
'bookly_app_required_employee' => $get_option['required_employee'],
|
153 |
+
'bookly_app_show_blocked_timeslots' => $get_option['blocked_timeslots'],
|
154 |
+
'bookly_app_show_calendar' => $get_option['show_calendar'],
|
155 |
+
'bookly_app_show_day_one_column' => $get_option['day_one_column'],
|
156 |
+
'bookly_app_show_progress_tracker' => $get_option['progress_tracker'],
|
157 |
+
'bookly_app_staff_name_with_price' => $get_option['staff_name_with_price'],
|
158 |
+
);
|
159 |
+
|
160 |
+
$options = apply_filters( 'bookly_prepare_appearance_settings', $options, $get_option );
|
161 |
+
|
162 |
+
// Save options.
|
163 |
+
foreach ( $options as $option_name => $option_value ) {
|
164 |
+
update_option( $option_name, $option_value );
|
165 |
+
// Register string for translate in WPML.
|
166 |
+
if ( strpos( $option_name, 'bookly_l10n_' ) === 0 ) {
|
167 |
+
do_action( 'wpml_register_single_string', 'bookly', $option_name, $option_value );
|
168 |
+
}
|
169 |
+
}
|
170 |
+
}
|
171 |
+
|
172 |
+
wp_send_json_success();
|
173 |
+
}
|
174 |
+
|
175 |
+
/**
|
176 |
+
* Ajax request to dismiss appearance notice for current user.
|
177 |
+
*/
|
178 |
+
public function executeDismissAppearanceNotice()
|
179 |
+
{
|
180 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_appearance_notice', 1 );
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
185 |
+
* so current 'execute*' methods look nicer.
|
186 |
+
*
|
187 |
+
* @param string $prefix
|
188 |
+
*/
|
189 |
+
protected function registerWpActions( $prefix = '' )
|
190 |
+
{
|
191 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
192 |
+
}
|
193 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
194 |
}
|
backend/modules/appearance/lib/Helper.php
ADDED
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Appearance\Lib;
|
3 |
+
|
4 |
+
class Helper
|
5 |
+
{
|
6 |
+
/**
|
7 |
+
* Render ui for editing frontend messages. <span>
|
8 |
+
*
|
9 |
+
* @param array $data l10n option name
|
10 |
+
* @param null $mirror_class the updated value will be displayed also for the objects with css class
|
11 |
+
*/
|
12 |
+
public static function renderSpan( array $data, $mirror_class = null )
|
13 |
+
{
|
14 |
+
$id = $data[0];
|
15 |
+
$options = array();
|
16 |
+
foreach ( $data as $option_name ) {
|
17 |
+
$options[ $option_name ] = get_option( $option_name );
|
18 |
+
}
|
19 |
+
if ( count( $options ) > 1 ) {
|
20 |
+
printf( '<span id="%s" data-options-default=\'%s\' data-type="multiple"%s%s>%s</span>',
|
21 |
+
$id, json_encode( $options ), $mirror_class ? ' class="' . $mirror_class . '"' : '',
|
22 |
+
$mirror_class ? ' data-mirror="' . $mirror_class . '"' : '', esc_html( $options[ $id ] )
|
23 |
+
);
|
24 |
+
} else {
|
25 |
+
printf( '<span id="%s" data-option-default=\'%s\' data-type="text" class="bookly-editable%s"%s>%s</span>',
|
26 |
+
$id, esc_attr( $options[ $id ] ), $mirror_class ? ' ' . $mirror_class : '',
|
27 |
+
$mirror_class ? ' data-mirror="' . $mirror_class . '"' : '', esc_html( $options[ $id ] )
|
28 |
+
);
|
29 |
+
}
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Render ui for editing frontend messages. <label>
|
34 |
+
*
|
35 |
+
* @param array $data l10n option name
|
36 |
+
* @param null $mirror_class the updated value will be displayed also for the objects with css class
|
37 |
+
*/
|
38 |
+
public static function renderLabel( array $data, $mirror_class = null )
|
39 |
+
{
|
40 |
+
$id = $data[0];
|
41 |
+
$options = array();
|
42 |
+
foreach ( $data as $option_name ) {
|
43 |
+
$options[ $option_name ] = get_option( $option_name );
|
44 |
+
}
|
45 |
+
if ( count( $options ) > 1 ) {
|
46 |
+
printf( '<label id="%s" data-type="multiple" data-options-default=\'%s\'%s%s>%s</label>',
|
47 |
+
$id, json_encode( $options ), $mirror_class ? ' class="' . $mirror_class . '"' : '',
|
48 |
+
$mirror_class ? ' data-mirror="' . $mirror_class . '"' : '', esc_html( $options[ $id ] )
|
49 |
+
);
|
50 |
+
} else {
|
51 |
+
printf( '<label id="%s" data-option-default=\'%s\' data-type="text" class="bookly-editable%s"%s>%s</label>',
|
52 |
+
$id, esc_attr( $options[ $id ] ), $mirror_class ? ' ' . $mirror_class : '',
|
53 |
+
$mirror_class ? ' data-mirror="' . $mirror_class . '"' : '', esc_html( $options[ $id ] )
|
54 |
+
);
|
55 |
+
}
|
56 |
+
}
|
57 |
+
|
58 |
+
}
|
backend/modules/appearance/resources/js/appearance.js
CHANGED
@@ -1,583 +1,598 @@
|
|
1 |
-
jQuery(function($) {
|
2 |
-
var // Progress Tracker.
|
3 |
-
$progress_tracker_option = $('input#ab-progress-tracker-checkbox'),
|
4 |
-
$staff_name_with_price_option = $('input#ab-staff-name-with-price-checkbox'),
|
5 |
-
// Time slots setting.
|
6 |
-
$blocked_timeslots_option = $('input#ab-blocked-timeslots-checkbox'),
|
7 |
-
$day_one_column_option
|
8 |
-
$show_calendar_option
|
9 |
-
$required_employee_option = $('input#ab-required-employee-checkbox'),
|
10 |
-
$required_location_option = $('input#ab-required-location-checkbox'),
|
11 |
-
// Buttons.
|
12 |
-
$save_button
|
13 |
-
$reset_button
|
14 |
-
// Texts.
|
15 |
-
$text_step_service
|
16 |
-
$text_step_extras
|
17 |
-
$text_step_time
|
18 |
-
$text_step_cart
|
19 |
-
$text_step_details
|
20 |
-
$text_step_payment
|
21 |
-
$text_step_done
|
22 |
-
$text_label_location
|
23 |
-
$text_label_multiply
|
24 |
-
$text_label_category
|
25 |
-
$text_option_location = $('#
|
26 |
-
$text_option_category = $('#
|
27 |
-
$text_option_service
|
28 |
-
$text_option_employee = $('#
|
29 |
-
$text_label_service
|
30 |
-
$text_label_number_of_persons = $('#
|
31 |
-
$text_label_employee
|
32 |
-
$text_label_select_date = $('#
|
33 |
-
$text_label_start_from = $('#
|
34 |
-
$text_button_next
|
35 |
-
$text_button_back
|
36 |
-
$text_button_book_more = $('#
|
37 |
-
$text_button_apply
|
38 |
-
$text_label_finish_by = $('#
|
39 |
-
$text_label_name
|
40 |
-
$text_label_phone
|
41 |
-
$text_label_email
|
42 |
-
$text_label_coupon
|
43 |
-
$text_info_service
|
44 |
-
$text_info_extras
|
45 |
-
$text_info_time
|
46 |
-
$text_info_cart
|
47 |
-
$text_info_details
|
48 |
-
$text_info_details_guest = $('#
|
49 |
-
$text_info_coupon
|
50 |
-
$text_info_payment
|
51 |
-
$text_info_complete
|
52 |
-
$text_label_pay_paypal = $('#
|
53 |
-
$text_label_pay_ccard = $('#
|
54 |
-
$text_label_ccard_number = $('#
|
55 |
-
$text_label_ccard_expire = $('#
|
56 |
-
$text_label_ccard_code = $('#
|
57 |
-
$color_picker
|
58 |
-
$ab_editable
|
59 |
-
$text_label_pay_locally = $('#
|
60 |
-
$text_label_pay_mollie = $('#
|
61 |
-
// Calendars.
|
62 |
-
$second_step_calendar = $('.ab-selected-date'),
|
63 |
-
$second_step_calendar_wrap = $('.ab-slot-calendar'),
|
64 |
-
// Step settings.
|
65 |
-
$step_settings
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
$('.
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
$('
|
89 |
-
$('
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
$
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
$('.
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
)
|
156 |
-
|
157 |
-
$(
|
158 |
-
$('.
|
159 |
-
$('.
|
160 |
-
|
161 |
-
$('
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
'
|
253 |
-
|
254 |
-
'
|
255 |
-
'
|
256 |
-
'
|
257 |
-
'
|
258 |
-
'
|
259 |
-
'
|
260 |
-
|
261 |
-
'
|
262 |
-
'
|
263 |
-
|
264 |
-
'
|
265 |
-
'
|
266 |
-
'
|
267 |
-
|
268 |
-
'
|
269 |
-
'
|
270 |
-
'
|
271 |
-
'
|
272 |
-
'
|
273 |
-
'
|
274 |
-
'
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
$('
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
}
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
$
|
479 |
-
value
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
$('[data-type=
|
551 |
-
$(
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
});
|
568 |
-
|
569 |
-
$(
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
}
|
582 |
-
})
|
583 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function($) {
|
2 |
+
var // Progress Tracker.
|
3 |
+
$progress_tracker_option = $('input#ab-progress-tracker-checkbox'),
|
4 |
+
$staff_name_with_price_option = $('input#ab-staff-name-with-price-checkbox'),
|
5 |
+
// Time slots setting.
|
6 |
+
$blocked_timeslots_option = $('input#ab-blocked-timeslots-checkbox'),
|
7 |
+
$day_one_column_option = $('input#ab-day-one-column-checkbox'),
|
8 |
+
$show_calendar_option = $('input#ab-show-calendar-checkbox'),
|
9 |
+
$required_employee_option = $('input#ab-required-employee-checkbox'),
|
10 |
+
$required_location_option = $('input#ab-required-location-checkbox'),
|
11 |
+
// Buttons.
|
12 |
+
$save_button = $('#ajax-send-appearance'),
|
13 |
+
$reset_button = $('button[type=reset]'),
|
14 |
+
// Texts.
|
15 |
+
$text_step_service = $('#bookly_l10n_step_service'),
|
16 |
+
$text_step_extras = $('#bookly_l10n_step_extras'),
|
17 |
+
$text_step_time = $('#bookly_l10n_step_time'),
|
18 |
+
$text_step_cart = $('#bookly_l10n_step_cart'),
|
19 |
+
$text_step_details = $('#bookly_l10n_step_details'),
|
20 |
+
$text_step_payment = $('#bookly_l10n_step_payment'),
|
21 |
+
$text_step_done = $('#bookly_l10n_step_done'),
|
22 |
+
$text_label_location = $('#bookly_l10n_label_location'),
|
23 |
+
$text_label_multiply = $('#bookly_l10n_label_multiply'),
|
24 |
+
$text_label_category = $('#bookly_l10n_label_category'),
|
25 |
+
$text_option_location = $('#bookly_l10n_option_location'),
|
26 |
+
$text_option_category = $('#bookly_l10n_option_category'),
|
27 |
+
$text_option_service = $('#bookly_l10n_option_service'),
|
28 |
+
$text_option_employee = $('#bookly_l10n_option_employee'),
|
29 |
+
$text_label_service = $('#bookly_l10n_label_service'),
|
30 |
+
$text_label_number_of_persons = $('#bookly_l10n_label_number_of_persons'),
|
31 |
+
$text_label_employee = $('#bookly_l10n_label_employee'),
|
32 |
+
$text_label_select_date = $('#bookly_l10n_label_select_date'),
|
33 |
+
$text_label_start_from = $('#bookly_l10n_label_start_from'),
|
34 |
+
$text_button_next = $('#bookly_l10n_button_next'),
|
35 |
+
$text_button_back = $('#bookly_l10n_button_back'),
|
36 |
+
$text_button_book_more = $('#bookly_l10n_button_book_more'),
|
37 |
+
$text_button_apply = $('#bookly_l10n_button_apply'),
|
38 |
+
$text_label_finish_by = $('#bookly_l10n_label_finish_by'),
|
39 |
+
$text_label_name = $('#bookly_l10n_label_name'),
|
40 |
+
$text_label_phone = $('#bookly_l10n_label_phone'),
|
41 |
+
$text_label_email = $('#bookly_l10n_label_email'),
|
42 |
+
$text_label_coupon = $('#bookly_l10n_label_coupon'),
|
43 |
+
$text_info_service = $('#bookly_l10n_info_service_step'),
|
44 |
+
$text_info_extras = $('#bookly_l10n_info_extras_step'),
|
45 |
+
$text_info_time = $('#bookly_l10n_info_time_step'),
|
46 |
+
$text_info_cart = $('#bookly_l10n_info_cart_step'),
|
47 |
+
$text_info_details = $('#bookly_l10n_info_details_step'),
|
48 |
+
$text_info_details_guest = $('#bookly_l10n_info_details_step_guest'),
|
49 |
+
$text_info_coupon = $('#bookly_l10n_info_coupon'),
|
50 |
+
$text_info_payment = $('#bookly_l10n_info_payment_step'),
|
51 |
+
$text_info_complete = $('#bookly_l10n_info_complete_step'),
|
52 |
+
$text_label_pay_paypal = $('#bookly_l10n_label_pay_paypal'),
|
53 |
+
$text_label_pay_ccard = $('#bookly_l10n_label_pay_ccard'),
|
54 |
+
$text_label_ccard_number = $('#bookly_l10n_label_ccard_number'),
|
55 |
+
$text_label_ccard_expire = $('#bookly_l10n_label_ccard_expire'),
|
56 |
+
$text_label_ccard_code = $('#bookly_l10n_label_ccard_code'),
|
57 |
+
$color_picker = $('.bookly-js-color-picker'),
|
58 |
+
$ab_editable = $('.bookly-editable'),
|
59 |
+
$text_label_pay_locally = $('#bookly_l10n_label_pay_locally'),
|
60 |
+
$text_label_pay_mollie = $('#bookly_l10n_label_pay_mollie'),
|
61 |
+
// Calendars.
|
62 |
+
$second_step_calendar = $('.ab-selected-date'),
|
63 |
+
$second_step_calendar_wrap = $('.ab-slot-calendar'),
|
64 |
+
// Step settings.
|
65 |
+
$step_settings = $('#bookly-js-step-settings'),
|
66 |
+
// Step repeat.
|
67 |
+
$repeat_ui_step_calendar = $('.bookly-repeat-until'),
|
68 |
+
$repeat_ui_variants = $('[class^="bookly-variant"]'),
|
69 |
+
$repeat_ui_variant = $('.bookly-repeat-variant'),
|
70 |
+
$repeat_ui_variant_monthly = $('.variant-monthly'),
|
71 |
+
$repeat_ui_weekly_week_day = $('.bookly-week-day'),
|
72 |
+
$repeat_ui_monthly_specific_day = $('.bookly-monthly-specific-day'),
|
73 |
+
$repeat_ui_monthly_week_day = $('.bookly-monthly-week-day'),
|
74 |
+
// Step repeat l10n
|
75 |
+
$text_info_repeat_step = $('#bookly_l10n_info_repeat_step'),
|
76 |
+
$text_label_repeat = $('#bookly_l10n_label_repeat'),
|
77 |
+
$text_repeat = $('#bookly_l10n_repeat'),
|
78 |
+
$text_repeat_another_time = $('#bookly_l10n_repeat_another_time'),
|
79 |
+
$text_repeat_biweekly = $('#bookly_l10n_repeat_biweekly'),
|
80 |
+
$text_repeat_daily = $('#bookly_l10n_repeat_daily'),
|
81 |
+
$text_repeat_day = $('#bookly_l10n_repeat_day'),
|
82 |
+
$text_repeat_days = $('#bookly_l10n_repeat_days'),
|
83 |
+
$text_repeat_deleted = $('#bookly_l10n_repeat_deleted'),
|
84 |
+
$text_repeat_every = $('#bookly_l10n_repeat_every'),
|
85 |
+
$text_repeat_first = $('#bookly_l10n_repeat_first'),
|
86 |
+
$text_repeat_first_in_cart_info = $('#bookly_l10n_repeat_first_in_cart_info').first(),
|
87 |
+
$text_repeat_fourth = $('#bookly_l10n_repeat_fourth'),
|
88 |
+
$text_repeat_last = $('#bookly_l10n_repeat_last'),
|
89 |
+
$text_repeat_monthly = $('#bookly_l10n_repeat_monthly'),
|
90 |
+
$text_repeat_on = $('#bookly_l10n_repeat_on'),
|
91 |
+
$text_repeat_on_week = $('#bookly_l10n_repeat_on_week'),
|
92 |
+
$text_repeat_required_week_days = $('#bookly_l10n_repeat_required_week_days'),
|
93 |
+
$text_repeat_schedule = $('#bookly_l10n_repeat_schedule'),
|
94 |
+
$text_repeat_schedule_help = $('#bookly_l10n_repeat_schedule_help'),
|
95 |
+
$text_repeat_schedule_info = $('#bookly_l10n_repeat_schedule_info'),
|
96 |
+
$text_repeat_second = $('#bookly_l10n_repeat_second'),
|
97 |
+
$text_repeat_specific = $('#bookly_l10n_repeat_specific'),
|
98 |
+
$text_repeat_third = $('#bookly_l10n_repeat_third'),
|
99 |
+
$text_repeat_this_appointment = $('#bookly_l10n_repeat_this_appointment'),
|
100 |
+
$text_repeat_until = $('#bookly_l10n_repeat_until'),
|
101 |
+
$text_repeat_weekly = $('#bookly_l10n_repeat_weekly'),
|
102 |
+
$text_step_repeat = $('#bookly_l10n_step_repeat')
|
103 |
+
;
|
104 |
+
|
105 |
+
if (BooklyL10n.intlTelInput.enabled) {
|
106 |
+
$('.ab-user-phone').intlTelInput({
|
107 |
+
preferredCountries: [BooklyL10n.intlTelInput.country],
|
108 |
+
defaultCountry: BooklyL10n.intlTelInput.country,
|
109 |
+
geoIpLookup: function (callback) {
|
110 |
+
$.get(ajaxurl, {action: 'bookly_ip_info'}, function () {
|
111 |
+
}, 'json').always(function (resp) {
|
112 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
113 |
+
callback(countryCode);
|
114 |
+
});
|
115 |
+
},
|
116 |
+
utilsScript: BooklyL10n.intlTelInput.utils
|
117 |
+
});
|
118 |
+
}
|
119 |
+
|
120 |
+
$staff_name_with_price_option.on('change', function () {
|
121 |
+
var staff = $('.ab-select-employee').val();
|
122 |
+
if (staff) {
|
123 |
+
$('.ab-select-employee').val(staff * -1);
|
124 |
+
}
|
125 |
+
$('.employee-name-price').toggle($staff_name_with_price_option.prop("checked"));
|
126 |
+
$('.employee-name').toggle(!$staff_name_with_price_option.prop("checked"));
|
127 |
+
}).trigger('change');
|
128 |
+
|
129 |
+
// menu fix for WP 3.8.1
|
130 |
+
$('#toplevel_page_ab-system > ul').css('margin-left', '0px');
|
131 |
+
|
132 |
+
// Tabs.
|
133 |
+
$('li.bookly-nav-item').on('shown.bs.tab', function (e) {
|
134 |
+
$step_settings.children().hide();
|
135 |
+
switch (e.target.getAttribute('data-target')) {
|
136 |
+
case '#ab-step-1': $step_settings.find('#bookly-js-step-service').show(); break;
|
137 |
+
case '#ab-step-3': $step_settings.find('#bookly-js-step-time').show(); break;
|
138 |
+
}
|
139 |
+
});
|
140 |
+
|
141 |
+
function getEditableValue(val) {
|
142 |
+
return $.trim(val == 'Empty' ? '' : val);
|
143 |
+
}
|
144 |
+
// Apply color from color picker.
|
145 |
+
var applyColor = function() {
|
146 |
+
var color_important = $color_picker.wpColorPicker('color') + '!important';
|
147 |
+
$('.ab-progress-tracker').find('.active').css('color', $color_picker.wpColorPicker('color')).find('.step').css('background', $color_picker.wpColorPicker('color'));
|
148 |
+
$('.ab-mobile-step_1 label').css('color', $color_picker.wpColorPicker('color'));
|
149 |
+
$('.ab-label-error').css('color', $color_picker.wpColorPicker('color'));
|
150 |
+
$('.bookly-js-actions > a').css('background-color', $color_picker.wpColorPicker('color'));
|
151 |
+
$('.bookly-next-step, .ab-mobile-next-step').css('background', $color_picker.wpColorPicker('color'));
|
152 |
+
$('.bookly-week-days label').css('background-color', $color_picker.wpColorPicker('color'));
|
153 |
+
$('.picker__frame').attr('style', 'background: ' + color_important);
|
154 |
+
$('.picker__header').attr('style', 'border-bottom: ' + '1px solid ' + color_important);
|
155 |
+
$('.picker__day').mouseenter(function(){
|
156 |
+
$(this).attr('style', 'color: ' + color_important);
|
157 |
+
}).mouseleave(function(){ $(this).attr('style', $(this).hasClass('picker__day--selected') ? 'color: ' + color_important : '') });
|
158 |
+
$('.picker__day--selected').attr('style', 'color: ' + color_important);
|
159 |
+
$('.picker__button--clear').attr('style', 'color: ' + color_important);
|
160 |
+
$('.picker__button--today').attr('style', 'color: ' + color_important);
|
161 |
+
$('.bookly-extra-step .bookly-extras-thumb.bookly-extras-selected').css('border-color', $color_picker.wpColorPicker('color'));
|
162 |
+
$('.ab-columnizer .ab-day, .bookly-schedule-date,.bookly-pagination li.active').css({
|
163 |
+
'background': $color_picker.wpColorPicker('color'),
|
164 |
+
'border-color': $color_picker.wpColorPicker('color')
|
165 |
+
});
|
166 |
+
$('.ab-columnizer .ab-hour').off().hover(
|
167 |
+
function() { // mouse-on
|
168 |
+
$(this).css({
|
169 |
+
'color': $color_picker.wpColorPicker('color'),
|
170 |
+
'border': '2px solid ' + $color_picker.wpColorPicker('color')
|
171 |
+
});
|
172 |
+
$(this).find('.ab-hour-icon').css({
|
173 |
+
'border-color': $color_picker.wpColorPicker('color'),
|
174 |
+
'color': $color_picker.wpColorPicker('color')
|
175 |
+
});
|
176 |
+
$(this).find('.ab-hour-icon > span').css({
|
177 |
+
'background': $color_picker.wpColorPicker('color')
|
178 |
+
});
|
179 |
+
},
|
180 |
+
function() { // mouse-out
|
181 |
+
$(this).css({
|
182 |
+
'color': '#333333',
|
183 |
+
'border': '1px solid #cccccc'
|
184 |
+
});
|
185 |
+
$(this).find('.ab-hour-icon').css({
|
186 |
+
'border-color': '#333333',
|
187 |
+
'color': '#cccccc'
|
188 |
+
});
|
189 |
+
$(this).find('.ab-hour-icon > span').css({
|
190 |
+
'background': '#cccccc'
|
191 |
+
});
|
192 |
+
}
|
193 |
+
);
|
194 |
+
$('.ab-details-step label').css('color', $color_picker.wpColorPicker('color'));
|
195 |
+
$('.ab-card-form label').css('color', $color_picker.wpColorPicker('color'));
|
196 |
+
$('.ab-nav-tabs .ladda-button, .bookly-nav-steps .ladda-button, .ab-btn, .bookly-round, .bookly-square').css('background-color', $color_picker.wpColorPicker('color'));
|
197 |
+
$('.bookly-triangle').css('border-bottom-color', $color_picker.wpColorPicker('color'));
|
198 |
+
$('.bookly-back-step, .bookly-next-step').css('background', $color_picker.wpColorPicker('color'));
|
199 |
+
var style_arrow = '.picker__nav--next:before { border-left: 6px solid ' + $color_picker.wpColorPicker('color') + '!important; } .picker__nav--prev:before { border-right: 6px solid ' + $color_picker.wpColorPicker('color') + '!important; }';
|
200 |
+
$('#ab--style-arrow').html(style_arrow);
|
201 |
+
};
|
202 |
+
$color_picker.wpColorPicker({
|
203 |
+
change : applyColor
|
204 |
+
});
|
205 |
+
// Init calendars.
|
206 |
+
$('.ab-date-from').pickadate({
|
207 |
+
formatSubmit : 'yyyy-mm-dd',
|
208 |
+
format : BooklyL10n.date_format,
|
209 |
+
min : true,
|
210 |
+
clear : false,
|
211 |
+
close : false,
|
212 |
+
today : BooklyL10n.today,
|
213 |
+
weekdaysShort : BooklyL10n.days,
|
214 |
+
monthsFull : BooklyL10n.months,
|
215 |
+
labelMonthNext : BooklyL10n.nextMonth,
|
216 |
+
labelMonthPrev : BooklyL10n.prevMonth,
|
217 |
+
onRender : applyColor,
|
218 |
+
firstDay : BooklyL10n.start_of_week == 1
|
219 |
+
});
|
220 |
+
|
221 |
+
$second_step_calendar.pickadate({
|
222 |
+
formatSubmit : 'yyyy-mm-dd',
|
223 |
+
format : BooklyL10n.date_format,
|
224 |
+
min : true,
|
225 |
+
weekdaysShort : BooklyL10n.days,
|
226 |
+
monthsFull : BooklyL10n.months,
|
227 |
+
labelMonthNext : BooklyL10n.nextMonth,
|
228 |
+
labelMonthPrev : BooklyL10n.prevMonth,
|
229 |
+
close : false,
|
230 |
+
clear : false,
|
231 |
+
today : false,
|
232 |
+
closeOnSelect : false,
|
233 |
+
onRender : applyColor,
|
234 |
+
firstDay : BooklyL10n.start_of_week == 1,
|
235 |
+
klass : {
|
236 |
+
picker: 'picker picker--opened picker--focused'
|
237 |
+
},
|
238 |
+
onClose : function() {
|
239 |
+
this.open(false);
|
240 |
+
}
|
241 |
+
});
|
242 |
+
$second_step_calendar_wrap.find('.picker__holder').css({ top : '0px', left : '0px' });
|
243 |
+
$second_step_calendar_wrap.toggle($show_calendar_option.prop('checked'));
|
244 |
+
|
245 |
+
// Update options.
|
246 |
+
$save_button.on('click', function(e) {
|
247 |
+
e.preventDefault();
|
248 |
+
var data = {
|
249 |
+
action: 'bookly_update_appearance_options',
|
250 |
+
options: {
|
251 |
+
// Color.
|
252 |
+
'color' : $color_picker.wpColorPicker('color'),
|
253 |
+
// Info text.
|
254 |
+
'text_info_service_step' : getEditableValue($text_info_service.text()),
|
255 |
+
'text_info_extras_step' : getEditableValue($text_info_extras.text()),
|
256 |
+
'text_info_time_step' : getEditableValue($text_info_time.text()),
|
257 |
+
'text_info_cart_step' : getEditableValue($text_info_cart.text()),
|
258 |
+
'text_info_details_step' : getEditableValue($text_info_details.text()),
|
259 |
+
'text_info_details_step_guest' : getEditableValue($text_info_details_guest.text()),
|
260 |
+
'text_info_payment_step' : getEditableValue($text_info_payment.text()),
|
261 |
+
'text_info_complete_step' : getEditableValue($text_info_complete.text()),
|
262 |
+
'text_info_coupon' : getEditableValue($text_info_coupon.text()),
|
263 |
+
// Step and label texts.
|
264 |
+
'text_step_service' : getEditableValue($text_step_service.text()),
|
265 |
+
'text_step_extras' : getEditableValue($text_step_extras.text()),
|
266 |
+
'text_step_time' : getEditableValue($text_step_time.text()),
|
267 |
+
'text_step_cart' : getEditableValue($text_step_cart.text()),
|
268 |
+
'text_step_details' : getEditableValue($text_step_details.text()),
|
269 |
+
'text_step_payment' : getEditableValue($text_step_payment.text()),
|
270 |
+
'text_step_done' : getEditableValue($text_step_done.text()),
|
271 |
+
'text_label_location' : getEditableValue($text_label_location.text()),
|
272 |
+
'text_label_category' : getEditableValue($text_label_category.text()),
|
273 |
+
'text_label_service' : getEditableValue($text_label_service.text()),
|
274 |
+
'text_label_number_of_persons' : getEditableValue($text_label_number_of_persons.text()),
|
275 |
+
'text_label_multiply' : getEditableValue($text_label_multiply.text()),
|
276 |
+
'text_label_employee' : getEditableValue($text_label_employee.text()),
|
277 |
+
'text_label_select_date' : getEditableValue($text_label_select_date.text()),
|
278 |
+
'text_label_start_from' : getEditableValue($text_label_start_from.text()),
|
279 |
+
'text_button_next' : getEditableValue($text_button_next.text()),
|
280 |
+
'text_button_back' : getEditableValue($text_button_back.text()),
|
281 |
+
'text_button_apply' : getEditableValue($text_button_apply.text()),
|
282 |
+
'text_button_book_more' : getEditableValue($text_button_book_more.text()),
|
283 |
+
'text_label_finish_by' : getEditableValue($text_label_finish_by.text()),
|
284 |
+
'text_label_name' : getEditableValue($text_label_name.text()),
|
285 |
+
'text_label_phone' : getEditableValue($text_label_phone.text()),
|
286 |
+
'text_label_email' : getEditableValue($text_label_email.text()),
|
287 |
+
'text_label_coupon' : getEditableValue($text_label_coupon.text()),
|
288 |
+
'text_option_location' : getEditableValue($text_option_location.text()),
|
289 |
+
'text_option_category' : getEditableValue($text_option_category.text()),
|
290 |
+
'text_option_service' : getEditableValue($text_option_service.text()),
|
291 |
+
'text_option_employee' : getEditableValue($text_option_employee.text()),
|
292 |
+
'text_label_pay_locally' : getEditableValue($text_label_pay_locally.text()),
|
293 |
+
'text_label_pay_mollie' : getEditableValue($text_label_pay_mollie.text()),
|
294 |
+
'text_label_pay_paypal' : getEditableValue($text_label_pay_paypal.text()),
|
295 |
+
'text_label_pay_ccard' : getEditableValue($text_label_pay_ccard.text()),
|
296 |
+
'text_label_ccard_number' : getEditableValue($text_label_ccard_number.text()),
|
297 |
+
'text_label_ccard_expire' : getEditableValue($text_label_ccard_expire.text()),
|
298 |
+
'text_label_ccard_code' : getEditableValue($text_label_ccard_code.text()),
|
299 |
+
// Repeat
|
300 |
+
'text_info_repeat_step' : getEditableValue($text_info_repeat_step.text()),
|
301 |
+
'text_label_repeat' : getEditableValue($text_label_repeat.text()),
|
302 |
+
'text_repeat' : getEditableValue($text_repeat.text()),
|
303 |
+
'text_repeat_another_time' : getEditableValue($text_repeat_another_time.text()),
|
304 |
+
'text_repeat_biweekly' : getEditableValue($text_repeat_biweekly.text()),
|
305 |
+
'text_repeat_daily' : getEditableValue($text_repeat_daily.text()),
|
306 |
+
'text_repeat_day' : getEditableValue($text_repeat_day.text()),
|
307 |
+
'text_repeat_days' : getEditableValue($text_repeat_days.text()),
|
308 |
+
'text_repeat_deleted' : getEditableValue($text_repeat_deleted.text()),
|
309 |
+
'text_repeat_every' : getEditableValue($text_repeat_every.text()),
|
310 |
+
'text_repeat_first' : getEditableValue($text_repeat_first.text()),
|
311 |
+
'text_repeat_first_in_cart_info' : getEditableValue($text_repeat_first_in_cart_info.text()),
|
312 |
+
'text_repeat_fourth' : getEditableValue($text_repeat_fourth.text()),
|
313 |
+
'text_repeat_last' : getEditableValue($text_repeat_last.text()),
|
314 |
+
'text_repeat_monthly' : getEditableValue($text_repeat_monthly.text()),
|
315 |
+
'text_repeat_on' : getEditableValue($text_repeat_on.text()),
|
316 |
+
'text_repeat_on_week' : getEditableValue($text_repeat_on_week.text()),
|
317 |
+
'text_repeat_required_week_days' : getEditableValue($text_repeat_required_week_days.text()),
|
318 |
+
'text_repeat_schedule' : getEditableValue($text_repeat_schedule.text()),
|
319 |
+
'text_repeat_schedule_help' : getEditableValue($text_repeat_schedule_help.text()),
|
320 |
+
'text_repeat_schedule_info' : getEditableValue($text_repeat_schedule_info.text()),
|
321 |
+
'text_repeat_second' : getEditableValue($text_repeat_second.text()),
|
322 |
+
'text_repeat_specific' : getEditableValue($text_repeat_specific.text()),
|
323 |
+
'text_repeat_third' : getEditableValue($text_repeat_third.text()),
|
324 |
+
'text_repeat_this_appointment' : getEditableValue($text_repeat_this_appointment.text()),
|
325 |
+
'text_repeat_until' : getEditableValue($text_repeat_until.text()),
|
326 |
+
'text_repeat_weekly' : getEditableValue($text_repeat_weekly.text()),
|
327 |
+
'text_step_repeat' : getEditableValue($text_step_repeat.text()),
|
328 |
+
// Validator.
|
329 |
+
'text_required_location' : getEditableValue($('#bookly_l10n_required_location').html()),
|
330 |
+
'text_required_service' : getEditableValue($('#bookly_l10n_required_service').html()),
|
331 |
+
'text_required_employee' : getEditableValue($('#bookly_l10n_required_employee').html()),
|
332 |
+
'text_required_name' : getEditableValue($('#bookly_l10n_required_name').html()),
|
333 |
+
'text_required_phone' : getEditableValue($('#bookly_l10n_required_phone').html()),
|
334 |
+
'text_required_email' : getEditableValue($('#bookly_l10n_required_email').html()),
|
335 |
+
// Checkboxes.
|
336 |
+
'progress_tracker' : Number($progress_tracker_option.prop('checked')),
|
337 |
+
'staff_name_with_price': Number($staff_name_with_price_option.prop('checked')),
|
338 |
+
'blocked_timeslots' : Number($blocked_timeslots_option.prop('checked')),
|
339 |
+
'day_one_column' : Number($day_one_column_option.prop('checked')),
|
340 |
+
'show_calendar' : Number($show_calendar_option.prop('checked')),
|
341 |
+
'required_employee' : Number($required_employee_option.prop('checked')),
|
342 |
+
'required_location' : Number($required_location_option.prop('checked'))
|
343 |
+
} // options
|
344 |
+
}; // data
|
345 |
+
|
346 |
+
// update data and show spinner while updating
|
347 |
+
var ladda = Ladda.create(this);
|
348 |
+
ladda.start();
|
349 |
+
$.post(ajaxurl, data, function (response) {
|
350 |
+
ladda.stop();
|
351 |
+
booklyAlert({success : [BooklyL10n.saved]});
|
352 |
+
});
|
353 |
+
});
|
354 |
+
|
355 |
+
// Reset options to defaults.
|
356 |
+
$reset_button.on('click', function() {
|
357 |
+
// Reset color.
|
358 |
+
$color_picker.wpColorPicker('color', $color_picker.data('selected'));
|
359 |
+
|
360 |
+
// Reset texts.
|
361 |
+
jQuery.each($('.editable:not([data-type=multiple])'), function() {
|
362 |
+
$(this).text($(this).data('option-default')); //default value for texts
|
363 |
+
$(this).editable('setValue', $(this).data('option-default')); // default value for editable inputs
|
364 |
+
});
|
365 |
+
|
366 |
+
// Reset texts.
|
367 |
+
jQuery.each($('.ab-service-list, .ab-employee-list'), function() {
|
368 |
+
$(this).html($(this).data('default')); //default value
|
369 |
+
});
|
370 |
+
|
371 |
+
// default value for multiple inputs
|
372 |
+
$('[data-type=multiple]').each(function () {
|
373 |
+
var $elem = $(this),
|
374 |
+
options = $elem.data('options-default'),
|
375 |
+
$target;
|
376 |
+
$elem.data('options',options);
|
377 |
+
$.each(options, function (name, value) {
|
378 |
+
$target = $('#' + name);
|
379 |
+
if ($target.is(':text')) {
|
380 |
+
$target.val(value);
|
381 |
+
} else {
|
382 |
+
$target.text(value);
|
383 |
+
}
|
384 |
+
$target = $('[name=' + name + ']:text');
|
385 |
+
if ($target.is(':text')) {
|
386 |
+
$target.val(value);
|
387 |
+
} else {
|
388 |
+
$target.text(value);
|
389 |
+
}
|
390 |
+
});
|
391 |
+
});
|
392 |
+
});
|
393 |
+
|
394 |
+
$progress_tracker_option.change(function(){
|
395 |
+
$('.ab-progress-tracker').toggle($(this).is(':checked'));
|
396 |
+
}).trigger('change');
|
397 |
+
|
398 |
+
var day_one_column = $('.ab-day-one-column'),
|
399 |
+
day_columns = $('.ab-day-columns');
|
400 |
+
|
401 |
+
if ($show_calendar_option.prop('checked')) {
|
402 |
+
$second_step_calendar_wrap.show();
|
403 |
+
day_columns.find('.col3,.col4,.col5,.col6,.col7').hide();
|
404 |
+
day_columns.find('.col2 button:gt(0)').attr('style', 'display: none !important');
|
405 |
+
day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').hide();
|
406 |
+
}
|
407 |
+
|
408 |
+
// Change show calendar
|
409 |
+
$show_calendar_option.change(function() {
|
410 |
+
if (this.checked) {
|
411 |
+
$second_step_calendar_wrap.show();
|
412 |
+
day_columns.find('.col3,.col4,.col5,.col6,.col7').hide();
|
413 |
+
day_columns.find('.col2 button:gt(0)').attr('style', 'display: none !important');
|
414 |
+
day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').hide();
|
415 |
+
} else {
|
416 |
+
$second_step_calendar_wrap.hide();
|
417 |
+
day_columns.find('.col2 button:gt(0)').attr('style', 'display: block !important');
|
418 |
+
day_columns.find('.col2 button.ab-first-child').attr('style', 'background: ' + $color_picker.wpColorPicker('color') + '!important;display: block !important');
|
419 |
+
day_columns.find('.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
420 |
+
day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
421 |
+
}
|
422 |
+
});
|
423 |
+
|
424 |
+
// Change blocked time slots.
|
425 |
+
$blocked_timeslots_option.change(function(){
|
426 |
+
if (this.checked) {
|
427 |
+
$('.ab-hour.no-booked').removeClass('no-booked').addClass('booked');
|
428 |
+
} else {
|
429 |
+
$('.ab-hour.booked').removeClass('booked').addClass('no-booked');
|
430 |
+
}
|
431 |
+
});
|
432 |
+
|
433 |
+
// Change day one column.
|
434 |
+
$day_one_column_option.change(function() {
|
435 |
+
if (this.checked) {
|
436 |
+
day_one_column.show();
|
437 |
+
day_columns.hide();
|
438 |
+
} else {
|
439 |
+
day_one_column.hide();
|
440 |
+
day_columns.show();
|
441 |
+
}
|
442 |
+
});
|
443 |
+
|
444 |
+
// Clickable week-days.
|
445 |
+
$('.bookly-week-day').on('change', function () {
|
446 |
+
var self = $(this);
|
447 |
+
if (self.is(':checked') && !self.parent().hasClass('active')) {
|
448 |
+
self.parent().addClass('active');
|
449 |
+
} else if (self.parent().hasClass('active')) {
|
450 |
+
self.parent().removeClass('active')
|
451 |
+
}
|
452 |
+
});
|
453 |
+
|
454 |
+
var multiple = function (options) {
|
455 |
+
this.init('multiple', options, multiple.defaults);
|
456 |
+
};
|
457 |
+
|
458 |
+
// Step repeat.
|
459 |
+
$repeat_ui_step_calendar.pickadate({
|
460 |
+
formatSubmit : 'yyyy-mm-dd',
|
461 |
+
format : BooklyL10n.date_format,
|
462 |
+
min : true,
|
463 |
+
clear : false,
|
464 |
+
close : false,
|
465 |
+
today : BooklyL10n.today,
|
466 |
+
weekdaysShort : BooklyL10n.days,
|
467 |
+
monthsFull : BooklyL10n.months,
|
468 |
+
labelMonthNext : BooklyL10n.nextMonth,
|
469 |
+
labelMonthPrev : BooklyL10n.prevMonth,
|
470 |
+
onRender : applyColor,
|
471 |
+
firstDay : BooklyL10n.start_of_week == 1
|
472 |
+
});
|
473 |
+
$repeat_ui_variant.on('change', function () {
|
474 |
+
$repeat_ui_variants.hide();
|
475 |
+
$('.bookly-variant-' + this.value).show()
|
476 |
+
}).trigger('change');
|
477 |
+
|
478 |
+
$repeat_ui_variant_monthly.on('change', function () {
|
479 |
+
$repeat_ui_monthly_week_day.toggle(this.value != 'specific');
|
480 |
+
$repeat_ui_monthly_specific_day.toggle(this.value == 'specific');
|
481 |
+
}).trigger('change');
|
482 |
+
|
483 |
+
$repeat_ui_weekly_week_day.on('change', function () {
|
484 |
+
var $this = $(this);
|
485 |
+
if ($this.is(':checked')) {
|
486 |
+
$this.parent().not("[class*='active']").addClass('active');
|
487 |
+
} else {
|
488 |
+
$this.parent().removeClass('active');
|
489 |
+
}
|
490 |
+
});
|
491 |
+
|
492 |
+
// Inherit from Abstract input.
|
493 |
+
$.fn.editableutils.inherit(multiple, $.fn.editabletypes.abstractinput);
|
494 |
+
|
495 |
+
$.extend(multiple.prototype, {
|
496 |
+
container: null,
|
497 |
+
$elem : null,
|
498 |
+
render : function() {
|
499 |
+
this.container = jQuery('div.bookly-js-container', this.tpl);
|
500 |
+
},
|
501 |
+
|
502 |
+
value2html: function (value, element) { },
|
503 |
+
|
504 |
+
activate: function () {
|
505 |
+
this.container.find(':text:eq(0)').focus();
|
506 |
+
},
|
507 |
+
|
508 |
+
value2input: function(value) {
|
509 |
+
if(!value) {
|
510 |
+
return;
|
511 |
+
}
|
512 |
+
var container = this.container;
|
513 |
+
this.$elem = value.elem;
|
514 |
+
if (!this.$elem.data('options')) {
|
515 |
+
this.$elem.data('options', this.$elem.data('options-default'));
|
516 |
+
}
|
517 |
+
container.html('');
|
518 |
+
$.each(this.$elem.data('options'), function (id, value) {
|
519 |
+
$('<input/>', {
|
520 |
+
type : 'text',
|
521 |
+
class: 'form-control input-sm',
|
522 |
+
name : id,
|
523 |
+
value: value || ''
|
524 |
+
}).appendTo(container);
|
525 |
+
});
|
526 |
+
},
|
527 |
+
|
528 |
+
input2value: function() {
|
529 |
+
var options = {};
|
530 |
+
$.each(this.container.find(':text'), function () {
|
531 |
+
var name = $(this).attr('name'),
|
532 |
+
$target = $('#' + name);
|
533 |
+
options[name] = this.value;
|
534 |
+
if($target.is(':text')){
|
535 |
+
$target.val(this.value);
|
536 |
+
} else {
|
537 |
+
$target.text(this.value);
|
538 |
+
}
|
539 |
+
});
|
540 |
+
this.$elem.data('options', options);
|
541 |
+
return {elem: this.$elem};
|
542 |
+
}
|
543 |
+
});
|
544 |
+
multiple.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
545 |
+
tpl: '<div class="bookly-editable-multiple"><div class="bookly-js-container">',
|
546 |
+
inputclass: ''
|
547 |
+
});
|
548 |
+
|
549 |
+
$.fn.editabletypes.multiple = multiple;
|
550 |
+
$('[data-type=multiple]').each(function () {
|
551 |
+
var $elem = $(this);
|
552 |
+
$elem.editable({ value: { elem: $elem}});
|
553 |
+
});
|
554 |
+
|
555 |
+
$text_info_service.add('#bookly_l10n_info_time_step').add('#bookly_l10n_info_details_step').add('#bookly_l10n_info_payment_step').add('#bookly_l10n_info_complete_step').add('#bookly_l10n_info_coupon').editable({placement: 'right'});
|
556 |
+
$ab_editable.editable();
|
557 |
+
|
558 |
+
$.fn.editableform.template = '<form class="form-inline editableform"> <div class="control-group"> <div> <div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-notes"></div><div class="editable-error-block"></div></div> </form>';
|
559 |
+
$.fn.editableform.buttons = '<div class="btn-group btn-group-sm"><button type="submit" class="btn btn-success editable-submit"><span class="glyphicon glyphicon-ok"></span></button><button type="button" class="btn btn-default editable-cancel"><span class="glyphicon glyphicon-remove"></span></button></div>';
|
560 |
+
|
561 |
+
$ab_editable.on('shown', function(e, editable) {
|
562 |
+
$('.popover').find('.arrow').removeClass().addClass('popover-arrow');
|
563 |
+
$('.editable-notes').html($(e.target).data('notes'));
|
564 |
+
});
|
565 |
+
$('[data-type="multiple"]').on('shown', function(e, editable) {
|
566 |
+
$('.popover').find('.arrow').removeClass().addClass('popover-arrow');
|
567 |
+
});
|
568 |
+
|
569 |
+
$("[data-mirror]").on('save', function (e, params) {
|
570 |
+
$("." + $(e.target).data('mirror')).editable('setValue', params.newValue);
|
571 |
+
switch ($(e.target).data('mirror')){
|
572 |
+
case 'text_services':
|
573 |
+
$(".ab-service-list").html(params.newValue.label);
|
574 |
+
break;
|
575 |
+
case 'text_locations':
|
576 |
+
$(".ab-location-list").html(params.newValue.label);
|
577 |
+
break;
|
578 |
+
case 'text_employee':
|
579 |
+
$(".ab-employee-list").html(params.newValue.label);
|
580 |
+
break;
|
581 |
+
}
|
582 |
+
});
|
583 |
+
|
584 |
+
$('input[type=radio]').change(function () {
|
585 |
+
if ($('.ab-card-payment').is(':checked')) {
|
586 |
+
$('form.ab-card-form').show();
|
587 |
+
} else {
|
588 |
+
$('form.ab-card-form').hide();
|
589 |
+
}
|
590 |
+
});
|
591 |
+
|
592 |
+
$('#bookly-js-hint-alert').on('closed.bs.alert', function () {
|
593 |
+
$.ajax({
|
594 |
+
url: ajaxurl,
|
595 |
+
data: { action: 'bookly_dismiss_appearance_notice' }
|
596 |
+
});
|
597 |
+
})
|
598 |
+
}); // jQuery
|
backend/modules/appearance/templates/_1_service.php
CHANGED
@@ -1,195 +1,179 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
/** @var WP_Locale $wp_locale */
|
3 |
-
global $wp_locale;
|
4 |
-
?>
|
5 |
-
<div class="bookly-form">
|
6 |
-
<?php include '_progress_tracker.php' ?>
|
7 |
-
|
8 |
-
<div class="
|
9 |
-
<div class="
|
10 |
-
<span data-default="<?php
|
11 |
-
class="
|
12 |
-
data-rows="7" data-type="textarea"><?php echo esc_html( get_option( '
|
13 |
-
</div>
|
14 |
-
<div class="ab-mobile-step_1
|
15 |
-
<div class="bookly-js-chain-item bookly-table
|
16 |
-
<?php if ( \BooklyLite\Lib\Config::
|
17 |
-
<div class="ab-formGroup">
|
18 |
-
<?php do_action( 'bookly_locations_render_appearance' ) ?>
|
19 |
-
</div>
|
20 |
-
<?php endif ?>
|
21 |
-
<div class="ab-formGroup">
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
<option value=""
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
<option value="
|
78 |
-
<option value="
|
79 |
-
<option value="-
|
80 |
-
<option value="
|
81 |
-
<option value="-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
<option
|
90 |
-
<option
|
91 |
-
<option
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
<?php
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
<div class="ab-
|
118 |
-
<
|
119 |
-
|
120 |
-
<
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
<div class="ab-right ab-next-step ab-btn">
|
180 |
-
<span class="text_next ab_editable" id="ab-text-button-next" data-mirror="text_next" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_next' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_next' ) ) ?></span>
|
181 |
-
</div>
|
182 |
-
<button class="ab-left ab-goto-cart bookly-round-button ladda-button"><span><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/cart.png' ) ?>" /></span></button>
|
183 |
-
</div>
|
184 |
-
</div>
|
185 |
-
</div>
|
186 |
-
</div>
|
187 |
-
<div style="display: none">
|
188 |
-
<?php foreach ( array( 'ab_appearance_text_required_service', 'ab_appearance_text_required_name', 'ab_appearance_text_required_phone', 'ab_appearance_text_required_email', 'ab_appearance_text_required_employee', 'ab_appearance_text_required_location' ) as $validator ) : ?>
|
189 |
-
<div id="<?php echo $validator ?>"><?php echo get_option( $validator ) ?></div>
|
190 |
-
<?php endforeach ?>
|
191 |
-
</div>
|
192 |
-
<style id="ab--style-arrow">
|
193 |
-
.picker__nav--next:before { border-left: 6px solid <?php echo get_option( 'ab_appearance_color' ) ?>!important; }
|
194 |
-
.picker__nav--prev:before { border-right: 6px solid <?php echo get_option( 'ab_appearance_color' ) ?>!important; }
|
195 |
</style>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var WP_Locale $wp_locale */
|
3 |
+
global $wp_locale;
|
4 |
+
?>
|
5 |
+
<div class="bookly-form">
|
6 |
+
<?php include '_progress_tracker.php' ?>
|
7 |
+
|
8 |
+
<div class="bookly-service-step">
|
9 |
+
<div class="bookly-box">
|
10 |
+
<span data-option-default="<?php form_option( 'bookly_l10n_info_service_step' ) ?>"
|
11 |
+
class="bookly-editable ab-bold ab-desc" id="bookly_l10n_info_service_step"
|
12 |
+
data-rows="7" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_service_step' ) ) ?></span>
|
13 |
+
</div>
|
14 |
+
<div class="ab-mobile-step_1 bookly-box">
|
15 |
+
<div class="bookly-js-chain-item bookly-table bookly-box">
|
16 |
+
<?php if ( \BooklyLite\Lib\Config::isLocationsEnabled() ) : ?>
|
17 |
+
<div class="ab-formGroup">
|
18 |
+
<?php do_action( 'bookly_locations_render_appearance' ) ?>
|
19 |
+
</div>
|
20 |
+
<?php endif ?>
|
21 |
+
<div class="ab-formGroup">
|
22 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_category', 'bookly_l10n_option_category', ) ) ?>
|
23 |
+
<div>
|
24 |
+
<select class="ab-select-mobile ab-select-category">
|
25 |
+
<option value="" id="bookly_l10n_option_category"><?php echo esc_html( get_option( 'bookly_l10n_option_category' ) ) ?></option>
|
26 |
+
<option value="1">Cosmetic Dentistry</option>
|
27 |
+
<option value="2">Invisalign</option>
|
28 |
+
<option value="3">Orthodontics</option>
|
29 |
+
<option value="4">Dentures</option>
|
30 |
+
</select>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="ab-formGroup">
|
34 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array(
|
35 |
+
'bookly_l10n_label_service',
|
36 |
+
'bookly_l10n_option_service',
|
37 |
+
'bookly_l10n_required_service',
|
38 |
+
) ) ?>
|
39 |
+
<div>
|
40 |
+
<select class="ab-select-mobile ab-select-service">
|
41 |
+
<option id="bookly_l10n_option_service"><?php echo esc_html( get_option( 'bookly_l10n_option_service' ) ) ?></option>
|
42 |
+
<option>Crown and Bridge</option>
|
43 |
+
<option>Teeth Whitening</option>
|
44 |
+
<option>Veneers</option>
|
45 |
+
<option>Invisalign (invisable braces)</option>
|
46 |
+
<option>Orthodontics (braces)</option>
|
47 |
+
<option>Wisdom tooth Removal</option>
|
48 |
+
<option>Root Canal Treatment</option>
|
49 |
+
<option>Dentures</option>
|
50 |
+
</select>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
<div class="ab-formGroup">
|
54 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array(
|
55 |
+
'bookly_l10n_label_employee',
|
56 |
+
'bookly_l10n_option_employee',
|
57 |
+
'bookly_l10n_required_employee',
|
58 |
+
) ) ?>
|
59 |
+
<div>
|
60 |
+
<select class="ab-select-mobile ab-select-employee">
|
61 |
+
<option value="0" id="bookly_l10n_option_employee"><?php echo esc_html( get_option( 'bookly_l10n_option_employee' ) ) ?></option>
|
62 |
+
<option value="1" class="employee-name-price">Nick Knight (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?>)</option>
|
63 |
+
<option value="-1" class="employee-name">Nick Knight</option>
|
64 |
+
<option value="2" class="employee-name-price">Jane Howard (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 375 ) ?>)</option>
|
65 |
+
<option value="-2" class="employee-name">Jane Howard</option>
|
66 |
+
<option value="3" class="employee-name-price">Ashley Stamp (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 300 ) ?>)</option>
|
67 |
+
<option value="-3" class="employee-name">Ashley Stamp</option>
|
68 |
+
<option value="4" class="employee-name-price">Bradley Tannen (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 400 ) ?>)</option>
|
69 |
+
<option value="-4" class="employee-name">Bradley Tannen</option>
|
70 |
+
<option value="5" class="employee-name-price">Wayne Turner (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?>)</option>
|
71 |
+
<option value="-5" class="employee-name">Wayne Turner</option>
|
72 |
+
<option value="6" class="employee-name-price">Emily Taylor (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?>)</option>
|
73 |
+
<option value="-6" class="employee-name">Emily Taylor</option>
|
74 |
+
<option value="7" class="employee-name-price">Hugh Canberg (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 380 ) ?>)</option>
|
75 |
+
<option value="-7" class="employee-name">Hugh Canberg</option>
|
76 |
+
<option value="8" class="employee-name-price">Jim Gonzalez (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 390 ) ?>)</option>
|
77 |
+
<option value="-8" class="employee-name">Jim Gonzalez</option>
|
78 |
+
<option value="9" class="employee-name-price">Nancy Stinson (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 360 ) ?>)</option>
|
79 |
+
<option value="-9" class="employee-name">Nancy Stinson</option>
|
80 |
+
<option value="10" class="employee-name-price">Marry Murphy (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?>)</option>
|
81 |
+
<option value="-10" class="employee-name">Marry Murphy</option>
|
82 |
+
</select>
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
<div class="ab-formGroup">
|
86 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_number_of_persons', ) ) ?>
|
87 |
+
<div>
|
88 |
+
<select class="ab-select-mobile ab-select-number-of-persons">
|
89 |
+
<option>1</option>
|
90 |
+
<option>2</option>
|
91 |
+
<option>3</option>
|
92 |
+
</select>
|
93 |
+
</div>
|
94 |
+
</div>
|
95 |
+
<?php if ( \BooklyLite\Lib\Config::isMultiplyAppointmentsEnabled() ) : ?>
|
96 |
+
<div class="ab-formGroup">
|
97 |
+
<?php do_action( 'bookly_multiply_appointments_render_appearance' ) ?>
|
98 |
+
</div>
|
99 |
+
<?php endif ?>
|
100 |
+
<?php if ( \BooklyLite\Lib\Config::isChainAppointmentsEnabled() ) : ?>
|
101 |
+
<div class="ab-formGroup">
|
102 |
+
<label></label>
|
103 |
+
<div>
|
104 |
+
<button class="bookly-round" ><i class="bookly-icon-sm bookly-icon-plus"></i></button>
|
105 |
+
</div>
|
106 |
+
</div>
|
107 |
+
<?php endif ?>
|
108 |
+
</div>
|
109 |
+
|
110 |
+
<div class="ab-right ab-mobile-next-step ab-btn ab-none" onclick="return false">
|
111 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_next' ), 'bookly-js-text-next' ) ?>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
<div class="ab-mobile-step_2">
|
115 |
+
<div class="bookly-box">
|
116 |
+
<div class="ab-left">
|
117 |
+
<div class="ab-available-date ab-left">
|
118 |
+
<div class="ab-formGroup">
|
119 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_select_date', ) ) ?>
|
120 |
+
<div>
|
121 |
+
<input class="ab-date-from" style="background-color: #fff;" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
</div>
|
125 |
+
<div class="bookly-week-days bookly-table ab-left">
|
126 |
+
<?php foreach ( $wp_locale->weekday_abbrev as $weekday_abbrev ) : ?>
|
127 |
+
<div>
|
128 |
+
<div class="bookly-font-bold"><?php echo $weekday_abbrev ?></div>
|
129 |
+
<label class="active">
|
130 |
+
<input class="bookly-week-day" value="1" checked="checked" type="checkbox">
|
131 |
+
</label>
|
132 |
+
</div>
|
133 |
+
<?php endforeach ?>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
<div class="ab-time-range ab-left">
|
137 |
+
<div class="ab-formGroup ab-time-from ab-left">
|
138 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_start_from', ) ) ?>
|
139 |
+
<div>
|
140 |
+
<select class="ab-select-time-from">
|
141 |
+
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
142 |
+
<option><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?></option>
|
143 |
+
<?php endfor ?>
|
144 |
+
</select>
|
145 |
+
</div>
|
146 |
+
</div>
|
147 |
+
<div class="ab-formGroup ab-time-to ab-left">
|
148 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_finish_by', ) ) ?>
|
149 |
+
<div>
|
150 |
+
<select class="ab-select-time-to">
|
151 |
+
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
152 |
+
<option<?php selected( $i == 64800 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?></option>
|
153 |
+
<?php endfor ?>
|
154 |
+
</select>
|
155 |
+
</div>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
+
</div>
|
159 |
+
<div class="bookly-box bookly-nav-steps">
|
160 |
+
<div class="ab-right ab-mobile-prev-step ab-btn ab-none">
|
161 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_back' ), 'bookly-js-text-back' ) ?>
|
162 |
+
</div>
|
163 |
+
<div class="bookly-next-step ab-btn">
|
164 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_next' ), 'bookly-js-text-next' ) ?>
|
165 |
+
</div>
|
166 |
+
<button class="bookly-go-to-cart bookly-round bookly-round-md ladda-button"><span><img src="<?php echo plugins_url( 'bookly-responsive-appointment-booking-tool/frontend/resources/images/cart.png' ) ?>" /></span></button>
|
167 |
+
</div>
|
168 |
+
</div>
|
169 |
+
</div>
|
170 |
+
</div>
|
171 |
+
<div style="display: none">
|
172 |
+
<?php foreach ( array( 'bookly_l10n_required_service', 'bookly_l10n_required_name', 'bookly_l10n_required_phone', 'bookly_l10n_required_email', 'bookly_l10n_required_employee', 'bookly_l10n_required_location' ) as $validator ) : ?>
|
173 |
+
<div id="<?php echo $validator ?>"><?php echo get_option( $validator ) ?></div>
|
174 |
+
<?php endforeach ?>
|
175 |
+
</div>
|
176 |
+
<style id="ab--style-arrow">
|
177 |
+
.picker__nav--next:before { border-left: 6px solid <?php echo get_option( 'bookly_app_color' ) ?>!important; }
|
178 |
+
.picker__nav--prev:before { border-right: 6px solid <?php echo get_option( 'bookly_app_color' ) ?>!important; }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
179 |
</style>
|
backend/modules/appearance/templates/_3_time.php
CHANGED
@@ -1,165 +1,165 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="bookly-form">
|
3 |
-
<?php include '_progress_tracker.php' ?>
|
4 |
-
|
5 |
-
<div class="
|
6 |
-
<span data-
|
7 |
-
</div>
|
8 |
-
<!-- timeslots -->
|
9 |
-
<div class="ab-time-step">
|
10 |
-
<div class="ab-columnizer-wrap">
|
11 |
-
<div class="ab-columnizer">
|
12 |
-
<div class="ab-time-screen ab-day-columns" style="display: <?php echo get_option( '
|
13 |
-
<div class="ab-input-wrap ab-slot-calendar">
|
14 |
-
<span class="ab-date-wrap">
|
15 |
-
<input style="display: none" class="ab-selected-date ab-formElement" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
16 |
-
</span>
|
17 |
-
</div>
|
18 |
-
<div class="ab-column col1">
|
19 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d' ) ?></button>
|
20 |
-
<?php for ( $i = 28800; $i <= 57600; $i += 3600 ) : ?>
|
21 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
22 |
-
<span class="ladda-label">
|
23 |
-
<i class="ab-hour-icon"><span></span></i>
|
24 |
-
<?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
25 |
-
</span>
|
26 |
-
</button>
|
27 |
-
<?php endfor ?>
|
28 |
-
</div>
|
29 |
-
<div class="ab-column col2">
|
30 |
-
<button class="ab-hour ladda-button ab-last-child">
|
31 |
-
<span class="ladda-label">
|
32 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 61200 ) ?>
|
33 |
-
</span>
|
34 |
-
</button>
|
35 |
-
<button class="ab-day ab-first-child" style="display: <?php echo get_option( '
|
36 |
-
<?php for ( $i = 28800; $i <= 54000; $i += 3600 ) : ?>
|
37 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
38 |
-
<span class="ladda-label">
|
39 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
40 |
-
</span>
|
41 |
-
</button>
|
42 |
-
<?php endfor ?>
|
43 |
-
</div>
|
44 |
-
<div class="ab-column col3" style="display: <?php echo get_option( '
|
45 |
-
<?php for ( $i = 57600; $i <= 61200; $i += 3600 ) : ?>
|
46 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
47 |
-
<span class="ladda-label">
|
48 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
49 |
-
</span>
|
50 |
-
</button>
|
51 |
-
<?php endfor ?>
|
52 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+2
|
53 |
-
<?php for ( $i = 28800; $i <= 50400; $i += 3600 ) : ?>
|
54 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
55 |
-
<span class="ladda-label">
|
56 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
57 |
-
</span>
|
58 |
-
</button>
|
59 |
-
<?php endfor ?>
|
60 |
-
</div>
|
61 |
-
<div class="ab-column col4" style="display: <?php echo get_option( '
|
62 |
-
<?php for ( $i = 54000; $i <= 61200; $i += 3600 ) : ?>
|
63 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
64 |
-
<span class="ladda-label">
|
65 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
66 |
-
</span>
|
67 |
-
</button>
|
68 |
-
<?php endfor ?>
|
69 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+3
|
70 |
-
<?php for ( $i = 28800; $i <= 46800; $i += 3600 ) : ?>
|
71 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
72 |
-
<span class="ladda-label">
|
73 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
74 |
-
</span>
|
75 |
-
</button>
|
76 |
-
<?php endfor ?>
|
77 |
-
</div>
|
78 |
-
<div class="ab-column col5" style="display:<?php echo get_option( '
|
79 |
-
<?php for ( $i = 50400; $i <= 61200; $i += 3600 ) : ?>
|
80 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
81 |
-
<span class="ladda-label">
|
82 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
83 |
-
</span>
|
84 |
-
</button>
|
85 |
-
<?php endfor ?>
|
86 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+4
|
87 |
-
<?php for ( $i = 28800; $i <= 43200; $i += 3600 ) : ?>
|
88 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
89 |
-
<span class="ladda-label">
|
90 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
91 |
-
</span>
|
92 |
-
</button>
|
93 |
-
<?php endfor ?>
|
94 |
-
</div>
|
95 |
-
<div class="ab-column col6" style="display: <?php echo get_option( '
|
96 |
-
<?php for ( $i = 46800; $i <= 61200; $i += 3600 ) : ?>
|
97 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
98 |
-
<span class="ladda-label">
|
99 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
100 |
-
</span>
|
101 |
-
</button>
|
102 |
-
<?php endfor ?>
|
103 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+5
|
104 |
-
<?php for ( $i = 28800; $i <= 39600; $i += 3600 ) : ?>
|
105 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
106 |
-
<span class="ladda-label">
|
107 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
108 |
-
</span>
|
109 |
-
</button>
|
110 |
-
<?php endfor ?>
|
111 |
-
</div>
|
112 |
-
<div class="ab-column col7" style="display:<?php echo get_option( '
|
113 |
-
<?php for ( $i = 43200; $i <= 61200; $i += 3600 ) : ?>
|
114 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
115 |
-
<span class="ladda-label">
|
116 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
117 |
-
</span>
|
118 |
-
</button>
|
119 |
-
<?php endfor ?>
|
120 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+6
|
121 |
-
<?php for ( $i = 28800; $i <= 36000; $i += 3600 ) : ?>
|
122 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
123 |
-
<span class="ladda-label">
|
124 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
125 |
-
</span>
|
126 |
-
</button>
|
127 |
-
<?php endfor ?>
|
128 |
-
</div>
|
129 |
-
</div>
|
130 |
-
|
131 |
-
<div class="ab-time-screen ab-day-one-column" style="display: <?php echo get_option( '
|
132 |
-
<div class="ab-input-wrap ab-slot-calendar">
|
133 |
-
<span class="ab-date-wrap">
|
134 |
-
<input style="display: none" class="ab-selected-date ab-formElement" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
135 |
-
</span>
|
136 |
-
</div>
|
137 |
-
<?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
|
138 |
-
<div class="ab-column col<?php echo $i ?>">
|
139 |
-
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+' . ( $i - 1 ) . '
|
140 |
-
<?php for ( $j = 28800; $j <= 61200; $j += 3600 ) : ?>
|
141 |
-
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( '
|
142 |
-
<span class="ladda-label">
|
143 |
-
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $j ) ?>
|
144 |
-
</span>
|
145 |
-
</button>
|
146 |
-
<?php endfor ?>
|
147 |
-
</div>
|
148 |
-
<?php endfor ?>
|
149 |
-
</div>
|
150 |
-
</div>
|
151 |
-
</div>
|
152 |
-
</div>
|
153 |
-
<div class="
|
154 |
-
<button class="ab-time-next ab-btn ab-right ladda-button">
|
155 |
-
<span class="ab_label">></span>
|
156 |
-
</button>
|
157 |
-
<button class="ab-time-prev ab-btn ab-right ladda-button">
|
158 |
-
<span class="ab_label"><</span>
|
159 |
-
</button>
|
160 |
-
<div class="
|
161 |
-
|
162 |
-
</div>
|
163 |
-
<button class="
|
164 |
-
</div>
|
165 |
-
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="bookly-form">
|
3 |
+
<?php include '_progress_tracker.php' ?>
|
4 |
+
|
5 |
+
<div class="bookly-box">
|
6 |
+
<span data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 3 ), false ) ) ?>" data-placement="bottom" data-option-default="<?php form_option( 'bookly_l10n_info_time_step' ) ?>" class="bookly-editable" id="bookly_l10n_info_time_step" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_time_step' ) ) ?></span>
|
7 |
+
</div>
|
8 |
+
<!-- timeslots -->
|
9 |
+
<div class="ab-time-step">
|
10 |
+
<div class="ab-columnizer-wrap">
|
11 |
+
<div class="ab-columnizer">
|
12 |
+
<div class="ab-time-screen ab-day-columns" style="display: <?php echo get_option( 'bookly_app_show_day_one_column' ) == 1 ? ' none' : 'block' ?>">
|
13 |
+
<div class="ab-input-wrap ab-slot-calendar">
|
14 |
+
<span class="ab-date-wrap">
|
15 |
+
<input style="display: none" class="ab-selected-date ab-formElement" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
16 |
+
</span>
|
17 |
+
</div>
|
18 |
+
<div class="ab-column col1">
|
19 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', current_time( 'timestamp' ) ) ?></button>
|
20 |
+
<?php for ( $i = 28800; $i <= 57600; $i += 3600 ) : ?>
|
21 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
22 |
+
<span class="ladda-label">
|
23 |
+
<i class="ab-hour-icon"><span></span></i>
|
24 |
+
<?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
25 |
+
</span>
|
26 |
+
</button>
|
27 |
+
<?php endfor ?>
|
28 |
+
</div>
|
29 |
+
<div class="ab-column col2">
|
30 |
+
<button class="ab-hour ladda-button ab-last-child">
|
31 |
+
<span class="ladda-label">
|
32 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 61200 ) ?>
|
33 |
+
</span>
|
34 |
+
</button>
|
35 |
+
<button class="ab-day ab-first-child" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'block' ?>"><?php echo date_i18n( 'D, M d', strtotime( '+1 day', current_time( 'timestamp' ) ) ) ?></button>
|
36 |
+
<?php for ( $i = 28800; $i <= 54000; $i += 3600 ) : ?>
|
37 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'block' ?>">
|
38 |
+
<span class="ladda-label">
|
39 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
40 |
+
</span>
|
41 |
+
</button>
|
42 |
+
<?php endfor ?>
|
43 |
+
</div>
|
44 |
+
<div class="ab-column col3" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
45 |
+
<?php for ( $i = 57600; $i <= 61200; $i += 3600 ) : ?>
|
46 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
47 |
+
<span class="ladda-label">
|
48 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
49 |
+
</span>
|
50 |
+
</button>
|
51 |
+
<?php endfor ?>
|
52 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+2 days', current_time('timestamp') ) ) ?></button>
|
53 |
+
<?php for ( $i = 28800; $i <= 50400; $i += 3600 ) : ?>
|
54 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
55 |
+
<span class="ladda-label">
|
56 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
57 |
+
</span>
|
58 |
+
</button>
|
59 |
+
<?php endfor ?>
|
60 |
+
</div>
|
61 |
+
<div class="ab-column col4" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
62 |
+
<?php for ( $i = 54000; $i <= 61200; $i += 3600 ) : ?>
|
63 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
64 |
+
<span class="ladda-label">
|
65 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
66 |
+
</span>
|
67 |
+
</button>
|
68 |
+
<?php endfor ?>
|
69 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+3 days', current_time( 'timestamp' ) ) ) ?></button>
|
70 |
+
<?php for ( $i = 28800; $i <= 46800; $i += 3600 ) : ?>
|
71 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
72 |
+
<span class="ladda-label">
|
73 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
74 |
+
</span>
|
75 |
+
</button>
|
76 |
+
<?php endfor ?>
|
77 |
+
</div>
|
78 |
+
<div class="ab-column col5" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
79 |
+
<?php for ( $i = 50400; $i <= 61200; $i += 3600 ) : ?>
|
80 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
81 |
+
<span class="ladda-label">
|
82 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
83 |
+
</span>
|
84 |
+
</button>
|
85 |
+
<?php endfor ?>
|
86 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+4 days', current_time( 'timestamp' ) ) ) ?></button>
|
87 |
+
<?php for ( $i = 28800; $i <= 43200; $i += 3600 ) : ?>
|
88 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
89 |
+
<span class="ladda-label">
|
90 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
91 |
+
</span>
|
92 |
+
</button>
|
93 |
+
<?php endfor ?>
|
94 |
+
</div>
|
95 |
+
<div class="ab-column col6" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
96 |
+
<?php for ( $i = 46800; $i <= 61200; $i += 3600 ) : ?>
|
97 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
98 |
+
<span class="ladda-label">
|
99 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
100 |
+
</span>
|
101 |
+
</button>
|
102 |
+
<?php endfor ?>
|
103 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+5 days', current_time( 'timestamp' ) ) ) ?></button>
|
104 |
+
<?php for ( $i = 28800; $i <= 39600; $i += 3600 ) : ?>
|
105 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
106 |
+
<span class="ladda-label">
|
107 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
108 |
+
</span>
|
109 |
+
</button>
|
110 |
+
<?php endfor ?>
|
111 |
+
</div>
|
112 |
+
<div class="ab-column col7" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
113 |
+
<?php for ( $i = 43200; $i <= 61200; $i += 3600 ) : ?>
|
114 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
115 |
+
<span class="ladda-label">
|
116 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
117 |
+
</span>
|
118 |
+
</button>
|
119 |
+
<?php endfor ?>
|
120 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+6 days', current_time( 'timestamp' ) ) ) ?></button>
|
121 |
+
<?php for ( $i = 28800; $i <= 36000; $i += 3600 ) : ?>
|
122 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
123 |
+
<span class="ladda-label">
|
124 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
125 |
+
</span>
|
126 |
+
</button>
|
127 |
+
<?php endfor ?>
|
128 |
+
</div>
|
129 |
+
</div>
|
130 |
+
|
131 |
+
<div class="ab-time-screen ab-day-one-column" style="display: <?php echo get_option( 'bookly_app_show_day_one_column' ) == 1 ? ' block' : 'none' ?>">
|
132 |
+
<div class="ab-input-wrap ab-slot-calendar">
|
133 |
+
<span class="ab-date-wrap">
|
134 |
+
<input style="display: none" class="ab-selected-date ab-formElement" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
135 |
+
</span>
|
136 |
+
</div>
|
137 |
+
<?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
|
138 |
+
<div class="ab-column col<?php echo $i ?>">
|
139 |
+
<button class="ab-day ab-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+' . ( $i - 1 ) . ' days', current_time( 'timestamp' ) ) ) ?></button>
|
140 |
+
<?php for ( $j = 28800; $j <= 61200; $j += 3600 ) : ?>
|
141 |
+
<button class="ab-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
142 |
+
<span class="ladda-label">
|
143 |
+
<i class="ab-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $j ) ?>
|
144 |
+
</span>
|
145 |
+
</button>
|
146 |
+
<?php endfor ?>
|
147 |
+
</div>
|
148 |
+
<?php endfor ?>
|
149 |
+
</div>
|
150 |
+
</div>
|
151 |
+
</div>
|
152 |
+
</div>
|
153 |
+
<div class="bookly-box bookly-nav-steps">
|
154 |
+
<button class="ab-time-next ab-btn ab-right ladda-button">
|
155 |
+
<span class="ab_label">></span>
|
156 |
+
</button>
|
157 |
+
<button class="ab-time-prev ab-btn ab-right ladda-button">
|
158 |
+
<span class="ab_label"><</span>
|
159 |
+
</button>
|
160 |
+
<div class="bookly-back-step ab-btn">
|
161 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_back' ), 'bookly-js-text-back' ) ?>
|
162 |
+
</div>
|
163 |
+
<button class="bookly-go-to-cart bookly-round bookly-round-md ladda-button" data-style="zoom-in" data-spinner-size="30"><span class="ladda-label"><img src="<?php echo plugins_url( 'bookly-responsive-appointment-booking-tool/frontend/resources/images/cart.png' ) ?>" /></span></button>
|
164 |
+
</div>
|
165 |
+
</div>
|
backend/modules/appearance/templates/_4_cart.php
DELETED
@@ -1,132 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="bookly-form">
|
3 |
-
<?php include '_progress_tracker.php' ?>
|
4 |
-
|
5 |
-
<div class="ab-row">
|
6 |
-
<span data-inputclass="input-xxlarge" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 4 ), false ) ) ?>" data-placement="bottom" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_cart_step' ) ) ?>" class="ab_editable" id="ab-text-info-cart" data-type="textarea"><?php echo esc_html( get_option( 'ab_appearance_text_info_cart_step' ) ) ?></span>
|
7 |
-
</div>
|
8 |
-
|
9 |
-
<div class="ab-row">
|
10 |
-
<div class="ab-btn ab-add-item ab-inline-block">
|
11 |
-
<span class="ab_editable" id="ab-text-button-book-more" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_book_more' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_book_more' ) ) ?></span>
|
12 |
-
</div>
|
13 |
-
</div>
|
14 |
-
|
15 |
-
<div class="ab-cart-step">
|
16 |
-
<div class="ab-cart ab-row">
|
17 |
-
<table>
|
18 |
-
<thead class="ab-desktop-version">
|
19 |
-
<tr>
|
20 |
-
<th data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_service' ) ) ?>" class="ab-service-list"><?php echo esc_html( get_option( 'ab_appearance_text_label_service' ) ) ?></th>
|
21 |
-
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
22 |
-
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
23 |
-
<th data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_employee' ) ) ?>" class="ab-employee-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'ab_appearance_text_label_employee' ) ?></th>
|
24 |
-
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
25 |
-
<th></th>
|
26 |
-
</tr>
|
27 |
-
</thead>
|
28 |
-
<tbody class="ab-desktop-version">
|
29 |
-
<tr>
|
30 |
-
<td>Crown and Bridge</td>
|
31 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( strtotime( '+2 days' ) ) ?></td>
|
32 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 28800 ) ?></td>
|
33 |
-
<td>Nick Knight</td>
|
34 |
-
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?></td>
|
35 |
-
<td>
|
36 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/edit.png' ) ?>" /></button>
|
37 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/delete.png' ) ?>" /></button>
|
38 |
-
</td>
|
39 |
-
</tr>
|
40 |
-
<tr>
|
41 |
-
<td>Teeth Whitening</td>
|
42 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( strtotime( '+3 days' ) ) ?></td>
|
43 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 57600 ) ?></td>
|
44 |
-
<td>Wayne Turner</td>
|
45 |
-
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 400 ) ?></td>
|
46 |
-
<td>
|
47 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/edit.png' ) ?>" /></button>
|
48 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/delete.png' ) ?>" /></button>
|
49 |
-
</td>
|
50 |
-
</tr>
|
51 |
-
</tbody>
|
52 |
-
<tbody class="ab-mobile-version">
|
53 |
-
<tr>
|
54 |
-
<th data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_service' ) ) ?>" class="ab-service-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'ab_appearance_text_label_service' ) ?></th>
|
55 |
-
<td>Crown and Bridge</td>
|
56 |
-
</tr>
|
57 |
-
<tr>
|
58 |
-
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
59 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( strtotime( '+2 days' ) ) ?></td>
|
60 |
-
</tr>
|
61 |
-
<tr>
|
62 |
-
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
63 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 28800 ) ?></td>
|
64 |
-
</tr>
|
65 |
-
<tr>
|
66 |
-
<th data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_employee' ) ) ?>" class="ab-employee-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'ab_appearance_text_label_employee' ) ?></th>
|
67 |
-
<td>Nick Knight</td>
|
68 |
-
</tr>
|
69 |
-
<tr>
|
70 |
-
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
71 |
-
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?></td>
|
72 |
-
</tr>
|
73 |
-
<tr>
|
74 |
-
<th></th>
|
75 |
-
<td>
|
76 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/edit.png' ) ?>" /></button>
|
77 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/delete.png' ) ?>" /></button>
|
78 |
-
</td>
|
79 |
-
</tr>
|
80 |
-
<tr>
|
81 |
-
<th data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_service' ) ) ?>" class="ab-service-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'ab_appearance_text_label_service' ) ?></th>
|
82 |
-
<td>Teeth Whitening</td>
|
83 |
-
</tr>
|
84 |
-
<tr>
|
85 |
-
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
86 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( strtotime( '+3 days' ) ) ?></td>
|
87 |
-
</tr>
|
88 |
-
<tr>
|
89 |
-
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
90 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 57600 ) ?></td>
|
91 |
-
</tr>
|
92 |
-
<tr>
|
93 |
-
<th data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_employee' ) ) ?>" class="ab-employee-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'ab_appearance_text_label_employee' ) ?></th>
|
94 |
-
<td>Wayne Turner</td>
|
95 |
-
</tr>
|
96 |
-
<tr>
|
97 |
-
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
98 |
-
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 400 ) ?></td>
|
99 |
-
</tr>
|
100 |
-
<tr>
|
101 |
-
<th></th>
|
102 |
-
<td>
|
103 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/edit.png' ) ?>" /></button>
|
104 |
-
<button class="bookly-round-button ladda-button" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><img src="<?php echo plugins_url( 'appointment-booking/frontend/resources/images/delete.png' ) ?>" /></button>
|
105 |
-
</td>
|
106 |
-
</tr>
|
107 |
-
</tbody>
|
108 |
-
<tfoot class="ab-desktop-version">
|
109 |
-
<tr>
|
110 |
-
<td colspan="4"><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></td>
|
111 |
-
<td><strong class="bookly-js-total-price"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 750 ) ?></strong></td>
|
112 |
-
<td></td>
|
113 |
-
</tr>
|
114 |
-
</tfoot>
|
115 |
-
<tfoot class="ab-mobile-version">
|
116 |
-
<tr>
|
117 |
-
<th><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></th>
|
118 |
-
<td><strong class="bookly-js-total-price"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 750 ) ?></strong></td>
|
119 |
-
</tr>
|
120 |
-
</tfoot>
|
121 |
-
</table>
|
122 |
-
</div>
|
123 |
-
</div>
|
124 |
-
<div class="ab-row ab-nav-steps">
|
125 |
-
<div class="ab-left ab-back-step ab-btn">
|
126 |
-
<span class="text_back ab_editable" id="ab-text-button-back" data-mirror="text_back" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_back' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_back' ) ) ?></span>
|
127 |
-
</div>
|
128 |
-
<div class="ab-right ab-next-step ab-btn">
|
129 |
-
<span class="text_next ab_editable" id="ab-text-button-next" data-mirror="text_next" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_next' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_next' ) ) ?></span>
|
130 |
-
</div>
|
131 |
-
</div>
|
132 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/appearance/templates/_5_cart.php
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="bookly-form">
|
3 |
+
<?php include '_progress_tracker.php' ?>
|
4 |
+
|
5 |
+
<div class="bookly-box">
|
6 |
+
<span data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 5 ), false ) ) ?>" data-placement="bottom" data-default="<?php form_option( 'bookly_l10n_info_cart_step' ) ?>" class="bookly-editable" id="bookly_l10n_info_cart_step" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_cart_step' ) ) ?></span>
|
7 |
+
</div>
|
8 |
+
|
9 |
+
<div class="bookly-box">
|
10 |
+
<div class="ab-btn ab-add-item ab-inline-block">
|
11 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_book_more', ) ) ?>
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
|
15 |
+
<div class="ab-cart-step">
|
16 |
+
<div class="ab-cart bookly-box">
|
17 |
+
<table>
|
18 |
+
<thead class="ab-desktop-version">
|
19 |
+
<tr>
|
20 |
+
<th data-default="<?php form_option( 'bookly_l10n_label_service' ) ?>" class="ab-service-list"><?php echo esc_html( get_option( 'bookly_l10n_label_service' ) ) ?></th>
|
21 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
22 |
+
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
23 |
+
<th data-default="<?php form_option( 'bookly_l10n_label_employee' ) ?>" class="ab-employee-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ?></th>
|
24 |
+
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
25 |
+
<th></th>
|
26 |
+
</tr>
|
27 |
+
</thead>
|
28 |
+
<tbody class="ab-desktop-version">
|
29 |
+
<tr>
|
30 |
+
<td>Crown and Bridge</td>
|
31 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( '+2 days' ) ?></td>
|
32 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 28800 ) ?></td>
|
33 |
+
<td>Nick Knight</td>
|
34 |
+
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?></td>
|
35 |
+
<td>
|
36 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
37 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
38 |
+
</td>
|
39 |
+
</tr>
|
40 |
+
<tr>
|
41 |
+
<td>Teeth Whitening</td>
|
42 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( '+3 days' ) ?></td>
|
43 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 57600 ) ?></td>
|
44 |
+
<td>Wayne Turner</td>
|
45 |
+
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 400 ) ?></td>
|
46 |
+
<td>
|
47 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
48 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
49 |
+
</td>
|
50 |
+
</tr>
|
51 |
+
</tbody>
|
52 |
+
<tbody class="ab-mobile-version">
|
53 |
+
<tr>
|
54 |
+
<th data-default="<?php form_option( 'bookly_l10n_label_service' ) ?>" class="ab-service-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_service' ) ?></th>
|
55 |
+
<td>Crown and Bridge</td>
|
56 |
+
</tr>
|
57 |
+
<tr>
|
58 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
59 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( '+2 days' ) ?></td>
|
60 |
+
</tr>
|
61 |
+
<tr>
|
62 |
+
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
63 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 28800 ) ?></td>
|
64 |
+
</tr>
|
65 |
+
<tr>
|
66 |
+
<th data-default="<?php form_option( 'bookly_l10n_label_employee' ) ?>" class="ab-employee-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ?></th>
|
67 |
+
<td>Nick Knight</td>
|
68 |
+
</tr>
|
69 |
+
<tr>
|
70 |
+
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
71 |
+
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 350 ) ?></td>
|
72 |
+
</tr>
|
73 |
+
<tr>
|
74 |
+
<th></th>
|
75 |
+
<td>
|
76 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
77 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
78 |
+
</td>
|
79 |
+
</tr>
|
80 |
+
<tr>
|
81 |
+
<th data-default="<?php form_option( 'bookly_l10n_label_service' ) ?>" class="ab-service-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_service' ) ?></th>
|
82 |
+
<td>Teeth Whitening</td>
|
83 |
+
</tr>
|
84 |
+
<tr>
|
85 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
86 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( '+3 days' ) ?></td>
|
87 |
+
</tr>
|
88 |
+
<tr>
|
89 |
+
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
90 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 57600 ) ?></td>
|
91 |
+
</tr>
|
92 |
+
<tr>
|
93 |
+
<th data-default="<?php form_option( 'bookly_l10n_label_employee' ) ?>" class="ab-employee-list"><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ?></th>
|
94 |
+
<td>Wayne Turner</td>
|
95 |
+
</tr>
|
96 |
+
<tr>
|
97 |
+
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
98 |
+
<td><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 400 ) ?></td>
|
99 |
+
</tr>
|
100 |
+
<tr>
|
101 |
+
<th></th>
|
102 |
+
<td>
|
103 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
104 |
+
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
105 |
+
</td>
|
106 |
+
</tr>
|
107 |
+
</tbody>
|
108 |
+
<tfoot class="ab-desktop-version">
|
109 |
+
<tr>
|
110 |
+
<td colspan="4"><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></td>
|
111 |
+
<td><strong class="bookly-js-total-price"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 750 ) ?></strong></td>
|
112 |
+
<td></td>
|
113 |
+
</tr>
|
114 |
+
</tfoot>
|
115 |
+
<tfoot class="ab-mobile-version">
|
116 |
+
<tr>
|
117 |
+
<th><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></th>
|
118 |
+
<td><strong class="bookly-js-total-price"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 750 ) ?></strong></td>
|
119 |
+
</tr>
|
120 |
+
</tfoot>
|
121 |
+
</table>
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
|
125 |
+
<?php do_action( 'bookly_recurring_appointments_render_editable_message_info' ) ?>
|
126 |
+
|
127 |
+
<div class="bookly-box bookly-nav-steps">
|
128 |
+
<div class="bookly-back-step ab-btn">
|
129 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_back' ), 'bookly-js-text-back' ) ?>
|
130 |
+
</div>
|
131 |
+
<div class="bookly-next-step ab-btn">
|
132 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_next' ), 'bookly-js-text-next' ) ?>
|
133 |
+
</div>
|
134 |
+
</div>
|
135 |
+
</div>
|
backend/modules/appearance/templates/_5_details.php
DELETED
@@ -1,63 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="bookly-form">
|
3 |
-
<?php include '_progress_tracker.php' ?>
|
4 |
-
|
5 |
-
<div class="ab-row">
|
6 |
-
<span data-inputclass="input-xxlarge" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 5, 'login' => false ), false ) ) ?>" data-placement="bottom" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_details_step' ) ) ?>" class="ab_editable" id="ab-text-info-details" data-type="textarea"><?php echo esc_html( get_option( 'ab_appearance_text_info_details_step' ) ) ?></span>
|
7 |
-
</div>
|
8 |
-
<div class="ab-row">
|
9 |
-
<span data-inputclass="input-xxlarge" data-title="<?php _e( 'Visible to non-logged in customers only', 'bookly' ) ?>" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 5, 'login' => true ), false ) ) ?>" data-placement="bottom" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_details_step_guest' ) ) ?>" class="ab_editable" id="ab-text-info-details-guest" data-type="textarea"><?php echo esc_html( get_option( 'ab_appearance_text_info_details_step_guest' ) ) ?></span>
|
10 |
-
</div>
|
11 |
-
<div class="ab-details-step">
|
12 |
-
<div class="ab-row bookly-table">
|
13 |
-
<div class="ab-formGroup">
|
14 |
-
<label>
|
15 |
-
<span
|
16 |
-
data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_name' ) ) ?>"
|
17 |
-
data-default-error="<?php echo esc_attr( get_option( 'ab_appearance_text_required_name' ) ) ?>"
|
18 |
-
id="ab-text-label-name"
|
19 |
-
data-type="multiple"
|
20 |
-
data-option-id="ab_appearance_text_required_name"><?php echo esc_html( get_option( 'ab_appearance_text_label_name' ) ) ?></span>
|
21 |
-
</label>
|
22 |
-
|
23 |
-
<div>
|
24 |
-
<input type="text" value="" maxlength="60" />
|
25 |
-
</div>
|
26 |
-
</div>
|
27 |
-
<div class="ab-formGroup">
|
28 |
-
<label>
|
29 |
-
<span
|
30 |
-
data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_phone' ) ) ?>"
|
31 |
-
data-default-error="<?php echo esc_attr( get_option( 'ab_appearance_text_required_phone' ) ) ?>"
|
32 |
-
id="ab-text-label-phone"
|
33 |
-
data-type="multiple"
|
34 |
-
data-option-id="ab_appearance_text_required_phone"><?php echo esc_html( get_option( 'ab_appearance_text_label_phone' ) ) ?></span>
|
35 |
-
</label>
|
36 |
-
<div>
|
37 |
-
<input type="text" class="<?php if ( get_option( 'ab_settings_phone_default_country' ) != 'disabled' ) : ?>ab-user-phone<?php endif ?>" value="" />
|
38 |
-
</div>
|
39 |
-
</div>
|
40 |
-
<div class="ab-formGroup">
|
41 |
-
<label>
|
42 |
-
<span
|
43 |
-
data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_email' ) ) ?>"
|
44 |
-
data-default-error="<?php echo esc_attr( get_option( 'ab_appearance_text_required_email' ) ) ?>"
|
45 |
-
id="ab-text-label-email"
|
46 |
-
data-type="multiple"
|
47 |
-
data-option-id="ab_appearance_text_required_email"><?php echo esc_html( get_option( 'ab_appearance_text_label_email' ) ) ?></span>
|
48 |
-
</label>
|
49 |
-
<div>
|
50 |
-
<input maxlength="40" type="text" value="" />
|
51 |
-
</div>
|
52 |
-
</div>
|
53 |
-
</div>
|
54 |
-
</div>
|
55 |
-
<div class="ab-row ab-nav-steps">
|
56 |
-
<div class="ab-left ab-back-step ab-btn">
|
57 |
-
<span class="text_back ab_editable" id="ab-text-button-back" data-mirror="text_back" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_back' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_back' ) ) ?></span>
|
58 |
-
</div>
|
59 |
-
<div class="ab-right ab-next-step ab-btn">
|
60 |
-
<span class="text_next ab_editable" id="ab-text-button-next" data-mirror="text_next" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_next' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_next' ) ) ?></span>
|
61 |
-
</div>
|
62 |
-
</div>
|
63 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/appearance/templates/_6_details.php
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="bookly-form">
|
3 |
+
<?php include '_progress_tracker.php' ?>
|
4 |
+
|
5 |
+
<div class="bookly-box">
|
6 |
+
<span data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 6, 'login' => false ), false ) ) ?>" data-placement="bottom" data-option-default="<?php form_option( 'bookly_l10n_info_details_step' ) ?>" class="bookly-editable" id="bookly_l10n_info_details_step" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_details_step' ) ) ?></span>
|
7 |
+
</div>
|
8 |
+
<div class="bookly-box">
|
9 |
+
<span data-title="<?php _e( 'Visible to non-logged in customers only', 'bookly' ) ?>" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 6, 'login' => true ), false ) ) ?>" data-placement="bottom" data-option-default="<?php form_option( 'bookly_l10n_info_details_step_guest' ) ?>" class="bookly-editable" id="bookly_l10n_info_details_step_guest" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_details_step_guest' ) ) ?></span>
|
10 |
+
</div>
|
11 |
+
<div class="ab-details-step">
|
12 |
+
<div class="bookly-box bookly-table">
|
13 |
+
<div class="ab-formGroup">
|
14 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_name', 'bookly_l10n_required_name', ) ) ?>
|
15 |
+
<div>
|
16 |
+
<input type="text" value="" maxlength="60" />
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
<div class="ab-formGroup">
|
20 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_phone', 'bookly_l10n_required_phone', ) ) ?>
|
21 |
+
<div>
|
22 |
+
<input type="text" class="<?php if ( get_option( 'bookly_cst_phone_default_country' ) != 'disabled' ) : ?>ab-user-phone<?php endif ?>" value="" />
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
<div class="ab-formGroup">
|
26 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderLabel( array( 'bookly_l10n_label_email', 'bookly_l10n_required_email', ) ) ?>
|
27 |
+
<div>
|
28 |
+
<input maxlength="40" type="text" value="" />
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
|
34 |
+
<?php do_action( 'bookly_recurring_appointments_render_editable_message_info' ) ?>
|
35 |
+
|
36 |
+
<div class="bookly-box bookly-nav-steps">
|
37 |
+
<div class="bookly-back-step ab-btn">
|
38 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_back' ), 'bookly-js-text-back' ) ?>
|
39 |
+
</div>
|
40 |
+
<div class="bookly-next-step ab-btn">
|
41 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_next' ), 'bookly-js-text-next' ) ?>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</div>
|
backend/modules/appearance/templates/_6_payment.php
DELETED
@@ -1,67 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="bookly-form">
|
3 |
-
<?php include '_progress_tracker.php' ?>
|
4 |
-
<!-- Coupons -->
|
5 |
-
<div class="ab-row">
|
6 |
-
<span data-inputclass="input-xxlarge" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_coupon' ) ) ?>" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 6 ), false ) ) ?>" class="ab_editable" id="ab-text-info-coupon" data-type="textarea"><?php echo esc_html( get_option( 'ab_appearance_text_info_coupon' ) ) ?></span>
|
7 |
-
</div>
|
8 |
-
|
9 |
-
<div class="ab-row ab-list">
|
10 |
-
<span data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_coupon' ) ) ?>" class="ab_editable editable editable-click inline-block" id="ab-text-label-coupon" data-type="text"><?php echo esc_html( get_option( 'ab_appearance_text_label_coupon' ) ) ?></span>
|
11 |
-
<div class="ab-inline-block">
|
12 |
-
<input class="ab-user-coupon" type="text" />
|
13 |
-
<div class="ab-btn btn-apply-coupon">
|
14 |
-
<span class="ab_editable" id="ab-text-button-apply" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_apply' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_apply' ) ) ?></span>
|
15 |
-
</div>
|
16 |
-
</div>
|
17 |
-
</div>
|
18 |
-
<div class="ab-payment-nav">
|
19 |
-
<div class="ab-row">
|
20 |
-
<span data-inputclass="input-xxlarge" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_payment_step' ) ) ?>" data-notes="<?php echo esc_attr( $this->render( '_codes', compact( 'step' ), false ) ) ?>" class="ab_editable" id="ab-text-info-payment" data-type="textarea"><?php echo esc_html( get_option( 'ab_appearance_text_info_payment_step' ) ) ?></span>
|
21 |
-
</div>
|
22 |
-
|
23 |
-
<div class="ab-row ab-list">
|
24 |
-
<label>
|
25 |
-
<input type="radio" name="payment" checked="checked" />
|
26 |
-
<span id="ab-text-label-pay-locally" class="ab_editable" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_pay_locally' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_label_pay_locally' ) ) ?></span>
|
27 |
-
</label>
|
28 |
-
</div>
|
29 |
-
|
30 |
-
<div class="ab-row ab-list">
|
31 |
-
<label>
|
32 |
-
<input type="radio" name="payment" />
|
33 |
-
<span data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_pay_paypal' ) ) ?>" class="ab_editable editable editable-click inline-block" id="ab-text-label-pay-paypal" data-type="text"><?php echo esc_html( get_option( 'ab_appearance_text_label_pay_paypal' ) ) ?></span>
|
34 |
-
<img src="<?php echo plugins_url( 'frontend/resources/images/paypal.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="paypal" />
|
35 |
-
</label>
|
36 |
-
</div>
|
37 |
-
|
38 |
-
<div class="ab-row ab-list">
|
39 |
-
<label>
|
40 |
-
<input type="radio" name="payment" class="ab-card-payment" />
|
41 |
-
<span data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_pay_ccard' ) ) ?>" class="ab_editable editable editable-click inline-block" id="ab-text-label-pay-ccard" data-type="text"><?php echo esc_html( get_option( 'ab_appearance_text_label_pay_ccard' ) ) ?></span>
|
42 |
-
<img src="<?php echo plugins_url( 'frontend/resources/images/cards.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="cards" />
|
43 |
-
</label>
|
44 |
-
<form class="ab-card-form ab-clearBottom" style="margin-top:15px;display: none;">
|
45 |
-
<?php include '_card_payment.php' ?>
|
46 |
-
</form>
|
47 |
-
</div>
|
48 |
-
|
49 |
-
<div class="ab-row ab-list">
|
50 |
-
<label>
|
51 |
-
<input type="radio" name="payment" />
|
52 |
-
<span id="ab-text-label-pay-mollie" class="ab_editable" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_label_pay_mollie' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_label_pay_mollie' ) ) ?></span>
|
53 |
-
<img src="<?php echo plugins_url( 'frontend/resources/images/mollie.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="mollie" />
|
54 |
-
</label>
|
55 |
-
</div>
|
56 |
-
</div>
|
57 |
-
|
58 |
-
<!-- buttons -->
|
59 |
-
<div class="ab-row ab-nav-steps">
|
60 |
-
<div class="ab-left ab-back-step ab-btn">
|
61 |
-
<span class="text_back ab_editable" id="ab-text-button-back" data-mirror="text_back" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_back' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_back' ) ) ?></span>
|
62 |
-
</div>
|
63 |
-
<div class="ab-right ab-next-step ab-btn">
|
64 |
-
<span class="text_next ab_editable" id="ab-text-button-next" data-mirror="text_next" data-type="text" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_button_next' ) ) ?>"><?php echo esc_html( get_option( 'ab_appearance_text_button_next' ) ) ?></span>
|
65 |
-
</div>
|
66 |
-
</div>
|
67 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/appearance/templates/_7_done.php
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="bookly-form">
|
3 |
-
<?php include '_progress_tracker.php' ?>
|
4 |
-
<div class="ab-row">
|
5 |
-
<span data-inputclass="input-xxlarge" class="ab_editable" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 7 ), false ) ) ?>" data-placement="bottom" data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_info_complete_step' ) ) ?>" id="ab-text-info-complete" data-type="textarea"><?php echo nl2br( esc_html( get_option( 'ab_appearance_text_info_complete_step' ) ) ) ?></span>
|
6 |
-
</div>
|
7 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/appearance/templates/_7_payment.php
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="bookly-form">
|
3 |
+
<?php include '_progress_tracker.php' ?>
|
4 |
+
<div class="bookly-box">
|
5 |
+
<span data-option-default="<?php form_option( 'bookly_l10n_info_coupon' ) ?>" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 7 ), false ) ) ?>" class="bookly-editable" id="bookly_l10n_info_coupon" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_coupon' ) ) ?></span>
|
6 |
+
</div>
|
7 |
+
|
8 |
+
<div class="bookly-box ab-list">
|
9 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_coupon', ) ) ?>
|
10 |
+
<div class="ab-inline-block">
|
11 |
+
<input class="ab-user-coupon" type="text" />
|
12 |
+
<div class="ab-btn btn-apply-coupon">
|
13 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_apply', ) ) ?>
|
14 |
+
</div>
|
15 |
+
</div>
|
16 |
+
</div>
|
17 |
+
<div class="ab-payment-nav">
|
18 |
+
<div class="bookly-box">
|
19 |
+
<span data-option-default="<?php form_option( 'bookly_l10n_info_payment_step' ) ?>" data-notes="<?php echo esc_attr( $this->render( '_codes', compact( 'step' ), false ) ) ?>" class="bookly-editable" id="bookly_l10n_info_payment_step" data-type="textarea"><?php echo esc_html( get_option( 'bookly_l10n_info_payment_step' ) ) ?></span>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div class="bookly-box ab-list">
|
23 |
+
<label>
|
24 |
+
<input type="radio" name="payment" checked="checked" />
|
25 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_pay_locally', ) ) ?>
|
26 |
+
</label>
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<div class="bookly-box ab-list">
|
30 |
+
<label>
|
31 |
+
<input type="radio" name="payment" />
|
32 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_pay_paypal', ) ) ?>
|
33 |
+
<img src="<?php echo plugins_url( 'frontend/resources/images/paypal.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="paypal" />
|
34 |
+
</label>
|
35 |
+
</div>
|
36 |
+
|
37 |
+
<div class="bookly-box ab-list">
|
38 |
+
<label>
|
39 |
+
<input type="radio" name="payment" class="ab-card-payment" />
|
40 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_pay_ccard', ) ) ?>
|
41 |
+
<img src="<?php echo plugins_url( 'frontend/resources/images/cards.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="cards" />
|
42 |
+
</label>
|
43 |
+
<form class="ab-card-form ab-clearBottom" style="margin-top:15px;display: none;">
|
44 |
+
<?php include '_card_payment.php' ?>
|
45 |
+
</form>
|
46 |
+
</div>
|
47 |
+
|
48 |
+
<div class="bookly-box ab-list">
|
49 |
+
<label>
|
50 |
+
<input type="radio" name="payment" />
|
51 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_pay_mollie', ) ) ?>
|
52 |
+
<img src="<?php echo plugins_url( 'frontend/resources/images/mollie.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="mollie" />
|
53 |
+
</label>
|
54 |
+
</div>
|
55 |
+
|
56 |
+
<?php do_action( 'bookly_render_appearance_payment_gateway_selector' ) ?>
|
57 |
+
</div>
|
58 |
+
|
59 |
+
<?php do_action( 'bookly_recurring_appointments_render_editable_message_info' ) ?>
|
60 |
+
|
61 |
+
<div class="bookly-box bookly-nav-steps">
|
62 |
+
<div class="bookly-back-step ab-btn">
|
63 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_back' ), 'bookly-js-text-back' ) ?>
|
64 |
+
</div>
|
65 |
+
<div class="bookly-next-step ab-btn">
|
66 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_button_next' ), 'bookly-js-text-next' ) ?>
|
67 |
+
</div>
|
68 |
+
</div>
|
69 |
+
</div>
|
backend/modules/appearance/templates/_8_complete.php
ADDED
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="bookly-form">
|
3 |
+
<?php include '_progress_tracker.php' ?>
|
4 |
+
<div class="bookly-box">
|
5 |
+
<span class="bookly-editable" data-notes="<?php echo esc_attr( $this->render( '_codes', array( 'step' => 8 ), false ) ) ?>" data-placement="bottom" data-option-default="<?php form_option( 'bookly_l10n_info_complete_step' ) ?>" id="bookly_l10n_info_complete_step" data-type="textarea"><?php echo nl2br( esc_html( get_option( 'bookly_l10n_info_complete_step' ) ) ) ?></span>
|
6 |
+
</div>
|
7 |
+
</div>
|
backend/modules/appearance/templates/_card_payment.php
CHANGED
@@ -1,38 +1,38 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="
|
3 |
-
<div class="ab-formGroup" style="width:200px!important">
|
4 |
-
<label>
|
5 |
-
|
6 |
-
</label>
|
7 |
-
<div>
|
8 |
-
<input type="text" />
|
9 |
-
</div>
|
10 |
-
</div>
|
11 |
-
<div class="ab-formGroup">
|
12 |
-
<label>
|
13 |
-
|
14 |
-
</label>
|
15 |
-
<div>
|
16 |
-
<select class="ab-card-exp">
|
17 |
-
<?php for ( $i = 1; $i <= 12; ++ $i ) : ?>
|
18 |
-
<option value="<?php echo $i ?>"><?php printf( '%02d', $i ) ?></option>
|
19 |
-
<?php endfor ?>
|
20 |
-
</select>
|
21 |
-
<select class="ab-card-exp">
|
22 |
-
<?php for ( $i = date( 'Y' ); $i <= date( 'Y' ) + 10; ++ $i ) : ?>
|
23 |
-
<option value="<?php echo $i ?>"><?php echo $i ?></option>
|
24 |
-
<?php endfor ?>
|
25 |
-
</select>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
</div>
|
29 |
-
<div class="
|
30 |
-
<div class="ab-formGroup">
|
31 |
-
<label>
|
32 |
-
|
33 |
-
</label>
|
34 |
-
<div>
|
35 |
-
<input class="ab-card-cvc" type="text" />
|
36 |
-
</div>
|
37 |
-
</div>
|
38 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="bookly-box bookly-table">
|
3 |
+
<div class="ab-formGroup" style="width:200px!important">
|
4 |
+
<label>
|
5 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_ccard_number', ) ) ?>
|
6 |
+
</label>
|
7 |
+
<div>
|
8 |
+
<input type="text" />
|
9 |
+
</div>
|
10 |
+
</div>
|
11 |
+
<div class="ab-formGroup">
|
12 |
+
<label>
|
13 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_ccard_expire', ) ) ?>
|
14 |
+
</label>
|
15 |
+
<div>
|
16 |
+
<select class="ab-card-exp">
|
17 |
+
<?php for ( $i = 1; $i <= 12; ++ $i ) : ?>
|
18 |
+
<option value="<?php echo $i ?>"><?php printf( '%02d', $i ) ?></option>
|
19 |
+
<?php endfor ?>
|
20 |
+
</select>
|
21 |
+
<select class="ab-card-exp">
|
22 |
+
<?php for ( $i = date( 'Y' ); $i <= date( 'Y' ) + 10; ++ $i ) : ?>
|
23 |
+
<option value="<?php echo $i ?>"><?php echo $i ?></option>
|
24 |
+
<?php endfor ?>
|
25 |
+
</select>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
</div>
|
29 |
+
<div class="bookly-box ab-clearBottom">
|
30 |
+
<div class="ab-formGroup">
|
31 |
+
<label>
|
32 |
+
<?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_label_ccard_code', ) ) ?>
|
33 |
+
</label>
|
34 |
+
<div>
|
35 |
+
<input class="ab-card-cvc" type="text" />
|
36 |
+
</div>
|
37 |
+
</div>
|
38 |
</div>
|
backend/modules/appearance/templates/_codes.php
CHANGED
@@ -1,25 +1,25 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ), ),
|
4 |
-
array( 'code' => 'login_form', 'description' => __( 'login form', 'bookly' ),
|
5 |
-
'step' =>
|
6 |
-
'login' => true,
|
7 |
-
),
|
8 |
-
array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ), ),
|
9 |
-
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ),
|
10 |
-
'step' =>
|
11 |
-
),
|
12 |
-
array( 'code' => 'service_date', 'description' => __( 'date of service', 'bookly' ),
|
13 |
-
'min_step' => 3,
|
14 |
-
),
|
15 |
-
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ), ),
|
16 |
-
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ), ),
|
17 |
-
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ), ),
|
18 |
-
array( 'code' => 'service_time', 'description' => __( 'time of service', 'bookly' ),
|
19 |
-
'min_step' => 3,
|
20 |
-
),
|
21 |
-
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ), ),
|
22 |
-
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ), ),
|
23 |
-
array( 'code' => 'total_price', 'description' => __( 'total price of booking', 'bookly' ), ),
|
24 |
-
);
|
25 |
-
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( '
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
$codes = array(
|
3 |
+
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ), ),
|
4 |
+
array( 'code' => 'login_form', 'description' => __( 'login form', 'bookly' ),
|
5 |
+
'step' => 6,
|
6 |
+
'login' => true,
|
7 |
+
),
|
8 |
+
array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ), ),
|
9 |
+
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ),
|
10 |
+
'step' => 8,
|
11 |
+
),
|
12 |
+
array( 'code' => 'service_date', 'description' => __( 'date of service', 'bookly' ),
|
13 |
+
'min_step' => 3,
|
14 |
+
),
|
15 |
+
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ), ),
|
16 |
+
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ), ),
|
17 |
+
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ), ),
|
18 |
+
array( 'code' => 'service_time', 'description' => __( 'time of service', 'bookly' ),
|
19 |
+
'min_step' => 3,
|
20 |
+
),
|
21 |
+
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ), ),
|
22 |
+
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ), ),
|
23 |
+
array( 'code' => 'total_price', 'description' => __( 'total price of booking', 'bookly' ), ),
|
24 |
+
);
|
25 |
+
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( 'bookly_prepare_appearance_short_codes', $codes ), $step, isset( $login ) ? $login : false );
|
backend/modules/appearance/templates/_progress_tracker.php
CHANGED
@@ -3,33 +3,39 @@
|
|
3 |
?>
|
4 |
<div class="ab-progress-tracker bookly-table">
|
5 |
<div class="active">
|
6 |
-
<?php echo $i ++ ?>.
|
7 |
<div class="step"></div>
|
8 |
</div>
|
9 |
-
<?php if ( \BooklyLite\Lib\Config::
|
10 |
-
<div <?php if (
|
11 |
-
<?php echo $i ++ ?>.
|
12 |
<div class="step"></div>
|
13 |
</div>
|
14 |
<?php endif ?>
|
15 |
<div <?php if ( $step >= 3 ) : ?>class="active"<?php endif ?>>
|
16 |
-
<?php echo $i ++ ?>.
|
17 |
-
<div class="step"></div>
|
18 |
-
</div>
|
19 |
-
<div <?php if ( $step >= 4 ) : ?>class="active"<?php endif ?>>
|
20 |
-
<?php echo $i ++ ?>. <span data-default="<?php echo esc_attr( get_option( 'ab_appearance_text_step_cart' ) ) ?>" data-mirror="text_cart" class="text_cart ab_editable" id="ab-text-step-cart" data-type="text"><?php echo esc_html( get_option( 'ab_appearance_text_step_cart' ) ) ?></span>
|
21 |
<div class="step"></div>
|
22 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
23 |
<div <?php if ( $step >= 5 ) : ?>class="active"<?php endif ?>>
|
24 |
-
<?php echo $i ++ ?>.
|
25 |
<div class="step"></div>
|
26 |
</div>
|
27 |
<div <?php if ( $step >= 6 ) : ?>class="active"<?php endif ?>>
|
28 |
-
<?php echo $i ++ ?>.
|
29 |
<div class="step"></div>
|
30 |
</div>
|
31 |
<div <?php if ( $step >= 7 ) : ?>class="active"<?php endif ?>>
|
32 |
-
<?php echo $i ++ ?>.
|
|
|
|
|
|
|
|
|
33 |
<div class="step"></div>
|
34 |
</div>
|
35 |
</div>
|
3 |
?>
|
4 |
<div class="ab-progress-tracker bookly-table">
|
5 |
<div class="active">
|
6 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_service' ), 'bookly-js-text-service' ) ?>
|
7 |
<div class="step"></div>
|
8 |
</div>
|
9 |
+
<?php if ( \BooklyLite\Lib\Config::isServiceExtrasEnabled() ) : ?>
|
10 |
+
<div <?php if ( $step >= 2 ) : ?>class="active"<?php endif ?>>
|
11 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_extras' ), 'bookly-js-text-extras' ) ?>
|
12 |
<div class="step"></div>
|
13 |
</div>
|
14 |
<?php endif ?>
|
15 |
<div <?php if ( $step >= 3 ) : ?>class="active"<?php endif ?>>
|
16 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_time' ), 'bookly-js-text-time' ) ?>
|
|
|
|
|
|
|
|
|
17 |
<div class="step"></div>
|
18 |
</div>
|
19 |
+
<?php if ( \BooklyLite\Lib\Config::isRecurringAppointmentsEnabled() ) : ?>
|
20 |
+
<div <?php if ( $step >= 4 ) : ?>class="active"<?php endif ?>>
|
21 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_repeat' ), 'bookly-js-text-repeat' ) ?>
|
22 |
+
<div class=step></div>
|
23 |
+
</div>
|
24 |
+
<?php endif ?>
|
25 |
<div <?php if ( $step >= 5 ) : ?>class="active"<?php endif ?>>
|
26 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_cart' ), 'bookly-js-text-cart' ) ?>
|
27 |
<div class="step"></div>
|
28 |
</div>
|
29 |
<div <?php if ( $step >= 6 ) : ?>class="active"<?php endif ?>>
|
30 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_details' ), 'bookly-js-text-details' ) ?>
|
31 |
<div class="step"></div>
|
32 |
</div>
|
33 |
<div <?php if ( $step >= 7 ) : ?>class="active"<?php endif ?>>
|
34 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_payment' ), 'bookly-js-text-payment' ) ?>
|
35 |
+
<div class="step"></div>
|
36 |
+
</div>
|
37 |
+
<div <?php if ( $step >= 8 ) : ?>class="active"<?php endif ?>>
|
38 |
+
<?php echo $i ++ ?>. <?php \BooklyLite\Backend\Modules\Appearance\Lib\Helper::renderSpan( array( 'bookly_l10n_step_done' ), 'bookly-js-text-done' ) ?>
|
39 |
<div class="step"></div>
|
40 |
</div>
|
41 |
</div>
|
backend/modules/appearance/templates/index.php
CHANGED
@@ -1,126 +1,128 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-tbs" class="wrap">
|
3 |
-
<div class="bookly-tbs-body">
|
4 |
-
<div class="page-header text-right clearfix">
|
5 |
-
<div class="bookly-page-title">
|
6 |
-
<?php _e( 'Appearance', 'bookly' ) ?>
|
7 |
-
</div>
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
<?php
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
<?php
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
</
|
57 |
-
</div>
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
</
|
65 |
-
</div>
|
66 |
-
</div>
|
67 |
-
</div>
|
68 |
-
<div id="bookly-js-step-time" class="bookly-margin-top-lg" style="display:none">
|
69 |
-
<div class="col-md-4">
|
70 |
-
<div class="checkbox">
|
71 |
-
<label>
|
72 |
-
<input type="checkbox" id="ab-show-calendar-checkbox" <?php checked( get_option( '
|
73 |
-
<?php _e( 'Show calendar', 'bookly' ) ?>
|
74 |
-
</label>
|
75 |
-
</div>
|
76 |
-
</div>
|
77 |
-
<div class="col-md-4">
|
78 |
-
<div class="checkbox">
|
79 |
-
<label>
|
80 |
-
<input type="checkbox" id="ab-blocked-timeslots-checkbox" <?php checked( get_option( '
|
81 |
-
<?php _e( 'Show blocked timeslots', 'bookly' ) ?>
|
82 |
-
</label>
|
83 |
-
</div>
|
84 |
-
</div>
|
85 |
-
<div class="col-md-4">
|
86 |
-
<div class="checkbox">
|
87 |
-
<label>
|
88 |
-
<input type="checkbox" id="ab-day-one-column-checkbox" <?php checked( get_option( '
|
89 |
-
<?php _e( 'Show each day in one column', 'bookly' ) ?>
|
90 |
-
</label>
|
91 |
-
</div>
|
92 |
-
</div>
|
93 |
-
</div>
|
94 |
-
</div>
|
95 |
-
|
96 |
-
<div class="panel panel-default bookly-margin-top-lg">
|
97 |
-
<div class="panel-body">
|
98 |
-
<div class="tab-content">
|
99 |
-
<?php foreach ( $steps as $step => $step_name ) : ?>
|
100 |
-
<div id="ab-step-<?php echo $step ?>" class="tab-pane <?php if ( $step == 1 ) : ?>active<?php endif ?>" data-target="<?php echo $step ?>">
|
101 |
-
<?php // Render unique data per step
|
102 |
-
switch ( $step ) :
|
103 |
-
case 1: include '_1_service.php';
|
104 |
-
case 2: do_action( '
|
105 |
-
break;
|
106 |
-
case 3: include '_3_time.php';
|
107 |
-
case 4:
|
108 |
-
|
109 |
-
case
|
110 |
-
case
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
|
|
|
|
126 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-tbs" class="wrap">
|
3 |
+
<div class="bookly-tbs-body">
|
4 |
+
<div class="page-header text-right clearfix">
|
5 |
+
<div class="bookly-page-title">
|
6 |
+
<?php _e( 'Appearance', 'bookly' ) ?>
|
7 |
+
</div>
|
8 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
9 |
+
</div>
|
10 |
+
<div class="panel panel-default bookly-main">
|
11 |
+
<div class="panel-body">
|
12 |
+
<div id="ab-appearance">
|
13 |
+
<div class="row">
|
14 |
+
<div class="col-sm-3 col-lg-2 bookly-color-picker-wrapper">
|
15 |
+
<input type="text" name="color" class="bookly-js-color-picker"
|
16 |
+
value="<?php form_option( 'bookly_app_color' ) ?>"
|
17 |
+
data-selected="<?php form_option( 'bookly_app_color' ) ?>" />
|
18 |
+
</div>
|
19 |
+
<div class="col-sm-9 col-lg-10">
|
20 |
+
<div class="checkbox">
|
21 |
+
<label>
|
22 |
+
<input type="checkbox" id=ab-progress-tracker-checkbox <?php checked( get_option( 'bookly_app_show_progress_tracker' ) ) ?>>
|
23 |
+
<?php _e( 'Show form progress tracker', 'bookly' ) ?>
|
24 |
+
</label>
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
|
29 |
+
<ul class="bookly-nav bookly-nav-tabs bookly-margin-top-lg" role="tablist">
|
30 |
+
<?php $i = 1 ?>
|
31 |
+
<?php foreach ( $steps as $step => $step_name ) : ?>
|
32 |
+
<?php if ( ( $step != 2 || \BooklyLite\Lib\Config::isServiceExtrasEnabled() )
|
33 |
+
&& ( $step != 4 || \BooklyLite\Lib\Config::isRecurringAppointmentsEnabled() ) ) : ?>
|
34 |
+
<li class="bookly-nav-item <?php if ( $step == 1 ) : ?>active<?php endif ?>" data-target="#ab-step-<?php echo $step ?>" data-toggle="tab">
|
35 |
+
<?php echo $i++ ?>. <?php echo esc_html( $step_name ) ?>
|
36 |
+
</li>
|
37 |
+
<?php endif ?>
|
38 |
+
<?php endforeach ?>
|
39 |
+
</ul>
|
40 |
+
|
41 |
+
<?php if ( ! get_user_meta( get_current_user_id(), \BooklyLite\Lib\Plugin::getPrefix() . 'dismiss_appearance_notice', true ) ): ?>
|
42 |
+
<div class="alert alert-info alert-dismissible fade in bookly-margin-top-lg bookly-margin-bottom-remove" id="bookly-js-hint-alert" role="alert">
|
43 |
+
<button type="button" class="close" data-dismiss="alert"></button>
|
44 |
+
<?php _e( 'Click on the underlined text to edit.', 'bookly' ) ?>
|
45 |
+
</div>
|
46 |
+
<?php endif ?>
|
47 |
+
|
48 |
+
<div class="row" id="bookly-js-step-settings">
|
49 |
+
<div id="bookly-js-step-service" class="bookly-margin-top-lg">
|
50 |
+
<?php do_action( 'bookly_render_appearance_step_service_settings' ) ?>
|
51 |
+
<div class="col-md-4">
|
52 |
+
<div class="checkbox">
|
53 |
+
<label>
|
54 |
+
<input type="checkbox" id=ab-required-employee-checkbox <?php checked( get_option( 'bookly_app_required_employee' ) ) ?>>
|
55 |
+
<?php _e( 'Make selecting employee required', 'bookly' ) ?>
|
56 |
+
</label>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
<div class="col-md-4">
|
60 |
+
<div class="checkbox">
|
61 |
+
<label>
|
62 |
+
<input type="checkbox" id=ab-staff-name-with-price-checkbox <?php checked( get_option( 'bookly_app_staff_name_with_price' ) ) ?>>
|
63 |
+
<?php _e( 'Show service price next to employee name', 'bookly' ) ?>
|
64 |
+
</label>
|
65 |
+
</div>
|
66 |
+
</div>
|
67 |
+
</div>
|
68 |
+
<div id="bookly-js-step-time" class="bookly-margin-top-lg" style="display:none">
|
69 |
+
<div class="col-md-4">
|
70 |
+
<div class="checkbox">
|
71 |
+
<label>
|
72 |
+
<input type="checkbox" id="ab-show-calendar-checkbox" <?php checked( get_option( 'bookly_app_show_calendar' ) ) ?>>
|
73 |
+
<?php _e( 'Show calendar', 'bookly' ) ?>
|
74 |
+
</label>
|
75 |
+
</div>
|
76 |
+
</div>
|
77 |
+
<div class="col-md-4">
|
78 |
+
<div class="checkbox">
|
79 |
+
<label>
|
80 |
+
<input type="checkbox" id="ab-blocked-timeslots-checkbox" <?php checked( get_option( 'bookly_app_show_blocked_timeslots' ) ) ?>>
|
81 |
+
<?php _e( 'Show blocked timeslots', 'bookly' ) ?>
|
82 |
+
</label>
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
<div class="col-md-4">
|
86 |
+
<div class="checkbox">
|
87 |
+
<label>
|
88 |
+
<input type="checkbox" id="ab-day-one-column-checkbox" <?php checked( get_option( 'bookly_app_show_day_one_column' ) ) ?>>
|
89 |
+
<?php _e( 'Show each day in one column', 'bookly' ) ?>
|
90 |
+
</label>
|
91 |
+
</div>
|
92 |
+
</div>
|
93 |
+
</div>
|
94 |
+
</div>
|
95 |
+
|
96 |
+
<div class="panel panel-default bookly-margin-top-lg">
|
97 |
+
<div class="panel-body">
|
98 |
+
<div class="tab-content">
|
99 |
+
<?php foreach ( $steps as $step => $step_name ) : ?>
|
100 |
+
<div id="ab-step-<?php echo $step ?>" class="tab-pane <?php if ( $step == 1 ) : ?>active<?php endif ?>" data-target="<?php echo $step ?>">
|
101 |
+
<?php // Render unique data per step
|
102 |
+
switch ( $step ) :
|
103 |
+
case 1: include '_1_service.php'; break;
|
104 |
+
case 2: do_action( 'bookly_service_extras_render_appearance', $this->render( '_progress_tracker', array( 'step' => $step ), false ) );
|
105 |
+
break;
|
106 |
+
case 3: include '_3_time.php'; break;
|
107 |
+
case 4: do_action( 'bookly_recurring_appointments_render_appearance', $this->render( '_progress_tracker', array( 'step' => $step ), false ) );
|
108 |
+
break;
|
109 |
+
case 5: include '_5_cart.php'; break;
|
110 |
+
case 6: include '_6_details.php'; break;
|
111 |
+
case 7: include '_7_payment.php'; break;
|
112 |
+
case 8: include '_8_complete.php'; break;
|
113 |
+
endswitch ?>
|
114 |
+
</div>
|
115 |
+
<?php endforeach ?>
|
116 |
+
</div>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
|
120 |
+
</div>
|
121 |
+
</div>
|
122 |
+
<div class="panel-footer">
|
123 |
+
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'ajax-send-appearance' ) ?>
|
124 |
+
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
+
</div>
|
128 |
</div>
|
backend/modules/appointments/Controller.php
CHANGED
@@ -1,246 +1,256 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Appointments;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Appointments
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
$
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
'js/
|
30 |
-
'js/
|
31 |
-
'js/
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
'js/
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
'
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
52 |
-
'
|
53 |
-
'
|
54 |
-
'
|
55 |
-
'
|
56 |
-
'
|
57 |
-
'
|
58 |
-
'
|
59 |
-
|
60 |
-
'
|
61 |
-
'
|
62 |
-
'
|
63 |
-
|
64 |
-
|
65 |
-
'
|
66 |
-
'
|
67 |
-
'
|
68 |
-
'
|
69 |
-
'
|
70 |
-
'
|
71 |
-
'
|
72 |
-
) )
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
$
|
78 |
-
|
79 |
-
$
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
$
|
90 |
-
|
91 |
-
$
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
ca.
|
96 |
-
ca.
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
c.
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
p.
|
108 |
-
p.
|
109 |
-
|
110 |
-
|
111 |
-
->leftJoin( '
|
112 |
-
->leftJoin( '
|
113 |
-
->leftJoin( '
|
114 |
-
->leftJoin( '
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
$
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
Lib\Entities\Payment::
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
'
|
191 |
-
'
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
'
|
197 |
-
'
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
'
|
202 |
-
'
|
203 |
-
|
204 |
-
|
205 |
-
'
|
206 |
-
'
|
207 |
-
'
|
208 |
-
'
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
'
|
219 |
-
'
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Appointments;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Appointments
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-appointments';
|
13 |
+
|
14 |
+
public function index()
|
15 |
+
{
|
16 |
+
/** @var \WP_Locale $wp_locale */
|
17 |
+
global $wp_locale;
|
18 |
+
|
19 |
+
$this->enqueueStyles( array(
|
20 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
21 |
+
'backend' => array(
|
22 |
+
'bootstrap/css/bootstrap-theme.min.css',
|
23 |
+
'css/daterangepicker.css',
|
24 |
+
),
|
25 |
+
) );
|
26 |
+
|
27 |
+
$this->enqueueScripts( array(
|
28 |
+
'backend' => array(
|
29 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
30 |
+
'js/datatables.min.js' => array( 'jquery' ),
|
31 |
+
'js/moment.min.js',
|
32 |
+
'js/daterangepicker.js' => array( 'jquery' ),
|
33 |
+
),
|
34 |
+
'frontend' => array(
|
35 |
+
'js/spin.min.js' => array( 'jquery' ),
|
36 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
37 |
+
),
|
38 |
+
'module' => array( 'js/appointments.js' => array( 'bookly-datatables.min.js' ), ),
|
39 |
+
) );
|
40 |
+
|
41 |
+
// Custom fields without captcha field.
|
42 |
+
$custom_fields = array_filter( json_decode( get_option( 'bookly_custom_fields' ) ), function( $field ) {
|
43 |
+
return ! in_array( $field->type, array( 'captcha', 'text-content' ) );
|
44 |
+
} );
|
45 |
+
|
46 |
+
wp_localize_script( 'bookly-appointments.js', 'BooklyL10n', array(
|
47 |
+
'tomorrow' => __( 'Tomorrow', 'bookly' ),
|
48 |
+
'today' => __( 'Today', 'bookly' ),
|
49 |
+
'yesterday' => __( 'Yesterday', 'bookly' ),
|
50 |
+
'last_7' => __( 'Last 7 Days', 'bookly' ),
|
51 |
+
'last_30' => __( 'Last 30 Days', 'bookly' ),
|
52 |
+
'this_month' => __( 'This Month', 'bookly' ),
|
53 |
+
'next_month' => __( 'Next Month', 'bookly' ),
|
54 |
+
'custom_range' => __( 'Custom Range', 'bookly' ),
|
55 |
+
'apply' => __( 'Apply', 'bookly' ),
|
56 |
+
'cancel' => __( 'Cancel', 'bookly' ),
|
57 |
+
'to' => __( 'To', 'bookly' ),
|
58 |
+
'from' => __( 'From', 'bookly' ),
|
59 |
+
'calendar' => array(
|
60 |
+
'longMonths' => array_values( $wp_locale->month ),
|
61 |
+
'shortMonths' => array_values( $wp_locale->month_abbrev ),
|
62 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
63 |
+
'shortDays' => array_values( $wp_locale->weekday_abbrev ),
|
64 |
+
),
|
65 |
+
'mjsDateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_MOMENT_JS ),
|
66 |
+
'startOfWeek' => (int) get_option( 'start_of_week' ),
|
67 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
68 |
+
'zeroRecords' => __( 'No appointments for selected period.', 'bookly' ),
|
69 |
+
'processing' => __( 'Processing...', 'bookly' ),
|
70 |
+
'edit' => __( 'Edit', 'bookly' ),
|
71 |
+
'cf_columns' => array_map( function ( $custom_field ) { return $custom_field->id; }, $custom_fields ),
|
72 |
+
'filter' => (array) get_user_meta( get_current_user_id(), 'bookly_filter_appointments_list', true ),
|
73 |
+
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
74 |
+
) );
|
75 |
+
|
76 |
+
// Filters data
|
77 |
+
$staff_members = Lib\Entities\Staff::query( 's' )->select( 's.id, s.full_name' )->fetchArray();
|
78 |
+
$customers = Lib\Entities\Customer::query( 'c' )->select( 'c.id, c.name' )->fetchArray();
|
79 |
+
$services = Lib\Entities\Service::query( 's' )->select( 's.id, s.title' )->where( 'type', Lib\Entities\Service::TYPE_SIMPLE )->fetchArray();
|
80 |
+
|
81 |
+
$this->render( 'index', compact( 'custom_fields', 'staff_members', 'customers', 'services' ) );
|
82 |
+
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Get list of appointments.
|
86 |
+
*/
|
87 |
+
public function executeGetAppointments()
|
88 |
+
{
|
89 |
+
$columns = $this->getParameter( 'columns' );
|
90 |
+
$order = $this->getParameter( 'order' );
|
91 |
+
$filter = $this->getParameter( 'filter' );
|
92 |
+
|
93 |
+
$query = Lib\Entities\CustomerAppointment::query( 'ca' )
|
94 |
+
->select( 'a.id,
|
95 |
+
ca.payment_id,
|
96 |
+
ca.status,
|
97 |
+
ca.id AS ca_id,
|
98 |
+
ca.extras,
|
99 |
+
a.start_date,
|
100 |
+
a.extras_duration,
|
101 |
+
c.name AS customer_name,
|
102 |
+
c.phone AS customer_phone,
|
103 |
+
c.email AS customer_email,
|
104 |
+
s.title AS service_title,
|
105 |
+
s.duration AS service_duration,
|
106 |
+
st.full_name AS staff_name,
|
107 |
+
p.paid AS payment,
|
108 |
+
p.total AS payment_total,
|
109 |
+
p.type AS payment_type,
|
110 |
+
p.status AS payment_status' )
|
111 |
+
->leftJoin( 'Appointment', 'a', 'a.id = ca.appointment_id' )
|
112 |
+
->leftJoin( 'Service', 's', 's.id = a.service_id' )
|
113 |
+
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
114 |
+
->leftJoin( 'Payment', 'p', 'p.id = ca.payment_id' )
|
115 |
+
->leftJoin( 'Staff', 'st', 'st.id = a.staff_id' )
|
116 |
+
->leftJoin( 'StaffService', 'ss', 'ss.staff_id = st.id AND ss.service_id = s.id' );
|
117 |
+
|
118 |
+
$total = $query->count();
|
119 |
+
|
120 |
+
if ( $filter['id'] != '' ) {
|
121 |
+
$query->where( 'a.id', $filter['id'] );
|
122 |
+
}
|
123 |
+
|
124 |
+
list ( $start, $end ) = explode( ' - ', $filter['date'], 2 );
|
125 |
+
$end = date( 'Y-m-d', strtotime( '+1 day', strtotime( $end ) ) );
|
126 |
+
$query->whereBetween( 'a.start_date', $start, $end );
|
127 |
+
|
128 |
+
if ( $filter['staff'] != -1 ) {
|
129 |
+
$query->where( 'a.staff_id', $filter['staff'] );
|
130 |
+
}
|
131 |
+
|
132 |
+
if ( $filter['customer'] != -1 ) {
|
133 |
+
$query->where( 'ca.customer_id', $filter['customer'] );
|
134 |
+
}
|
135 |
+
|
136 |
+
if ( $filter['service'] != -1 ) {
|
137 |
+
$query->where( 'a.service_id', $filter['service'] );
|
138 |
+
}
|
139 |
+
|
140 |
+
if ( $filter['status'] != -1 ) {
|
141 |
+
$query->where( 'ca.status', $filter['status'] );
|
142 |
+
}
|
143 |
+
|
144 |
+
foreach ( $order as $sort_by ) {
|
145 |
+
$query->sortBy( str_replace( '.', '_', $columns[ $sort_by['column'] ]['data'] ) )
|
146 |
+
->order( $sort_by['dir'] == 'desc' ? Lib\Query::ORDER_DESCENDING : Lib\Query::ORDER_ASCENDING );
|
147 |
+
}
|
148 |
+
|
149 |
+
$custom_fields = array();
|
150 |
+
$fields_data = array_filter( json_decode( get_option( 'bookly_custom_fields' ) ), function( $field ) {
|
151 |
+
return ! in_array( $field->type, array( 'captcha', 'text-content' ) );
|
152 |
+
} );
|
153 |
+
foreach ( $fields_data as $field_data ) {
|
154 |
+
$custom_fields[ $field_data->id ] = '';
|
155 |
+
}
|
156 |
+
|
157 |
+
$data = array();
|
158 |
+
foreach ( $query->fetchArray() as $row ) {
|
159 |
+
// Service duration.
|
160 |
+
$service_duration = Lib\Utils\DateTime::secondsToInterval( $row['service_duration'] );
|
161 |
+
if ( $row['extras_duration'] > 0 ) {
|
162 |
+
$service_duration .= ' + ' . Lib\Utils\DateTime::secondsToInterval( $row['extras_duration'] );
|
163 |
+
}
|
164 |
+
// Appointment status.
|
165 |
+
$row['status'] = Lib\Entities\CustomerAppointment::statusToString( $row['status'] );
|
166 |
+
|
167 |
+
// Payment title.
|
168 |
+
$payment_title = '';
|
169 |
+
if ( $row['payment'] !== null ) {
|
170 |
+
$payment_title = Lib\Utils\Common::formatPrice( $row['payment'] );
|
171 |
+
if ( $row['payment'] != $row['payment_total'] ) {
|
172 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Common::formatPrice( $row['payment_total'] ) );
|
173 |
+
}
|
174 |
+
$payment_title .= sprintf(
|
175 |
+
' %s <span%s>%s</span>',
|
176 |
+
Lib\Entities\Payment::typeToString( $row['payment_type'] ),
|
177 |
+
$row['payment_status'] == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
178 |
+
Lib\Entities\Payment::statusToString( $row['payment_status'] )
|
179 |
+
);
|
180 |
+
}
|
181 |
+
// Custom fields
|
182 |
+
$customer_appointment = new Lib\Entities\CustomerAppointment();
|
183 |
+
$customer_appointment->load( $row['ca_id'] );
|
184 |
+
foreach ( $customer_appointment->getCustomFields() as $custom_field ) {
|
185 |
+
$custom_fields[ $custom_field['id'] ] = $custom_field['value'];
|
186 |
+
}
|
187 |
+
|
188 |
+
$data[] = array(
|
189 |
+
'id' => $row['id'],
|
190 |
+
'start_date' => Lib\Utils\DateTime::formatDateTime( $row['start_date'] ),
|
191 |
+
'staff' => array(
|
192 |
+
'name' => $row['staff_name'],
|
193 |
+
),
|
194 |
+
'customer' => array(
|
195 |
+
'name' => $row['customer_name'],
|
196 |
+
'phone' => $row['customer_phone'],
|
197 |
+
'email' => $row['customer_email'],
|
198 |
+
),
|
199 |
+
'service' => array(
|
200 |
+
'title' => $row['service_title'],
|
201 |
+
'duration' => $service_duration,
|
202 |
+
'extras' => apply_filters( 'bookly_service_extras_get_data_for_appointment', array(), $row['extras'], false ),
|
203 |
+
),
|
204 |
+
'status' => $row['status'],
|
205 |
+
'payment' => $payment_title,
|
206 |
+
'custom_fields' => $custom_fields,
|
207 |
+
'ca_id' => $row['ca_id'],
|
208 |
+
'payment_id' => $row['payment_id'],
|
209 |
+
);
|
210 |
+
|
211 |
+
$custom_fields = array_map( function () { return ''; }, $custom_fields );
|
212 |
+
}
|
213 |
+
|
214 |
+
unset( $filter['date'] );
|
215 |
+
update_user_meta( get_current_user_id(), 'bookly_filter_appointments_list', $filter );
|
216 |
+
|
217 |
+
wp_send_json( array(
|
218 |
+
'draw' => ( int ) $this->getParameter( 'draw' ),
|
219 |
+
'recordsTotal' => $total,
|
220 |
+
'recordsFiltered' => count( $data ),
|
221 |
+
'data' => $data,
|
222 |
+
) );
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Delete customer appointments.
|
227 |
+
*/
|
228 |
+
public function executeDeleteCustomerAppointments()
|
229 |
+
{
|
230 |
+
/** @var Lib\Entities\CustomerAppointment $ca */
|
231 |
+
foreach ( Lib\Entities\CustomerAppointment::query()->whereIn( 'id', $this->getParameter( 'data', array() ) )->find() as $ca ) {
|
232 |
+
if ( $this->getParameter( 'notify' ) ) {
|
233 |
+
if ( $ca->get('status') === Lib\Entities\CustomerAppointment::STATUS_PENDING ) {
|
234 |
+
$ca->set( 'status', Lib\Entities\CustomerAppointment::STATUS_REJECTED );
|
235 |
+
} else { // STATUS_APPROVED
|
236 |
+
$ca->set( 'status', Lib\Entities\CustomerAppointment::STATUS_CANCELLED );
|
237 |
+
}
|
238 |
+
\BooklyLite\Lib\NotificationSender::send( $ca, array( 'cancellation_reason' => $this->getParameter( 'reason' ) ) );
|
239 |
+
}
|
240 |
+
$ca->deleteCascade();
|
241 |
+
}
|
242 |
+
wp_send_json_success();
|
243 |
+
}
|
244 |
+
|
245 |
+
/**
|
246 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
247 |
+
* so current 'execute*' methods look nicer.
|
248 |
+
*
|
249 |
+
* @param string $prefix
|
250 |
+
*/
|
251 |
+
protected function registerWpActions( $prefix = '' )
|
252 |
+
{
|
253 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
254 |
+
}
|
255 |
+
|
256 |
}
|
backend/modules/appointments/resources/js/appointments.js
CHANGED
@@ -10,13 +10,25 @@ jQuery(function($) {
|
|
10 |
$service_filter = $('#bookly-filter-service'),
|
11 |
$status_filter = $('#bookly-filter-status'),
|
12 |
$add_button = $('#bookly-add'),
|
13 |
-
$print_dialog = $('#bookly-print-dialog'),
|
14 |
-
$print_button = $('#bookly-print'),
|
15 |
$export_dialog = $('#bookly-export-dialog'),
|
16 |
$export_button = $('#bookly-export'),
|
17 |
-
$delete_button = $('#bookly-delete')
|
|
|
18 |
;
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
/**
|
21 |
* Init DataTables.
|
22 |
*/
|
@@ -24,14 +36,24 @@ jQuery(function($) {
|
|
24 |
{ data: 'id', responsivePriority: 2 },
|
25 |
{ data: 'start_date', responsivePriority: 2 },
|
26 |
{ data: 'staff.name', responsivePriority: 2 },
|
27 |
-
{ data: 'customer.name', responsivePriority: 2 },
|
28 |
-
{
|
29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
{
|
31 |
data: 'service.title',
|
32 |
responsivePriority: 2,
|
33 |
render: function ( data, type, row, meta ) {
|
34 |
-
if(
|
35 |
var extras = '<ul class="bookly-list list-dots">';
|
36 |
$.each(row.service.extras, function (key, item) {
|
37 |
extras += '<li><nobr>' + item.title + '</nobr></li>';
|
@@ -57,6 +79,7 @@ jQuery(function($) {
|
|
57 |
$.each(BooklyL10n.cf_columns, function (i, cf_id) {
|
58 |
columns.push({
|
59 |
data: 'custom_fields.' + cf_id,
|
|
|
60 |
responsivePriority: 4,
|
61 |
orderable: false
|
62 |
});
|
@@ -73,7 +96,7 @@ jQuery(function($) {
|
|
73 |
url : ajaxurl,
|
74 |
type: 'POST',
|
75 |
data: function (d) {
|
76 |
-
return $.extend({action: '
|
77 |
filter: {
|
78 |
id : $id_filter.val(),
|
79 |
date : $date_filter.data('date'),
|
@@ -178,34 +201,35 @@ jQuery(function($) {
|
|
178 |
* Delete appointments.
|
179 |
*/
|
180 |
$delete_button.on('click', function () {
|
181 |
-
|
182 |
-
|
183 |
-
ladda.start();
|
184 |
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
|
|
|
|
206 |
}
|
207 |
-
}
|
208 |
-
}
|
209 |
});
|
210 |
|
211 |
/**
|
10 |
$service_filter = $('#bookly-filter-service'),
|
11 |
$status_filter = $('#bookly-filter-status'),
|
12 |
$add_button = $('#bookly-add'),
|
|
|
|
|
13 |
$export_dialog = $('#bookly-export-dialog'),
|
14 |
$export_button = $('#bookly-export'),
|
15 |
+
$delete_button = $('#bookly-delete'),
|
16 |
+
isMobile = false
|
17 |
;
|
18 |
|
19 |
+
try {
|
20 |
+
document.createEvent("TouchEvent");
|
21 |
+
isMobile = true;
|
22 |
+
} catch (e) {
|
23 |
+
|
24 |
+
}
|
25 |
+
|
26 |
+
$.each(BooklyL10n.filter, function (field, value) {
|
27 |
+
if (value != -1) {
|
28 |
+
$('#bookly-filter-' + field).val(value);
|
29 |
+
}
|
30 |
+
});
|
31 |
+
|
32 |
/**
|
33 |
* Init DataTables.
|
34 |
*/
|
36 |
{ data: 'id', responsivePriority: 2 },
|
37 |
{ data: 'start_date', responsivePriority: 2 },
|
38 |
{ data: 'staff.name', responsivePriority: 2 },
|
39 |
+
{ data: 'customer.name', render: $.fn.dataTable.render.text(), responsivePriority: 2 },
|
40 |
+
{
|
41 |
+
data: 'customer.phone',
|
42 |
+
responsivePriority: 3,
|
43 |
+
render: function (data, type, row, meta) {
|
44 |
+
if (isMobile) {
|
45 |
+
return '<a href="tel:' + data + '">' + $.fn.dataTable.render.text().display(data) + '</a>';
|
46 |
+
} else {
|
47 |
+
return $.fn.dataTable.render.text().display(data);
|
48 |
+
}
|
49 |
+
}
|
50 |
+
},
|
51 |
+
{ data: 'customer.email', render: $.fn.dataTable.render.text(), responsivePriority: 3 },
|
52 |
{
|
53 |
data: 'service.title',
|
54 |
responsivePriority: 2,
|
55 |
render: function ( data, type, row, meta ) {
|
56 |
+
if (row.service.extras.length) {
|
57 |
var extras = '<ul class="bookly-list list-dots">';
|
58 |
$.each(row.service.extras, function (key, item) {
|
59 |
extras += '<li><nobr>' + item.title + '</nobr></li>';
|
79 |
$.each(BooklyL10n.cf_columns, function (i, cf_id) {
|
80 |
columns.push({
|
81 |
data: 'custom_fields.' + cf_id,
|
82 |
+
render: $.fn.dataTable.render.text(),
|
83 |
responsivePriority: 4,
|
84 |
orderable: false
|
85 |
});
|
96 |
url : ajaxurl,
|
97 |
type: 'POST',
|
98 |
data: function (d) {
|
99 |
+
return $.extend({action: 'bookly_get_appointments'}, {
|
100 |
filter: {
|
101 |
id : $id_filter.val(),
|
102 |
date : $date_filter.data('date'),
|
201 |
* Delete appointments.
|
202 |
*/
|
203 |
$delete_button.on('click', function () {
|
204 |
+
var ladda = Ladda.create(this);
|
205 |
+
ladda.start();
|
|
|
206 |
|
207 |
+
var data = [];
|
208 |
+
var $checkboxes = $appointments_list.find('tbody input:checked');
|
209 |
+
$checkboxes.each(function () {
|
210 |
+
data.push(this.value);
|
211 |
+
});
|
212 |
|
213 |
+
$.ajax({
|
214 |
+
url : ajaxurl,
|
215 |
+
type : 'POST',
|
216 |
+
data : {
|
217 |
+
action : 'bookly_delete_customer_appointments',
|
218 |
+
data : data,
|
219 |
+
notify : $('#bookly-delete-notify').prop('checked') ? 1 : 0,
|
220 |
+
reason : $('#bookly-delete-reason').val()
|
221 |
+
},
|
222 |
+
dataType : 'json',
|
223 |
+
success : function(response) {
|
224 |
+
ladda.stop();
|
225 |
+
$('#bookly-delete-dialog').modal('hide');
|
226 |
+
if (response.success) {
|
227 |
+
dt.draw(false);
|
228 |
+
} else {
|
229 |
+
alert(response.data.message);
|
230 |
}
|
231 |
+
}
|
232 |
+
});
|
233 |
});
|
234 |
|
235 |
/**
|
backend/modules/appointments/templates/_export_dialog.php
CHANGED
@@ -1,40 +1,40 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-export-dialog" class="modal fade" tabindex=-1 role="dialog">
|
3 |
-
<div class="modal-dialog">
|
4 |
-
<div class="modal-content">
|
5 |
-
<div class="modal-header">
|
6 |
-
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
7 |
-
<div class="modal-title h2"><?php _e( 'Export to CSV', 'bookly' ) ?></div>
|
8 |
-
</div>
|
9 |
-
<div class="modal-body">
|
10 |
-
<div class="form-group">
|
11 |
-
<label for="bookly-csv-delimiter"><?php _e( 'Delimiter', 'bookly' ) ?></label>
|
12 |
-
<select id="bookly-csv-delimiter" class="form-control">
|
13 |
-
<option value=","><?php _e( 'Comma (,)', 'bookly' ) ?></option>
|
14 |
-
<option value=";"><?php _e( 'Semicolon (;)', 'bookly' ) ?></option>
|
15 |
-
</select>
|
16 |
-
</div>
|
17 |
-
<div class="form-group">
|
18 |
-
<div class="checkbox"><label><input checked value="0" type="checkbox" /><?php _e( 'No.', 'bookly' ) ?></label></div>
|
19 |
-
<div class="checkbox"><label><input checked value="1" type="checkbox" /><?php _e( 'Booking Time', 'bookly' ) ?></label></div>
|
20 |
-
<div class="checkbox"><label><input checked value="2" type="checkbox" /><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( '
|
21 |
-
<div class="checkbox"><label><input checked value="3" type="checkbox" /><?php _e( 'Customer Name', 'bookly' ) ?></label></div>
|
22 |
-
<div class="checkbox"><label><input checked value="4" type="checkbox" /><?php _e( 'Customer Phone', 'bookly' ) ?></label></div>
|
23 |
-
<div class="checkbox"><label><input checked value="5" type="checkbox" /><?php _e( 'Customer Email', 'bookly' ) ?></label></div>
|
24 |
-
<div class="checkbox"><label><input checked value="6" type="checkbox" /><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( '
|
25 |
-
<div class="checkbox"><label><input checked value="7" type="checkbox" /><?php _e( 'Duration', 'bookly' ) ?></label></div>
|
26 |
-
<div class="checkbox"><label><input checked value="8" type="checkbox" /><?php _e( 'Status', 'bookly' ) ?></label></div>
|
27 |
-
<div class="checkbox"><label><input checked value="9" type="checkbox" /><?php _e( 'Payment', 'bookly' ) ?></label></div>
|
28 |
-
<?php $i = 10; foreach ( $custom_fields as $custom_field ) : ?>
|
29 |
-
<div class="checkbox"><label><input checked value="<?php echo $i ++ ?>" type="checkbox"/><?php echo $custom_field->label ?></label></div>
|
30 |
-
<?php endforeach ?>
|
31 |
-
</div>
|
32 |
-
</div>
|
33 |
-
<div class="modal-footer">
|
34 |
-
<button type="submit" class="btn btn-lg btn-success" id="bookly-export" data-dismiss="modal">
|
35 |
-
<?php _e( 'Export to CSV', 'bookly' ) ?>
|
36 |
-
</button>
|
37 |
-
</div>
|
38 |
-
</div>
|
39 |
-
</div>
|
40 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-export-dialog" class="modal fade" tabindex=-1 role="dialog">
|
3 |
+
<div class="modal-dialog">
|
4 |
+
<div class="modal-content">
|
5 |
+
<div class="modal-header">
|
6 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
7 |
+
<div class="modal-title h2"><?php _e( 'Export to CSV', 'bookly' ) ?></div>
|
8 |
+
</div>
|
9 |
+
<div class="modal-body">
|
10 |
+
<div class="form-group">
|
11 |
+
<label for="bookly-csv-delimiter"><?php _e( 'Delimiter', 'bookly' ) ?></label>
|
12 |
+
<select id="bookly-csv-delimiter" class="form-control">
|
13 |
+
<option value=","><?php _e( 'Comma (,)', 'bookly' ) ?></option>
|
14 |
+
<option value=";"><?php _e( 'Semicolon (;)', 'bookly' ) ?></option>
|
15 |
+
</select>
|
16 |
+
</div>
|
17 |
+
<div class="form-group">
|
18 |
+
<div class="checkbox"><label><input checked value="0" type="checkbox" /><?php _e( 'No.', 'bookly' ) ?></label></div>
|
19 |
+
<div class="checkbox"><label><input checked value="1" type="checkbox" /><?php _e( 'Booking Time', 'bookly' ) ?></label></div>
|
20 |
+
<div class="checkbox"><label><input checked value="2" type="checkbox" /><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ?></label></div>
|
21 |
+
<div class="checkbox"><label><input checked value="3" type="checkbox" /><?php _e( 'Customer Name', 'bookly' ) ?></label></div>
|
22 |
+
<div class="checkbox"><label><input checked value="4" type="checkbox" /><?php _e( 'Customer Phone', 'bookly' ) ?></label></div>
|
23 |
+
<div class="checkbox"><label><input checked value="5" type="checkbox" /><?php _e( 'Customer Email', 'bookly' ) ?></label></div>
|
24 |
+
<div class="checkbox"><label><input checked value="6" type="checkbox" /><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_service' ) ?></label></div>
|
25 |
+
<div class="checkbox"><label><input checked value="7" type="checkbox" /><?php _e( 'Duration', 'bookly' ) ?></label></div>
|
26 |
+
<div class="checkbox"><label><input checked value="8" type="checkbox" /><?php _e( 'Status', 'bookly' ) ?></label></div>
|
27 |
+
<div class="checkbox"><label><input checked value="9" type="checkbox" /><?php _e( 'Payment', 'bookly' ) ?></label></div>
|
28 |
+
<?php $i = 10; foreach ( $custom_fields as $custom_field ) : ?>
|
29 |
+
<div class="checkbox"><label><input checked value="<?php echo $i ++ ?>" type="checkbox"/><?php echo $custom_field->label ?></label></div>
|
30 |
+
<?php endforeach ?>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="modal-footer">
|
34 |
+
<button type="submit" class="btn btn-lg btn-success" id="bookly-export" data-dismiss="modal">
|
35 |
+
<?php _e( 'Export to CSV', 'bookly' ) ?>
|
36 |
+
</button>
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
</div>
|
40 |
</div>
|
backend/modules/appointments/templates/_print_dialog.php
CHANGED
@@ -1 +1,33 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-print-dialog" class="modal fade" tabindex=-1 role="dialog">
|
3 |
+
<div class="modal-dialog">
|
4 |
+
<div class="modal-content">
|
5 |
+
<div class="modal-header">
|
6 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
7 |
+
<h4 class="modal-title"><?php _e( 'Print', 'bookly' ) ?></h4>
|
8 |
+
</div>
|
9 |
+
<div class="modal-body">
|
10 |
+
<div class="form-group">
|
11 |
+
<div class="checkbox"><label><input checked value="0" type="checkbox"/><?php _e( 'No.', 'bookly' ) ?></label></div>
|
12 |
+
<div class="checkbox"><label><input checked value="1" type="checkbox"/><?php _e( 'Appointment Date', 'bookly' ) ?></label></div>
|
13 |
+
<div class="checkbox"><label><input checked value="2" type="checkbox"/><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ?></label></div>
|
14 |
+
<div class="checkbox"><label><input checked value="3" type="checkbox"/><?php _e( 'Customer Name', 'bookly' ) ?></label></div>
|
15 |
+
<div class="checkbox"><label><input checked value="4" type="checkbox"/><?php _e( 'Customer Phone', 'bookly' ) ?></label></div>
|
16 |
+
<div class="checkbox"><label><input checked value="5" type="checkbox"/><?php _e( 'Customer Email', 'bookly' ) ?></label></div>
|
17 |
+
<div class="checkbox"><label><input checked value="6" type="checkbox"/><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_service' ) ?></label></div>
|
18 |
+
<div class="checkbox"><label><input checked value="7" type="checkbox"/><?php _e( 'Duration', 'bookly' ) ?></label></div>
|
19 |
+
<div class="checkbox"><label><input checked value="8" type="checkbox"/><?php _e( 'Status', 'bookly' ) ?></label></div>
|
20 |
+
<div class="checkbox"><label><input checked value="9" type="checkbox"/><?php _e( 'Payment', 'bookly' ) ?></label></div>
|
21 |
+
<?php $i = 10; foreach ( $custom_fields as $custom_field ) : ?>
|
22 |
+
<div class="checkbox"><label><input checked value="<?php echo $i ++ ?>" type="checkbox"/><?php echo $custom_field->label ?></label></div>
|
23 |
+
<?php endforeach ?>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
<div class="modal-footer">
|
27 |
+
<button type="button" class="btn btn-lg btn-success" id="bookly-print" data-dismiss="modal">
|
28 |
+
<?php _e( 'Print', 'bookly' ) ?>
|
29 |
+
</button>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
backend/modules/appointments/templates/index.php
CHANGED
@@ -1,118 +1,121 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use
|
3 |
-
?>
|
4 |
-
<div id="bookly-tbs" class="wrap">
|
5 |
-
<div class="bookly-tbs-body">
|
6 |
-
<div class="page-header text-right clearfix">
|
7 |
-
<div class="bookly-page-title">
|
8 |
-
<?php _e( 'Appointments', 'bookly' ) ?>
|
9 |
-
</div>
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
<
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
<div class="
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
<option value="
|
77 |
-
<option value="<?php echo CustomerAppointment::
|
78 |
-
<option value="<?php echo CustomerAppointment::
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
<th><?php
|
90 |
-
<th><?php _e( '
|
91 |
-
<th><?php
|
92 |
-
<th><?php _e( 'Customer
|
93 |
-
<th><?php
|
94 |
-
<th><?php _e( '
|
95 |
-
<th><?php
|
96 |
-
<th><?php _e( '
|
97 |
-
|
98 |
-
|
99 |
-
<?php
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
<?php
|
116 |
-
<?php
|
117 |
-
|
118 |
-
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Entities\CustomerAppointment;
|
3 |
+
?>
|
4 |
+
<div id="bookly-tbs" class="wrap">
|
5 |
+
<div class="bookly-tbs-body">
|
6 |
+
<div class="page-header text-right clearfix">
|
7 |
+
<div class="bookly-page-title">
|
8 |
+
<?php _e( 'Appointments', 'bookly' ) ?>
|
9 |
+
</div>
|
10 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
11 |
+
</div>
|
12 |
+
<div class="panel panel-default bookly-main">
|
13 |
+
<div class="panel-body">
|
14 |
+
<div class="row">
|
15 |
+
<div class="form-inline bookly-margin-bottom-lg text-right">
|
16 |
+
<div class="form-group">
|
17 |
+
<button type="button" class="btn btn-default bookly-btn-block-xs" data-toggle="modal" data-target="#bookly-export-dialog"><i class="glyphicon glyphicon-export"></i> <?php _e( 'Export to CSV', 'bookly' ) ?></button>
|
18 |
+
</div>
|
19 |
+
<div class="form-group">
|
20 |
+
<button type="button" class="btn btn-default bookly-btn-block-xs bookly-limitation"><i class="glyphicon glyphicon-print"></i> <?php _e( 'Print', 'bookly' ) ?></button>
|
21 |
+
</div>
|
22 |
+
<div class="form-group">
|
23 |
+
<button type="button" class="btn btn-success bookly-btn-block-xs" id="bookly-add"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'New appointment', 'bookly' ) ?></button>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<div class="col-md-4 col-lg-1">
|
28 |
+
<div class="form-group">
|
29 |
+
<input class="form-control" type="text" id="bookly-filter-id" placeholder="<?php esc_attr_e( 'No.', 'bookly' ) ?>" />
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
<div class="col-md-4 col-lg-3">
|
33 |
+
<div class="bookly-margin-bottom-lg bookly-relative">
|
34 |
+
<button type="button" class="btn btn-block btn-default" id="bookly-filter-date" data-date="<?php echo date( 'Y-m-d', strtotime( 'first day of' ) ) ?> - <?php echo date( 'Y-m-d', strtotime( 'last day of' ) ) ?>">
|
35 |
+
<i class="dashicons dashicons-calendar-alt"></i>
|
36 |
+
<span>
|
37 |
+
<?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( 'first day of this month' ) ?> - <?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( 'last day of this month' ) ?>
|
38 |
+
</span>
|
39 |
+
</button>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
<div class="col-md-4 col-lg-2">
|
43 |
+
<div class="form-group">
|
44 |
+
<select class="form-control bookly-js-chosen-select" id="bookly-filter-staff" data-placeholder="<?php echo esc_attr( \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ) ?>">
|
45 |
+
<option value="-1"></option>
|
46 |
+
<?php foreach ( $staff_members as $staff ) : ?>
|
47 |
+
<option value="<?php echo $staff['id'] ?>"><?php esc_html_e( $staff['full_name'] ) ?></option>
|
48 |
+
<?php endforeach ?>
|
49 |
+
</select>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
<div class="clearfix visible-md-block"></div>
|
53 |
+
<div class="col-md-4 col-lg-2">
|
54 |
+
<div class="form-group">
|
55 |
+
<select class="form-control bookly-js-chosen-select" id="bookly-filter-customer" data-placeholder="<?php esc_attr_e( 'Customer', 'bookly' ) ?>">
|
56 |
+
<option value="-1"></option>
|
57 |
+
<?php foreach ( $customers as $customer ) : ?>
|
58 |
+
<option value="<?php echo $customer['id'] ?>"><?php esc_html_e( $customer['name'] ) ?></option>
|
59 |
+
<?php endforeach ?>
|
60 |
+
</select>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
<div class="col-md-4 col-lg-2">
|
64 |
+
<div class="form-group">
|
65 |
+
<select class="form-control bookly-js-chosen-select" id="bookly-filter-service" data-placeholder="<?php echo esc_attr( \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_service' ) ) ?>">
|
66 |
+
<option value="-1"></option>
|
67 |
+
<?php foreach ( $services as $service ) : ?>
|
68 |
+
<option value="<?php echo $service['id'] ?>"><?php esc_html_e( $service['title'] ) ?></option>
|
69 |
+
<?php endforeach ?>
|
70 |
+
</select>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
<div class="col-md-4 col-lg-2">
|
74 |
+
<div class="form-group">
|
75 |
+
<select class="form-control bookly-js-chosen-select" id="bookly-filter-status" data-placeholder="<?php esc_attr_e( 'Status', 'bookly' ) ?>">
|
76 |
+
<option value="-1"></option>
|
77 |
+
<option value="<?php echo CustomerAppointment::STATUS_PENDING ?>"><?php echo CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ?></option>
|
78 |
+
<option value="<?php echo CustomerAppointment::STATUS_APPROVED ?>"><?php echo CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ?></option>
|
79 |
+
<option value="<?php echo CustomerAppointment::STATUS_CANCELLED ?>"><?php echo CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ?></option>
|
80 |
+
<option value="<?php echo CustomerAppointment::STATUS_REJECTED ?>"><?php echo CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ?></option>
|
81 |
+
</select>
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
|
86 |
+
<table id="bookly-appointments-list" class="table table-striped" width="100%">
|
87 |
+
<thead>
|
88 |
+
<tr>
|
89 |
+
<th><?php _e( 'No.', 'bookly' ) ?></th>
|
90 |
+
<th><?php _e( 'Appointment Date', 'bookly' ) ?></th>
|
91 |
+
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ?></th>
|
92 |
+
<th><?php _e( 'Customer Name', 'bookly' ) ?></th>
|
93 |
+
<th><?php _e( 'Customer Phone', 'bookly' ) ?></th>
|
94 |
+
<th><?php _e( 'Customer Email', 'bookly' ) ?></th>
|
95 |
+
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_service' ) ?></th>
|
96 |
+
<th><?php _e( 'Duration', 'bookly' ) ?></th>
|
97 |
+
<th><?php _e( 'Status', 'bookly' ) ?></th>
|
98 |
+
<th><?php _e( 'Payment', 'bookly' ) ?></th>
|
99 |
+
<?php foreach ( $custom_fields as $custom_field ) : ?>
|
100 |
+
<th><?php echo $custom_field->label ?></th>
|
101 |
+
<?php endforeach ?>
|
102 |
+
<th></th>
|
103 |
+
<th width="16"><input type="checkbox" id="bookly-check-all" /></th>
|
104 |
+
</tr>
|
105 |
+
</thead>
|
106 |
+
</table>
|
107 |
+
|
108 |
+
<div class="text-right bookly-margin-top-lg">
|
109 |
+
<?php \BooklyLite\Lib\Utils\Common::deleteButton( '', '', '#bookly-delete-dialog' ) ?>
|
110 |
+
</div>
|
111 |
+
</div>
|
112 |
+
</div>
|
113 |
+
|
114 |
+
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderDeleteDialog(); ?>
|
115 |
+
<?php include '_export_dialog.php' ?>
|
116 |
+
<?php include '_print_dialog.php' ?>
|
117 |
+
|
118 |
+
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderAppointmentDialog() ?>
|
119 |
+
<?php do_action( 'bookly_render_component_appointments' ) ?>
|
120 |
+
</div>
|
121 |
+
</div>
|
backend/modules/calendar/Components.php
CHANGED
@@ -19,22 +19,27 @@ class Components extends Lib\Base\Components
|
|
19 |
|
20 |
$this->enqueueStyles( array(
|
21 |
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', ),
|
|
|
22 |
) );
|
23 |
|
24 |
$this->enqueueScripts( array(
|
25 |
'backend' => array(
|
26 |
'js/angular.min.js' => array( 'jquery' ),
|
27 |
-
'js/angular-ui-date-0.0.8.js' => array( '
|
28 |
'js/moment.min.js' => array( 'jquery' ),
|
29 |
'js/chosen.jquery.min.js' => array( 'jquery' ),
|
30 |
'js/help.js' => array( 'jquery' ),
|
31 |
),
|
|
|
|
|
|
|
|
|
32 |
'module' => array(
|
33 |
-
'js/ng-appointment_dialog.js' => array( '
|
34 |
)
|
35 |
) );
|
36 |
|
37 |
-
wp_localize_script( '
|
38 |
'calendar' => array(
|
39 |
'shortMonths' => array_values( $wp_locale->month_abbrev ),
|
40 |
'longMonths' => array_values( $wp_locale->month ),
|
@@ -52,11 +57,32 @@ class Components extends Lib\Base\Components
|
|
52 |
|
53 |
// Custom fields without captcha field.
|
54 |
$custom_fields = array_filter(
|
55 |
-
json_decode( get_option( '
|
56 |
function( $field ) { return ! in_array( $field->type, array( 'captcha', 'text-content' ) ); }
|
57 |
);
|
58 |
|
59 |
$this->render( '_appointment_dialog', compact( 'custom_fields' ) );
|
60 |
}
|
61 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
19 |
|
20 |
$this->enqueueStyles( array(
|
21 |
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', ),
|
22 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
23 |
) );
|
24 |
|
25 |
$this->enqueueScripts( array(
|
26 |
'backend' => array(
|
27 |
'js/angular.min.js' => array( 'jquery' ),
|
28 |
+
'js/angular-ui-date-0.0.8.js' => array( 'bookly-angular.min.js' ),
|
29 |
'js/moment.min.js' => array( 'jquery' ),
|
30 |
'js/chosen.jquery.min.js' => array( 'jquery' ),
|
31 |
'js/help.js' => array( 'jquery' ),
|
32 |
),
|
33 |
+
'frontend' => array(
|
34 |
+
'js/spin.min.js' => array( 'jquery' ),
|
35 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
36 |
+
),
|
37 |
'module' => array(
|
38 |
+
'js/ng-appointment_dialog.js' => array( 'bookly-angular-ui-date-0.0.8.js', 'jquery-ui-datepicker' ),
|
39 |
)
|
40 |
) );
|
41 |
|
42 |
+
wp_localize_script( 'bookly-ng-appointment_dialog.js', 'BooklyL10nAppDialog', array(
|
43 |
'calendar' => array(
|
44 |
'shortMonths' => array_values( $wp_locale->month_abbrev ),
|
45 |
'longMonths' => array_values( $wp_locale->month ),
|
57 |
|
58 |
// Custom fields without captcha field.
|
59 |
$custom_fields = array_filter(
|
60 |
+
json_decode( get_option( 'bookly_custom_fields' ) ),
|
61 |
function( $field ) { return ! in_array( $field->type, array( 'captcha', 'text-content' ) ); }
|
62 |
);
|
63 |
|
64 |
$this->render( '_appointment_dialog', compact( 'custom_fields' ) );
|
65 |
}
|
66 |
|
67 |
+
/**
|
68 |
+
* Render delete appointment dialog
|
69 |
+
*/
|
70 |
+
public function renderDeleteDialog()
|
71 |
+
{
|
72 |
+
$this->enqueueStyles( array(
|
73 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
74 |
+
) );
|
75 |
+
|
76 |
+
$this->enqueueScripts( array(
|
77 |
+
'frontend' => array(
|
78 |
+
'js/spin.min.js' => array( 'jquery' ),
|
79 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
80 |
+
),
|
81 |
+
'module' => array(
|
82 |
+
'js/delete_dialog.js' => array( 'jquery' ),
|
83 |
+
),
|
84 |
+
) );
|
85 |
+
$this->render( '_delete_dialog' );
|
86 |
+
}
|
87 |
+
|
88 |
}
|
backend/modules/calendar/Controller.php
CHANGED
@@ -1,584 +1,748 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Calendar;
|
3 |
-
|
4 |
-
use
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Calendar
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
$
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
'js/
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
$
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
'
|
49 |
-
'
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
'
|
54 |
-
'
|
55 |
-
'
|
56 |
-
'
|
57 |
-
'
|
58 |
-
'
|
59 |
-
'
|
60 |
-
'
|
61 |
-
'
|
62 |
-
'
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
$
|
79 |
-
$
|
80 |
-
|
81 |
-
$
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
->
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
$day
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
$
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
$
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
$
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
'
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
'
|
203 |
-
'
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
'
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
$
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
$
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
$
|
407 |
-
|
408 |
-
$
|
409 |
-
|
410 |
-
|
411 |
-
$
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
$
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
->
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
}
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
$
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
$
|
496 |
-
$
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
)
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
584 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Calendar;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Calendar
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-calendar';
|
13 |
+
|
14 |
+
protected function getPermissions()
|
15 |
+
{
|
16 |
+
return array( '_this' => 'user' );
|
17 |
+
}
|
18 |
+
|
19 |
+
public function index()
|
20 |
+
{
|
21 |
+
/** @var \WP_Locale $wp_locale */
|
22 |
+
global $wp_locale;
|
23 |
+
|
24 |
+
$this->enqueueStyles( array(
|
25 |
+
'module' => array( 'css/fullcalendar.min.css', ),
|
26 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
27 |
+
) );
|
28 |
+
|
29 |
+
$this->enqueueScripts( array(
|
30 |
+
'backend' => array( 'bootstrap/js/bootstrap.min.js' => array( 'jquery' ), ),
|
31 |
+
'module' => array(
|
32 |
+
'js/fullcalendar.min.js' => array( 'bookly-moment.min.js' ),
|
33 |
+
'js/fc-multistaff-view.js' => array( 'bookly-fullcalendar.min.js' ),
|
34 |
+
'js/calendar.js' => array( 'bookly-fc-multistaff-view.js' ),
|
35 |
+
),
|
36 |
+
) );
|
37 |
+
|
38 |
+
$slot_length_minutes = get_option( 'bookly_gen_time_slot_length', '15' );
|
39 |
+
$slot = new \DateInterval( 'PT' . $slot_length_minutes . 'M' );
|
40 |
+
|
41 |
+
$staff_members = Lib\Utils\Common::isCurrentUserAdmin()
|
42 |
+
? Lib\Entities\Staff::query()->sortBy( 'position' )->find()
|
43 |
+
: Lib\Entities\Staff::query()->where( 'wp_user_id', get_current_user_id() )->find();
|
44 |
+
|
45 |
+
wp_localize_script( 'bookly-calendar.js', 'BooklyL10n', array(
|
46 |
+
'slotDuration' => $slot->format( '%H:%I:%S' ),
|
47 |
+
'calendar' => array(
|
48 |
+
'shortMonths' => array_values( $wp_locale->month_abbrev ),
|
49 |
+
'longMonths' => array_values( $wp_locale->month ),
|
50 |
+
'shortDays' => array_values( $wp_locale->weekday_abbrev ),
|
51 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
52 |
+
),
|
53 |
+
'dpDateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_JQUERY_DATEPICKER ),
|
54 |
+
'mjsDateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_MOMENT_JS ),
|
55 |
+
'mjsTimeFormat' => Lib\Utils\DateTime::convertFormat( 'time', Lib\Utils\DateTime::FORMAT_MOMENT_JS ),
|
56 |
+
'today' => __( 'Today', 'bookly' ),
|
57 |
+
'week' => __( 'Week', 'bookly' ),
|
58 |
+
'day' => __( 'Day', 'bookly' ),
|
59 |
+
'month' => __( 'Month', 'bookly' ),
|
60 |
+
'allDay' => __( 'All Day', 'bookly' ),
|
61 |
+
'delete' => __( 'Delete', 'bookly' ),
|
62 |
+
'noStaffSelected' => __( 'No staff selected', 'bookly' ),
|
63 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
64 |
+
'startOfWeek' => (int) get_option( 'start_of_week' ),
|
65 |
+
'recurring_appointments_enabled' => (int) Lib\Config::isRecurringAppointmentsEnabled(),
|
66 |
+
) );
|
67 |
+
|
68 |
+
$this->render( 'calendar', compact( 'staff_members' ) );
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Get data for FullCalendar.
|
73 |
+
*
|
74 |
+
* return string json
|
75 |
+
*/
|
76 |
+
public function executeGetStaffAppointments()
|
77 |
+
{
|
78 |
+
$result = array();
|
79 |
+
$staff_members = array();
|
80 |
+
$one_day = new \DateInterval( 'P1D' );
|
81 |
+
$start_date = new \DateTime( $this->getParameter( 'start' ) );
|
82 |
+
$end_date = new \DateTime( $this->getParameter( 'end' ) );
|
83 |
+
// FullCalendar sends end date as 1 day further.
|
84 |
+
$end_date->sub( $one_day );
|
85 |
+
|
86 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
87 |
+
$staff_members = Lib\Entities\Staff::query()
|
88 |
+
->where( 'id', 1 )
|
89 |
+
->find();
|
90 |
+
} else {
|
91 |
+
$staff_members[] = Lib\Entities\Staff::query()
|
92 |
+
->where( 'wp_user_id', get_current_user_id() )
|
93 |
+
->findOne();
|
94 |
+
$staff_ids = array( 1 );
|
95 |
+
}
|
96 |
+
// Load special days.
|
97 |
+
$special_days = array();
|
98 |
+
foreach ( apply_filters( 'bookly_special_days_get_data_for_available_time', array(), $staff_ids, $start_date, $end_date ) as $day ) {
|
99 |
+
$special_days[ $day['staff_id'] ][ $day['date'] ][] = $day;
|
100 |
+
}
|
101 |
+
|
102 |
+
foreach ( $staff_members as $staff ) {
|
103 |
+
/** @var Lib\Entities\Staff $staff */
|
104 |
+
$result = array_merge( $result, $this->_getAppointmentsForFC( $staff->get( 'id' ), $start_date, $end_date ) );
|
105 |
+
|
106 |
+
// Schedule.
|
107 |
+
$items = $staff->getScheduleItems();
|
108 |
+
$day = clone $start_date;
|
109 |
+
// Find previous day end time.
|
110 |
+
$last_end = clone $day;
|
111 |
+
$last_end->sub( $one_day );
|
112 |
+
$w = (int) $day->format( 'w' );
|
113 |
+
$end_time = $items[ $w > 0 ? $w : 7 ]->get( 'end_time' );
|
114 |
+
if ( $end_time !== null ) {
|
115 |
+
$end_time = explode( ':', $end_time );
|
116 |
+
$last_end->setTime( $end_time[0], $end_time[1] );
|
117 |
+
} else {
|
118 |
+
$last_end->setTime( 24, 0 );
|
119 |
+
}
|
120 |
+
// Do the loop.
|
121 |
+
while ( $day <= $end_date ) {
|
122 |
+
$start = $last_end->format( 'Y-m-d H:i:s' );
|
123 |
+
// Check if $day is Special Day for current staff.
|
124 |
+
if ( isset( $special_days[ $staff->get( 'id' ) ][ $day->format( 'Y-m-d' ) ] ) ) {
|
125 |
+
$sp_days = $special_days[ $staff->get( 'id' ) ][ $day->format( 'Y-m-d' ) ];
|
126 |
+
$sp_day = array_shift( $sp_days );
|
127 |
+
$end = $sp_day['date'] . ' ' . $sp_day['start_time'];
|
128 |
+
if ( $start < $end ) {
|
129 |
+
$result[] = array(
|
130 |
+
'start' => $start,
|
131 |
+
'end' => $end,
|
132 |
+
'rendering' => 'background',
|
133 |
+
'staffId' => $staff->get( 'id' ),
|
134 |
+
);
|
135 |
+
// Check if the first break exists.
|
136 |
+
if ( isset( $sp_day['break_start'] ) ) {
|
137 |
+
$result[] = array(
|
138 |
+
'start' => $sp_day['date'] . ' ' . $sp_day['break_start'],
|
139 |
+
'end' => $sp_day['date'] . ' ' . $sp_day['break_end'],
|
140 |
+
'rendering' => 'background',
|
141 |
+
'staffId' => $staff->get( 'id' ),
|
142 |
+
);
|
143 |
+
}
|
144 |
+
}
|
145 |
+
// Breaks.
|
146 |
+
foreach ( $sp_days as $sp_day ) {
|
147 |
+
$result[] = array(
|
148 |
+
'start' => $sp_day['date'] . ' ' . $sp_day['break_start'],
|
149 |
+
'end' => $sp_day['date'] . ' ' . $sp_day['break_end'],
|
150 |
+
'rendering' => 'background',
|
151 |
+
'staffId' => $staff->get( 'id' ),
|
152 |
+
);
|
153 |
+
}
|
154 |
+
$end_time = explode( ':', $sp_day['end_time'] );
|
155 |
+
$last_end = clone $day;
|
156 |
+
$last_end->setTime( $end_time[0], $end_time[1] );
|
157 |
+
} else {
|
158 |
+
/** @var Lib\Entities\StaffScheduleItem $item */
|
159 |
+
$item = $items[ (int) $day->format( 'w' ) + 1 ];
|
160 |
+
if ( $item->get( 'start_time' ) && ! $staff->isOnHoliday( $day ) ) {
|
161 |
+
$end = $day->format( 'Y-m-d ' . $item->get( 'start_time' ) );
|
162 |
+
if ( $start < $end ) {
|
163 |
+
$result[] = array(
|
164 |
+
'start' => $start,
|
165 |
+
'end' => $end,
|
166 |
+
'rendering' => 'background',
|
167 |
+
'staffId' => $staff->get( 'id' ),
|
168 |
+
);
|
169 |
+
}
|
170 |
+
$last_end = clone $day;
|
171 |
+
$end_time = explode( ':', $item->get( 'end_time' ) );
|
172 |
+
$last_end->setTime( $end_time[0], $end_time[1] );
|
173 |
+
|
174 |
+
// Breaks.
|
175 |
+
foreach ( $item->getBreaksList() as $break ) {
|
176 |
+
$result[] = array(
|
177 |
+
'start' => $day->format( 'Y-m-d ' . $break['start_time'] ),
|
178 |
+
'end' => $day->format( 'Y-m-d ' . $break['end_time'] ),
|
179 |
+
'rendering' => 'background',
|
180 |
+
'staffId' => $staff->get( 'id' ),
|
181 |
+
);
|
182 |
+
}
|
183 |
+
} else {
|
184 |
+
$result[] = array(
|
185 |
+
'start' => $last_end->format( 'Y-m-d H:i:s' ),
|
186 |
+
'end' => $day->format( 'Y-m-d 24:00:00' ),
|
187 |
+
'rendering' => 'background',
|
188 |
+
'staffId' => $staff->get( 'id' ),
|
189 |
+
);
|
190 |
+
$last_end = clone $day;
|
191 |
+
$last_end->setTime( 24, 0 );
|
192 |
+
}
|
193 |
+
}
|
194 |
+
|
195 |
+
$day->add( $one_day );
|
196 |
+
}
|
197 |
+
|
198 |
+
if ( $last_end->format( 'H' ) != 24 ) {
|
199 |
+
$result[] = array(
|
200 |
+
'start' => $last_end->format( 'Y-m-d H:i:s' ),
|
201 |
+
'end' => $last_end->format( 'Y-m-d 24:00:00' ),
|
202 |
+
'rendering' => 'background',
|
203 |
+
'staffId' => $staff->get( 'id' ),
|
204 |
+
);
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
wp_send_json( $result );
|
209 |
+
}
|
210 |
+
|
211 |
+
/**
|
212 |
+
* Get data needed for appointment form initialisation.
|
213 |
+
*/
|
214 |
+
public function executeGetDataForAppointmentForm()
|
215 |
+
{
|
216 |
+
$result = array(
|
217 |
+
'staff' => array(),
|
218 |
+
'customers' => array(),
|
219 |
+
'start_time' => array(),
|
220 |
+
'end_time' => array(),
|
221 |
+
'time_interval' => Lib\Config::getTimeSlotLength(),
|
222 |
+
'status' => array(
|
223 |
+
'items' => array(
|
224 |
+
'pending' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_PENDING ),
|
225 |
+
'approved' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_APPROVED ),
|
226 |
+
'cancelled' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_CANCELLED ),
|
227 |
+
'rejected' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_REJECTED ),//@todo I didn't find the place it uses
|
228 |
+
),
|
229 |
+
'default' => get_option( 'bookly_gen_default_appointment_status' ),
|
230 |
+
),
|
231 |
+
);
|
232 |
+
|
233 |
+
// Staff list.
|
234 |
+
$staff_members = Lib\Utils\Common::isCurrentUserAdmin()
|
235 |
+
? Lib\Entities\Staff::query()->sortBy( 'position' )->find()
|
236 |
+
: Lib\Entities\Staff::query()->where( 'wp_user_id', get_current_user_id() )->find();
|
237 |
+
|
238 |
+
/** @var Lib\Entities\Staff $staff_member */
|
239 |
+
foreach ( $staff_members as $staff_member ) {
|
240 |
+
$services = array();
|
241 |
+
foreach ( $staff_member->getStaffServices() as $staff_service ) {
|
242 |
+
$services[] = array(
|
243 |
+
'id' => $staff_service->service->get( 'id' ),
|
244 |
+
'title' => sprintf(
|
245 |
+
'%s (%s)',
|
246 |
+
$staff_service->service->get( 'title' ),
|
247 |
+
Lib\Utils\DateTime::secondsToInterval( $staff_service->service->get( 'duration' ) )
|
248 |
+
),
|
249 |
+
'duration' => $staff_service->service->get( 'duration' ),
|
250 |
+
'capacity' => $staff_service->get( 'capacity' )
|
251 |
+
);
|
252 |
+
}
|
253 |
+
$result['staff'][] = array(
|
254 |
+
'id' => $staff_member->get( 'id' ),
|
255 |
+
'full_name' => $staff_member->get( 'full_name' ),
|
256 |
+
'services' => $services
|
257 |
+
);
|
258 |
+
}
|
259 |
+
|
260 |
+
// Customers list.
|
261 |
+
foreach ( Lib\Entities\Customer::query()->sortBy( 'name' )->find() as $customer ) {
|
262 |
+
$name = $customer->get( 'name' );
|
263 |
+
if ( $customer->get( 'email' ) != '' || $customer->get( 'phone' ) != '' ) {
|
264 |
+
$name .= ' (' . trim( $customer->get( 'email' ) . ', ' . $customer->get( 'phone' ) , ', ' ) . ')';
|
265 |
+
}
|
266 |
+
|
267 |
+
$result['customers'][] = array(
|
268 |
+
'id' => $customer->get( 'id' ),
|
269 |
+
'name' => $name,
|
270 |
+
'custom_fields' => array(),
|
271 |
+
'number_of_persons' => 1,
|
272 |
+
);
|
273 |
+
}
|
274 |
+
|
275 |
+
// Time list.
|
276 |
+
$ts_length = Lib\Config::getTimeSlotLength();
|
277 |
+
$time_start = 0;
|
278 |
+
$time_end = DAY_IN_SECONDS * 2;
|
279 |
+
|
280 |
+
// Run the loop.
|
281 |
+
while ( $time_start <= $time_end ) {
|
282 |
+
$slot = array(
|
283 |
+
'value' => Lib\Utils\DateTime::buildTimeString( $time_start, false ),
|
284 |
+
'title' => Lib\Utils\DateTime::formatTime( $time_start )
|
285 |
+
);
|
286 |
+
if ( $time_start < DAY_IN_SECONDS ) {
|
287 |
+
$result['start_time'][] = $slot;
|
288 |
+
}
|
289 |
+
$result['end_time'][] = $slot;
|
290 |
+
$time_start += $ts_length;
|
291 |
+
}
|
292 |
+
|
293 |
+
wp_send_json( $result );
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Get appointment data when editing an appointment.
|
298 |
+
*/
|
299 |
+
public function executeGetDataForAppointment()
|
300 |
+
{
|
301 |
+
$response = array( 'success' => false, 'data' => array( 'customers' => array() ) );
|
302 |
+
|
303 |
+
$appointment = new Lib\Entities\Appointment();
|
304 |
+
if ( $appointment->load( $this->getParameter( 'id' ) ) ) {
|
305 |
+
$response['success'] = true;
|
306 |
+
|
307 |
+
$info = Lib\Entities\Appointment::query( 'a' )
|
308 |
+
->select( 'ss.capacity AS max_capacity, SUM( ca.number_of_persons ) AS total_number_of_persons, a.staff_id, a.service_id, a.start_date, a.end_date, a.internal_note' )
|
309 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
310 |
+
->leftJoin( 'StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id' )
|
311 |
+
->where( 'a.id', $appointment->get( 'id' ) )
|
312 |
+
->fetchRow();
|
313 |
+
|
314 |
+
$response['data']['total_number_of_persons'] = $info['total_number_of_persons'];
|
315 |
+
$response['data']['max_capacity'] = $info['max_capacity'];
|
316 |
+
$response['data']['start_date'] = $info['start_date'];
|
317 |
+
$response['data']['end_date'] = $info['end_date'];
|
318 |
+
$response['data']['staff_id'] = $info['staff_id'];
|
319 |
+
$response['data']['service_id'] = $info['service_id'];
|
320 |
+
$response['data']['internal_note'] = $info['internal_note'];
|
321 |
+
$customers = Lib\Entities\CustomerAppointment::query( 'ca' )
|
322 |
+
->select( 'ca.id,
|
323 |
+
ca.customer_id,
|
324 |
+
ca.custom_fields,
|
325 |
+
ca.extras,
|
326 |
+
ca.number_of_persons,
|
327 |
+
ca.status,
|
328 |
+
ca.payment_id,
|
329 |
+
ca.compound_service_id,
|
330 |
+
ca.compound_token,
|
331 |
+
ca.location_id,
|
332 |
+
p.paid AS payment,
|
333 |
+
p.total AS payment_total,
|
334 |
+
p.type AS payment_type,
|
335 |
+
p.details AS payment_details,
|
336 |
+
p.status AS payment_status' )
|
337 |
+
->leftJoin( 'Payment', 'p', 'p.id = ca.payment_id' )
|
338 |
+
->where( 'ca.appointment_id', $appointment->get( 'id' ) )
|
339 |
+
->fetchArray();
|
340 |
+
foreach ( $customers as $customer ) {
|
341 |
+
$payment_title = '';
|
342 |
+
if ( $customer['payment'] !== null ) {
|
343 |
+
$payment_title = Lib\Utils\Common::formatPrice( $customer['payment'] );
|
344 |
+
if ( $customer['payment'] != $customer['payment_total'] ) {
|
345 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Common::formatPrice( $customer['payment_total'] ) );
|
346 |
+
}
|
347 |
+
$payment_title .= sprintf(
|
348 |
+
' %s <span%s>%s</span>',
|
349 |
+
Lib\Entities\Payment::typeToString( $customer['payment_type'] ),
|
350 |
+
$customer['payment_status'] == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
351 |
+
Lib\Entities\Payment::statusToString( $customer['payment_status'] )
|
352 |
+
);
|
353 |
+
}
|
354 |
+
$compound_service = '';
|
355 |
+
if ( $customer['compound_service_id'] !== null ) {
|
356 |
+
$service = new Lib\Entities\Service();
|
357 |
+
if ( $service->load( $customer['compound_service_id'] ) ) {
|
358 |
+
$compound_service = $service->getTitle();
|
359 |
+
}
|
360 |
+
}
|
361 |
+
$response['data']['customers'][] = array(
|
362 |
+
'id' => $customer['customer_id'],
|
363 |
+
'ca_id' => $customer['id'],
|
364 |
+
'compound_service' => $compound_service,
|
365 |
+
'compound_token' => $customer['compound_token'],
|
366 |
+
'custom_fields' => (array) json_decode( $customer['custom_fields'], true ),
|
367 |
+
'extras' => (array) json_decode( $customer['extras'], true ),
|
368 |
+
'location_id' => $customer['location_id'],
|
369 |
+
'number_of_persons' => $customer['number_of_persons'],
|
370 |
+
'payment_id' => $customer['payment_id'],
|
371 |
+
'payment_type' => $customer['payment'] != $customer['payment_total'] ? 'partial' : 'full',
|
372 |
+
'payment_title' => $payment_title,
|
373 |
+
'status' => $customer['status'],
|
374 |
+
);
|
375 |
+
}
|
376 |
+
}
|
377 |
+
wp_send_json( $response );
|
378 |
+
}
|
379 |
+
|
380 |
+
/**
|
381 |
+
* Save appointment form (for both create and edit).
|
382 |
+
*/
|
383 |
+
public function executeSaveAppointmentForm()
|
384 |
+
{
|
385 |
+
$response = array( 'success' => false );
|
386 |
+
|
387 |
+
$internal_note = $this->getParameter( 'internal_note' );
|
388 |
+
$start_date = $this->getParameter( 'start_date' );
|
389 |
+
$end_date = $this->getParameter( 'end_date' );
|
390 |
+
$service_id = $this->getParameter( 'service_id' );
|
391 |
+
$appointment_id = $this->getParameter( 'id', 0 );
|
392 |
+
$repeat = json_decode( $this->getParameter( 'repeat', '[]' ), true );
|
393 |
+
$schedule = $this->getParameter( 'schedule', array() );
|
394 |
+
$customers = json_decode( $this->getParameter( 'customers', '[]' ), true );
|
395 |
+
|
396 |
+
$staff_service = new Lib\Entities\StaffService();
|
397 |
+
$staff_service->loadBy( array(
|
398 |
+
'staff_id' => 1,
|
399 |
+
'service_id' => $service_id
|
400 |
+
) );
|
401 |
+
|
402 |
+
// Check for errors.
|
403 |
+
if ( ! $start_date ) {
|
404 |
+
$response['errors']['time_interval'] = __( 'Start time must not be empty', 'bookly' );
|
405 |
+
} elseif ( ! $end_date ) {
|
406 |
+
$response['errors']['time_interval'] = __( 'End time must not be empty', 'bookly' );
|
407 |
+
} elseif ( $start_date == $end_date ) {
|
408 |
+
$response['errors']['time_interval'] = __( 'End time must not be equal to start time', 'bookly' );
|
409 |
+
}
|
410 |
+
if ( ! $service_id ) {
|
411 |
+
$response['errors']['service_required'] = true;
|
412 |
+
}
|
413 |
+
if ( empty ( $customers ) ) {
|
414 |
+
$response['errors']['customers_required'] = true;
|
415 |
+
}
|
416 |
+
$total_number_of_persons = 0;
|
417 |
+
$max_extras_duration = 0;
|
418 |
+
foreach ( $customers as $customer ) {
|
419 |
+
if (
|
420 |
+
( $customer['status'] != Lib\Entities\CustomerAppointment::STATUS_CANCELLED )
|
421 |
+
&& ( $customer['status'] != Lib\Entities\CustomerAppointment::STATUS_REJECTED )
|
422 |
+
) {
|
423 |
+
$total_number_of_persons += $customer['number_of_persons'];
|
424 |
+
$extras_duration = apply_filters( 'bookly_service_extras_get_total_duration', 0, $customer['extras'] );
|
425 |
+
if ( $extras_duration > $max_extras_duration ) {
|
426 |
+
$max_extras_duration = $extras_duration;
|
427 |
+
}
|
428 |
+
}
|
429 |
+
}
|
430 |
+
if ( $total_number_of_persons > $staff_service->get( 'capacity' ) ) {
|
431 |
+
$response['errors']['overflow_capacity'] = sprintf(
|
432 |
+
__( 'The number of customers should not be more than %d', 'bookly' ),
|
433 |
+
$staff_service->get( 'capacity' )
|
434 |
+
);
|
435 |
+
}
|
436 |
+
$total_end_date = $end_date;
|
437 |
+
if ( $max_extras_duration > 0 ) {
|
438 |
+
$total_end_date = date_create( $end_date )->modify( '+' . $max_extras_duration . ' sec' )->format( 'Y-m-d H:i:s' );
|
439 |
+
}
|
440 |
+
if ( ! $this->dateIntervalIsAvailableForAppointment( $start_date, $total_end_date, 1, $appointment_id ) ) {
|
441 |
+
$response['errors']['date_interval_not_available'] = true;
|
442 |
+
}
|
443 |
+
$notification = $this->getParameter( 'notification' );
|
444 |
+
|
445 |
+
// If no errors then try to save the appointment.
|
446 |
+
if ( ! isset ( $response['errors'] ) ) {
|
447 |
+
if ( $repeat['enabled'] ) {
|
448 |
+
if ( ! empty ( $schedule ) ) {
|
449 |
+
$recurring_list = array( 'customers' => $customers, 'appointments' => array() );
|
450 |
+
// Create new series.
|
451 |
+
$series = new Lib\Entities\Series();
|
452 |
+
$series
|
453 |
+
->set( 'repeat', $this->getParameter( 'repeat' ) )
|
454 |
+
->set( 'token', Lib\Utils\Common::generateToken( get_class( $series ), 'token' ) )
|
455 |
+
->save();
|
456 |
+
|
457 |
+
$service = new Lib\Entities\Service();
|
458 |
+
$service->load( $service_id );
|
459 |
+
|
460 |
+
foreach ( $schedule as $slot ) {
|
461 |
+
$slot = json_decode( $slot );
|
462 |
+
$appointment = new Lib\Entities\Appointment();
|
463 |
+
$appointment
|
464 |
+
->set( 'series_id', $series->get( 'id' ) )
|
465 |
+
->set( 'staff_id', 1 )
|
466 |
+
->set( 'service_id', $service_id )
|
467 |
+
->set( 'start_date', date( 'Y-m-d H:i:s', $slot[0][2] ) )
|
468 |
+
->set( 'end_date', date( 'Y-m-d H:i:s', $slot[0][2] + $service->get( 'duration' ) ) )
|
469 |
+
->set( 'internal_note', $internal_note )
|
470 |
+
->set( 'extras_duration', $max_extras_duration )
|
471 |
+
;
|
472 |
+
|
473 |
+
if ( $appointment->save() !== false ) {
|
474 |
+
// Google Calendar.
|
475 |
+
$appointment->handleGoogleCalendar();
|
476 |
+
$appointment->saveCustomerAppointments( $customers );
|
477 |
+
|
478 |
+
if ( $notification != 'no' ) {
|
479 |
+
// Collect all appointments for sending recurring notification
|
480 |
+
$recurring_list['appointments'][] = $appointment ;
|
481 |
+
}
|
482 |
+
}
|
483 |
+
}
|
484 |
+
Lib\NotificationSender::sendRecurring( $recurring_list );
|
485 |
+
}
|
486 |
+
$response['success'] = true;
|
487 |
+
$response['data'] = array( 'staffId' => 1 ); // make FullCalendar refetch events
|
488 |
+
} else {
|
489 |
+
$appointment = new Lib\Entities\Appointment();
|
490 |
+
if ( $appointment_id ) {
|
491 |
+
// Edit.
|
492 |
+
$appointment->load( $appointment_id );
|
493 |
+
}
|
494 |
+
$appointment->set( 'start_date', $start_date );
|
495 |
+
$appointment->set( 'end_date', $end_date );
|
496 |
+
$appointment->set( 'staff_id', 1 );
|
497 |
+
$appointment->set( 'service_id', $service_id );
|
498 |
+
$appointment->set( 'internal_note', $internal_note );
|
499 |
+
$appointment->set( 'extras_duration', $max_extras_duration );
|
500 |
+
|
501 |
+
if ( $appointment->save() !== false ) {
|
502 |
+
// Save customer appointments.
|
503 |
+
$ca_status_changed = $appointment->saveCustomerAppointments( $customers );
|
504 |
+
$customer_appointments = $appointment->getCustomerAppointments( true );
|
505 |
+
|
506 |
+
// Google Calendar.
|
507 |
+
$appointment->handleGoogleCalendar();
|
508 |
+
|
509 |
+
// Send notifications.
|
510 |
+
if ( $notification != 'no' ) {
|
511 |
+
foreach ( $customer_appointments as $ca ) {
|
512 |
+
// Send notification.
|
513 |
+
if ( $notification == 'all' || in_array( $ca->get( 'id' ), $ca_status_changed ) ) {
|
514 |
+
Lib\NotificationSender::send( $ca );
|
515 |
+
}
|
516 |
+
}
|
517 |
+
}
|
518 |
+
|
519 |
+
$response['success'] = true;
|
520 |
+
$response['data'] = $this->_getAppointmentForFC( 1, $appointment->get( 'id' ) );
|
521 |
+
} else {
|
522 |
+
$response['errors'] = array( 'db' => __( 'Could not save appointment in database.', 'bookly' ) );
|
523 |
+
}
|
524 |
+
}
|
525 |
+
}
|
526 |
+
|
527 |
+
wp_send_json( $response );
|
528 |
+
}
|
529 |
+
|
530 |
+
public function executeCheckAppointmentDateSelection()
|
531 |
+
{
|
532 |
+
$start_date = $this->getParameter( 'start_date' );
|
533 |
+
$end_date = $this->getParameter( 'end_date' );
|
534 |
+
$service_id = $this->getParameter( 'service_id' );
|
535 |
+
$appointment_id = $this->getParameter( 'appointment_id' );
|
536 |
+
$timestamp_diff = strtotime( $end_date ) - strtotime( $start_date );
|
537 |
+
|
538 |
+
$result = array(
|
539 |
+
'date_interval_not_available' => false,
|
540 |
+
'date_interval_warning' => false,
|
541 |
+
);
|
542 |
+
|
543 |
+
if ( ! $this->dateIntervalIsAvailableForAppointment( $start_date, $end_date, 1, $appointment_id ) ) {
|
544 |
+
$result['date_interval_not_available'] = true;
|
545 |
+
}
|
546 |
+
|
547 |
+
if ( $service_id ) {
|
548 |
+
$service = new Lib\Entities\Service();
|
549 |
+
$service->load( $service_id );
|
550 |
+
|
551 |
+
$duration = $service->get( 'duration' );
|
552 |
+
|
553 |
+
// Service duration interval is not equal to.
|
554 |
+
$result['date_interval_warning'] = ( $timestamp_diff != $duration );
|
555 |
+
}
|
556 |
+
|
557 |
+
wp_send_json( $result );
|
558 |
+
}
|
559 |
+
|
560 |
+
/**
|
561 |
+
* Delete single appointment.
|
562 |
+
*/
|
563 |
+
public function executeDeleteAppointment()
|
564 |
+
{
|
565 |
+
$appointment_id = $this->getParameter( 'appointment_id' );
|
566 |
+
$reason = $this->getParameter( 'reason' );
|
567 |
+
|
568 |
+
if ( $this->getParameter( 'notify' ) ) {
|
569 |
+
$ca_list = Lib\Entities\CustomerAppointment::query()
|
570 |
+
->where( 'appointment_id', $appointment_id )
|
571 |
+
->find();
|
572 |
+
/** @var Lib\Entities\CustomerAppointment $ca */
|
573 |
+
foreach ( $ca_list as $ca ) {
|
574 |
+
switch ( $ca->get('status') ) {
|
575 |
+
case Lib\Entities\CustomerAppointment::STATUS_PENDING:
|
576 |
+
$ca->set( 'status', Lib\Entities\CustomerAppointment::STATUS_REJECTED );
|
577 |
+
break;
|
578 |
+
case Lib\Entities\CustomerAppointment::STATUS_APPROVED:
|
579 |
+
$ca->set( 'status', Lib\Entities\CustomerAppointment::STATUS_CANCELLED );
|
580 |
+
break;
|
581 |
+
}
|
582 |
+
Lib\NotificationSender::send( $ca, array( 'cancellation_reason' => $reason ) );
|
583 |
+
}
|
584 |
+
}
|
585 |
+
|
586 |
+
$appointment = new Lib\Entities\Appointment();
|
587 |
+
$appointment->load( $appointment_id );
|
588 |
+
$appointment->delete();
|
589 |
+
|
590 |
+
wp_send_json_success();
|
591 |
+
}
|
592 |
+
|
593 |
+
/**
|
594 |
+
* @param $start_date
|
595 |
+
* @param $end_date
|
596 |
+
* @param $staff_id
|
597 |
+
* @param $appointment_id
|
598 |
+
* @return bool
|
599 |
+
*/
|
600 |
+
private function dateIntervalIsAvailableForAppointment( $start_date, $end_date, $staff_id, $appointment_id )
|
601 |
+
{
|
602 |
+
return Lib\Entities\Appointment::query( 'a' )
|
603 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
604 |
+
->whereNot( 'a.id', $appointment_id )
|
605 |
+
->where( 'a.staff_id', $staff_id )
|
606 |
+
->whereNot( 'ca.status', Lib\Entities\CustomerAppointment::STATUS_CANCELLED )
|
607 |
+
->whereNot( 'ca.status', Lib\Entities\CustomerAppointment::STATUS_REJECTED )
|
608 |
+
->whereLt( 'start_date', $end_date )
|
609 |
+
->whereGt( 'end_date', $start_date )
|
610 |
+
->count() == 0;
|
611 |
+
}
|
612 |
+
|
613 |
+
/**
|
614 |
+
* Get appointments for FullCalendar.
|
615 |
+
*
|
616 |
+
* @param integer $staff_id
|
617 |
+
* @param \DateTime $start_date
|
618 |
+
* @param \DateTime $end_date
|
619 |
+
* @return array
|
620 |
+
*/
|
621 |
+
private function _getAppointmentsForFC( $staff_id, \DateTime $start_date, \DateTime $end_date )
|
622 |
+
{
|
623 |
+
$query = Lib\Entities\Appointment::query( 'a' )
|
624 |
+
->where( 'st.id', $staff_id )
|
625 |
+
->whereBetween( 'DATE(a.start_date)', $start_date->format( 'Y-m-d' ), $end_date->format( 'Y-m-d' ) );
|
626 |
+
|
627 |
+
return $this->_buildAppointmentsForFC( $staff_id, $query );
|
628 |
+
}
|
629 |
+
|
630 |
+
/**
|
631 |
+
* Get appointment for FullCalendar.
|
632 |
+
*
|
633 |
+
* @param integer $staff_id
|
634 |
+
* @param int $appointment_id
|
635 |
+
* @return array
|
636 |
+
*/
|
637 |
+
private function _getAppointmentForFC( $staff_id, $appointment_id )
|
638 |
+
{
|
639 |
+
$query = Lib\Entities\Appointment::query( 'a' )
|
640 |
+
->where( 'a.id', $appointment_id );
|
641 |
+
|
642 |
+
$appointments = $this->_buildAppointmentsForFC( $staff_id, $query );
|
643 |
+
|
644 |
+
return $appointments[0];
|
645 |
+
}
|
646 |
+
|
647 |
+
/**
|
648 |
+
* Build appointments for FullCalendar.
|
649 |
+
*
|
650 |
+
* @param integer $staff_id
|
651 |
+
* @param Lib\Query $query
|
652 |
+
* @return mixed
|
653 |
+
*/
|
654 |
+
private function _buildAppointmentsForFC( $staff_id, Lib\Query $query )
|
655 |
+
{
|
656 |
+
$appointments = $query
|
657 |
+
->select( 'a.id, a.series_id, a.start_date, DATE_ADD(a.end_date, INTERVAL a.extras_duration SECOND) AS end_date,
|
658 |
+
s.title AS service_title, s.color AS service_color,
|
659 |
+
ss.capacity AS max_capacity,
|
660 |
+
(SELECT SUM(ca.number_of_persons) FROM ' . Lib\Entities\CustomerAppointment::getTableName() . ' ca WHERE ca.appointment_id = a.id) AS total_number_of_persons,
|
661 |
+
ca.number_of_persons,
|
662 |
+
ca.custom_fields,
|
663 |
+
ca.status AS appointment_status,
|
664 |
+
ca.extras,
|
665 |
+
ca.location_id,
|
666 |
+
c.name AS customer_name, c.phone AS customer_phone, c.email AS customer_email, c.id AS customer_id,
|
667 |
+
p.total,
|
668 |
+
p.type AS payment_gateway,
|
669 |
+
p.status AS payment_status' )
|
670 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
671 |
+
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
672 |
+
->leftJoin( 'Payment', 'p', 'p.id = ca.payment_id' )
|
673 |
+
->leftJoin( 'Service', 's', 's.id = a.service_id' )
|
674 |
+
->leftJoin( 'Staff', 'st', 'st.id = a.staff_id' )
|
675 |
+
->leftJoin( 'StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id' )
|
676 |
+
->where( 'st.id', 1 )
|
677 |
+
->groupBy( 'a.id' )
|
678 |
+
->fetchArray();
|
679 |
+
|
680 |
+
foreach ( $appointments as $key => $appointment ) {
|
681 |
+
$desc = '';
|
682 |
+
// Display customer information only if there is 1 customer. Don't confuse with number_of_persons.
|
683 |
+
if ( $appointment['number_of_persons'] == $appointment['total_number_of_persons'] ) {
|
684 |
+
// Customer information.
|
685 |
+
foreach ( array( 'customer_name', 'customer_phone', 'customer_email' ) as $data_entry ) {
|
686 |
+
if ( $appointment[ $data_entry ] ) {
|
687 |
+
$desc .= '<div>' . esc_html( $appointment[ $data_entry ] ) . '</div>';
|
688 |
+
}
|
689 |
+
}
|
690 |
+
$desc = apply_filters( 'bookly_prepare_calendar_appointment_description', $desc, $appointment );
|
691 |
+
// Custom fields.
|
692 |
+
if ( $appointment['custom_fields'] != '[]' ) {
|
693 |
+
$desc .= '<br/>';
|
694 |
+
$ca = new Lib\Entities\CustomerAppointment();
|
695 |
+
$ca->set( 'custom_fields', $appointment['custom_fields'] );
|
696 |
+
$ca->set( 'appointment_id', $appointment['id'] );
|
697 |
+
foreach ( $ca->getCustomFields() as $custom_field ) {
|
698 |
+
$desc .= sprintf( '<div>%s: %s</div>', wp_strip_all_tags( $custom_field['label'] ), nl2br( esc_html( $custom_field['value'] ) ) );
|
699 |
+
}
|
700 |
+
}
|
701 |
+
// Payment.
|
702 |
+
if ( $appointment['total'] ) {
|
703 |
+
$desc .= sprintf(
|
704 |
+
'<br/><div>%s: %s %s %s</div>',
|
705 |
+
__( 'Payment', 'bookly' ),
|
706 |
+
Lib\Utils\Common::formatPrice( $appointment['total'] ),
|
707 |
+
Lib\Entities\Payment::typeToString( $appointment['payment_gateway'] ),
|
708 |
+
Lib\Entities\Payment::statusToString( $appointment['payment_status'] )
|
709 |
+
);
|
710 |
+
}
|
711 |
+
// Status.
|
712 |
+
$desc .= sprintf( '<br/><div>%s: %s</div>', __( 'Status', 'bookly' ), Lib\Entities\CustomerAppointment::statusToString( $appointment['appointment_status'] ) );
|
713 |
+
// Signed up & Capacity.
|
714 |
+
if ( $appointment['max_capacity'] > 1 ) {
|
715 |
+
$desc .= sprintf( '<br/><div>%s: %d</div>', __( 'Signed up', 'bookly' ), $appointment['total_number_of_persons'] );
|
716 |
+
$desc .= sprintf( '<div>%s: %d</div>', __( 'Capacity', 'bookly' ), $appointment['max_capacity'] );
|
717 |
+
}
|
718 |
+
} else {
|
719 |
+
$desc .= sprintf( '<div>%s: %d</div>', __( 'Signed up', 'bookly' ), $appointment['total_number_of_persons'] );
|
720 |
+
$desc .= sprintf( '<div>%s: %d</div>', __( 'Capacity', 'bookly' ), $appointment['max_capacity'] );
|
721 |
+
}
|
722 |
+
$appointments[ $key ] = array(
|
723 |
+
'id' => $appointment['id'],
|
724 |
+
'series_id' => (int) $appointment['series_id'],
|
725 |
+
'start' => $appointment['start_date'],
|
726 |
+
'end' => $appointment['end_date'],
|
727 |
+
'title' => $appointment['service_title'] ? esc_html( $appointment['service_title'] ) : __( 'Untitled', 'bookly' ),
|
728 |
+
'desc' => $desc,
|
729 |
+
'color' => $appointment['service_color'],
|
730 |
+
'staffId' => 1,
|
731 |
+
);
|
732 |
+
}
|
733 |
+
|
734 |
+
return $appointments;
|
735 |
+
}
|
736 |
+
|
737 |
+
/**
|
738 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
739 |
+
* so current 'execute*' methods look nicer.
|
740 |
+
*
|
741 |
+
* @param string $prefix
|
742 |
+
*/
|
743 |
+
protected function registerWpActions( $prefix = '' )
|
744 |
+
{
|
745 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
746 |
+
}
|
747 |
+
|
748 |
}
|
backend/modules/calendar/resources/css/fullcalendar.min.css
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
-
/*!
|
2 |
-
* FullCalendar v2.4.0 Stylesheet
|
3 |
-
* Docs & License: http://fullcalendar.io/
|
4 |
-
* (c) 2015 Adam Shaw
|
5 |
*/.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}body .fc{font-size:1em}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1;opacity:.3;filter:alpha(opacity=30)}.fc-bgevent{background:#8fdf82;opacity:.3;filter:alpha(opacity=30)}.fc-nonbusiness{background:#d7d7d7}.fc-icon{display:inline-block;width:1em;height:1em;line-height:1em;font-size:1em;text-align:center;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative;margin:0 -1em}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%;left:3%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%;left:-3%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%;left:-2%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%;left:2%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;white-space:nowrap;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-default{background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.fc-button-group{display:inline-block}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-popover .fc-header .fc-close{cursor:pointer}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc-bg{bottom:0}.fc-bg table{height:100%}.fc table{width:100%;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{overflow-y:scroll;overflow-x:hidden}.fc-scroller>*{position:relative;width:100%;overflow:hidden}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;background-color:#3a87ad;font-weight:400}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-event.fc-draggable,.fc-event[href]{cursor:pointer}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25;filter:alpha(opacity=25)}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:3}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-h-event .fc-resizer{top:-1px;bottom:-1px;left:-1px;right:-1px;width:5px}.fc-ltr .fc-h-event .fc-start-resizer,.fc-ltr .fc-h-event .fc-start-resizer:after,.fc-ltr .fc-h-event .fc-start-resizer:before,.fc-rtl .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-end-resizer:after,.fc-rtl .fc-h-event .fc-end-resizer:before{right:auto;cursor:w-resize}.fc-ltr .fc-h-event .fc-end-resizer,.fc-ltr .fc-h-event .fc-end-resizer:after,.fc-ltr .fc-h-event .fc-end-resizer:before,.fc-rtl .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-start-resizer:after,.fc-rtl .fc-h-event .fc-start-resizer:before{left:auto;cursor:e-resize}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-day-grid-event .fc-resizer{left:-3px;right:-3px;width:7px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-toolbar{text-align:center;margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid{overflow:hidden}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:0 2px}.fc-basic-view td.fc-day-number,.fc-basic-view td.fc-week-number span{padding-top:2px;padding-bottom:2px}.fc-basic-view .fc-week-number{text-align:center}.fc-basic-view .fc-week-number span{display:inline-block;min-width:1.25em}.fc-ltr .fc-basic-view .fc-day-number{text-align:right}.fc-rtl .fc-basic-view .fc-day-number{text-align:left}.fc-day-number.fc-other-month{opacity:.3;filter:alpha(opacity=30)}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-bgevent-skeleton,.fc-time-grid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-time-grid .fc-bgevent-skeleton{z-index:3}.fc-time-grid .fc-highlight-skeleton{z-index:4}.fc-time-grid .fc-content-skeleton{z-index:5}.fc-time-grid .fc-helper-skeleton{z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight-container{position:relative}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-time-grid .fc-bgevent-container,.fc-time-grid .fc-event-container{position:relative}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event .fc-resizer:after{content:"="}
|
1 |
+
/*!
|
2 |
+
* FullCalendar v2.4.0 Stylesheet
|
3 |
+
* Docs & License: http://fullcalendar.io/
|
4 |
+
* (c) 2015 Adam Shaw
|
5 |
*/.fc{direction:ltr;text-align:left}.fc-rtl{text-align:right}body .fc{font-size:1em}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover,.fc-unthemed .fc-row,.fc-unthemed tbody,.fc-unthemed td,.fc-unthemed th,.fc-unthemed thead{border-color:#ddd}.fc-unthemed .fc-popover{background-color:#fff}.fc-unthemed .fc-divider,.fc-unthemed .fc-popover .fc-header{background:#eee}.fc-unthemed .fc-popover .fc-header .fc-close{color:#666}.fc-unthemed .fc-today{background:#fcf8e3}.fc-highlight{background:#bce8f1;opacity:.3;filter:alpha(opacity=30)}.fc-bgevent{background:#8fdf82;opacity:.3;filter:alpha(opacity=30)}.fc-nonbusiness{background:#d7d7d7}.fc-icon{display:inline-block;width:1em;height:1em;line-height:1em;font-size:1em;text-align:center;overflow:hidden;font-family:"Courier New",Courier,monospace;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.fc-icon:after{position:relative;margin:0 -1em}.fc-icon-left-single-arrow:after{content:"\02039";font-weight:700;font-size:200%;top:-7%;left:3%}.fc-icon-right-single-arrow:after{content:"\0203A";font-weight:700;font-size:200%;top:-7%;left:-3%}.fc-icon-left-double-arrow:after{content:"\000AB";font-size:160%;top:-7%}.fc-icon-right-double-arrow:after{content:"\000BB";font-size:160%;top:-7%}.fc-icon-left-triangle:after{content:"\25C4";font-size:125%;top:3%;left:-2%}.fc-icon-right-triangle:after{content:"\25BA";font-size:125%;top:3%;left:2%}.fc-icon-down-triangle:after{content:"\25BC";font-size:125%;top:2%}.fc-icon-x:after{content:"\000D7";font-size:200%;top:6%}.fc button{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;height:2.1em;padding:0 .6em;font-size:1em;white-space:nowrap;cursor:pointer}.fc button::-moz-focus-inner{margin:0;padding:0}.fc-state-default{border:1px solid}.fc-state-default.fc-corner-left{border-top-left-radius:4px;border-bottom-left-radius:4px}.fc-state-default.fc-corner-right{border-top-right-radius:4px;border-bottom-right-radius:4px}.fc button .fc-icon{position:relative;top:-.05em;margin:0 .2em;vertical-align:middle}.fc-state-default{background-color:#f5f5f5;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,.1) rgba(0,0,0,.1) rgba(0,0,0,.25);color:#333;text-shadow:0 1px 1px rgba(255,255,255,.75);box-shadow:inset 0 1px 0 rgba(255,255,255,.2),0 1px 2px rgba(0,0,0,.05)}.fc-state-active,.fc-state-disabled,.fc-state-down,.fc-state-hover{color:#333;background-color:#e6e6e6}.fc-state-hover{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.fc-state-active,.fc-state-down{background-color:#ccc;background-image:none;box-shadow:inset 0 2px 4px rgba(0,0,0,.15),0 1px 2px rgba(0,0,0,.05)}.fc-state-disabled{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);box-shadow:none}.fc-button-group{display:inline-block}.fc .fc-button-group>*{float:left;margin:0 0 0 -1px}.fc .fc-button-group>:first-child{margin-left:0}.fc-popover{position:absolute;box-shadow:0 2px 6px rgba(0,0,0,.15)}.fc-popover .fc-header{padding:2px 4px}.fc-popover .fc-header .fc-title{margin:0 2px}.fc-popover .fc-header .fc-close{cursor:pointer}.fc-ltr .fc-popover .fc-header .fc-title,.fc-rtl .fc-popover .fc-header .fc-close{float:left}.fc-ltr .fc-popover .fc-header .fc-close,.fc-rtl .fc-popover .fc-header .fc-title{float:right}.fc-unthemed .fc-popover{border-width:1px;border-style:solid}.fc-unthemed .fc-popover .fc-header .fc-close{font-size:.9em;margin-top:2px}.fc-popover>.ui-widget-header+.ui-widget-content{border-top:0}.fc-divider{border-style:solid;border-width:1px}hr.fc-divider{height:0;margin:0;padding:0 0 2px;border-width:1px 0}.fc-clear{clear:both}.fc-bg,.fc-bgevent-skeleton,.fc-helper-skeleton,.fc-highlight-skeleton{position:absolute;top:0;left:0;right:0}.fc-bg{bottom:0}.fc-bg table{height:100%}.fc table{width:100%;table-layout:fixed;border-collapse:collapse;border-spacing:0;font-size:1em}.fc th{text-align:center}.fc td,.fc th{border-style:solid;border-width:1px;padding:0;vertical-align:top}.fc td.fc-today{border-style:double}.fc .fc-row{border-style:solid;border-width:0}.fc-row table{border-left:0 hidden transparent;border-right:0 hidden transparent;border-bottom:0 hidden transparent}.fc-row:first-child table{border-top:0 hidden transparent}.fc-row{position:relative}.fc-row .fc-bg{z-index:1}.fc-row .fc-bgevent-skeleton,.fc-row .fc-highlight-skeleton{bottom:0}.fc-row .fc-bgevent-skeleton table,.fc-row .fc-highlight-skeleton table{height:100%}.fc-row .fc-bgevent-skeleton td,.fc-row .fc-highlight-skeleton td{border-color:transparent}.fc-row .fc-bgevent-skeleton{z-index:2}.fc-row .fc-highlight-skeleton{z-index:3}.fc-row .fc-content-skeleton{position:relative;z-index:4;padding-bottom:2px}.fc-row .fc-helper-skeleton{z-index:5}.fc-row .fc-content-skeleton td,.fc-row .fc-helper-skeleton td{background:0 0;border-color:transparent;border-bottom:0}.fc-row .fc-content-skeleton tbody td,.fc-row .fc-helper-skeleton tbody td{border-top:0}.fc-scroller{overflow-y:scroll;overflow-x:hidden}.fc-scroller>*{position:relative;width:100%;overflow:hidden}.fc-event{position:relative;display:block;font-size:.85em;line-height:1.3;border-radius:3px;border:1px solid #3a87ad;background-color:#3a87ad;font-weight:400}.fc-event,.fc-event:hover,.ui-widget .fc-event{color:#fff;text-decoration:none}.fc-event.fc-draggable,.fc-event[href]{cursor:pointer}.fc-not-allowed,.fc-not-allowed .fc-event{cursor:not-allowed}.fc-event .fc-bg{z-index:1;background:#fff;opacity:.25;filter:alpha(opacity=25)}.fc-event .fc-content{position:relative;z-index:2}.fc-event .fc-resizer{position:absolute;z-index:3}.fc-ltr .fc-h-event.fc-not-start,.fc-rtl .fc-h-event.fc-not-end{margin-left:0;border-left-width:0;padding-left:1px;border-top-left-radius:0;border-bottom-left-radius:0}.fc-ltr .fc-h-event.fc-not-end,.fc-rtl .fc-h-event.fc-not-start{margin-right:0;border-right-width:0;padding-right:1px;border-top-right-radius:0;border-bottom-right-radius:0}.fc-h-event .fc-resizer{top:-1px;bottom:-1px;left:-1px;right:-1px;width:5px}.fc-ltr .fc-h-event .fc-start-resizer,.fc-ltr .fc-h-event .fc-start-resizer:after,.fc-ltr .fc-h-event .fc-start-resizer:before,.fc-rtl .fc-h-event .fc-end-resizer,.fc-rtl .fc-h-event .fc-end-resizer:after,.fc-rtl .fc-h-event .fc-end-resizer:before{right:auto;cursor:w-resize}.fc-ltr .fc-h-event .fc-end-resizer,.fc-ltr .fc-h-event .fc-end-resizer:after,.fc-ltr .fc-h-event .fc-end-resizer:before,.fc-rtl .fc-h-event .fc-start-resizer,.fc-rtl .fc-h-event .fc-start-resizer:after,.fc-rtl .fc-h-event .fc-start-resizer:before{left:auto;cursor:e-resize}.fc-day-grid-event{margin:1px 2px 0;padding:0 1px}.fc-day-grid-event .fc-content{white-space:nowrap;overflow:hidden}.fc-day-grid-event .fc-time{font-weight:700}.fc-day-grid-event .fc-resizer{left:-3px;right:-3px;width:7px}a.fc-more{margin:1px 3px;font-size:.85em;cursor:pointer;text-decoration:none}a.fc-more:hover{text-decoration:underline}.fc-limited{display:none}.fc-day-grid .fc-row{z-index:1}.fc-more-popover{z-index:2;width:220px}.fc-more-popover .fc-event-container{padding:10px}.fc-toolbar{text-align:center;margin-bottom:1em}.fc-toolbar .fc-left{float:left}.fc-toolbar .fc-right{float:right}.fc-toolbar .fc-center{display:inline-block}.fc .fc-toolbar>*>*{float:left;margin-left:.75em}.fc .fc-toolbar>*>:first-child{margin-left:0}.fc-toolbar h2{margin:0}.fc-toolbar button{position:relative}.fc-toolbar .fc-state-hover,.fc-toolbar .ui-state-hover{z-index:2}.fc-toolbar .fc-state-down{z-index:3}.fc-toolbar .fc-state-active,.fc-toolbar .ui-state-active{z-index:4}.fc-toolbar button:focus{z-index:5}.fc-view-container *,.fc-view-container :after,.fc-view-container :before{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.fc-view,.fc-view>table{position:relative;z-index:1}.fc-basicDay-view .fc-content-skeleton,.fc-basicWeek-view .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc-basic-view .fc-body .fc-row{min-height:4em}.fc-row.fc-rigid{overflow:hidden}.fc-row.fc-rigid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-basic-view .fc-day-number,.fc-basic-view .fc-week-number{padding:0 2px}.fc-basic-view td.fc-day-number,.fc-basic-view td.fc-week-number span{padding-top:2px;padding-bottom:2px}.fc-basic-view .fc-week-number{text-align:center}.fc-basic-view .fc-week-number span{display:inline-block;min-width:1.25em}.fc-ltr .fc-basic-view .fc-day-number{text-align:right}.fc-rtl .fc-basic-view .fc-day-number{text-align:left}.fc-day-number.fc-other-month{opacity:.3;filter:alpha(opacity=30)}.fc-agenda-view .fc-day-grid{position:relative;z-index:2}.fc-agenda-view .fc-day-grid .fc-row{min-height:3em}.fc-agenda-view .fc-day-grid .fc-row .fc-content-skeleton{padding-top:1px;padding-bottom:1em}.fc .fc-axis{vertical-align:middle;padding:0 4px;white-space:nowrap}.fc-ltr .fc-axis{text-align:right}.fc-rtl .fc-axis{text-align:left}.ui-widget td.fc-axis{font-weight:400}.fc-time-grid,.fc-time-grid-container{position:relative;z-index:1}.fc-time-grid{min-height:100%}.fc-time-grid table{border:0 hidden transparent}.fc-time-grid>.fc-bg{z-index:1}.fc-time-grid .fc-slats,.fc-time-grid>hr{position:relative;z-index:2}.fc-time-grid .fc-bgevent-skeleton,.fc-time-grid .fc-content-skeleton{position:absolute;top:0;left:0;right:0}.fc-time-grid .fc-bgevent-skeleton{z-index:3}.fc-time-grid .fc-highlight-skeleton{z-index:4}.fc-time-grid .fc-content-skeleton{z-index:5}.fc-time-grid .fc-helper-skeleton{z-index:6}.fc-time-grid .fc-slats td{height:1.5em;border-bottom:0}.fc-time-grid .fc-slats .fc-minor td{border-top-style:dotted}.fc-time-grid .fc-slats .ui-widget-content{background:0 0}.fc-time-grid .fc-highlight-container{position:relative}.fc-time-grid .fc-highlight{position:absolute;left:0;right:0}.fc-time-grid .fc-bgevent-container,.fc-time-grid .fc-event-container{position:relative}.fc-ltr .fc-time-grid .fc-event-container{margin:0 2.5% 0 2px}.fc-rtl .fc-time-grid .fc-event-container{margin:0 2px 0 2.5%}.fc-time-grid .fc-bgevent,.fc-time-grid .fc-event{position:absolute;z-index:1}.fc-time-grid .fc-bgevent{left:0;right:0}.fc-v-event.fc-not-start{border-top-width:0;padding-top:1px;border-top-left-radius:0;border-top-right-radius:0}.fc-v-event.fc-not-end{border-bottom-width:0;padding-bottom:1px;border-bottom-left-radius:0;border-bottom-right-radius:0}.fc-time-grid-event{overflow:hidden}.fc-time-grid-event .fc-time,.fc-time-grid-event .fc-title{padding:0 1px}.fc-time-grid-event .fc-time{font-size:.85em;white-space:nowrap}.fc-time-grid-event.fc-short .fc-content{white-space:nowrap}.fc-time-grid-event.fc-short .fc-time,.fc-time-grid-event.fc-short .fc-title{display:inline-block;vertical-align:top}.fc-time-grid-event.fc-short .fc-time span{display:none}.fc-time-grid-event.fc-short .fc-time:before{content:attr(data-start)}.fc-time-grid-event.fc-short .fc-time:after{content:"\000A0-\000A0"}.fc-time-grid-event.fc-short .fc-title{font-size:.85em;padding:0}.fc-time-grid-event .fc-resizer{left:0;right:0;bottom:0;height:8px;overflow:hidden;line-height:8px;font-size:11px;font-family:monospace;text-align:center;cursor:s-resize}.fc-time-grid-event .fc-resizer:after{content:"="}
|
backend/modules/calendar/resources/js/calendar.js
CHANGED
@@ -1,371 +1,401 @@
|
|
1 |
-
jQuery(function ($) {
|
2 |
-
|
3 |
-
var $fullCalendar = $('#bookly-fc-wrapper .bookly-js-calendar-element'),
|
4 |
-
$tabs = $('.bookly-js-calendar-tab'),
|
5 |
-
$staff = $('input.bookly-js-check-entity'),
|
6 |
-
$showAll = $('input#bookly-check-all-entities'),
|
7 |
-
firstHour = new Date().getHours(),
|
8 |
-
$staffButton = $('#ab-staff-button'),
|
9 |
-
staffMembers = [],
|
10 |
-
staffIds = getCookie('bookly_cal_st_ids'),
|
11 |
-
tabId = getCookie('bookly_cal_tab_id'),
|
12 |
-
lastView = getCookie('bookly_cal_view'),
|
13 |
-
views = 'month,agendaWeek,agendaDay,multiStaffDay'
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
}
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
// Event
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
}
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
$
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
$calEvent.
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
staff_id =
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
}
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
$
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
$
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
371 |
});
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
var $fullCalendar = $('#bookly-fc-wrapper .bookly-js-calendar-element'),
|
4 |
+
$tabs = $('.bookly-js-calendar-tab'),
|
5 |
+
$staff = $('input.bookly-js-check-entity'),
|
6 |
+
$showAll = $('input#bookly-check-all-entities'),
|
7 |
+
firstHour = new Date().getHours(),
|
8 |
+
$staffButton = $('#ab-staff-button'),
|
9 |
+
staffMembers = [],
|
10 |
+
staffIds = getCookie('bookly_cal_st_ids'),
|
11 |
+
tabId = getCookie('bookly_cal_tab_id'),
|
12 |
+
lastView = getCookie('bookly_cal_view'),
|
13 |
+
views = 'month,agendaWeek,agendaDay,multiStaffDay',
|
14 |
+
$deleteDialog = $('#bookly-delete-dialog'),
|
15 |
+
$deleteButton = $('#bookly-delete');
|
16 |
+
|
17 |
+
if (views.indexOf(lastView) == -1) {
|
18 |
+
lastView = 'multiStaffDay';
|
19 |
+
}
|
20 |
+
// Init tabs and staff member filters.
|
21 |
+
if (staffIds === null) {
|
22 |
+
$staff.each(function (index, value) {
|
23 |
+
this.checked = true;
|
24 |
+
$tabs.filter('[data-staff_id=' + this.value + ']').show();
|
25 |
+
});
|
26 |
+
} else if (staffIds != '') {
|
27 |
+
$.each(staffIds.split(','), function (index, value) {
|
28 |
+
$staff.filter('[value=' + value + ']').prop('checked', true);
|
29 |
+
$tabs.filter('[data-staff_id=' + value + ']').show();
|
30 |
+
});
|
31 |
+
} else {
|
32 |
+
$('.dropdown-toggle').dropdown('toggle');
|
33 |
+
}
|
34 |
+
|
35 |
+
$tabs.filter('[data-staff_id=' + tabId + ']').addClass('active');
|
36 |
+
if ($tabs.filter('li.active').length == 0) {
|
37 |
+
$tabs.eq(0).addClass('active').show();
|
38 |
+
$staff.filter('[value=' + $tabs.eq(0).data('staff_id') + ']').prop('checked', true);
|
39 |
+
}
|
40 |
+
updateStaffButton();
|
41 |
+
|
42 |
+
// Init FullCalendar.
|
43 |
+
$fullCalendar.fullCalendar({
|
44 |
+
// General Display.
|
45 |
+
firstDay: BooklyL10n.startOfWeek,
|
46 |
+
header: {
|
47 |
+
left: 'prev,next today',
|
48 |
+
center: 'title',
|
49 |
+
right: views
|
50 |
+
},
|
51 |
+
height: heightFC(),
|
52 |
+
// Views.
|
53 |
+
defaultView: lastView,
|
54 |
+
scrollTime: firstHour + ':00:00',
|
55 |
+
views: {
|
56 |
+
agendaWeek: {
|
57 |
+
columnFormat: 'ddd, D'
|
58 |
+
},
|
59 |
+
multiStaffDay: {
|
60 |
+
staffMembers: staffMembers
|
61 |
+
}
|
62 |
+
},
|
63 |
+
eventBackgroundColor: 'silver',
|
64 |
+
// Agenda Options.
|
65 |
+
allDaySlot: false,
|
66 |
+
allDayText: BooklyL10n.allDay,
|
67 |
+
axisFormat: BooklyL10n.mjsTimeFormat,
|
68 |
+
slotDuration: BooklyL10n.slotDuration,
|
69 |
+
// Text/Time Customization.
|
70 |
+
timeFormat: BooklyL10n.mjsTimeFormat,
|
71 |
+
displayEventEnd: true,
|
72 |
+
buttonText: {
|
73 |
+
today: BooklyL10n.today,
|
74 |
+
month: BooklyL10n.month,
|
75 |
+
week: BooklyL10n.week,
|
76 |
+
day: BooklyL10n.day
|
77 |
+
},
|
78 |
+
monthNames: BooklyL10n.calendar.longMonths,
|
79 |
+
monthNamesShort: BooklyL10n.calendar.shortMonths,
|
80 |
+
dayNames: BooklyL10n.calendar.longDays,
|
81 |
+
dayNamesShort: BooklyL10n.calendar.shortDays,
|
82 |
+
// Event Dragging & Resizing.
|
83 |
+
editable: false,
|
84 |
+
// Event Data.
|
85 |
+
eventSources: [{
|
86 |
+
url: ajaxurl,
|
87 |
+
data: {
|
88 |
+
action : 'bookly_get_staff_appointments',
|
89 |
+
staff_ids : function () {
|
90 |
+
var ids = [];
|
91 |
+
if ($tabs.filter('.active').data('staff_id') == 0) {
|
92 |
+
for (var i = 0; i < staffMembers.length; ++i) {
|
93 |
+
ids.push(staffMembers[i].id);
|
94 |
+
}
|
95 |
+
} else {
|
96 |
+
ids.push($tabs.filter('.active').data('staff_id'));
|
97 |
+
}
|
98 |
+
return ids;
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}],
|
102 |
+
// Event Rendering.
|
103 |
+
eventRender : function (calEvent, $event) {
|
104 |
+
var body = calEvent.title + '<a class="delete-event dashicons dashicons-trash" title="' + BooklyL10n.delete + '"></a>';
|
105 |
+
|
106 |
+
if (calEvent.desc) {
|
107 |
+
body += calEvent.desc;
|
108 |
+
}
|
109 |
+
|
110 |
+
$event.find('.fc-title').html(body);
|
111 |
+
|
112 |
+
var $time = $event.find('.fc-time');
|
113 |
+
$time.attr('data-start', $time.find('span').text());
|
114 |
+
|
115 |
+
$event.find('.delete-event').on('click', function(e) {
|
116 |
+
e.stopPropagation();
|
117 |
+
// Localize contains only string values
|
118 |
+
if (BooklyL10n.recurring_appointments_enabled == '1' && calEvent.series_id) {
|
119 |
+
$(document.body).trigger( 'recurring_appointments.delete_dialog', [ $fullCalendar, calEvent ] );
|
120 |
+
} else {
|
121 |
+
$deleteDialog.data('calEvent', calEvent).modal('show');
|
122 |
+
}
|
123 |
+
});
|
124 |
+
},
|
125 |
+
eventAfterRender : function (calEvent, $calEventList, calendar) {
|
126 |
+
$calEventList.each(function () {
|
127 |
+
var $calEvent = $(this);
|
128 |
+
var titleHeight = $calEvent.find('.fc-title').height(),
|
129 |
+
origHeight = $calEvent.outerHeight();
|
130 |
+
if (origHeight < titleHeight) {
|
131 |
+
var z_index = $calEvent.zIndex();
|
132 |
+
// Mouse handlers.
|
133 |
+
$calEvent.on('mouseenter', function () {
|
134 |
+
$calEvent.removeClass('fc-short')
|
135 |
+
.css({'z-index': 64, bottom: '', height: ''});
|
136 |
+
}).on('mouseleave', function () {
|
137 |
+
$calEvent.css({'z-index': z_index, height: origHeight});
|
138 |
+
});
|
139 |
+
}
|
140 |
+
});
|
141 |
+
},
|
142 |
+
// Clicking & Hovering.
|
143 |
+
dayClick: function (date, jsEvent, view) {
|
144 |
+
var staff_id, visible_staff_id;
|
145 |
+
if (view.type == 'multiStaffDay') {
|
146 |
+
var cell = view.coordMap.getCell(jsEvent.pageX, jsEvent.pageY);
|
147 |
+
var staffMembers = view.opt('staffMembers');
|
148 |
+
staff_id = staffMembers[cell.col].id;
|
149 |
+
visible_staff_id = 0;
|
150 |
+
} else {
|
151 |
+
staff_id = visible_staff_id = $tabs.filter('.active').data('staff_id');
|
152 |
+
}
|
153 |
+
|
154 |
+
showAppointmentDialog(
|
155 |
+
null,
|
156 |
+
staff_id,
|
157 |
+
date,
|
158 |
+
function (event) {
|
159 |
+
if (visible_staff_id == event.staffId || visible_staff_id == 0) {
|
160 |
+
if (event.id) {
|
161 |
+
// Create event in calendar.
|
162 |
+
$fullCalendar.fullCalendar('renderEvent', event);
|
163 |
+
} else {
|
164 |
+
$fullCalendar.fullCalendar('refetchEvents');
|
165 |
+
}
|
166 |
+
} else {
|
167 |
+
// Switch to the event owner tab.
|
168 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
169 |
+
}
|
170 |
+
}
|
171 |
+
);
|
172 |
+
},
|
173 |
+
eventClick: function (calEvent, jsEvent, view) {
|
174 |
+
var visible_staff_id;
|
175 |
+
if (view.type == 'multiStaffDay') {
|
176 |
+
visible_staff_id = 0;
|
177 |
+
} else {
|
178 |
+
visible_staff_id = calEvent.staffId;
|
179 |
+
}
|
180 |
+
|
181 |
+
showAppointmentDialog(
|
182 |
+
calEvent.id,
|
183 |
+
null,
|
184 |
+
null,
|
185 |
+
function (event) {
|
186 |
+
if (visible_staff_id == event.staffId || visible_staff_id == 0) {
|
187 |
+
// Update event in calendar.
|
188 |
+
jQuery.extend(calEvent, event);
|
189 |
+
$fullCalendar.fullCalendar('updateEvent', calEvent);
|
190 |
+
} else {
|
191 |
+
// Switch to the event owner tab.
|
192 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
193 |
+
}
|
194 |
+
}
|
195 |
+
);
|
196 |
+
},
|
197 |
+
loading: function (bool) {
|
198 |
+
$('.fc-loading-inner').toggle(bool);
|
199 |
+
},
|
200 |
+
viewRender: function (view, element) {
|
201 |
+
setCookie('bookly_cal_view', view.type);
|
202 |
+
}
|
203 |
+
});
|
204 |
+
|
205 |
+
$('.fc-agendaDay-button').addClass('fc-corner-right');
|
206 |
+
if ($tabs.filter('.active').data('staff_id') == 0) {
|
207 |
+
$('.fc-agendaDay-button').hide();
|
208 |
+
} else {
|
209 |
+
$('.fc-multiStaffDay-button').hide();
|
210 |
+
}
|
211 |
+
|
212 |
+
// Init date picker for fast navigation in FullCalendar.
|
213 |
+
var $fcDatePicker = $('<input type=hidden />');
|
214 |
+
$('.fc-toolbar .fc-center h2').before($fcDatePicker).on('click', function () {
|
215 |
+
$fcDatePicker.datepicker('setDate', $fullCalendar.fullCalendar('getDate').toDate()).datepicker('show');
|
216 |
+
});
|
217 |
+
$fcDatePicker.datepicker({
|
218 |
+
dayNamesMin : BooklyL10n.calendar.shortDays,
|
219 |
+
monthNames : BooklyL10n.calendar.longMonths,
|
220 |
+
monthNamesShort : BooklyL10n.calendar.shortMonths,
|
221 |
+
firstDay : BooklyL10n.startOfWeek,
|
222 |
+
beforeShow: function (input, inst) {
|
223 |
+
inst.dpDiv.queue(function () {
|
224 |
+
inst.dpDiv.css({marginTop: '35px'});
|
225 |
+
inst.dpDiv.dequeue();
|
226 |
+
});
|
227 |
+
},
|
228 |
+
onSelect: function (dateText, inst) {
|
229 |
+
var d = new Date(dateText);
|
230 |
+
$fullCalendar.fullCalendar('gotoDate', d);
|
231 |
+
if ($fullCalendar.fullCalendar('getView').type != 'agendaDay' &&
|
232 |
+
$fullCalendar.fullCalendar('getView').type != 'multiStaffDay')
|
233 |
+
{
|
234 |
+
$fullCalendar.find('.fc-day').removeClass('bookly-fc-day-active');
|
235 |
+
$fullCalendar.find('.fc-day[data-date="' + moment(d).format('YYYY-MM-DD') + '"]').addClass('bookly-fc-day-active');
|
236 |
+
}
|
237 |
+
},
|
238 |
+
onClose: function (dateText, inst) {
|
239 |
+
inst.dpDiv.queue(function () {
|
240 |
+
inst.dpDiv.css({marginTop: '0'});
|
241 |
+
inst.dpDiv.dequeue();
|
242 |
+
});
|
243 |
+
}
|
244 |
+
});
|
245 |
+
|
246 |
+
$(window).on('resize', function () {
|
247 |
+
$fullCalendar.fullCalendar('option', 'height', heightFC());
|
248 |
+
});
|
249 |
+
|
250 |
+
// Click on tabs.
|
251 |
+
$tabs.on('click', function (e) {
|
252 |
+
e.preventDefault();
|
253 |
+
$tabs.removeClass('active');
|
254 |
+
$(this).addClass('active');
|
255 |
+
|
256 |
+
var staff_id = $(this).data('staff_id');
|
257 |
+
setCookie('bookly_cal_tab_id', staff_id);
|
258 |
+
|
259 |
+
if (staff_id == 0) {
|
260 |
+
$('.fc-agendaDay-button').hide();
|
261 |
+
$('.fc-multiStaffDay-button').show();
|
262 |
+
$fullCalendar.fullCalendar('changeView', 'multiStaffDay');
|
263 |
+
$fullCalendar.fullCalendar('refetchEvents');
|
264 |
+
} else {
|
265 |
+
$('.fc-multiStaffDay-button').hide();
|
266 |
+
$('.fc-agendaDay-button').show();
|
267 |
+
var view = $fullCalendar.fullCalendar('getView');
|
268 |
+
if (view.type == 'multiStaffDay') {
|
269 |
+
$fullCalendar.fullCalendar('changeView', 'agendaDay');
|
270 |
+
}
|
271 |
+
$fullCalendar.fullCalendar('refetchEvents');
|
272 |
+
}
|
273 |
+
});
|
274 |
+
|
275 |
+
$('.dropdown-menu').on('click', function (e) {
|
276 |
+
e.stopPropagation();
|
277 |
+
});
|
278 |
+
|
279 |
+
/**
|
280 |
+
* On show all staff checkbox click.
|
281 |
+
*/
|
282 |
+
$showAll.on('change', function () {
|
283 |
+
$tabs.filter('[data-staff_id!=0]').toggle(this.checked);
|
284 |
+
$staff
|
285 |
+
.prop('checked', this.checked)
|
286 |
+
.filter(':first').triggerHandler('change');
|
287 |
+
});
|
288 |
+
|
289 |
+
/**
|
290 |
+
* On staff checkbox click.
|
291 |
+
*/
|
292 |
+
$staff.on('change', function (e) {
|
293 |
+
updateStaffButton();
|
294 |
+
|
295 |
+
$tabs.filter('[data-staff_id=' + this.value + ']').toggle(this.checked);
|
296 |
+
if ($tabs.filter(':visible.active').length == 0) {
|
297 |
+
$tabs.filter(':visible:first').triggerHandler('click');
|
298 |
+
} else if ($tabs.filter('.active').data('staff_id') == 0) {
|
299 |
+
var view = $fullCalendar.fullCalendar('getView');
|
300 |
+
if (view.type == 'multiStaffDay') {
|
301 |
+
view.displayView($fullCalendar.fullCalendar('getDate'));
|
302 |
+
}
|
303 |
+
$fullCalendar.fullCalendar('refetchEvents');
|
304 |
+
}
|
305 |
+
});
|
306 |
+
|
307 |
+
/**
|
308 |
+
* On delete appointment click.
|
309 |
+
*/
|
310 |
+
$deleteButton.on('click', function (e) {
|
311 |
+
var calEvent = $deleteDialog.data('calEvent'),
|
312 |
+
ladda = Ladda.create(this);
|
313 |
+
ladda.start();
|
314 |
+
$.post(
|
315 |
+
ajaxurl,
|
316 |
+
{
|
317 |
+
'action' : 'bookly_delete_appointment',
|
318 |
+
'appointment_id' : calEvent.id,
|
319 |
+
'notify' : $('#bookly-delete-notify').prop('checked') ? 1 : 0,
|
320 |
+
'reason' : $('#bookly-delete-reason').val()
|
321 |
+
},
|
322 |
+
function () {
|
323 |
+
ladda.stop();
|
324 |
+
$fullCalendar.fullCalendar('removeEvents', calEvent.id);
|
325 |
+
$deleteDialog.modal('hide');
|
326 |
+
}
|
327 |
+
);
|
328 |
+
});
|
329 |
+
|
330 |
+
function updateStaffButton() {
|
331 |
+
$showAll.prop('checked', $staff.filter(':not(:checked)').length == 0);
|
332 |
+
|
333 |
+
// Update staffMembers array.
|
334 |
+
var ids = [];
|
335 |
+
staffMembers.length = 0;
|
336 |
+
$staff.filter(':checked').each(function () {
|
337 |
+
staffMembers.push({id: this.value, name: this.getAttribute('data-staff_name')});
|
338 |
+
ids.push(this.value);
|
339 |
+
});
|
340 |
+
setCookie('bookly_cal_st_ids', ids);
|
341 |
+
|
342 |
+
// Update button text.
|
343 |
+
var number = $staff.filter(':checked').length;
|
344 |
+
if (number == 0) {
|
345 |
+
$staffButton.text(BooklyL10n.noStaffSelected);
|
346 |
+
} else if (number == 1) {
|
347 |
+
$staffButton.text($staff.filter(':checked').data('staff_name'));
|
348 |
+
} else {
|
349 |
+
$staffButton.text(number + '/' + $staff.length);
|
350 |
+
}
|
351 |
+
}
|
352 |
+
|
353 |
+
/**
|
354 |
+
* Set cookie.
|
355 |
+
*
|
356 |
+
* @param key
|
357 |
+
* @param value
|
358 |
+
*/
|
359 |
+
function setCookie(key, value) {
|
360 |
+
var expires = new Date();
|
361 |
+
expires.setTime(expires.getTime() + 86400000); // 60 × 60 × 24 × 1000
|
362 |
+
document.cookie = key + '=' + value + ';expires=' + expires.toUTCString();
|
363 |
+
}
|
364 |
+
|
365 |
+
/**
|
366 |
+
* Get cookie.
|
367 |
+
*
|
368 |
+
* @param key
|
369 |
+
* @return {*}
|
370 |
+
*/
|
371 |
+
function getCookie(key) {
|
372 |
+
var keyValue = document.cookie.match('(^|;) ?' + key + '=([^;]*)(;|$)');
|
373 |
+
return keyValue ? keyValue[2] : null;
|
374 |
+
}
|
375 |
+
|
376 |
+
/**
|
377 |
+
* Calculate height of FullCalendar.
|
378 |
+
*
|
379 |
+
* @return {number}
|
380 |
+
*/
|
381 |
+
function heightFC() {
|
382 |
+
var window_height = $(window).height(),
|
383 |
+
wp_admin_bar_height = $('#wpadminbar').height(),
|
384 |
+
ab_calendar_tabs_height = $('#bookly-fc-wrapper .tabbable').outerHeight(true),
|
385 |
+
height_to_reduce = wp_admin_bar_height + ab_calendar_tabs_height,
|
386 |
+
$wrap = $('#wpbody-content .wrap');
|
387 |
+
|
388 |
+
if ($wrap.css('margin-top')) {
|
389 |
+
height_to_reduce += parseInt($wrap.css('margin-top').replace('px', ''), 10);
|
390 |
+
}
|
391 |
+
|
392 |
+
if ($wrap.css('margin-bottom')) {
|
393 |
+
height_to_reduce += parseInt($wrap.css('margin-bottom').replace('px', ''), 10);
|
394 |
+
}
|
395 |
+
|
396 |
+
var res = window_height - height_to_reduce - 130;
|
397 |
+
|
398 |
+
return res > 620 ? res : 620;
|
399 |
+
}
|
400 |
+
|
401 |
});
|
backend/modules/calendar/resources/js/delete_dialog.js
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/**
|
2 |
+
* Scripts for delete dialog
|
3 |
+
*/
|
4 |
+
|
5 |
+
jQuery(function($) {
|
6 |
+
$("#bookly-delete-notify").on('change', function() {
|
7 |
+
$('#bookly-delete-reason-cover').toggle();
|
8 |
+
})
|
9 |
+
});
|
backend/modules/calendar/resources/js/fullcalendar.min.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
-
/*!
|
2 |
-
* FullCalendar v2.4.0
|
3 |
-
* Docs & License: http://fullcalendar.io/
|
4 |
-
* (c) 2015 Adam Shaw
|
5 |
-
*/
|
6 |
-
!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){function c(a){return Q(a,Oa)}function d(b){var c,d={views:b.views||{}};return a.each(b,function(b,e){"views"!=b&&(a.isPlainObject(e)&&!/(time|duration|interval)$/i.test(b)&&-1==a.inArray(b,Oa)?(c=null,a.each(e,function(a,e){/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(a)?(d.views[a]||(d.views[a]={}),d.views[a][b]=e):(c||(c={}),c[a]=e)}),c&&(d[b]=c)):d[b]=e)}),d}function e(a,b){b.left&&a.css({"border-left-width":1,"margin-left":b.left-1}),b.right&&a.css({"border-right-width":1,"margin-right":b.right-1})}function f(a){a.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function g(){a("body").addClass("fc-not-allowed")}function h(){a("body").removeClass("fc-not-allowed")}function i(b,c,d){var e=Math.floor(c/b.length),f=Math.floor(c-e*(b.length-1)),g=[],h=[],i=[],k=0;j(b),b.each(function(c,d){var j=c===b.length-1?f:e,l=a(d).outerHeight(!0);j>l?(g.push(d),h.push(l),i.push(a(d).height())):k+=l}),d&&(c-=k,e=Math.floor(c/g.length),f=Math.floor(c-e*(g.length-1))),a(g).each(function(b,c){var d=b===g.length-1?f:e,j=h[b],k=i[b],l=d-(j-k);d>j&&a(c).height(l)})}function j(a){a.height("")}function k(b){var c=0;return b.find("> *").each(function(b,d){var e=a(d).outerWidth();e>c&&(c=e)}),c++,b.width(c),c}function l(a,b){return a.height(b).addClass("fc-scroller"),a[0].scrollHeight-1>a[0].clientHeight?!0:(m(a),!1)}function m(a){a.height("").removeClass("fc-scroller")}function n(b){var c=b.css("position"),d=b.parents().filter(function(){var b=a(this);return/(auto|scroll)/.test(b.css("overflow")+b.css("overflow-y")+b.css("overflow-x"))}).eq(0);return"fixed"!==c&&d.length?d:a(b[0].ownerDocument||document)}function o(a){var b=a.offset();return{left:b.left,right:b.left+a.outerWidth(),top:b.top,bottom:b.top+a.outerHeight()}}function p(a){var b=a.offset(),c=r(a),d=b.left+u(a,"border-left-width")+c.left,e=b.top+u(a,"border-top-width")+c.top;return{left:d,right:d+a[0].clientWidth,top:e,bottom:e+a[0].clientHeight}}function q(a){var b=a.offset(),c=b.left+u(a,"border-left-width")+u(a,"padding-left"),d=b.top+u(a,"border-top-width")+u(a,"padding-top");return{left:c,right:c+a.width(),top:d,bottom:d+a.height()}}function r(a){var b=a.innerWidth()-a[0].clientWidth,c={left:0,right:0,top:0,bottom:a.innerHeight()-a[0].clientHeight};return s()&&"rtl"==a.css("direction")?c.left=b:c.right=b,c}function s(){return null===Pa&&(Pa=t()),Pa}function t(){var b=a("<div><div/></div>").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),c=b.children(),d=c.offset().left>b.offset().left;return b.remove(),d}function u(a,b){return parseFloat(a.css(b))||0}function v(a){return 1==a.which&&!a.ctrlKey}function w(a,b){var c={left:Math.max(a.left,b.left),right:Math.min(a.right,b.right),top:Math.max(a.top,b.top),bottom:Math.min(a.bottom,b.bottom)};return c.left<c.right&&c.top<c.bottom?c:!1}function x(a,b){return{left:Math.min(Math.max(a.left,b.left),b.right),top:Math.min(Math.max(a.top,b.top),b.bottom)}}function y(a){return{left:(a.left+a.right)/2,top:(a.top+a.bottom)/2}}function z(a,b){return{left:a.left-b.left,top:a.top-b.top}}function A(b){var c,d,e=[],f=[];for("string"==typeof b?f=b.split(/\s*,\s*/):"function"==typeof b?f=[b]:a.isArray(b)&&(f=b),c=0;c<f.length;c++)d=f[c],"string"==typeof d?e.push("-"==d.charAt(0)?{field:d.substring(1),order:-1}:{field:d,order:1}):"function"==typeof d&&e.push({func:d});return e}function B(a,b,c){var d,e;for(d=0;d<c.length;d++)if(e=C(a,b,c[d]))return e;return 0}function C(a,b,c){return c.func?c.func(a,b):D(a[c.field],b[c.field])*(c.order||1)}function D(b,c){return b||c?null==c?-1:null==b?1:"string"===a.type(b)||"string"===a.type(c)?String(b).localeCompare(String(c)):b-c:0}function E(a,b){var c,d,e,f,g=a.start,h=a.end,i=b.start,j=b.end;return h>i&&j>g?(g>=i?(c=g.clone(),e=!0):(c=i.clone(),e=!1),j>=h?(d=h.clone(),f=!0):(d=j.clone(),f=!1),{start:c,end:d,isStart:e,isEnd:f}):void 0}function F(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days"),ms:a.time()-c.time()})}function G(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days")})}function H(a,c,d){return b.duration(Math.round(a.diff(c,d,!0)),d)}function I(a,b){var c,d,e;for(c=0;c<Ra.length&&(d=Ra[c],e=J(d,a,b),!(e>=1&&ba(e)));c++);return d}function J(a,c,d){return null!=d?d.diff(c,a,!0):b.isDuration(c)?c.as(a):c.end.diff(c.start,a,!0)}function K(a,b,c){var d;return N(c)?(b-a)/c:(d=c.asMonths(),Math.abs(d)>=1&&ba(d)?b.diff(a,"months",!0)/d:b.diff(a,"days",!0)/c.asDays())}function L(a,b){var c,d;return N(a)||N(b)?a/b:(c=a.asMonths(),d=b.asMonths(),Math.abs(c)>=1&&ba(c)&&Math.abs(d)>=1&&ba(d)?c/d:a.asDays()/b.asDays())}function M(a,c){var d;return N(a)?b.duration(a*c):(d=a.asMonths(),Math.abs(d)>=1&&ba(d)?b.duration({months:d*c}):b.duration({days:a.asDays()*c}))}function N(a){return Boolean(a.hours()||a.minutes()||a.seconds()||a.milliseconds())}function O(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function P(a){return/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(a)}function Q(a,b){var c,d,e,f,g,h,i={};if(b)for(c=0;c<b.length;c++){for(d=b[c],e=[],f=a.length-1;f>=0;f--)if(g=a[f][d],"object"==typeof g)e.unshift(g);else if(void 0!==g){i[d]=g;break}e.length&&(i[d]=Q(e))}for(c=a.length-1;c>=0;c--){h=a[c];for(d in h)d in i||(i[d]=h[d])}return i}function R(a){var b=function(){};return b.prototype=a,new b}function S(a,b){for(var c in a)U(a,c)&&(b[c]=a[c])}function T(a,b){var c,d,e=["constructor","toString","valueOf"];for(c=0;c<e.length;c++)d=e[c],a[d]!==Object.prototype[d]&&(b[d]=a[d])}function U(a,b){return Va.call(a,b)}function V(b){return/undefined|null|boolean|number|string/.test(a.type(b))}function W(b,c,d){if(a.isFunction(b)&&(b=[b]),b){var e,f;for(e=0;e<b.length;e++)f=b[e].apply(c,d)||f;return f}}function X(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]}function Y(a){return(a+"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function Z(a){return a.replace(/&.*?;/g,"")}function $(b){var c=[];return a.each(b,function(a,b){null!=b&&c.push(a+":"+b)}),c.join(";")}function _(a){return a.charAt(0).toUpperCase()+a.slice(1)}function aa(a,b){return a-b}function ba(a){return a%1===0}function ca(a,b){var c=a[b];return function(){return c.apply(a,arguments)}}function da(a,b){var c,d,e,f,g=function(){var h=+new Date-f;b>h&&h>0?c=setTimeout(g,b-h):(c=null,a.apply(e,d),c||(e=d=null))};return function(){e=this,d=arguments,f=+new Date,c||(c=setTimeout(g,b))}}function ea(c,d,e){var f,g,h,i,j=c[0],k=1==c.length&&"string"==typeof j;return b.isMoment(j)?(i=b.apply(null,c),ga(j,i)):O(j)||void 0===j?i=b.apply(null,c):(f=!1,g=!1,k?Wa.test(j)?(j+="-01",c=[j],f=!0,g=!0):(h=Xa.exec(j))&&(f=!h[5],g=!0):a.isArray(j)&&(g=!0),i=d||f?b.utc.apply(b,c):b.apply(null,c),f?(i._ambigTime=!0,i._ambigZone=!0):e&&(g?i._ambigZone=!0:k&&(i.utcOffset?i.utcOffset(j):i.zone(j)))),i._fullCalendar=!0,i}function fa(a,c){var d,e,f=!1,g=!1,h=a.length,i=[];for(d=0;h>d;d++)e=a[d],b.isMoment(e)||(e=Ma.moment.parseZone(e)),f=f||e._ambigTime,g=g||e._ambigZone,i.push(e);for(d=0;h>d;d++)e=i[d],c||!f||e._ambigTime?g&&!e._ambigZone&&(i[d]=e.clone().stripZone()):i[d]=e.clone().stripTime();return i}function ga(a,b){a._ambigTime?b._ambigTime=!0:b._ambigTime&&(b._ambigTime=!1),a._ambigZone?b._ambigZone=!0:b._ambigZone&&(b._ambigZone=!1)}function ha(a,b){a.year(b[0]||0).month(b[1]||0).date(b[2]||0).hours(b[3]||0).minutes(b[4]||0).seconds(b[5]||0).milliseconds(b[6]||0)}function ia(a,b){return Za.format.call(a,b)}function ja(a,b){return ka(a,pa(b))}function ka(a,b){var c,d="";for(c=0;c<b.length;c++)d+=la(a,b[c]);return d}function la(a,b){var c,d;return"string"==typeof b?b:(c=b.token)?$a[c]?$a[c](a):ia(a,c):b.maybe&&(d=ka(a,b.maybe),d.match(/[1-9]/))?d:""}function ma(a,b,c,d,e){var f;return a=Ma.moment.parseZone(a),b=Ma.moment.parseZone(b),f=(a.localeData||a.lang).call(a),c=f.longDateFormat(c)||c,d=d||" - ",na(a,b,pa(c),d,e)}function na(a,b,c,d,e){var f,g,h,i,j="",k="",l="",m="",n="";for(g=0;g<c.length&&(f=oa(a,b,c[g]),f!==!1);g++)j+=f;for(h=c.length-1;h>g&&(f=oa(a,b,c[h]),f!==!1);h--)k=f+k;for(i=g;h>=i;i++)l+=la(a,c[i]),m+=la(b,c[i]);return(l||m)&&(n=e?m+d+l:l+d+m),j+n+k}function oa(a,b,c){var d,e;return"string"==typeof c?c:(d=c.token)&&(e=_a[d.charAt(0)],e&&a.isSame(b,e))?ia(a,d):!1}function pa(a){return a in ab?ab[a]:ab[a]=qa(a)}function qa(a){for(var b,c=[],d=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;b=d.exec(a);)b[1]?c.push(b[1]):b[2]?c.push({maybe:qa(b[2])}):b[3]?c.push({token:b[3]}):b[5]&&c.push(b[5]);return c}function ra(){}function sa(a,b){return a||b?a&&b?a.grid===b.grid&&a.row===b.row&&a.col===b.col:!1:!0}function ta(a){var b=va(a);return"background"===b||"inverse-background"===b}function ua(a){return"inverse-background"===va(a)}function va(a){return X((a.source||{}).rendering,a.rendering)}function wa(a){var b,c,d={};for(b=0;b<a.length;b++)c=a[b],(d[c._id]||(d[c._id]=[])).push(c);return d}function xa(a,b){return a.eventStartMS-b.eventStartMS}function ya(c){var d,e,f,g,h=Ma.dataAttrPrefix;return h&&(h+="-"),d=c.data(h+"event")||null,d&&(d="object"==typeof d?a.extend({},d):{},e=d.start,null==e&&(e=d.time),f=d.duration,g=d.stick,delete d.start,delete d.time,delete d.duration,delete d.stick),null==e&&(e=c.data(h+"start")),null==e&&(e=c.data(h+"time")),null==f&&(f=c.data(h+"duration")),null==g&&(g=c.data(h+"stick")),e=null!=e?b.duration(e):null,f=null!=f?b.duration(f):null,g=Boolean(g),{eventProps:d,startTime:e,duration:f,stick:g}}function za(a,b){var c,d;for(c=0;c<b.length;c++)if(d=b[c],d.leftCol<=a.rightCol&&d.rightCol>=a.leftCol)return!0;return!1}function Aa(a,b){return a.leftCol-b.leftCol}function Ba(a){var b,c,d,e=[];for(b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&Ea(c,e[d]).length;d++);c.level=d,(e[d]||(e[d]=[])).push(c)}return e}function Ca(a){var b,c,d,e,f;for(b=0;b<a.length;b++)for(c=a[b],d=0;d<c.length;d++)for(e=c[d],e.forwardSegs=[],f=b+1;f<a.length;f++)Ea(e,a[f],e.forwardSegs)}function Da(a){var b,c,d=a.forwardSegs,e=0;if(void 0===a.forwardPressure){for(b=0;b<d.length;b++)c=d[b],Da(c),e=Math.max(e,1+c.forwardPressure);a.forwardPressure=e}}function Ea(a,b,c){c=c||[];for(var d=0;d<b.length;d++)Fa(a,b[d])&&c.push(b[d]);return c}function Fa(a,b){return a.bottom>b.top&&a.top<b.bottom}function Ga(c,d){function e(){U?h()&&(k(),i()):f()}function f(){V=O.theme?"ui":"fc",c.addClass("fc"),O.isRTL?c.addClass("fc-rtl"):c.addClass("fc-ltr"),O.theme?c.addClass("ui-widget"):c.addClass("fc-unthemed"),U=a("<div class='fc-view-container'/>").prependTo(c),S=N.header=new Ja(N,O),T=S.render(),T&&c.prepend(T),i(O.defaultView),O.handleWindowResize&&(Y=da(m,O.windowResizeDelay),a(window).resize(Y))}function g(){W&&W.removeElement(),S.removeElement(),U.remove(),c.removeClass("fc fc-ltr fc-rtl fc-unthemed ui-widget"),Y&&a(window).unbind("resize",Y)}function h(){return c.is(":visible")}function i(b){ca++,W&&b&&W.type!==b&&(S.deactivateButton(W.type),H(),W.removeElement(),W=N.view=null),!W&&b&&(W=N.view=ba[b]||(ba[b]=N.instantiateView(b)),W.setElement(a("<div class='fc-view fc-"+b+"-view' />").appendTo(U)),S.activateButton(b)),W&&(Z=W.massageCurrentDate(Z),W.displaying&&Z.isWithin(W.intervalStart,W.intervalEnd)||h()&&(H(),W.display(Z),I(),u(),v(),q())),I(),ca--}function j(a){return h()?(a&&l(),ca++,W.updateSize(!0),ca--,!0):void 0}function k(){h()&&l()}function l(){X="number"==typeof O.contentHeight?O.contentHeight:"number"==typeof O.height?O.height-(T?T.outerHeight(!0):0):Math.round(U.width()/Math.max(O.aspectRatio,.5))}function m(a){!ca&&a.target===window&&W.start&&j(!0)&&W.trigger("windowResize",aa)}function n(){p(),r()}function o(){h()&&(H(),W.displayEvents(ea),I())}function p(){H(),W.clearEvents(),I()}function q(){!O.lazyFetching||$(W.start,W.end)?r():o()}function r(){_(W.start,W.end)}function s(a){ea=a,o()}function t(){o()}function u(){S.updateTitle(W.title)}function v(){var a=N.getNow();a.isWithin(W.intervalStart,W.intervalEnd)?S.disableButton("today"):S.enableButton("today")}function w(a,b){W.select(N.buildSelectRange.apply(N,arguments))}function x(){W&&W.unselect()}function y(){Z=W.computePrevDate(Z),i()}function z(){Z=W.computeNextDate(Z),i()}function A(){Z.add(-1,"years"),i()}function B(){Z.add(1,"years"),i()}function C(){Z=N.getNow(),i()}function D(a){Z=N.moment(a),i()}function E(a){Z.add(b.duration(a)),i()}function F(a,b){var c;b=b||"day",c=N.getViewSpec(b)||N.getUnitViewSpec(b),Z=a,i(c?c.type:null)}function G(){return Z.clone()}function H(){U.css({width:"100%",height:U.height(),overflow:"hidden"})}function I(){U.css({width:"",height:"",overflow:""})}function J(){return N}function K(){return W}function L(a,b){return void 0===b?O[a]:void(("height"==a||"contentHeight"==a||"aspectRatio"==a)&&(O[a]=b,j(!0)))}function M(a,b){var c=Array.prototype.slice.call(arguments,2);return b=b||aa,this.triggerWith(a,b,c),O[a]?O[a].apply(b,c):void 0}var N=this;N.initOptions(d||{});var O=this.options;N.render=e,N.destroy=g,N.refetchEvents=n,N.reportEvents=s,N.reportEventChange=t,N.rerenderEvents=o,N.changeView=i,N.select=w,N.unselect=x,N.prev=y,N.next=z,N.prevYear=A,N.nextYear=B,N.today=C,N.gotoDate=D,N.incrementDate=E,N.zoomTo=F,N.getDate=G,N.getCalendar=J,N.getView=K,N.option=L,N.trigger=M;var P=R(Ia(O.lang));if(O.monthNames&&(P._months=O.monthNames),O.monthNamesShort&&(P._monthsShort=O.monthNamesShort),O.dayNames&&(P._weekdays=O.dayNames),O.dayNamesShort&&(P._weekdaysShort=O.dayNamesShort),null!=O.firstDay){var Q=R(P._week);Q.dow=O.firstDay,P._week=Q}P._fullCalendar_weekCalc=function(a){return"function"==typeof a?a:"local"===a?a:"iso"===a||"ISO"===a?"ISO":void 0}(O.weekNumberCalculation),N.defaultAllDayEventDuration=b.duration(O.defaultAllDayEventDuration),N.defaultTimedEventDuration=b.duration(O.defaultTimedEventDuration),N.moment=function(){var a;return"local"===O.timezone?(a=Ma.moment.apply(null,arguments),a.hasTime()&&a.local()):a="UTC"===O.timezone?Ma.moment.utc.apply(null,arguments):Ma.moment.parseZone.apply(null,arguments),"_locale"in a?a._locale=P:a._lang=P,a},N.getIsAmbigTimezone=function(){return"local"!==O.timezone&&"UTC"!==O.timezone},N.rezoneDate=function(a){return N.moment(a.toArray())},N.getNow=function(){var a=O.now;return"function"==typeof a&&(a=a()),N.moment(a)},N.getEventEnd=function(a){return a.end?a.end.clone():N.getDefaultEventEnd(a.allDay,a.start)},N.getDefaultEventEnd=function(a,b){var c=b.clone();return a?c.stripTime().add(N.defaultAllDayEventDuration):c.add(N.defaultTimedEventDuration),N.getIsAmbigTimezone()&&c.stripZone(),c},N.humanizeDuration=function(a){return(a.locale||a.lang).call(a,O.lang).humanize()},Ka.call(N,O);var S,T,U,V,W,X,Y,Z,$=N.isFetchNeeded,_=N.fetchEvents,aa=c[0],ba={},ca=0,ea=[];Z=null!=O.defaultDate?N.moment(O.defaultDate):N.getNow(),N.getSuggestedViewHeight=function(){return void 0===X&&k(),X},N.isHeightAuto=function(){return"auto"===O.contentHeight||"auto"===O.height},N.initialize()}function Ha(b){a.each(rb,function(a,c){null==b[a]&&(b[a]=c(b))})}function Ia(a){var c=b.localeData||b.langData;return c.call(b,a)||c.call(b,"en")}function Ja(b,c){function d(){var b=c.header;return n=c.theme?"ui":"fc",b?o=a("<div class='fc-toolbar'/>").append(f("left")).append(f("right")).append(f("center")).append('<div class="fc-clear"/>'):void 0}function e(){o.remove(),o=a()}function f(d){var e=a('<div class="fc-'+d+'"/>'),f=c.header[d];return f&&a.each(f.split(" "),function(d){var f,g=a(),h=!0;a.each(this.split(","),function(d,e){var f,i,j,k,l,m,o,q,r,s;"title"==e?(g=g.add(a("<h2> </h2>")),h=!1):((f=(b.options.customButtons||{})[e])?(j=function(a){f.click&&f.click.call(s[0],a)},k="",l=f.text):(i=b.getViewSpec(e))?(j=function(){b.changeView(e)},p.push(e),k=i.buttonTextOverride,l=i.buttonTextDefault):b[e]&&(j=function(){b[e]()},k=(b.overrides.buttonText||{})[e],l=c.buttonText[e]),j&&(m=f?f.themeIcon:c.themeButtonIcons[e],o=f?f.icon:c.buttonIcons[e],q=k?Y(k):m&&c.theme?"<span class='ui-icon ui-icon-"+m+"'></span>":o&&!c.theme?"<span class='fc-icon fc-icon-"+o+"'></span>":Y(l),r=["fc-"+e+"-button",n+"-button",n+"-state-default"],s=a('<button type="button" class="'+r.join(" ")+'">'+q+"</button>").click(function(a){s.hasClass(n+"-state-disabled")||(j(a),(s.hasClass(n+"-state-active")||s.hasClass(n+"-state-disabled"))&&s.removeClass(n+"-state-hover"))}).mousedown(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-down")}).mouseup(function(){s.removeClass(n+"-state-down")}).hover(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-hover")},function(){s.removeClass(n+"-state-hover").removeClass(n+"-state-down")}),g=g.add(s)))}),h&&g.first().addClass(n+"-corner-left").end().last().addClass(n+"-corner-right").end(),g.length>1?(f=a("<div/>"),h&&f.addClass("fc-button-group"),f.append(g),e.append(f)):e.append(g)}),e}function g(a){o.find("h2").text(a)}function h(a){o.find(".fc-"+a+"-button").addClass(n+"-state-active")}function i(a){o.find(".fc-"+a+"-button").removeClass(n+"-state-active")}function j(a){o.find(".fc-"+a+"-button").attr("disabled","disabled").addClass(n+"-state-disabled")}function k(a){o.find(".fc-"+a+"-button").removeAttr("disabled").removeClass(n+"-state-disabled")}function l(){return p}var m=this;m.render=d,m.removeElement=e,m.updateTitle=g,m.activateButton=h,m.deactivateButton=i,m.disableButton=j,m.enableButton=k,m.getViewsWithButtons=l;var n,o=a(),p=[]}function Ka(c){function d(a,b){return!M||a.clone().stripZone()<M.clone().stripZone()||b.clone().stripZone()>N.clone().stripZone()}function e(a,b){M=a,N=b,U=[];var c=++S,d=R.length;T=d;for(var e=0;d>e;e++)f(R[e],c)}function f(b,c){g(b,function(d){var e,f,g,h=a.isArray(b.events);if(c==S){if(d)for(e=0;e<d.length;e++)f=d[e],g=h?f:s(f,b),g&&U.push.apply(U,x(g));T--,T||O(U)}})}function g(b,d){var e,f,h=Ma.sourceFetchers;for(e=0;e<h.length;e++){if(f=h[e].call(L,b,M.clone(),N.clone(),c.timezone,d),f===!0)return;if("object"==typeof f)return void g(f,d)}var i=b.events;if(i)a.isFunction(i)?(L.pushLoading(),i.call(L,M.clone(),N.clone(),c.timezone,function(a){d(a),L.popLoading()})):a.isArray(i)?d(i):d();else{var j=b.url;if(j){var k,l=b.success,m=b.error,n=b.complete;k=a.isFunction(b.data)?b.data():b.data;var o=a.extend({},k||{}),p=X(b.startParam,c.startParam),q=X(b.endParam,c.endParam),r=X(b.timezoneParam,c.timezoneParam);p&&(o[p]=M.format()),q&&(o[q]=N.format()),c.timezone&&"local"!=c.timezone&&(o[r]=c.timezone),L.pushLoading(),a.ajax(a.extend({},sb,b,{data:o,success:function(b){b=b||[];var c=W(l,this,arguments);a.isArray(c)&&(b=c),d(b)},error:function(){W(m,this,arguments),d()},complete:function(){W(n,this,arguments),L.popLoading()}}))}else d()}}function h(a){var b=i(a);b&&(R.push(b),T++,f(b,S))}function i(b){var c,d,e=Ma.sourceNormalizers;if(a.isFunction(b)||a.isArray(b)?c={events:b}:"string"==typeof b?c={url:b}:"object"==typeof b&&(c=a.extend({},b)),c){for(c.className?"string"==typeof c.className&&(c.className=c.className.split(/\s+/)):c.className=[],a.isArray(c.events)&&(c.origArray=c.events,c.events=a.map(c.events,function(a){return s(a,c)})),d=0;d<e.length;d++)e[d].call(L,c);return c}}function j(b){R=a.grep(R,function(a){return!k(a,b)}),U=a.grep(U,function(a){return!k(a.source,b)}),O(U)}function k(a,b){return a&&b&&l(a)==l(b)}function l(a){return("object"==typeof a?a.origArray||a.googleCalendarId||a.url||a.events:null)||a}function m(a){a.start=L.moment(a.start),a.end?a.end=L.moment(a.end):a.end=null,y(a,n(a)),O(U)}function n(b){var c={};return a.each(b,function(a,b){o(a)&&void 0!==b&&V(b)&&(c[a]=b)}),c}function o(a){return!/^_|^(id|allDay|start|end)$/.test(a)}function p(a,b){var c,d,e,f=s(a);if(f){for(c=x(f),d=0;d<c.length;d++)e=c[d],e.source||(b&&(Q.events.push(e),e.source=Q),U.push(e));return O(U),c}return[]}function q(b){var c,d;for(null==b?b=function(){return!0}:a.isFunction(b)||(c=b+"",b=function(a){return a._id==c}),U=a.grep(U,b,!0),d=0;d<R.length;d++)a.isArray(R[d].events)&&(R[d].events=a.grep(R[d].events,b,!0));O(U)}function r(b){return a.isFunction(b)?a.grep(U,b):null!=b?(b+="",a.grep(U,function(a){return a._id==b})):U}function s(d,e){var f,g,h,i={};if(c.eventDataTransform&&(d=c.eventDataTransform(d)),e&&e.eventDataTransform&&(d=e.eventDataTransform(d)),a.extend(i,d),e&&(i.source=e),i._id=d._id||(void 0===d.id?"_fc"+tb++:d.id+""),d.className?"string"==typeof d.className?i.className=d.className.split(/\s+/):i.className=d.className:i.className=[],f=d.start||d.date,g=d.end,P(f)&&(f=b.duration(f)),P(g)&&(g=b.duration(g)),d.dow||b.isDuration(f)||b.isDuration(g))i.start=f?b.duration(f):null,i.end=g?b.duration(g):null,i._recurring=!0;else{if(f&&(f=L.moment(f),!f.isValid()))return!1;g&&(g=L.moment(g),g.isValid()||(g=null)),h=d.allDay,void 0===h&&(h=X(e?e.allDayDefault:void 0,c.allDayDefault)),t(f,g,h,i)}return i}function t(a,b,c,d){d.start=a,d.end=b,d.allDay=c,u(d),La(d)}function u(a){v(a),a.end&&!a.end.isAfter(a.start)&&(a.end=null),a.end||(c.forceEventDuration?a.end=L.getDefaultEventEnd(a.allDay,a.start):a.end=null)}function v(a){null==a.allDay&&(a.allDay=!(a.start.hasTime()||a.end&&a.end.hasTime())),a.allDay?(a.start.stripTime(),a.end&&a.end.stripTime()):(a.start.hasTime()||(a.start=L.rezoneDate(a.start)),a.end&&!a.end.hasTime()&&(a.end=L.rezoneDate(a.end)))}function w(b){var c;return b.end||(c=b.allDay,null==c&&(c=!b.start.hasTime()),b=a.extend({},b),b.end=L.getDefaultEventEnd(c,b.start)),b}function x(b,c,d){var e,f,g,h,i,j,k,l,m,n=[];if(c=c||M,d=d||N,b)if(b._recurring){if(f=b.dow)for(e={},g=0;g<f.length;g++)e[f[g]]=!0;for(h=c.clone().stripTime();h.isBefore(d);)(!e||e[h.day()])&&(i=b.start,j=b.end,k=h.clone(),l=null,i&&(k=k.time(i)),j&&(l=h.clone().time(j)),m=a.extend({},b),t(k,l,!i&&!j,m),n.push(m)),h.add(1,"days")}else n.push(b);return n}function y(b,c,d){function e(a,b){return d?H(a,b,d):c.allDay?G(a,b):F(a,b)}var f,g,h,i,j,k,l={};return c=c||{},c.start||(c.start=b.start.clone()),void 0===c.end&&(c.end=b.end?b.end.clone():null),null==c.allDay&&(c.allDay=b.allDay),u(c),f={start:b._start.clone(),end:b._end?b._end.clone():L.getDefaultEventEnd(b._allDay,b._start),allDay:c.allDay},u(f),g=null!==b._end&&null===c.end,h=e(c.start,f.start),c.end?(i=e(c.end,f.end),j=i.subtract(h)):j=null,a.each(c,function(a,b){o(a)&&void 0!==b&&(l[a]=b)}),k=z(r(b._id),g,c.allDay,h,j,l),{dateDelta:h,durationDelta:j,undo:k}}function z(b,c,d,e,f,g){var h=L.getIsAmbigTimezone(),i=[];return e&&!e.valueOf()&&(e=null),f&&!f.valueOf()&&(f=null),a.each(b,function(b,j){var k,l;k={start:j.start.clone(),end:j.end?j.end.clone():null,allDay:j.allDay},a.each(g,function(a){k[a]=j[a]}),l={start:j._start,end:j._end,allDay:d},u(l),c?l.end=null:f&&!l.end&&(l.end=L.getDefaultEventEnd(l.allDay,l.start)),e&&(l.start.add(e),l.end&&l.end.add(e)),f&&l.end.add(f),h&&!l.allDay&&(e||f)&&(l.start.stripZone(),l.end&&l.end.stripZone()),a.extend(j,g,l),La(j),i.push(function(){a.extend(j,k),La(j)})}),function(){for(var a=0;a<i.length;a++)i[a]()}}function A(b){var d,e=c.businessHours,f={className:"fc-nonbusiness",start:"09:00",end:"17:00",dow:[1,2,3,4,5],rendering:"inverse-background"},g=L.getView();return e&&(d=a.extend({},f,"object"==typeof e?e:{})),d?(b&&(d.start=null,d.end=null),x(s(d),g.start,g.end)):[]}function B(a,b){var d=b.source||{},e=X(b.constraint,d.constraint,c.eventConstraint),f=X(b.overlap,d.overlap,c.eventOverlap);return a=w(a),E(a,e,f,b)}function C(a){return E(a,c.selectConstraint,c.selectOverlap)}function D(b,c){var d,e;return c&&(d=a.extend({},c,b),e=x(s(d))[0]),e?B(b,e):(b=w(b),C(b))}function E(b,c,d,e){var f,g,h,i,j,k;if(b=a.extend({},b),b.start=b.start.clone().stripZone(),b.end=b.end.clone().stripZone(),null!=c){for(f=I(c),g=!1,i=0;i<f.length;i++)if(J(f[i],b)){g=!0;break}if(!g)return!1}for(h=L.getPeerEvents(e,b),i=0;i<h.length;i++)if(j=h[i],K(j,b)){if(d===!1)return!1;if("function"==typeof d&&!d(j,e))return!1;if(e){if(k=X(j.overlap,(j.source||{}).overlap),k===!1)return!1;if("function"==typeof k&&!k(e,j))return!1}}return!0}function I(a){return"businessHours"===a?A():"object"==typeof a?x(s(a)):r(a)}function J(a,b){var c=a.start.clone().stripZone(),d=L.getEventEnd(a).stripZone();return b.start>=c&&b.end<=d}function K(a,b){var c=a.start.clone().stripZone(),d=L.getEventEnd(a).stripZone();return b.start<d&&b.end>c}var L=this;L.isFetchNeeded=d,L.fetchEvents=e,L.addEventSource=h,L.removeEventSource=j,L.updateEvent=m,L.renderEvent=p,L.removeEvents=q,L.clientEvents=r,L.mutateEvent=y,L.normalizeEventRange=u,L.normalizeEventRangeTimes=v,L.ensureVisibleEventRange=w;var M,N,O=L.reportEvents,Q={events:[]},R=[Q],S=0,T=0,U=[];a.each((c.events?[c.events]:[]).concat(c.eventSources||[]),function(a,b){var c=i(b);c&&R.push(c)}),L.getBusinessHoursEvents=A,L.isEventRangeAllowed=B,L.isSelectionRangeAllowed=C,L.isExternalDropRangeAllowed=D,L.getEventCache=function(){return U}}function La(a){a._allDay=a.allDay,a._start=a.start.clone(),a._end=a.end?a.end.clone():null}var Ma=a.fullCalendar={version:"2.4.0"},Na=Ma.views={};a.fn.fullCalendar=function(b){var c=Array.prototype.slice.call(arguments,1),d=this;return this.each(function(e,f){var g,h=a(f),i=h.data("fullCalendar");"string"==typeof b?i&&a.isFunction(i[b])&&(g=i[b].apply(i,c),e||(d=g),"destroy"===b&&h.removeData("fullCalendar")):i||(i=new nb(h,b),h.data("fullCalendar",i),i.render())}),d};var Oa=["header","buttonText","buttonIcons","themeButtonIcons"];Ma.intersectionToSeg=E,Ma.applyAll=W,Ma.debounce=da,Ma.isInt=ba,Ma.htmlEscape=Y,Ma.cssToStr=$,Ma.proxy=ca,Ma.capitaliseFirstLetter=_,Ma.getClientRect=p,Ma.getContentRect=q,Ma.getScrollbarWidths=r;var Pa=null;Ma.intersectRects=w,Ma.parseFieldSpecs=A,Ma.compareByFieldSpecs=B,Ma.compareByFieldSpec=C,Ma.flexibleCompare=D,Ma.computeIntervalUnit=I,Ma.divideRangeByDuration=K,Ma.divideDurationByDuration=L,Ma.multiplyDuration=M,Ma.durationHasTime=N;var Qa=["sun","mon","tue","wed","thu","fri","sat"],Ra=["year","month","week","day","hour","minute","second","millisecond"];Ma.log=function(){var a=window.console;return a&&a.log?a.log.apply(a,arguments):void 0},Ma.warn=function(){var a=window.console;return a&&a.warn?a.warn.apply(a,arguments):Ma.log.apply(Ma,arguments)};var Sa,Ta,Ua,Va={}.hasOwnProperty,Wa=/^\s*\d{4}-\d\d$/,Xa=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,Ya=b.fn,Za=a.extend({},Ya);Ma.moment=function(){return ea(arguments)},Ma.moment.utc=function(){var a=ea(arguments,!0);return a.hasTime()&&a.utc(),a},Ma.moment.parseZone=function(){return ea(arguments,!0,!0)},Ya.clone=function(){var a=Za.clone.apply(this,arguments);return ga(this,a),this._fullCalendar&&(a._fullCalendar=!0),a},Ya.week=Ya.weeks=function(a){var b=(this._locale||this._lang)._fullCalendar_weekCalc;return null==a&&"function"==typeof b?b(this):"ISO"===b?Za.isoWeek.apply(this,arguments):Za.week.apply(this,arguments)},Ya.time=function(a){if(!this._fullCalendar)return Za.time.apply(this,arguments);if(null==a)return b.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,b.isDuration(a)||b.isMoment(a)||(a=b.duration(a));var c=0;return b.isDuration(a)&&(c=24*Math.floor(a.asDays())),this.hours(c+a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds())},Ya.stripTime=function(){var a;return this._ambigTime||(a=this.toArray(),this.utc(),Ta(this,a.slice(0,3)),this._ambigTime=!0,this._ambigZone=!0),this},Ya.hasTime=function(){return!this._ambigTime},Ya.stripZone=function(){var a,b;return this._ambigZone||(a=this.toArray(),b=this._ambigTime,this.utc(),Ta(this,a),this._ambigTime=b||!1,this._ambigZone=!0),this},Ya.hasZone=function(){return!this._ambigZone},Ya.local=function(){var a=this.toArray(),b=this._ambigZone;return Za.local.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,b&&Ua(this,a),this},Ya.utc=function(){return Za.utc.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,this},a.each(["zone","utcOffset"],function(a,b){Za[b]&&(Ya[b]=function(a){return null!=a&&(this._ambigTime=!1,this._ambigZone=!1),Za[b].apply(this,arguments)})}),Ya.format=function(){return this._fullCalendar&&arguments[0]?ja(this,arguments[0]):this._ambigTime?ia(this,"YYYY-MM-DD"):this._ambigZone?ia(this,"YYYY-MM-DD[T]HH:mm:ss"):Za.format.apply(this,arguments)},Ya.toISOString=function(){return this._ambigTime?ia(this,"YYYY-MM-DD"):this._ambigZone?ia(this,"YYYY-MM-DD[T]HH:mm:ss"):Za.toISOString.apply(this,arguments)},Ya.isWithin=function(a,b){var c=fa([this,a,b]);return c[0]>=c[1]&&c[0]<c[2]},Ya.isSame=function(a,b){var c;return this._fullCalendar?b?(c=fa([this,a],!0),Za.isSame.call(c[0],c[1],b)):(a=Ma.moment.parseZone(a),Za.isSame.call(this,a)&&Boolean(this._ambigTime)===Boolean(a._ambigTime)&&Boolean(this._ambigZone)===Boolean(a._ambigZone)):Za.isSame.apply(this,arguments)},a.each(["isBefore","isAfter"],function(a,b){Ya[b]=function(a,c){var d;return this._fullCalendar?(d=fa([this,a]),Za[b].call(d[0],d[1],c)):Za[b].apply(this,arguments)}}),Sa="_d"in b()&&"updateOffset"in b,Ta=Sa?function(a,c){a._d.setTime(Date.UTC.apply(Date,c)),b.updateOffset(a,!1)}:ha,Ua=Sa?function(a,c){a._d.setTime(+new Date(c[0]||0,c[1]||0,c[2]||0,c[3]||0,c[4]||0,c[5]||0,c[6]||0)),b.updateOffset(a,!1)}:ha;var $a={t:function(a){return ia(a,"a").charAt(0)},T:function(a){return ia(a,"A").charAt(0)}};Ma.formatRange=ma;var _a={Y:"year",M:"month",D:"day",d:"day",A:"second",a:"second",T:"second",t:"second",H:"second",h:"second",m:"second",s:"second"},ab={};Ma.Class=ra,ra.extend=function(a){var b,c=this;return a=a||{},U(a,"constructor")&&(b=a.constructor),"function"!=typeof b&&(b=a.constructor=function(){c.apply(this,arguments)}),b.prototype=R(c.prototype),S(a,b.prototype),T(a,b.prototype),S(c,b),b},ra.mixin=function(a){S(a.prototype||a,this.prototype)};var bb=Ma.Emitter=ra.extend({callbackHash:null,on:function(a,b){return this.getCallbacks(a).add(b),this},off:function(a,b){return this.getCallbacks(a).remove(b),this},trigger:function(a){var b=Array.prototype.slice.call(arguments,1);return this.triggerWith(a,this,b),this},triggerWith:function(a,b,c){var d=this.getCallbacks(a);return d.fireWith(b,c),this},getCallbacks:function(b){var c;return this.callbackHash||(this.callbackHash={}),c=this.callbackHash[b],c||(c=this.callbackHash[b]=a.Callbacks()),c}}),cb=ra.extend({isHidden:!0,options:null,el:null,documentMousedownProxy:null,margin:10,constructor:function(a){this.options=a||{}},show:function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},hide:function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},render:function(){var b=this,c=this.options;this.el=a('<div class="fc-popover"/>').addClass(c.className||"").css({top:0,left:0}).append(c.content).appendTo(c.parentEl),this.el.on("click",".fc-close",function(){b.hide()}),c.autoHide&&a(document).on("mousedown",this.documentMousedownProxy=ca(this,"documentMousedown"))},documentMousedown:function(b){this.el&&!a(b.target).closest(this.el).length&&this.hide()},removeElement:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),a(document).off("mousedown",this.documentMousedownProxy)},position:function(){var b,c,d,e,f,g=this.options,h=this.el.offsetParent().offset(),i=this.el.outerWidth(),j=this.el.outerHeight(),k=a(window),l=n(this.el);e=g.top||0,f=void 0!==g.left?g.left:void 0!==g.right?g.right-i:0,l.is(window)||l.is(document)?(l=k,b=0,c=0):(d=l.offset(),b=d.top,c=d.left),b+=k.scrollTop(),c+=k.scrollLeft(),g.viewportConstrain!==!1&&(e=Math.min(e,b+l.outerHeight()-j-this.margin),e=Math.max(e,b+this.margin),f=Math.min(f,c+l.outerWidth()-i-this.margin),f=Math.max(f,c+this.margin)),this.el.css({top:e-h.top,left:f-h.left})},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1));
|
7 |
-
}}),db=ra.extend({grid:null,rowCoords:null,colCoords:null,containerEl:null,bounds:null,constructor:function(a){this.grid=a},build:function(){this.grid.build(),this.rowCoords=this.grid.computeRowCoords(),this.colCoords=this.grid.computeColCoords(),this.computeBounds()},clear:function(){this.grid.clear(),this.rowCoords=null,this.colCoords=null},getCell:function(b,c){var d,e,f,g=this.rowCoords,h=g.length,i=this.colCoords,j=i.length,k=null,l=null;if(this.inBounds(b,c)){for(d=0;h>d;d++)if(e=g[d],c>=e.top&&c<e.bottom){k=d;break}for(d=0;j>d;d++)if(e=i[d],b>=e.left&&b<e.right){l=d;break}if(null!==k&&null!==l)return f=this.grid.getCell(k,l),f.grid=this.grid,a.extend(f,g[k],i[l]),f}return null},computeBounds:function(){this.bounds=this.containerEl?p(this.containerEl):null},inBounds:function(a,b){var c=this.bounds;return c?a>=c.left&&a<c.right&&b>=c.top&&b<c.bottom:!0}}),eb=ra.extend({coordMaps:null,constructor:function(a){this.coordMaps=a},build:function(){var a,b=this.coordMaps;for(a=0;a<b.length;a++)b[a].build()},getCell:function(a,b){var c,d=this.coordMaps,e=null;for(c=0;c<d.length&&!e;c++)e=d[c].getCell(a,b);return e},clear:function(){var a,b=this.coordMaps;for(a=0;a<b.length;a++)b[a].clear()}}),fb=Ma.DragListener=ra.extend({options:null,isListening:!1,isDragging:!1,originX:null,originY:null,mousemoveProxy:null,mouseupProxy:null,subjectEl:null,subjectHref:null,scrollEl:null,scrollBounds:null,scrollTopVel:null,scrollLeftVel:null,scrollIntervalId:null,scrollHandlerProxy:null,scrollSensitivity:30,scrollSpeed:200,scrollIntervalMs:50,constructor:function(a){a=a||{},this.options=a,this.subjectEl=a.subjectEl},mousedown:function(a){v(a)&&(a.preventDefault(),this.startListening(a),this.options.distance||this.startDrag(a))},startListening:function(b){var c;this.isListening||(b&&this.options.scroll&&(c=n(a(b.target)),c.is(window)||c.is(document)||(this.scrollEl=c,this.scrollHandlerProxy=da(ca(this,"scrollHandler"),100),this.scrollEl.on("scroll",this.scrollHandlerProxy))),a(document).on("mousemove",this.mousemoveProxy=ca(this,"mousemove")).on("mouseup",this.mouseupProxy=ca(this,"mouseup")).on("selectstart",this.preventDefault),b?(this.originX=b.pageX,this.originY=b.pageY):(this.originX=0,this.originY=0),this.isListening=!0,this.listenStart(b))},listenStart:function(a){this.trigger("listenStart",a)},mousemove:function(a){var b,c,d=a.pageX-this.originX,e=a.pageY-this.originY;this.isDragging||(b=this.options.distance||1,c=d*d+e*e,c>=b*b&&this.startDrag(a)),this.isDragging&&this.drag(d,e,a)},startDrag:function(a){this.isListening||this.startListening(),this.isDragging||(this.isDragging=!0,this.dragStart(a))},dragStart:function(a){var b=this.subjectEl;this.trigger("dragStart",a),(this.subjectHref=b?b.attr("href"):null)&&b.removeAttr("href")},drag:function(a,b,c){this.trigger("drag",a,b,c),this.updateScroll(c)},mouseup:function(a){this.stopListening(a)},stopDrag:function(a){this.isDragging&&(this.stopScrolling(),this.dragStop(a),this.isDragging=!1)},dragStop:function(a){var b=this;this.trigger("dragStop",a),setTimeout(function(){b.subjectHref&&b.subjectEl.attr("href",b.subjectHref)},0)},stopListening:function(b){this.stopDrag(b),this.isListening&&(this.scrollEl&&(this.scrollEl.off("scroll",this.scrollHandlerProxy),this.scrollHandlerProxy=null),a(document).off("mousemove",this.mousemoveProxy).off("mouseup",this.mouseupProxy).off("selectstart",this.preventDefault),this.mousemoveProxy=null,this.mouseupProxy=null,this.isListening=!1,this.listenStop(b))},listenStop:function(a){this.trigger("listenStop",a)},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1))},preventDefault:function(a){a.preventDefault()},computeScrollBounds:function(){var a=this.scrollEl;this.scrollBounds=a?o(a):null},updateScroll:function(a){var b,c,d,e,f=this.scrollSensitivity,g=this.scrollBounds,h=0,i=0;g&&(b=(f-(a.pageY-g.top))/f,c=(f-(g.bottom-a.pageY))/f,d=(f-(a.pageX-g.left))/f,e=(f-(g.right-a.pageX))/f,b>=0&&1>=b?h=b*this.scrollSpeed*-1:c>=0&&1>=c&&(h=c*this.scrollSpeed),d>=0&&1>=d?i=d*this.scrollSpeed*-1:e>=0&&1>=e&&(i=e*this.scrollSpeed)),this.setScrollVel(h,i)},setScrollVel:function(a,b){this.scrollTopVel=a,this.scrollLeftVel=b,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(ca(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var a=this.scrollEl;this.scrollTopVel<0?a.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&a.scrollTop()+a[0].clientHeight>=a[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?a.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&a.scrollLeft()+a[0].clientWidth>=a[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var a=this.scrollEl,b=this.scrollIntervalMs/1e3;this.scrollTopVel&&a.scrollTop(a.scrollTop()+this.scrollTopVel*b),this.scrollLeftVel&&a.scrollLeft(a.scrollLeft()+this.scrollLeftVel*b),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.stopScrolling()},stopScrolling:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.scrollStop())},scrollHandler:function(){this.scrollIntervalId||this.scrollStop()},scrollStop:function(){}}),gb=fb.extend({coordMap:null,origCell:null,cell:null,coordAdjust:null,constructor:function(a,b){fb.prototype.constructor.call(this,b),this.coordMap=a},listenStart:function(a){var b,c,d,e=this.subjectEl;fb.prototype.listenStart.apply(this,arguments),this.computeCoords(),a?(c={left:a.pageX,top:a.pageY},d=c,e&&(b=o(e),d=x(d,b)),this.origCell=this.getCell(d.left,d.top),e&&this.options.subjectCenter&&(this.origCell&&(b=w(this.origCell,b)||b),d=y(b)),this.coordAdjust=z(d,c)):(this.origCell=null,this.coordAdjust=null)},computeCoords:function(){this.coordMap.build(),this.computeScrollBounds()},dragStart:function(a){var b;fb.prototype.dragStart.apply(this,arguments),b=this.getCell(a.pageX,a.pageY),b&&this.cellOver(b)},drag:function(a,b,c){var d;fb.prototype.drag.apply(this,arguments),d=this.getCell(c.pageX,c.pageY),sa(d,this.cell)||(this.cell&&this.cellOut(),d&&this.cellOver(d))},dragStop:function(){this.cellDone(),fb.prototype.dragStop.apply(this,arguments)},cellOver:function(a){this.cell=a,this.trigger("cellOver",a,sa(a,this.origCell),this.origCell)},cellOut:function(){this.cell&&(this.trigger("cellOut",this.cell),this.cellDone(),this.cell=null)},cellDone:function(){this.cell&&this.trigger("cellDone",this.cell)},listenStop:function(){fb.prototype.listenStop.apply(this,arguments),this.origCell=this.cell=null,this.coordMap.clear()},scrollStop:function(){fb.prototype.scrollStop.apply(this,arguments),this.computeCoords()},getCell:function(a,b){return this.coordAdjust&&(a+=this.coordAdjust.left,b+=this.coordAdjust.top),this.coordMap.getCell(a,b)}}),hb=ra.extend({options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,mouseY0:null,mouseX0:null,topDelta:null,leftDelta:null,mousemoveProxy:null,isFollowing:!1,isHidden:!1,isAnimating:!1,constructor:function(b,c){this.options=c=c||{},this.sourceEl=b,this.parentEl=c.parentEl?a(c.parentEl):b.parent()},start:function(b){this.isFollowing||(this.isFollowing=!0,this.mouseY0=b.pageY,this.mouseX0=b.pageX,this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),a(document).on("mousemove",this.mousemoveProxy=ca(this,"mousemove")))},stop:function(b,c){function d(){this.isAnimating=!1,e.removeElement(),this.top0=this.left0=null,c&&c()}var e=this,f=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,a(document).off("mousemove",this.mousemoveProxy),b&&f&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:f,complete:d})):d())},getEl:function(){var a=this.el;return a||(this.sourceEl.width(),a=this.el=this.sourceEl.clone().css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}).appendTo(this.parentEl)),a},removeElement:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var a,b;this.getEl(),null===this.top0&&(this.sourceEl.width(),a=this.sourceEl.offset(),b=this.el.offsetParent().offset(),this.top0=a.top-b.top,this.left0=a.left-b.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},mousemove:function(a){this.topDelta=a.pageY-this.mouseY0,this.leftDelta=a.pageX-this.mouseX0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}}),ib=ra.extend({view:null,isRTL:null,cellHtml:"<td/>",constructor:function(a){this.view=a,this.isRTL=a.opt("isRTL")},rowHtml:function(a,b){var c,d,e=this.getHtmlRenderer("cell",a),f="";for(b=b||0,c=0;c<this.colCnt;c++)d=this.getCell(b,c),f+=e(d);return f=this.bookendCells(f,a,b),"<tr>"+f+"</tr>"},bookendCells:function(a,b,c){var d=this.getHtmlRenderer("intro",b)(c||0),e=this.getHtmlRenderer("outro",b)(c||0),f=this.isRTL?e:d,g=this.isRTL?d:e;return"string"==typeof a?f+a+g:a.prepend(f).append(g)},getHtmlRenderer:function(a,b){var c,d,e,f,g=this.view;return c=a+"Html",b&&(d=b+_(a)+"Html"),d&&(f=g[d])?e=g:d&&(f=this[d])?e=this:(f=g[c])?e=g:(f=this[c])&&(e=this),"function"==typeof f?function(){return f.apply(e,arguments)||""}:function(){return f||""}}}),jb=Ma.Grid=ib.extend({start:null,end:null,rowCnt:0,colCnt:0,el:null,coordMap:null,elsByFill:null,externalDragStartProxy:null,colHeadFormat:null,eventTimeFormat:null,displayEventTime:null,displayEventEnd:null,cellDuration:null,largeUnit:null,constructor:function(){ib.apply(this,arguments),this.coordMap=new db(this),this.elsByFill={},this.externalDragStartProxy=ca(this,"externalDragStart")},computeColHeadFormat:function(){},computeEventTimeFormat:function(){return this.view.opt("smallTimeFormat")},computeDisplayEventTime:function(){return!0},computeDisplayEventEnd:function(){return!0},setRange:function(a){this.start=a.start.clone(),this.end=a.end.clone(),this.rangeUpdated(),this.processRangeOptions()},rangeUpdated:function(){},processRangeOptions:function(){var a,b,c=this.view;this.colHeadFormat=c.opt("columnFormat")||this.computeColHeadFormat(),this.eventTimeFormat=c.opt("eventTimeFormat")||c.opt("timeFormat")||this.computeEventTimeFormat(),a=c.opt("displayEventTime"),null==a&&(a=this.computeDisplayEventTime()),b=c.opt("displayEventEnd"),null==b&&(b=this.computeDisplayEventEnd()),this.displayEventTime=a,this.displayEventEnd=b},build:function(){},clear:function(){},rangeToSegs:function(a){},diffDates:function(a,b){return this.largeUnit?H(a,b,this.largeUnit):F(a,b)},getCell:function(b,c){var d;return null==c&&("number"==typeof b?(c=b%this.colCnt,b=Math.floor(b/this.colCnt)):(c=b.col,b=b.row)),d={row:b,col:c},a.extend(d,this.getRowData(b),this.getColData(c)),a.extend(d,this.computeCellRange(d)),d},computeCellRange:function(a){var b=this.computeCellDate(a);return{start:b,end:b.clone().add(this.cellDuration)}},computeCellDate:function(a){},getRowData:function(a){return{}},getColData:function(a){return{}},getRowEl:function(a){},getColEl:function(a){},getCellDayEl:function(a){return this.getColEl(a.col)||this.getRowEl(a.row)},computeRowCoords:function(){var a,b,c,d=[];for(a=0;a<this.rowCnt;a++)b=this.getRowEl(a),c=b.offset().top,d.push({top:c,bottom:c+b.outerHeight()});return d},computeColCoords:function(){var a,b,c,d=[];for(a=0;a<this.colCnt;a++)b=this.getColEl(a),c=b.offset().left,d.push({left:c,right:c+b.outerWidth()});return d},setElement:function(b){var c=this;this.el=b,b.on("mousedown",function(b){a(b.target).is(".fc-event-container *, .fc-more")||a(b.target).closest(".fc-popover").length||c.dayMousedown(b)}),this.bindSegHandlers(),this.bindGlobalHandlers()},removeElement:function(){this.unbindGlobalHandlers(),this.el.remove()},renderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},bindGlobalHandlers:function(){a(document).on("dragstart sortstart",this.externalDragStartProxy)},unbindGlobalHandlers:function(){a(document).off("dragstart sortstart",this.externalDragStartProxy)},dayMousedown:function(a){var b,c,d=this,e=this.view,f=e.opt("selectable"),i=new gb(this.coordMap,{scroll:e.opt("dragScroll"),dragStart:function(){e.unselect()},cellOver:function(a,e,h){h&&(b=e?a:null,f&&(c=d.computeSelection(h,a),c?d.renderSelection(c):g()))},cellOut:function(a){b=null,c=null,d.unrenderSelection(),h()},listenStop:function(a){b&&e.triggerDayClick(b,d.getCellDayEl(b),a),c&&e.reportSelection(c,a),h()}});i.mousedown(a)},renderRangeHelper:function(a,b){var c=this.fabricateHelperEvent(a,b);this.renderHelper(c,b)},fabricateHelperEvent:function(a,b){var c=b?R(b.event):{};return c.start=a.start.clone(),c.end=a.end?a.end.clone():null,c.allDay=null,this.view.calendar.normalizeEventRange(c),c.className=(c.className||[]).concat("fc-helper"),b||(c.editable=!1),c},renderHelper:function(a,b){},unrenderHelper:function(){},renderSelection:function(a){this.renderHighlight(this.selectionRangeToSegs(a))},unrenderSelection:function(){this.unrenderHighlight()},computeSelection:function(a,b){var c,d=[a.start,a.end,b.start,b.end];return d.sort(aa),c={start:d[0].clone(),end:d[3].clone()},this.view.calendar.isSelectionRangeAllowed(c)?c:null},selectionRangeToSegs:function(a){return this.rangeToSegs(a)},renderHighlight:function(a){this.renderFill("highlight",a)},unrenderHighlight:function(){this.unrenderFill("highlight")},highlightSegClasses:function(){return["fc-highlight"]},renderFill:function(a,b){},unrenderFill:function(a){var b=this.elsByFill[a];b&&(b.remove(),delete this.elsByFill[a])},renderFillSegEls:function(b,c){var d,e=this,f=this[b+"SegEl"],g="",h=[];if(c.length){for(d=0;d<c.length;d++)g+=this.fillSegHtml(b,c[d]);a(g).each(function(b,d){var g=c[b],i=a(d);f&&(i=f.call(e,g,i)),i&&(i=a(i),i.is(e.fillSegTag)&&(g.el=i,h.push(g)))})}return h},fillSegTag:"div",fillSegHtml:function(a,b){var c=this[a+"SegClasses"],d=this[a+"SegCss"],e=c?c.call(this,b):[],f=$(d?d.call(this,b):{});return"<"+this.fillSegTag+(e.length?' class="'+e.join(" ")+'"':"")+(f?' style="'+f+'"':"")+" />"},headHtml:function(){return'<div class="fc-row '+this.view.widgetHeaderClass+'"><table><thead>'+this.rowHtml("head")+"</thead></table></div>"},headCellHtml:function(a){var b=this.view,c=a.start;return'<th class="fc-day-header '+b.widgetHeaderClass+" fc-"+Qa[c.day()]+'">'+Y(c.format(this.colHeadFormat))+"</th>"},bgCellHtml:function(a){var b=this.view,c=a.start,d=this.getDayClasses(c);return d.unshift("fc-day",b.widgetContentClass),'<td class="'+d.join(" ")+'" data-date="'+c.format("YYYY-MM-DD")+'"></td>'},getDayClasses:function(a){var b=this.view,c=b.calendar.getNow().stripTime(),d=["fc-"+Qa[a.day()]];return 1==b.intervalDuration.as("months")&&a.month()!=b.intervalStart.month()&&d.push("fc-other-month"),a.isSame(c,"day")?d.push("fc-today",b.highlightStateClass):c>a?d.push("fc-past"):d.push("fc-future"),d}});jb.mixin({mousedOverSeg:null,isDraggingSeg:!1,isResizingSeg:!1,isDraggingExternal:!1,segs:null,renderEvents:function(a){var b,c,d=this.eventsToSegs(a),e=[],f=[];for(b=0;b<d.length;b++)c=d[b],ta(c.event)?e.push(c):f.push(c);e=this.renderBgSegs(e)||e,f=this.renderFgSegs(f)||f,this.segs=e.concat(f)},unrenderEvents:function(){this.triggerSegMouseout(),this.unrenderFgSegs(),this.unrenderBgSegs(),this.segs=null},getEventSegs:function(){return this.segs||[]},renderFgSegs:function(a){},unrenderFgSegs:function(){},renderFgSegEls:function(b,c){var d,e=this.view,f="",g=[];if(b.length){for(d=0;d<b.length;d++)f+=this.fgSegHtml(b[d],c);a(f).each(function(c,d){var f=b[c],h=e.resolveEventEl(f.event,a(d));h&&(h.data("fc-seg",f),f.el=h,g.push(f))})}return g},fgSegHtml:function(a,b){},renderBgSegs:function(a){return this.renderFill("bgEvent",a)},unrenderBgSegs:function(){this.unrenderFill("bgEvent")},bgEventSegEl:function(a,b){return this.view.resolveEventEl(a.event,b)},bgEventSegClasses:function(a){var b=a.event,c=b.source||{};return["fc-bgevent"].concat(b.className,c.className||[])},bgEventSegCss:function(a){var b=this.view,c=a.event,d=c.source||{};return{"background-color":c.backgroundColor||c.color||d.backgroundColor||d.color||b.opt("eventBackgroundColor")||b.opt("eventColor")}},businessHoursSegClasses:function(a){return["fc-nonbusiness","fc-bgevent"]},bindSegHandlers:function(){var b=this,c=this.view;a.each({mouseenter:function(a,c){b.triggerSegMouseover(a,c)},mouseleave:function(a,c){b.triggerSegMouseout(a,c)},click:function(a,b){return c.trigger("eventClick",this,a.event,b)},mousedown:function(d,e){a(e.target).is(".fc-resizer")&&c.isEventResizable(d.event)?b.segResizeMousedown(d,e,a(e.target).is(".fc-start-resizer")):c.isEventDraggable(d.event)&&b.segDragMousedown(d,e)}},function(c,d){b.el.on(c,".fc-event-container > *",function(c){var e=a(this).data("fc-seg");return!e||b.isDraggingSeg||b.isResizingSeg?void 0:d.call(this,e,c)})})},triggerSegMouseover:function(a,b){this.mousedOverSeg||(this.mousedOverSeg=a,this.view.trigger("eventMouseover",a.el[0],a.event,b))},triggerSegMouseout:function(a,b){b=b||{},this.mousedOverSeg&&(a=a||this.mousedOverSeg,this.mousedOverSeg=null,this.view.trigger("eventMouseout",a.el[0],a.event,b))},segDragMousedown:function(a,b){var c,d=this,e=this.view,f=e.calendar,i=a.el,j=a.event,k=new hb(a.el,{parentEl:e.el,opacity:e.opt("dragOpacity"),revertDuration:e.opt("dragRevertDuration"),zIndex:2}),l=new gb(e.coordMap,{distance:5,scroll:e.opt("dragScroll"),subjectEl:i,subjectCenter:!0,listenStart:function(a){k.hide(),k.start(a)},dragStart:function(b){d.triggerSegMouseout(a,b),d.segDragStart(a,b),e.hideEvent(j)},cellOver:function(b,h,i){a.cell&&(i=a.cell),c=d.computeEventDrop(i,b,j),c&&!f.isEventRangeAllowed(c,j)&&(g(),c=null),c&&e.renderDrag(c,a)?k.hide():k.show(),h&&(c=null)},cellOut:function(){e.unrenderDrag(),k.show(),c=null},cellDone:function(){h()},dragStop:function(b){k.stop(!c,function(){e.unrenderDrag(),e.showEvent(j),d.segDragStop(a,b),c&&e.reportEventDrop(j,c,this.largeUnit,i,b)})},listenStop:function(){k.stop()}});l.mousedown(b)},segDragStart:function(a,b){this.isDraggingSeg=!0,this.view.trigger("eventDragStart",a.el[0],a.event,b,{})},segDragStop:function(a,b){this.isDraggingSeg=!1,this.view.trigger("eventDragStop",a.el[0],a.event,b,{})},computeEventDrop:function(a,b,c){var d,e,f=this.view.calendar,g=a.start,h=b.start;return g.hasTime()===h.hasTime()?(d=this.diffDates(h,g),c.allDay&&N(d)?(e={start:c.start.clone(),end:f.getEventEnd(c),allDay:!1},f.normalizeEventRangeTimes(e)):e={start:c.start.clone(),end:c.end?c.end.clone():null,allDay:c.allDay},e.start.add(d),e.end&&e.end.add(d)):e={start:h.clone(),end:null,allDay:!h.hasTime()},e},applyDragOpacity:function(a){var b=this.view.opt("dragOpacity");null!=b&&a.each(function(a,c){c.style.opacity=b})},externalDragStart:function(b,c){var d,e,f=this.view;f.opt("droppable")&&(d=a((c?c.item:null)||b.target),e=f.opt("dropAccept"),(a.isFunction(e)?e.call(d[0],d):d.is(e))&&(this.isDraggingExternal||this.listenToExternalDrag(d,b,c)))},listenToExternalDrag:function(a,b,c){var d,e,f=this,i=ya(a);d=new gb(this.coordMap,{listenStart:function(){f.isDraggingExternal=!0},cellOver:function(a){e=f.computeExternalDrop(a,i),e?f.renderDrag(e):g()},cellOut:function(){e=null,f.unrenderDrag(),h()},dragStop:function(){f.unrenderDrag(),h(),e&&f.view.reportExternalDrop(i,e,a,b,c)},listenStop:function(){f.isDraggingExternal=!1}}),d.startDrag(b)},computeExternalDrop:function(a,b){var c={start:a.start.clone(),end:null};return b.startTime&&!c.start.hasTime()&&c.start.time(b.startTime),b.duration&&(c.end=c.start.clone().add(b.duration)),this.view.calendar.isExternalDropRangeAllowed(c,b.eventProps)?c:null},renderDrag:function(a,b){},unrenderDrag:function(){},segResizeMousedown:function(a,b,c){var d,e,f=this,i=this.view,j=i.calendar,k=a.el,l=a.event,m=j.getEventEnd(l);d=new gb(this.coordMap,{distance:5,scroll:i.opt("dragScroll"),subjectEl:k,dragStart:function(b){f.triggerSegMouseout(a,b),f.segResizeStart(a,b)},cellOver:function(b,d,h){e=c?f.computeEventStartResize(h,b,l):f.computeEventEndResize(h,b,l),e&&(j.isEventRangeAllowed(e,l)?e.start.isSame(l.start)&&e.end.isSame(m)&&(e=null):(g(),e=null)),e&&(i.hideEvent(l),f.renderEventResize(e,a))},cellOut:function(){e=null},cellDone:function(){f.unrenderEventResize(),i.showEvent(l),h()},dragStop:function(b){f.segResizeStop(a,b),e&&i.reportEventResize(l,e,this.largeUnit,k,b)}}),d.mousedown(b)},segResizeStart:function(a,b){this.isResizingSeg=!0,this.view.trigger("eventResizeStart",a.el[0],a.event,b,{})},segResizeStop:function(a,b){this.isResizingSeg=!1,this.view.trigger("eventResizeStop",a.el[0],a.event,b,{})},computeEventStartResize:function(a,b,c){return this.computeEventResize("start",a,b,c)},computeEventEndResize:function(a,b,c){return this.computeEventResize("end",a,b,c)},computeEventResize:function(a,b,c,d){var e,f,g=this.view.calendar,h=this.diffDates(c[a],b[a]);return e={start:d.start.clone(),end:g.getEventEnd(d),allDay:d.allDay},e.allDay&&N(h)&&(e.allDay=!1,g.normalizeEventRangeTimes(e)),e[a].add(h),e.start.isBefore(e.end)||(f=d.allDay?g.defaultAllDayEventDuration:g.defaultTimedEventDuration,this.cellDuration&&this.cellDuration<f&&(f=this.cellDuration),"start"==a?e.start=e.end.clone().subtract(f):e.end=e.start.clone().add(f)),e},renderEventResize:function(a,b){},unrenderEventResize:function(){},getEventTimeText:function(a,b,c){return null==b&&(b=this.eventTimeFormat),null==c&&(c=this.displayEventEnd),this.displayEventTime&&a.start.hasTime()?c&&a.end?this.view.formatRange(a,b):a.start.format(b):""},getSegClasses:function(a,b,c){var d=a.event,e=["fc-event",a.isStart?"fc-start":"fc-not-start",a.isEnd?"fc-end":"fc-not-end"].concat(d.className,d.source?d.source.className:[]);return b&&e.push("fc-draggable"),c&&e.push("fc-resizable"),e},getEventSkinCss:function(a){var b=this.view,c=a.source||{},d=a.color,e=c.color,f=b.opt("eventColor");return{"background-color":a.backgroundColor||d||c.backgroundColor||e||b.opt("eventBackgroundColor")||f,"border-color":a.borderColor||d||c.borderColor||e||b.opt("eventBorderColor")||f,color:a.textColor||c.textColor||b.opt("eventTextColor")}},eventsToSegs:function(a,b){var c,d=this.eventsToRanges(a),e=[];for(c=0;c<d.length;c++)e.push.apply(e,this.eventRangeToSegs(d[c],b));return e},eventsToRanges:function(b){var c=this,d=wa(b),e=[];return a.each(d,function(a,b){b.length&&e.push.apply(e,ua(b[0])?c.eventsToInverseRanges(b):c.eventsToNormalRanges(b))}),e},eventsToNormalRanges:function(a){var b,c,d,e,f=this.view.calendar,g=[];for(b=0;b<a.length;b++)c=a[b],d=c.start.clone().stripZone(),e=f.getEventEnd(c).stripZone(),g.push({event:c,start:d,end:e,eventStartMS:+d,eventDurationMS:e-d});return g},eventsToInverseRanges:function(a){var b,c,d=this.view,e=d.start.clone().stripZone(),f=d.end.clone().stripZone(),g=this.eventsToNormalRanges(a),h=[],i=a[0],j=e;for(g.sort(xa),b=0;b<g.length;b++)c=g[b],c.start>j&&h.push({event:i,start:j,end:c.start}),j=c.end;return f>j&&h.push({event:i,start:j,end:f}),h},eventRangeToSegs:function(a,b){var c,d,e;for(a=this.view.calendar.ensureVisibleEventRange(a),c=b?b(a):this.rangeToSegs(a),d=0;d<c.length;d++)e=c[d],e.event=a.event,e.eventStartMS=a.eventStartMS,e.eventDurationMS=a.eventDurationMS;return c},sortSegs:function(a){a.sort(ca(this,"compareSegs"))},compareSegs:function(a,b){return a.eventStartMS-b.eventStartMS||b.eventDurationMS-a.eventDurationMS||b.event.allDay-a.event.allDay||B(a.event,b.event,this.view.eventOrderSpecs)}}),Ma.dataAttrPrefix="";var kb=jb.extend({numbersVisible:!1,bottomCoordPadding:0,breakOnWeeks:null,cellDates:null,dayToCellOffsets:null,rowEls:null,dayEls:null,helperEls:null,constructor:function(){jb.apply(this,arguments),this.cellDuration=b.duration(1,"day")},renderDates:function(a){var b,c,d,e=this.view,f=this.rowCnt,g=this.colCnt,h=f*g,i="";for(b=0;f>b;b++)i+=this.dayRowHtml(b,a);for(this.el.html(i),this.rowEls=this.el.find(".fc-row"),this.dayEls=this.el.find(".fc-day"),c=0;h>c;c++)d=this.getCell(c),e.trigger("dayRender",null,d.start,this.dayEls.eq(c))},unrenderDates:function(){this.removeSegPopover()},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents(!0),b=this.eventsToSegs(a);this.renderFill("businessHours",b,"bgevent")},dayRowHtml:function(a,b){var c=this.view,d=["fc-row","fc-week",c.widgetContentClass];return b&&d.push("fc-rigid"),'<div class="'+d.join(" ")+'"><div class="fc-bg"><table>'+this.rowHtml("day",a)+'</table></div><div class="fc-content-skeleton"><table>'+(this.numbersVisible?"<thead>"+this.rowHtml("number",a)+"</thead>":"")+"</table></div></div>"},dayCellHtml:function(a){return this.bgCellHtml(a)},computeColHeadFormat:function(){return this.rowCnt>1?"ddd":this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},computeEventTimeFormat:function(){return this.view.opt("extraSmallTimeFormat")},computeDisplayEventEnd:function(){return 1==this.colCnt},rangeUpdated:function(){var a,b,c,d;if(this.updateCellDates(),a=this.cellDates,this.breakOnWeeks){for(b=a[0].day(),d=1;d<a.length&&a[d].day()!=b;d++);c=Math.ceil(a.length/d)}else c=1,d=a.length;this.rowCnt=c,this.colCnt=d},updateCellDates:function(){for(var a=this.view,b=this.start.clone(),c=[],d=-1,e=[];b.isBefore(this.end);)a.isHiddenDay(b)?e.push(d+.5):(d++,e.push(d),c.push(b.clone())),b.add(1,"days");this.cellDates=c,this.dayToCellOffsets=e},computeCellDate:function(a){var b=this.colCnt,c=a.row*b+(this.isRTL?b-a.col-1:a.col);return this.cellDates[c].clone()},getRowEl:function(a){return this.rowEls.eq(a)},getColEl:function(a){return this.dayEls.eq(a)},getCellDayEl:function(a){return this.dayEls.eq(a.row*this.colCnt+a.col)},computeRowCoords:function(){var a=jb.prototype.computeRowCoords.call(this);return a[a.length-1].bottom+=this.bottomCoordPadding,a},rangeToSegs:function(a){var b,c,d,e,f,g,h,i,j,k,l=this.isRTL,m=this.rowCnt,n=this.colCnt,o=[];for(a=this.view.computeDayRange(a),b=this.dateToCellOffset(a.start),c=this.dateToCellOffset(a.end.subtract(1,"days")),d=0;m>d;d++)e=d*n,f=e+n-1,i=Math.max(e,b),j=Math.min(f,c),i=Math.ceil(i),j=Math.floor(j),j>=i&&(g=i===b,h=j===c,i-=e,j-=e,k={row:d,isStart:g,isEnd:h},l?(k.leftCol=n-j-1,k.rightCol=n-i-1):(k.leftCol=i,k.rightCol=j),o.push(k));return o},dateToCellOffset:function(a){var b=this.dayToCellOffsets,c=a.diff(this.start,"days");return 0>c?b[0]-1:c>=b.length?b[b.length-1]+1:b[c]},renderDrag:function(a,b){return this.renderHighlight(this.eventRangeToSegs(a)),b&&!b.el.closest(this.el).length?(this.renderRangeHelper(a,b),this.applyDragOpacity(this.helperEls),!0):void 0},unrenderDrag:function(){this.unrenderHighlight(),this.unrenderHelper()},renderEventResize:function(a,b){this.renderHighlight(this.eventRangeToSegs(a)),this.renderRangeHelper(a,b)},unrenderEventResize:function(){this.unrenderHighlight(),this.unrenderHelper()},renderHelper:function(b,c){var d,e=[],f=this.eventsToSegs([b]);f=this.renderFgSegEls(f),d=this.renderSegRows(f),this.rowEls.each(function(b,f){var g,h=a(f),i=a('<div class="fc-helper-skeleton"><table/></div>');g=c&&c.row===b?c.el.position().top:h.find(".fc-content-skeleton tbody").position().top,i.css("top",g).find("table").append(d[b].tbodyEl),h.append(i),e.push(i[0])}),this.helperEls=a(e)},unrenderHelper:function(){this.helperEls&&(this.helperEls.remove(),this.helperEls=null)},fillSegTag:"td",renderFill:function(b,c,d){var e,f,g,h=[];for(c=this.renderFillSegEls(b,c),e=0;e<c.length;e++)f=c[e],g=this.renderFillRow(b,f,d),this.rowEls.eq(f.row).append(g),h.push(g[0]);return this.elsByFill[b]=a(h),c},renderFillRow:function(b,c,d){var e,f,g=this.colCnt,h=c.leftCol,i=c.rightCol+1;return d=d||b.toLowerCase(),e=a('<div class="fc-'+d+'-skeleton"><table><tr/></table></div>'),f=e.find("tr"),h>0&&f.append('<td colspan="'+h+'"/>'),f.append(c.el.attr("colspan",i-h)),g>i&&f.append('<td colspan="'+(g-i)+'"/>'),this.bookendCells(f,b),e}});kb.mixin({rowStructs:null,unrenderEvents:function(){this.removeSegPopover(),jb.prototype.unrenderEvents.apply(this,arguments)},getEventSegs:function(){return jb.prototype.getEventSegs.call(this).concat(this.popoverSegs||[])},renderBgSegs:function(b){var c=a.grep(b,function(a){return a.event.allDay});return jb.prototype.renderBgSegs.call(this,c)},renderFgSegs:function(b){var c;return b=this.renderFgSegEls(b),c=this.rowStructs=this.renderSegRows(b),this.rowEls.each(function(b,d){a(d).find(".fc-content-skeleton > table").append(c[b].tbodyEl)}),b},unrenderFgSegs:function(){for(var a,b=this.rowStructs||[];a=b.pop();)a.tbodyEl.remove();this.rowStructs=null},renderSegRows:function(a){var b,c,d=[];for(b=this.groupSegRows(a),c=0;c<b.length;c++)d.push(this.renderSegRow(c,b[c]));return d},fgSegHtml:function(a,b){var c,d,e=this.view,f=a.event,g=e.isEventDraggable(f),h=!b&&f.allDay&&a.isStart&&e.isEventResizableFromStart(f),i=!b&&f.allDay&&a.isEnd&&e.isEventResizableFromEnd(f),j=this.getSegClasses(a,g,h||i),k=$(this.getEventSkinCss(f)),l="";return j.unshift("fc-day-grid-event","fc-h-event"),a.isStart&&(c=this.getEventTimeText(f),c&&(l='<span class="fc-time">'+Y(c)+"</span>")),d='<span class="fc-title">'+(Y(f.title||"")||" ")+"</span>",'<a class="'+j.join(" ")+'"'+(f.url?' href="'+Y(f.url)+'"':"")+(k?' style="'+k+'"':"")+'><div class="fc-content">'+(this.isRTL?d+" "+l:l+" "+d)+"</div>"+(h?'<div class="fc-resizer fc-start-resizer" />':"")+(i?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},renderSegRow:function(b,c){function d(b){for(;b>g;)k=(r[e-1]||[])[g],k?k.attr("rowspan",parseInt(k.attr("rowspan")||1,10)+1):(k=a("<td/>"),h.append(k)),q[e][g]=k,r[e][g]=k,g++}var e,f,g,h,i,j,k,l=this.colCnt,m=this.buildSegLevels(c),n=Math.max(1,m.length),o=a("<tbody/>"),p=[],q=[],r=[];for(e=0;n>e;e++){if(f=m[e],g=0,h=a("<tr/>"),p.push([]),q.push([]),r.push([]),f)for(i=0;i<f.length;i++){for(j=f[i],d(j.leftCol),k=a('<td class="fc-event-container"/>').append(j.el),j.leftCol!=j.rightCol?k.attr("colspan",j.rightCol-j.leftCol+1):r[e][g]=k;g<=j.rightCol;)q[e][g]=k,p[e][g]=j,g++;h.append(k)}d(l),this.bookendCells(h,"eventSkeleton"),o.append(h)}return{row:b,tbodyEl:o,cellMatrix:q,segMatrix:p,segLevels:m,segs:c}},buildSegLevels:function(a){var b,c,d,e=[];for(this.sortSegs(a),b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&za(c,e[d]);d++);c.level=d,(e[d]||(e[d]=[])).push(c)}for(d=0;d<e.length;d++)e[d].sort(Aa);return e},groupSegRows:function(a){var b,c=[];for(b=0;b<this.rowCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].row].push(a[b]);return c}}),kb.mixin({segPopover:null,popoverSegs:null,removeSegPopover:function(){this.segPopover&&this.segPopover.hide()},limitRows:function(a){var b,c,d=this.rowStructs||[];for(b=0;b<d.length;b++)this.unlimitRow(b),c=a?"number"==typeof a?a:this.computeRowLevelLimit(b):!1,c!==!1&&this.limitRow(b,c)},computeRowLevelLimit:function(b){function c(b,c){f=Math.max(f,a(c).outerHeight())}var d,e,f,g=this.rowEls.eq(b),h=g.height(),i=this.rowStructs[b].tbodyEl.children();for(d=0;d<i.length;d++)if(e=i.eq(d).removeClass("fc-limited"),f=0,e.find("> td > :first-child").each(c),e.position().top+f>h)return d;return!1},limitRow:function(b,c){function d(d){for(;d>x;)e=u.getCell(b,x),k=u.getCellSegs(e,c),k.length&&(n=g[c-1][x],t=u.renderMoreLink(e,k),s=a("<div/>").append(t),n.append(s),w.push(s[0])),x++}var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=this,v=this.rowStructs[b],w=[],x=0;if(c&&c<v.segLevels.length){for(f=v.segLevels[c-1],g=v.cellMatrix,h=v.tbodyEl.children().slice(c).addClass("fc-limited").get(),i=0;i<f.length;i++){for(j=f[i],d(j.leftCol),m=[],l=0;x<=j.rightCol;)e=this.getCell(b,x),k=this.getCellSegs(e,c),m.push(k),l+=k.length,x++;if(l){for(n=g[c-1][j.leftCol],o=n.attr("rowspan")||1,p=[],q=0;q<m.length;q++)r=a('<td class="fc-more-cell"/>').attr("rowspan",o),k=m[q],e=this.getCell(b,j.leftCol+q),t=this.renderMoreLink(e,[j].concat(k)),s=a("<div/>").append(t),r.append(s),p.push(r[0]),w.push(r[0]);n.addClass("fc-limited").after(a(p)),h.push(n[0])}}d(this.colCnt),v.moreEls=a(w),v.limitedEls=a(h)}},
|
8 |
-
unlimitRow:function(a){var b=this.rowStructs[a];b.moreEls&&(b.moreEls.remove(),b.moreEls=null),b.limitedEls&&(b.limitedEls.removeClass("fc-limited"),b.limitedEls=null)},renderMoreLink:function(b,c){var d=this,e=this.view;return a('<a class="fc-more"/>').text(this.getMoreLinkText(c.length)).on("click",function(f){var g=e.opt("eventLimitClick"),h=b.start,i=a(this),j=d.getCellDayEl(b),k=d.getCellSegs(b),l=d.resliceDaySegs(k,h),m=d.resliceDaySegs(c,h);"function"==typeof g&&(g=e.trigger("eventLimitClick",null,{date:h,dayEl:j,moreEl:i,segs:l,hiddenSegs:m},f)),"popover"===g?d.showSegPopover(b,i,l):"string"==typeof g&&e.calendar.zoomTo(h,g)})},showSegPopover:function(a,b,c){var d,e,f=this,g=this.view,h=b.parent();d=1==this.rowCnt?g.el:this.rowEls.eq(a.row),e={className:"fc-more-popover",content:this.renderSegPopoverContent(a,c),parentEl:this.el,top:d.offset().top,autoHide:!0,viewportConstrain:g.opt("popoverViewportConstrain"),hide:function(){f.segPopover.removeElement(),f.segPopover=null,f.popoverSegs=null}},this.isRTL?e.right=h.offset().left+h.outerWidth()+1:e.left=h.offset().left-1,this.segPopover=new cb(e),this.segPopover.show()},renderSegPopoverContent:function(b,c){var d,e=this.view,f=e.opt("theme"),g=b.start.format(e.opt("dayPopoverFormat")),h=a('<div class="fc-header '+e.widgetHeaderClass+'"><span class="fc-close '+(f?"ui-icon ui-icon-closethick":"fc-icon fc-icon-x")+'"></span><span class="fc-title">'+Y(g)+'</span><div class="fc-clear"/></div><div class="fc-body '+e.widgetContentClass+'"><div class="fc-event-container"></div></div>'),i=h.find(".fc-event-container");for(c=this.renderFgSegEls(c,!0),this.popoverSegs=c,d=0;d<c.length;d++)c[d].cell=b,i.append(c[d].el);return h},resliceDaySegs:function(b,c){var d=a.map(b,function(a){return a.event}),e=c.clone().stripTime(),f=e.clone().add(1,"days"),g={start:e,end:f};return b=this.eventsToSegs(d,function(a){var b=E(a,g);return b?[b]:[]}),this.sortSegs(b),b},getMoreLinkText:function(a){var b=this.view.opt("eventLimitText");return"function"==typeof b?b(a):"+"+a+" "+b},getCellSegs:function(a,b){for(var c,d=this.rowStructs[a.row].segMatrix,e=b||0,f=[];e<d.length;)c=d[e][a.col],c&&f.push(c),e++;return f}});var lb=jb.extend({slotDuration:null,snapDuration:null,minTime:null,maxTime:null,colDates:null,labelFormat:null,labelInterval:null,dayEls:null,slatEls:null,slatTops:null,helperEl:null,businessHourSegs:null,constructor:function(){jb.apply(this,arguments),this.processOptions()},renderDates:function(){this.el.html(this.renderHtml()),this.dayEls=this.el.find(".fc-day"),this.slatEls=this.el.find(".fc-slats tr")},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents();this.businessHourSegs=this.renderFill("businessHours",this.eventsToSegs(a),"bgevent")},renderHtml:function(){return'<div class="fc-bg"><table>'+this.rowHtml("slotBg")+'</table></div><div class="fc-slats"><table>'+this.slatRowHtml()+"</table></div>"},slotBgCellHtml:function(a){return this.bgCellHtml(a)},slatRowHtml:function(){for(var a,c,d,e=this.view,f=this.isRTL,g="",h=b.duration(+this.minTime);h<this.maxTime;)a=this.start.clone().time(h),c=ba(L(h,this.labelInterval)),d='<td class="fc-axis fc-time '+e.widgetContentClass+'" '+e.axisStyleAttr()+">"+(c?"<span>"+Y(a.format(this.labelFormat))+"</span>":"")+"</td>",g+="<tr "+(c?"":'class="fc-minor"')+">"+(f?"":d)+'<td class="'+e.widgetContentClass+'"/>'+(f?d:"")+"</tr>",h.add(this.slotDuration);return g},processOptions:function(){var c,d=this.view,e=d.opt("slotDuration"),f=d.opt("snapDuration");e=b.duration(e),f=f?b.duration(f):e,this.slotDuration=e,this.snapDuration=f,this.cellDuration=f,this.minTime=b.duration(d.opt("minTime")),this.maxTime=b.duration(d.opt("maxTime")),c=d.opt("slotLabelFormat"),a.isArray(c)&&(c=c[c.length-1]),this.labelFormat=c||d.opt("axisFormat")||d.opt("smallTimeFormat"),c=d.opt("slotLabelInterval"),this.labelInterval=c?b.duration(c):this.computeLabelInterval(e)},computeLabelInterval:function(a){var c,d,e;for(c=yb.length-1;c>=0;c--)if(d=b.duration(yb[c]),e=L(d,a),ba(e)&&e>1)return d;return b.duration(a)},computeColHeadFormat:function(){return this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},computeEventTimeFormat:function(){return this.view.opt("noMeridiemTimeFormat")},computeDisplayEventEnd:function(){return!0},rangeUpdated:function(){var a,b=this.view,c=[];for(a=this.start.clone();a.isBefore(this.end);)c.push(a.clone()),a.add(1,"day"),a=b.skipHiddenDays(a);this.isRTL&&c.reverse(),this.colDates=c,this.colCnt=c.length,this.rowCnt=Math.ceil((this.maxTime-this.minTime)/this.snapDuration)},computeCellDate:function(a){var b=this.colDates[a.col],c=this.computeSnapTime(a.row);return b=this.view.calendar.rezoneDate(b),b.time(c),b},getColEl:function(a){return this.dayEls.eq(a)},computeSnapTime:function(a){return b.duration(this.minTime+this.snapDuration*a)},rangeToSegs:function(a){var b,c,d,e,f=this.colCnt,g=[];for(a={start:a.start.clone().stripZone(),end:a.end.clone().stripZone()},c=0;f>c;c++)d=this.colDates[c],e={start:d.clone().time(this.minTime),end:d.clone().time(this.maxTime)},b=E(a,e),b&&(b.col=c,g.push(b));return g},updateSize:function(a){this.computeSlatTops(),a&&this.updateSegVerticals()},computeRowCoords:function(){var a,b,c=this.el.offset().top,d=[];for(a=0;a<this.rowCnt;a++)b={top:c+this.computeTimeTop(this.computeSnapTime(a))},a>0&&(d[a-1].bottom=b.top),d.push(b);return b.bottom=b.top+this.computeTimeTop(this.computeSnapTime(a)),d},computeDateTop:function(a,c){return this.computeTimeTop(b.duration(a.clone().stripZone()-c.clone().stripTime()))},computeTimeTop:function(a){var b,c,d,e,f=(a-this.minTime)/this.slotDuration;return f=Math.max(0,f),f=Math.min(this.slatEls.length,f),b=Math.floor(f),c=f-b,d=this.slatTops[b],c?(e=this.slatTops[b+1],d+(e-d)*c):d},computeSlatTops:function(){var b,c=[];this.slatEls.each(function(d,e){b=a(e).position().top,c.push(b)}),c.push(b+this.slatEls.last().outerHeight()),this.slatTops=c},renderDrag:function(a,b){return b?(this.renderRangeHelper(a,b),this.applyDragOpacity(this.helperEl),!0):void this.renderHighlight(this.eventRangeToSegs(a))},unrenderDrag:function(){this.unrenderHelper(),this.unrenderHighlight()},renderEventResize:function(a,b){this.renderRangeHelper(a,b)},unrenderEventResize:function(){this.unrenderHelper()},renderHelper:function(b,c){var d,e,f,g,h=this.eventsToSegs([b]);for(h=this.renderFgSegEls(h),d=this.renderSegTable(h),e=0;e<h.length;e++)f=h[e],c&&c.col===f.col&&(g=c.el,f.el.css({left:g.css("left"),right:g.css("right"),"margin-left":g.css("margin-left"),"margin-right":g.css("margin-right")}));this.helperEl=a('<div class="fc-helper-skeleton"/>').append(d).appendTo(this.el)},unrenderHelper:function(){this.helperEl&&(this.helperEl.remove(),this.helperEl=null)},renderSelection:function(a){this.view.opt("selectHelper")?this.renderRangeHelper(a):this.renderHighlight(this.selectionRangeToSegs(a))},unrenderSelection:function(){this.unrenderHelper(),this.unrenderHighlight()},renderFill:function(b,c,d){var e,f,g,h,i,j,k,l,m,n;if(c.length){for(c=this.renderFillSegEls(b,c),e=this.groupSegCols(c),d=d||b.toLowerCase(),f=a('<div class="fc-'+d+'-skeleton"><table><tr/></table></div>'),g=f.find("tr"),h=0;h<e.length;h++)if(i=e[h],j=a("<td/>").appendTo(g),i.length)for(k=a('<div class="fc-'+d+'-container"/>').appendTo(j),l=this.colDates[h],m=0;m<i.length;m++)n=i[m],k.append(n.el.css({top:this.computeDateTop(n.start,l),bottom:-this.computeDateTop(n.end,l)}));this.bookendCells(g,b),this.el.append(f),this.elsByFill[b]=f}return c}});lb.mixin({eventSkeletonEl:null,renderFgSegs:function(b){return b=this.renderFgSegEls(b),this.el.append(this.eventSkeletonEl=a('<div class="fc-content-skeleton"/>').append(this.renderSegTable(b))),b},unrenderFgSegs:function(a){this.eventSkeletonEl&&(this.eventSkeletonEl.remove(),this.eventSkeletonEl=null)},renderSegTable:function(b){var c,d,e,f,g,h,i=a("<table><tr/></table>"),j=i.find("tr");for(c=this.groupSegCols(b),this.computeSegVerticals(b),f=0;f<c.length;f++){for(g=c[f],this.placeSlotSegs(g),h=a('<div class="fc-event-container"/>'),d=0;d<g.length;d++)e=g[d],e.el.css(this.generateSegPositionCss(e)),e.bottom-e.top<30&&e.el.addClass("fc-short"),h.append(e.el);j.append(a("<td/>").append(h))}return this.bookendCells(j,"eventSkeleton"),i},placeSlotSegs:function(a){var b,c,d;if(this.sortSegs(a),b=Ba(a),Ca(b),c=b[0]){for(d=0;d<c.length;d++)Da(c[d]);for(d=0;d<c.length;d++)this.computeSlotSegCoords(c[d],0,0)}},computeSlotSegCoords:function(a,b,c){var d,e=a.forwardSegs;if(void 0===a.forwardCoord)for(e.length?(this.sortForwardSlotSegs(e),this.computeSlotSegCoords(e[0],b+1,c),a.forwardCoord=e[0].backwardCoord):a.forwardCoord=1,a.backwardCoord=a.forwardCoord-(a.forwardCoord-c)/(b+1),d=0;d<e.length;d++)this.computeSlotSegCoords(e[d],0,a.forwardCoord)},updateSegVerticals:function(){var a,b=(this.segs||[]).concat(this.businessHourSegs||[]);for(this.computeSegVerticals(b),a=0;a<b.length;a++)b[a].el.css(this.generateSegVerticalCss(b[a]))},computeSegVerticals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.top=this.computeDateTop(c.start,c.start),c.bottom=this.computeDateTop(c.end,c.start)},fgSegHtml:function(a,b){var c,d,e,f=this.view,g=a.event,h=f.isEventDraggable(g),i=!b&&a.isStart&&f.isEventResizableFromStart(g),j=!b&&a.isEnd&&f.isEventResizableFromEnd(g),k=this.getSegClasses(a,h,i||j),l=$(this.getEventSkinCss(g));return k.unshift("fc-time-grid-event","fc-v-event"),f.isMultiDayEvent(g)?(a.isStart||a.isEnd)&&(c=this.getEventTimeText(a),d=this.getEventTimeText(a,"LT"),e=this.getEventTimeText(a,null,!1)):(c=this.getEventTimeText(g),d=this.getEventTimeText(g,"LT"),e=this.getEventTimeText(g,null,!1)),'<a class="'+k.join(" ")+'"'+(g.url?' href="'+Y(g.url)+'"':"")+(l?' style="'+l+'"':"")+'><div class="fc-content">'+(c?'<div class="fc-time" data-start="'+Y(e)+'" data-full="'+Y(d)+'"><span>'+Y(c)+"</span></div>":"")+(g.title?'<div class="fc-title">'+Y(g.title)+"</div>":"")+'</div><div class="fc-bg"/>'+(j?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},generateSegPositionCss:function(a){var b,c,d=this.view.opt("slotEventOverlap"),e=a.backwardCoord,f=a.forwardCoord,g=this.generateSegVerticalCss(a);return d&&(f=Math.min(1,e+2*(f-e))),this.isRTL?(b=1-f,c=e):(b=e,c=1-f),g.zIndex=a.level+1,g.left=100*b+"%",g.right=100*c+"%",d&&a.forwardPressure&&(g[this.isRTL?"marginLeft":"marginRight"]=20),g},generateSegVerticalCss:function(a){return{top:a.top,bottom:-a.bottom}},groupSegCols:function(a){var b,c=[];for(b=0;b<this.colCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].col].push(a[b]);return c},sortForwardSlotSegs:function(a){a.sort(ca(this,"compareForwardSlotSegs"))},compareForwardSlotSegs:function(a,b){return b.forwardPressure-a.forwardPressure||(a.backwardCoord||0)-(b.backwardCoord||0)||this.compareSegs(a,b)}});var mb=Ma.View=ra.extend({type:null,name:null,title:null,calendar:null,options:null,coordMap:null,el:null,displaying:null,isSkeletonRendered:!1,isEventsRendered:!1,start:null,end:null,intervalStart:null,intervalEnd:null,intervalDuration:null,intervalUnit:null,isRTL:!1,isSelected:!1,eventOrderSpecs:null,scrollerEl:null,scrollTop:null,widgetHeaderClass:null,widgetContentClass:null,highlightStateClass:null,nextDayThreshold:null,isHiddenDayHash:null,documentMousedownProxy:null,constructor:function(a,c,d,e){this.calendar=a,this.type=this.name=c,this.options=d,this.intervalDuration=e||b.duration(1,"day"),this.nextDayThreshold=b.duration(this.opt("nextDayThreshold")),this.initThemingProps(),this.initHiddenDays(),this.isRTL=this.opt("isRTL"),this.eventOrderSpecs=A(this.opt("eventOrder")),this.documentMousedownProxy=ca(this,"documentMousedown"),this.initialize()},initialize:function(){},opt:function(a){return this.options[a]},trigger:function(a,b){var c=this.calendar;return c.trigger.apply(c,[a,b||this].concat(Array.prototype.slice.call(arguments,2),[this]))},setDate:function(a){this.setRange(this.computeRange(a))},setRange:function(b){a.extend(this,b),this.updateTitle()},computeRange:function(a){var b,c,d=I(this.intervalDuration),e=a.clone().startOf(d),f=e.clone().add(this.intervalDuration);return/year|month|week|day/.test(d)?(e.stripTime(),f.stripTime()):(e.hasTime()||(e=this.calendar.rezoneDate(e)),f.hasTime()||(f=this.calendar.rezoneDate(f))),b=e.clone(),b=this.skipHiddenDays(b),c=f.clone(),c=this.skipHiddenDays(c,-1,!0),{intervalUnit:d,intervalStart:e,intervalEnd:f,start:b,end:c}},computePrevDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).subtract(this.intervalDuration),-1)},computeNextDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).add(this.intervalDuration))},massageCurrentDate:function(a,b){return this.intervalDuration.as("days")<=1&&this.isHiddenDay(a)&&(a=this.skipHiddenDays(a,b),a.startOf("day")),a},updateTitle:function(){this.title=this.computeTitle()},computeTitle:function(){return this.formatRange({start:this.intervalStart,end:this.intervalEnd},this.opt("titleFormat")||this.computeTitleFormat(),this.opt("titleRangeSeparator"))},computeTitleFormat:function(){return"year"==this.intervalUnit?"YYYY":"month"==this.intervalUnit?this.opt("monthYearFormat"):this.intervalDuration.as("days")>1?"ll":"LL"},formatRange:function(a,b,c){var d=a.end;return d.hasTime()||(d=d.clone().subtract(1)),ma(a.start,d,b,c,this.opt("isRTL"))},setElement:function(a){this.el=a,this.bindGlobalHandlers()},removeElement:function(){this.clear(),this.isSkeletonRendered&&(this.unrenderSkeleton(),this.isSkeletonRendered=!1),this.unbindGlobalHandlers(),this.el.remove()},display:function(b){var c=this,d=null;return this.displaying&&(d=this.queryScroll()),this.clear().then(function(){return c.displaying=a.when(c.displayView(b)).then(function(){c.forceScroll(c.computeInitialScroll(d)),c.triggerRender()})})},clear:function(){var b=this,c=this.displaying;return c?c.then(function(){return b.displaying=null,b.clearEvents(),b.clearView()}):a.when()},displayView:function(a){this.isSkeletonRendered||(this.renderSkeleton(),this.isSkeletonRendered=!0),this.setDate(a),this.render&&this.render(),this.renderDates(),this.updateSize(),this.renderBusinessHours()},clearView:function(){this.unselect(),this.triggerUnrender(),this.unrenderBusinessHours(),this.unrenderDates(),this.destroy&&this.destroy()},renderSkeleton:function(){},unrenderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},renderBusinessHours:function(){},unrenderBusinessHours:function(){},triggerRender:function(){this.trigger("viewRender",this,this,this.el)},triggerUnrender:function(){this.trigger("viewDestroy",this,this,this.el)},bindGlobalHandlers:function(){a(document).on("mousedown",this.documentMousedownProxy)},unbindGlobalHandlers:function(){a(document).off("mousedown",this.documentMousedownProxy)},initThemingProps:function(){var a=this.opt("theme")?"ui":"fc";this.widgetHeaderClass=a+"-widget-header",this.widgetContentClass=a+"-widget-content",this.highlightStateClass=a+"-state-highlight"},updateSize:function(a){var b;a&&(b=this.queryScroll()),this.updateHeight(a),this.updateWidth(a),a&&this.setScroll(b)},updateWidth:function(a){},updateHeight:function(a){var b=this.calendar;this.setHeight(b.getSuggestedViewHeight(),b.isHeightAuto())},setHeight:function(a,b){},computeScrollerHeight:function(a){var b,c,d=this.scrollerEl;return b=this.el.add(d),b.css({position:"relative",left:-1}),c=this.el.outerHeight()-d.height(),b.css({position:"",left:""}),a-c},computeInitialScroll:function(a){return 0},queryScroll:function(){return this.scrollerEl?this.scrollerEl.scrollTop():void 0},setScroll:function(a){return this.scrollerEl?this.scrollerEl.scrollTop(a):void 0},forceScroll:function(a){var b=this;this.setScroll(a),setTimeout(function(){b.setScroll(a)},0)},displayEvents:function(a){var b=this.queryScroll();this.clearEvents(),this.renderEvents(a),this.isEventsRendered=!0,this.setScroll(b),this.triggerEventRender()},clearEvents:function(){this.isEventsRendered&&(this.triggerEventUnrender(),this.destroyEvents&&this.destroyEvents(),this.unrenderEvents(),this.isEventsRendered=!1)},renderEvents:function(a){},unrenderEvents:function(){},triggerEventRender:function(){this.renderedEventSegEach(function(a){this.trigger("eventAfterRender",a.event,a.event,a.el)}),this.trigger("eventAfterAllRender")},triggerEventUnrender:function(){this.renderedEventSegEach(function(a){this.trigger("eventDestroy",a.event,a.event,a.el)})},resolveEventEl:function(b,c){var d=this.trigger("eventRender",b,b,c);return d===!1?c=null:d&&d!==!0&&(c=a(d)),c},showEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","")},a)},hideEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","hidden")},a)},renderedEventSegEach:function(a,b){var c,d=this.getEventSegs();for(c=0;c<d.length;c++)b&&d[c].event._id!==b._id||d[c].el&&a.call(this,d[c])},getEventSegs:function(){return[]},isEventDraggable:function(a){var b=a.source||{};return X(a.startEditable,b.startEditable,this.opt("eventStartEditable"),a.editable,b.editable,this.opt("editable"))},reportEventDrop:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventDrop(a,g.dateDelta,h,d,e),f.reportEventChange()},triggerEventDrop:function(a,b,c,d,e){this.trigger("eventDrop",d[0],a,b,c,e,{})},reportExternalDrop:function(b,c,d,e,f){var g,h,i=b.eventProps;i&&(g=a.extend({},i,c),h=this.calendar.renderEvent(g,b.stick)[0]),this.triggerExternalDrop(h,c,d,e,f)},triggerExternalDrop:function(a,b,c,d,e){this.trigger("drop",c[0],b.start,d,e),a&&this.trigger("eventReceive",null,a)},renderDrag:function(a,b){},unrenderDrag:function(){},isEventResizableFromStart:function(a){return this.opt("eventResizableFromStart")&&this.isEventResizable(a)},isEventResizableFromEnd:function(a){return this.isEventResizable(a)},isEventResizable:function(a){var b=a.source||{};return X(a.durationEditable,b.durationEditable,this.opt("eventDurationEditable"),a.editable,b.editable,this.opt("editable"))},reportEventResize:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventResize(a,g.durationDelta,h,d,e),f.reportEventChange()},triggerEventResize:function(a,b,c,d,e){this.trigger("eventResize",d[0],a,b,c,e,{})},select:function(a,b){this.unselect(b),this.renderSelection(a),this.reportSelection(a,b)},renderSelection:function(a){},reportSelection:function(a,b){this.isSelected=!0,this.triggerSelect(a,b)},triggerSelect:function(a,b){this.trigger("select",null,a.start,a.end,b)},unselect:function(a){this.isSelected&&(this.isSelected=!1,this.destroySelection&&this.destroySelection(),this.unrenderSelection(),this.trigger("unselect",null,a))},unrenderSelection:function(){},documentMousedown:function(b){var c;this.isSelected&&this.opt("unselectAuto")&&v(b)&&(c=this.opt("unselectCancel"),c&&a(b.target).closest(c).length||this.unselect(b))},triggerDayClick:function(a,b,c){this.trigger("dayClick",b,a.start,c)},initHiddenDays:function(){var b,c=this.opt("hiddenDays")||[],d=[],e=0;for(this.opt("weekends")===!1&&c.push(0,6),b=0;7>b;b++)(d[b]=-1!==a.inArray(b,c))||e++;if(!e)throw"invalid hiddenDays";this.isHiddenDayHash=d},isHiddenDay:function(a){return b.isMoment(a)&&(a=a.day()),this.isHiddenDayHash[a]},skipHiddenDays:function(a,b,c){var d=a.clone();for(b=b||1;this.isHiddenDayHash[(d.day()+(c?b:0)+7)%7];)d.add(b,"days");return d},computeDayRange:function(a){var b,c=a.start.clone().stripTime(),d=a.end,e=null;return d&&(e=d.clone().stripTime(),b=+d.time(),b&&b>=this.nextDayThreshold&&e.add(1,"days")),(!d||c>=e)&&(e=c.clone().add(1,"days")),{start:c,end:e}},isMultiDayEvent:function(a){var b=this.computeDayRange(a);return b.end.diff(b.start,"days")>1}}),nb=Ma.Calendar=ra.extend({dirDefaults:null,langDefaults:null,overrides:null,options:null,viewSpecCache:null,view:null,header:null,loadingLevel:0,constructor:Ga,initialize:function(){},initOptions:function(a){var b,e,f,g;a=d(a),b=a.lang,e=ob[b],e||(b=nb.defaults.lang,e=ob[b]||{}),f=X(a.isRTL,e.isRTL,nb.defaults.isRTL),g=f?nb.rtlDefaults:{},this.dirDefaults=g,this.langDefaults=e,this.overrides=a,this.options=c([nb.defaults,g,e,a]),Ha(this.options),this.viewSpecCache={}},getViewSpec:function(a){var b=this.viewSpecCache;return b[a]||(b[a]=this.buildViewSpec(a))},getUnitViewSpec:function(b){var c,d,e;if(-1!=a.inArray(b,Ra))for(c=this.header.getViewsWithButtons(),a.each(Ma.views,function(a){c.push(a)}),d=0;d<c.length;d++)if(e=this.getViewSpec(c[d]),e&&e.singleUnit==b)return e},buildViewSpec:function(a){for(var d,e,f,g,h=this.overrides.views||{},i=[],j=[],k=[],l=a;l;)d=Na[l],e=h[l],l=null,"function"==typeof d&&(d={"class":d}),d&&(i.unshift(d),j.unshift(d.defaults||{}),f=f||d.duration,l=l||d.type),e&&(k.unshift(e),f=f||e.duration,l=l||e.type);return d=Q(i),d.type=a,d["class"]?(f&&(f=b.duration(f),f.valueOf()&&(d.duration=f,g=I(f),1===f.as(g)&&(d.singleUnit=g,k.unshift(h[g]||{})))),d.defaults=c(j),d.overrides=c(k),this.buildViewSpecOptions(d),this.buildViewSpecButtonText(d,a),d):!1},buildViewSpecOptions:function(a){a.options=c([nb.defaults,a.defaults,this.dirDefaults,this.langDefaults,this.overrides,a.overrides]),Ha(a.options)},buildViewSpecButtonText:function(a,b){function c(c){var d=c.buttonText||{};return d[b]||(a.singleUnit?d[a.singleUnit]:null)}a.buttonTextOverride=c(this.overrides)||a.overrides.buttonText,a.buttonTextDefault=c(this.langDefaults)||c(this.dirDefaults)||a.defaults.buttonText||c(nb.defaults)||(a.duration?this.humanizeDuration(a.duration):null)||b},instantiateView:function(a){var b=this.getViewSpec(a);return new b["class"](this,a,b.options,b.duration)},isValidViewType:function(a){return Boolean(this.getViewSpec(a))},pushLoading:function(){this.loadingLevel++||this.trigger("loading",null,!0,this.view)},popLoading:function(){--this.loadingLevel||this.trigger("loading",null,!1,this.view)},buildSelectRange:function(a,b){return a=this.moment(a),b=b?this.moment(b):a.hasTime()?a.clone().add(this.defaultTimedEventDuration):a.clone().add(this.defaultAllDayEventDuration),{start:a,end:b}}});nb.mixin(bb),nb.defaults={titleRangeSeparator:" — ",monthYearFormat:"MMMM YYYY",defaultTimedEventDuration:"02:00:00",defaultAllDayEventDuration:{days:1},forceEventDuration:!1,nextDayThreshold:"09:00:00",defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberTitle:"W",weekNumberCalculation:"local",scrollTime:"06:00:00",lazyFetching:!0,startParam:"start",endParam:"end",timezoneParam:"timezone",timezone:!1,isRTL:!1,buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day"},buttonIcons:{prev:"left-single-arrow",next:"right-single-arrow",prevYear:"left-double-arrow",nextYear:"right-double-arrow"},theme:!1,themeButtonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e",prevYear:"seek-prev",nextYear:"seek-next"},dragOpacity:.75,dragRevertDuration:500,dragScroll:!0,unselectAuto:!0,dropAccept:"*",eventOrder:"title",eventLimit:!1,eventLimitText:"more",eventLimitClick:"popover",dayPopoverFormat:"LL",handleWindowResize:!0,windowResizeDelay:200},nb.englishDefaults={dayPopoverFormat:"dddd, MMMM D"},nb.rtlDefaults={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"right-single-arrow",next:"left-single-arrow",prevYear:"right-double-arrow",nextYear:"left-double-arrow"},themeButtonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w",nextYear:"seek-prev",prevYear:"seek-next"}};var ob=Ma.langs={};Ma.datepickerLang=function(b,c,d){var e=ob[b]||(ob[b]={});e.isRTL=d.isRTL,e.weekNumberTitle=d.weekHeader,a.each(pb,function(a,b){e[a]=b(d)}),a.datepicker&&(a.datepicker.regional[c]=a.datepicker.regional[b]=d,a.datepicker.regional.en=a.datepicker.regional[""],a.datepicker.setDefaults(d))},Ma.lang=function(b,d){var e,f;e=ob[b]||(ob[b]={}),d&&(e=ob[b]=c([e,d])),f=Ia(b),a.each(qb,function(a,b){null==e[a]&&(e[a]=b(f,e))}),nb.defaults.lang=b};var pb={buttonText:function(a){return{prev:Z(a.prevText),next:Z(a.nextText),today:Z(a.currentText)}},monthYearFormat:function(a){return a.showMonthAfterYear?"YYYY["+a.yearSuffix+"] MMMM":"MMMM YYYY["+a.yearSuffix+"]"}},qb={dayOfMonthFormat:function(a,b){var c=a.longDateFormat("l");return c=c.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g,""),b.isRTL?c+=" ddd":c="ddd "+c,c},mediumTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"a")},smallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"a")},extraSmallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"t")},hourFormat:function(a){return a.longDateFormat("LT").replace(":mm","").replace(/(\Wmm)$/,"").replace(/\s*a$/i,"a")},noMeridiemTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"")}},rb={smallDayDateFormat:function(a){return a.isRTL?"D dd":"dd D"},weekFormat:function(a){return a.isRTL?"w[ "+a.weekNumberTitle+"]":"["+a.weekNumberTitle+" ]w"},smallWeekFormat:function(a){return a.isRTL?"w["+a.weekNumberTitle+"]":"["+a.weekNumberTitle+"]w"}};Ma.lang("en",nb.englishDefaults),Ma.sourceNormalizers=[],Ma.sourceFetchers=[];var sb={dataType:"json",cache:!1},tb=1;nb.prototype.getPeerEvents=function(a,b){var c,d,e=this.getEventCache(),f=[];for(c=0;c<e.length;c++)d=e[c],a&&a._id===d._id||f.push(d);return f};var ub=mb.extend({dayGrid:null,dayNumbersVisible:!1,weekNumbersVisible:!1,weekNumberWidth:null,headRowEl:null,initialize:function(){this.dayGrid=new kb(this),this.coordMap=this.dayGrid.coordMap},setRange:function(a){mb.prototype.setRange.call(this,a),this.dayGrid.breakOnWeeks=/year|month|week/.test(this.intervalUnit),this.dayGrid.setRange(a)},computeRange:function(a){var b=mb.prototype.computeRange.call(this,a);return/year|month/.test(b.intervalUnit)&&(b.start.startOf("week"),b.start=this.skipHiddenDays(b.start),b.end.weekday()&&(b.end.add(1,"week").startOf("week"),b.end=this.skipHiddenDays(b.end,-1,!0))),b},renderDates:function(){this.dayNumbersVisible=this.dayGrid.rowCnt>1,this.weekNumbersVisible=this.opt("weekNumbers"),this.dayGrid.numbersVisible=this.dayNumbersVisible||this.weekNumbersVisible,this.el.addClass("fc-basic-view").html(this.renderHtml()),this.headRowEl=this.el.find("thead .fc-row"),this.scrollerEl=this.el.find(".fc-day-grid-container"),this.dayGrid.coordMap.containerEl=this.scrollerEl,this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(this.hasRigidRows())},unrenderDates:function(){this.dayGrid.unrenderDates(),this.dayGrid.removeElement()},renderBusinessHours:function(){this.dayGrid.renderBusinessHours()},renderHtml:function(){return'<table><thead class="fc-head"><tr><td class="'+this.widgetHeaderClass+'">'+this.dayGrid.headHtml()+'</td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'"><div class="fc-day-grid-container"><div class="fc-day-grid"/></div></td></tr></tbody></table>'},headIntroHtml:function(){return this.weekNumbersVisible?'<th class="fc-week-number '+this.widgetHeaderClass+'" '+this.weekNumberStyleAttr()+"><span>"+Y(this.opt("weekNumberTitle"))+"</span></th>":void 0},numberIntroHtml:function(a){return this.weekNumbersVisible?'<td class="fc-week-number" '+this.weekNumberStyleAttr()+"><span>"+this.dayGrid.getCell(a,0).start.format("w")+"</span></td>":void 0},dayIntroHtml:function(){return this.weekNumbersVisible?'<td class="fc-week-number '+this.widgetContentClass+'" '+this.weekNumberStyleAttr()+"></td>":void 0},introHtml:function(){return this.weekNumbersVisible?'<td class="fc-week-number" '+this.weekNumberStyleAttr()+"></td>":void 0},numberCellHtml:function(a){var b,c=a.start;return this.dayNumbersVisible?(b=this.dayGrid.getDayClasses(c),b.unshift("fc-day-number"),'<td class="'+b.join(" ")+'" data-date="'+c.format()+'">'+c.date()+"</td>"):"<td/>"},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var a=this.opt("eventLimit");return a&&"number"!=typeof a},updateWidth:function(){this.weekNumbersVisible&&(this.weekNumberWidth=k(this.el.find(".fc-week-number")))},setHeight:function(a,b){var c,d=this.opt("eventLimit");m(this.scrollerEl),f(this.headRowEl),this.dayGrid.removeSegPopover(),d&&"number"==typeof d&&this.dayGrid.limitRows(d),c=this.computeScrollerHeight(a),this.setGridHeight(c,b),d&&"number"!=typeof d&&this.dayGrid.limitRows(d),!b&&l(this.scrollerEl,c)&&(e(this.headRowEl,r(this.scrollerEl)),c=this.computeScrollerHeight(a),this.scrollerEl.height(c))},setGridHeight:function(a,b){b?j(this.dayGrid.rowEls):i(this.dayGrid.rowEls,a,!0)},renderEvents:function(a){this.dayGrid.renderEvents(a),this.updateHeight()},getEventSegs:function(){return this.dayGrid.getEventSegs()},unrenderEvents:function(){this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return this.dayGrid.renderDrag(a,b)},unrenderDrag:function(){this.dayGrid.unrenderDrag()},renderSelection:function(a){this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.dayGrid.unrenderSelection()}}),vb=ub.extend({computeRange:function(a){var b,c=ub.prototype.computeRange.call(this,a);return this.isFixedWeeks()&&(b=Math.ceil(c.end.diff(c.start,"weeks",!0)),c.end.add(6-b,"weeks")),c},setGridHeight:function(a,b){b=b||"variable"===this.opt("weekMode"),b&&(a*=this.rowCnt/6),i(this.dayGrid.rowEls,a,!b)},isFixedWeeks:function(){var a=this.opt("weekMode");return a?"fixed"===a:this.opt("fixedWeekCount")}});Na.basic={"class":ub},Na.basicDay={type:"basic",duration:{days:1}},Na.basicWeek={type:"basic",duration:{weeks:1}},Na.month={"class":vb,duration:{months:1},defaults:{fixedWeekCount:!0}};var wb=mb.extend({timeGrid:null,dayGrid:null,axisWidth:null,noScrollRowEls:null,bottomRuleEl:null,bottomRuleHeight:null,initialize:function(){this.timeGrid=new lb(this),this.opt("allDaySlot")?(this.dayGrid=new kb(this),this.coordMap=new eb([this.dayGrid.coordMap,this.timeGrid.coordMap])):this.coordMap=this.timeGrid.coordMap},setRange:function(a){mb.prototype.setRange.call(this,a),this.timeGrid.setRange(a),this.dayGrid&&this.dayGrid.setRange(a)},renderDates:function(){this.el.addClass("fc-agenda-view").html(this.renderHtml()),this.scrollerEl=this.el.find(".fc-time-grid-container"),this.timeGrid.coordMap.containerEl=this.scrollerEl,this.timeGrid.setElement(this.el.find(".fc-time-grid")),this.timeGrid.renderDates(),this.bottomRuleEl=a('<hr class="fc-divider '+this.widgetHeaderClass+'"/>').appendTo(this.timeGrid.el),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight()),this.noScrollRowEls=this.el.find(".fc-row:not(.fc-scroller *)")},unrenderDates:function(){this.timeGrid.unrenderDates(),this.timeGrid.removeElement(),this.dayGrid&&(this.dayGrid.unrenderDates(),this.dayGrid.removeElement())},renderBusinessHours:function(){this.timeGrid.renderBusinessHours(),this.dayGrid&&this.dayGrid.renderBusinessHours()},renderHtml:function(){return'<table><thead class="fc-head"><tr><td class="'+this.widgetHeaderClass+'">'+this.timeGrid.headHtml()+'</td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'">'+(this.dayGrid?'<div class="fc-day-grid"/><hr class="fc-divider '+this.widgetHeaderClass+'"/>':"")+'<div class="fc-time-grid-container"><div class="fc-time-grid"/></div></td></tr></tbody></table>'},headIntroHtml:function(){var a,b;return this.opt("weekNumbers")?(a=this.timeGrid.getCell(0).start,b=a.format(this.opt("smallWeekFormat")),'<th class="fc-axis fc-week-number '+this.widgetHeaderClass+'" '+this.axisStyleAttr()+"><span>"+Y(b)+"</span></th>"):'<th class="fc-axis '+this.widgetHeaderClass+'" '+this.axisStyleAttr()+"></th>"},dayIntroHtml:function(){return'<td class="fc-axis '+this.widgetContentClass+'" '+this.axisStyleAttr()+"><span>"+(this.opt("allDayHtml")||Y(this.opt("allDayText")))+"</span></td>"},slotBgIntroHtml:function(){return'<td class="fc-axis '+this.widgetContentClass+'" '+this.axisStyleAttr()+"></td>";
|
9 |
},introHtml:function(){return'<td class="fc-axis" '+this.axisStyleAttr()+"></td>"},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},updateSize:function(a){this.timeGrid.updateSize(a),mb.prototype.updateSize.call(this,a)},updateWidth:function(){this.axisWidth=k(this.el.find(".fc-axis"))},setHeight:function(a,b){var c,d;null===this.bottomRuleHeight&&(this.bottomRuleHeight=this.bottomRuleEl.outerHeight()),this.bottomRuleEl.hide(),this.scrollerEl.css("overflow",""),m(this.scrollerEl),f(this.noScrollRowEls),this.dayGrid&&(this.dayGrid.removeSegPopover(),c=this.opt("eventLimit"),c&&"number"!=typeof c&&(c=xb),c&&this.dayGrid.limitRows(c)),b||(d=this.computeScrollerHeight(a),l(this.scrollerEl,d)?(e(this.noScrollRowEls,r(this.scrollerEl)),d=this.computeScrollerHeight(a),this.scrollerEl.height(d)):(this.scrollerEl.height(d).css("overflow","hidden"),this.bottomRuleEl.show()))},computeInitialScroll:function(){var a=b.duration(this.opt("scrollTime")),c=this.timeGrid.computeTimeTop(a);return c=Math.ceil(c),c&&c++,c},renderEvents:function(a){var b,c,d=[],e=[],f=[];for(c=0;c<a.length;c++)a[c].allDay?d.push(a[c]):e.push(a[c]);b=this.timeGrid.renderEvents(e),this.dayGrid&&(f=this.dayGrid.renderEvents(d)),this.updateHeight()},getEventSegs:function(){return this.timeGrid.getEventSegs().concat(this.dayGrid?this.dayGrid.getEventSegs():[])},unrenderEvents:function(){this.timeGrid.unrenderEvents(),this.dayGrid&&this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return a.start.hasTime()?this.timeGrid.renderDrag(a,b):this.dayGrid?this.dayGrid.renderDrag(a,b):void 0},unrenderDrag:function(){this.timeGrid.unrenderDrag(),this.dayGrid&&this.dayGrid.unrenderDrag()},renderSelection:function(a){a.start.hasTime()||a.end.hasTime()?this.timeGrid.renderSelection(a):this.dayGrid&&this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.timeGrid.unrenderSelection(),this.dayGrid&&this.dayGrid.unrenderSelection()}}),xb=5,yb=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];return Na.agenda={"class":wb,defaults:{allDaySlot:!0,allDayText:"all-day",slotDuration:"00:30:00",minTime:"00:00:00",maxTime:"24:00:00",slotEventOverlap:!0}},Na.agendaDay={type:"agenda",duration:{days:1}},Na.agendaWeek={type:"agenda",duration:{weeks:1}},Ma});
|
1 |
+
/*!
|
2 |
+
* FullCalendar v2.4.0
|
3 |
+
* Docs & License: http://fullcalendar.io/
|
4 |
+
* (c) 2015 Adam Shaw
|
5 |
+
*/
|
6 |
+
!function(a){"function"==typeof define&&define.amd?define(["jquery","moment"],a):"object"==typeof exports?module.exports=a(require("jquery"),require("moment")):a(jQuery,moment)}(function(a,b){function c(a){return Q(a,Oa)}function d(b){var c,d={views:b.views||{}};return a.each(b,function(b,e){"views"!=b&&(a.isPlainObject(e)&&!/(time|duration|interval)$/i.test(b)&&-1==a.inArray(b,Oa)?(c=null,a.each(e,function(a,e){/^(month|week|day|default|basic(Week|Day)?|agenda(Week|Day)?)$/.test(a)?(d.views[a]||(d.views[a]={}),d.views[a][b]=e):(c||(c={}),c[a]=e)}),c&&(d[b]=c)):d[b]=e)}),d}function e(a,b){b.left&&a.css({"border-left-width":1,"margin-left":b.left-1}),b.right&&a.css({"border-right-width":1,"margin-right":b.right-1})}function f(a){a.css({"margin-left":"","margin-right":"","border-left-width":"","border-right-width":""})}function g(){a("body").addClass("fc-not-allowed")}function h(){a("body").removeClass("fc-not-allowed")}function i(b,c,d){var e=Math.floor(c/b.length),f=Math.floor(c-e*(b.length-1)),g=[],h=[],i=[],k=0;j(b),b.each(function(c,d){var j=c===b.length-1?f:e,l=a(d).outerHeight(!0);j>l?(g.push(d),h.push(l),i.push(a(d).height())):k+=l}),d&&(c-=k,e=Math.floor(c/g.length),f=Math.floor(c-e*(g.length-1))),a(g).each(function(b,c){var d=b===g.length-1?f:e,j=h[b],k=i[b],l=d-(j-k);d>j&&a(c).height(l)})}function j(a){a.height("")}function k(b){var c=0;return b.find("> *").each(function(b,d){var e=a(d).outerWidth();e>c&&(c=e)}),c++,b.width(c),c}function l(a,b){return a.height(b).addClass("fc-scroller"),a[0].scrollHeight-1>a[0].clientHeight?!0:(m(a),!1)}function m(a){a.height("").removeClass("fc-scroller")}function n(b){var c=b.css("position"),d=b.parents().filter(function(){var b=a(this);return/(auto|scroll)/.test(b.css("overflow")+b.css("overflow-y")+b.css("overflow-x"))}).eq(0);return"fixed"!==c&&d.length?d:a(b[0].ownerDocument||document)}function o(a){var b=a.offset();return{left:b.left,right:b.left+a.outerWidth(),top:b.top,bottom:b.top+a.outerHeight()}}function p(a){var b=a.offset(),c=r(a),d=b.left+u(a,"border-left-width")+c.left,e=b.top+u(a,"border-top-width")+c.top;return{left:d,right:d+a[0].clientWidth,top:e,bottom:e+a[0].clientHeight}}function q(a){var b=a.offset(),c=b.left+u(a,"border-left-width")+u(a,"padding-left"),d=b.top+u(a,"border-top-width")+u(a,"padding-top");return{left:c,right:c+a.width(),top:d,bottom:d+a.height()}}function r(a){var b=a.innerWidth()-a[0].clientWidth,c={left:0,right:0,top:0,bottom:a.innerHeight()-a[0].clientHeight};return s()&&"rtl"==a.css("direction")?c.left=b:c.right=b,c}function s(){return null===Pa&&(Pa=t()),Pa}function t(){var b=a("<div><div/></div>").css({position:"absolute",top:-1e3,left:0,border:0,padding:0,overflow:"scroll",direction:"rtl"}).appendTo("body"),c=b.children(),d=c.offset().left>b.offset().left;return b.remove(),d}function u(a,b){return parseFloat(a.css(b))||0}function v(a){return 1==a.which&&!a.ctrlKey}function w(a,b){var c={left:Math.max(a.left,b.left),right:Math.min(a.right,b.right),top:Math.max(a.top,b.top),bottom:Math.min(a.bottom,b.bottom)};return c.left<c.right&&c.top<c.bottom?c:!1}function x(a,b){return{left:Math.min(Math.max(a.left,b.left),b.right),top:Math.min(Math.max(a.top,b.top),b.bottom)}}function y(a){return{left:(a.left+a.right)/2,top:(a.top+a.bottom)/2}}function z(a,b){return{left:a.left-b.left,top:a.top-b.top}}function A(b){var c,d,e=[],f=[];for("string"==typeof b?f=b.split(/\s*,\s*/):"function"==typeof b?f=[b]:a.isArray(b)&&(f=b),c=0;c<f.length;c++)d=f[c],"string"==typeof d?e.push("-"==d.charAt(0)?{field:d.substring(1),order:-1}:{field:d,order:1}):"function"==typeof d&&e.push({func:d});return e}function B(a,b,c){var d,e;for(d=0;d<c.length;d++)if(e=C(a,b,c[d]))return e;return 0}function C(a,b,c){return c.func?c.func(a,b):D(a[c.field],b[c.field])*(c.order||1)}function D(b,c){return b||c?null==c?-1:null==b?1:"string"===a.type(b)||"string"===a.type(c)?String(b).localeCompare(String(c)):b-c:0}function E(a,b){var c,d,e,f,g=a.start,h=a.end,i=b.start,j=b.end;return h>i&&j>g?(g>=i?(c=g.clone(),e=!0):(c=i.clone(),e=!1),j>=h?(d=h.clone(),f=!0):(d=j.clone(),f=!1),{start:c,end:d,isStart:e,isEnd:f}):void 0}function F(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days"),ms:a.time()-c.time()})}function G(a,c){return b.duration({days:a.clone().stripTime().diff(c.clone().stripTime(),"days")})}function H(a,c,d){return b.duration(Math.round(a.diff(c,d,!0)),d)}function I(a,b){var c,d,e;for(c=0;c<Ra.length&&(d=Ra[c],e=J(d,a,b),!(e>=1&&ba(e)));c++);return d}function J(a,c,d){return null!=d?d.diff(c,a,!0):b.isDuration(c)?c.as(a):c.end.diff(c.start,a,!0)}function K(a,b,c){var d;return N(c)?(b-a)/c:(d=c.asMonths(),Math.abs(d)>=1&&ba(d)?b.diff(a,"months",!0)/d:b.diff(a,"days",!0)/c.asDays())}function L(a,b){var c,d;return N(a)||N(b)?a/b:(c=a.asMonths(),d=b.asMonths(),Math.abs(c)>=1&&ba(c)&&Math.abs(d)>=1&&ba(d)?c/d:a.asDays()/b.asDays())}function M(a,c){var d;return N(a)?b.duration(a*c):(d=a.asMonths(),Math.abs(d)>=1&&ba(d)?b.duration({months:d*c}):b.duration({days:a.asDays()*c}))}function N(a){return Boolean(a.hours()||a.minutes()||a.seconds()||a.milliseconds())}function O(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function P(a){return/^\d+\:\d+(?:\:\d+\.?(?:\d{3})?)?$/.test(a)}function Q(a,b){var c,d,e,f,g,h,i={};if(b)for(c=0;c<b.length;c++){for(d=b[c],e=[],f=a.length-1;f>=0;f--)if(g=a[f][d],"object"==typeof g)e.unshift(g);else if(void 0!==g){i[d]=g;break}e.length&&(i[d]=Q(e))}for(c=a.length-1;c>=0;c--){h=a[c];for(d in h)d in i||(i[d]=h[d])}return i}function R(a){var b=function(){};return b.prototype=a,new b}function S(a,b){for(var c in a)U(a,c)&&(b[c]=a[c])}function T(a,b){var c,d,e=["constructor","toString","valueOf"];for(c=0;c<e.length;c++)d=e[c],a[d]!==Object.prototype[d]&&(b[d]=a[d])}function U(a,b){return Va.call(a,b)}function V(b){return/undefined|null|boolean|number|string/.test(a.type(b))}function W(b,c,d){if(a.isFunction(b)&&(b=[b]),b){var e,f;for(e=0;e<b.length;e++)f=b[e].apply(c,d)||f;return f}}function X(){for(var a=0;a<arguments.length;a++)if(void 0!==arguments[a])return arguments[a]}function Y(a){return(a+"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/'/g,"'").replace(/"/g,""").replace(/\n/g,"<br />")}function Z(a){return a.replace(/&.*?;/g,"")}function $(b){var c=[];return a.each(b,function(a,b){null!=b&&c.push(a+":"+b)}),c.join(";")}function _(a){return a.charAt(0).toUpperCase()+a.slice(1)}function aa(a,b){return a-b}function ba(a){return a%1===0}function ca(a,b){var c=a[b];return function(){return c.apply(a,arguments)}}function da(a,b){var c,d,e,f,g=function(){var h=+new Date-f;b>h&&h>0?c=setTimeout(g,b-h):(c=null,a.apply(e,d),c||(e=d=null))};return function(){e=this,d=arguments,f=+new Date,c||(c=setTimeout(g,b))}}function ea(c,d,e){var f,g,h,i,j=c[0],k=1==c.length&&"string"==typeof j;return b.isMoment(j)?(i=b.apply(null,c),ga(j,i)):O(j)||void 0===j?i=b.apply(null,c):(f=!1,g=!1,k?Wa.test(j)?(j+="-01",c=[j],f=!0,g=!0):(h=Xa.exec(j))&&(f=!h[5],g=!0):a.isArray(j)&&(g=!0),i=d||f?b.utc.apply(b,c):b.apply(null,c),f?(i._ambigTime=!0,i._ambigZone=!0):e&&(g?i._ambigZone=!0:k&&(i.utcOffset?i.utcOffset(j):i.zone(j)))),i._fullCalendar=!0,i}function fa(a,c){var d,e,f=!1,g=!1,h=a.length,i=[];for(d=0;h>d;d++)e=a[d],b.isMoment(e)||(e=Ma.moment.parseZone(e)),f=f||e._ambigTime,g=g||e._ambigZone,i.push(e);for(d=0;h>d;d++)e=i[d],c||!f||e._ambigTime?g&&!e._ambigZone&&(i[d]=e.clone().stripZone()):i[d]=e.clone().stripTime();return i}function ga(a,b){a._ambigTime?b._ambigTime=!0:b._ambigTime&&(b._ambigTime=!1),a._ambigZone?b._ambigZone=!0:b._ambigZone&&(b._ambigZone=!1)}function ha(a,b){a.year(b[0]||0).month(b[1]||0).date(b[2]||0).hours(b[3]||0).minutes(b[4]||0).seconds(b[5]||0).milliseconds(b[6]||0)}function ia(a,b){return Za.format.call(a,b)}function ja(a,b){return ka(a,pa(b))}function ka(a,b){var c,d="";for(c=0;c<b.length;c++)d+=la(a,b[c]);return d}function la(a,b){var c,d;return"string"==typeof b?b:(c=b.token)?$a[c]?$a[c](a):ia(a,c):b.maybe&&(d=ka(a,b.maybe),d.match(/[1-9]/))?d:""}function ma(a,b,c,d,e){var f;return a=Ma.moment.parseZone(a),b=Ma.moment.parseZone(b),f=(a.localeData||a.lang).call(a),c=f.longDateFormat(c)||c,d=d||" - ",na(a,b,pa(c),d,e)}function na(a,b,c,d,e){var f,g,h,i,j="",k="",l="",m="",n="";for(g=0;g<c.length&&(f=oa(a,b,c[g]),f!==!1);g++)j+=f;for(h=c.length-1;h>g&&(f=oa(a,b,c[h]),f!==!1);h--)k=f+k;for(i=g;h>=i;i++)l+=la(a,c[i]),m+=la(b,c[i]);return(l||m)&&(n=e?m+d+l:l+d+m),j+n+k}function oa(a,b,c){var d,e;return"string"==typeof c?c:(d=c.token)&&(e=_a[d.charAt(0)],e&&a.isSame(b,e))?ia(a,d):!1}function pa(a){return a in ab?ab[a]:ab[a]=qa(a)}function qa(a){for(var b,c=[],d=/\[([^\]]*)\]|\(([^\)]*)\)|(LTS|LT|(\w)\4*o?)|([^\w\[\(]+)/g;b=d.exec(a);)b[1]?c.push(b[1]):b[2]?c.push({maybe:qa(b[2])}):b[3]?c.push({token:b[3]}):b[5]&&c.push(b[5]);return c}function ra(){}function sa(a,b){return a||b?a&&b?a.grid===b.grid&&a.row===b.row&&a.col===b.col:!1:!0}function ta(a){var b=va(a);return"background"===b||"inverse-background"===b}function ua(a){return"inverse-background"===va(a)}function va(a){return X((a.source||{}).rendering,a.rendering)}function wa(a){var b,c,d={};for(b=0;b<a.length;b++)c=a[b],(d[c._id]||(d[c._id]=[])).push(c);return d}function xa(a,b){return a.eventStartMS-b.eventStartMS}function ya(c){var d,e,f,g,h=Ma.dataAttrPrefix;return h&&(h+="-"),d=c.data(h+"event")||null,d&&(d="object"==typeof d?a.extend({},d):{},e=d.start,null==e&&(e=d.time),f=d.duration,g=d.stick,delete d.start,delete d.time,delete d.duration,delete d.stick),null==e&&(e=c.data(h+"start")),null==e&&(e=c.data(h+"time")),null==f&&(f=c.data(h+"duration")),null==g&&(g=c.data(h+"stick")),e=null!=e?b.duration(e):null,f=null!=f?b.duration(f):null,g=Boolean(g),{eventProps:d,startTime:e,duration:f,stick:g}}function za(a,b){var c,d;for(c=0;c<b.length;c++)if(d=b[c],d.leftCol<=a.rightCol&&d.rightCol>=a.leftCol)return!0;return!1}function Aa(a,b){return a.leftCol-b.leftCol}function Ba(a){var b,c,d,e=[];for(b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&Ea(c,e[d]).length;d++);c.level=d,(e[d]||(e[d]=[])).push(c)}return e}function Ca(a){var b,c,d,e,f;for(b=0;b<a.length;b++)for(c=a[b],d=0;d<c.length;d++)for(e=c[d],e.forwardSegs=[],f=b+1;f<a.length;f++)Ea(e,a[f],e.forwardSegs)}function Da(a){var b,c,d=a.forwardSegs,e=0;if(void 0===a.forwardPressure){for(b=0;b<d.length;b++)c=d[b],Da(c),e=Math.max(e,1+c.forwardPressure);a.forwardPressure=e}}function Ea(a,b,c){c=c||[];for(var d=0;d<b.length;d++)Fa(a,b[d])&&c.push(b[d]);return c}function Fa(a,b){return a.bottom>b.top&&a.top<b.bottom}function Ga(c,d){function e(){U?h()&&(k(),i()):f()}function f(){V=O.theme?"ui":"fc",c.addClass("fc"),O.isRTL?c.addClass("fc-rtl"):c.addClass("fc-ltr"),O.theme?c.addClass("ui-widget"):c.addClass("fc-unthemed"),U=a("<div class='fc-view-container'/>").prependTo(c),S=N.header=new Ja(N,O),T=S.render(),T&&c.prepend(T),i(O.defaultView),O.handleWindowResize&&(Y=da(m,O.windowResizeDelay),a(window).resize(Y))}function g(){W&&W.removeElement(),S.removeElement(),U.remove(),c.removeClass("fc fc-ltr fc-rtl fc-unthemed ui-widget"),Y&&a(window).unbind("resize",Y)}function h(){return c.is(":visible")}function i(b){ca++,W&&b&&W.type!==b&&(S.deactivateButton(W.type),H(),W.removeElement(),W=N.view=null),!W&&b&&(W=N.view=ba[b]||(ba[b]=N.instantiateView(b)),W.setElement(a("<div class='fc-view fc-"+b+"-view' />").appendTo(U)),S.activateButton(b)),W&&(Z=W.massageCurrentDate(Z),W.displaying&&Z.isWithin(W.intervalStart,W.intervalEnd)||h()&&(H(),W.display(Z),I(),u(),v(),q())),I(),ca--}function j(a){return h()?(a&&l(),ca++,W.updateSize(!0),ca--,!0):void 0}function k(){h()&&l()}function l(){X="number"==typeof O.contentHeight?O.contentHeight:"number"==typeof O.height?O.height-(T?T.outerHeight(!0):0):Math.round(U.width()/Math.max(O.aspectRatio,.5))}function m(a){!ca&&a.target===window&&W.start&&j(!0)&&W.trigger("windowResize",aa)}function n(){p(),r()}function o(){h()&&(H(),W.displayEvents(ea),I())}function p(){H(),W.clearEvents(),I()}function q(){!O.lazyFetching||$(W.start,W.end)?r():o()}function r(){_(W.start,W.end)}function s(a){ea=a,o()}function t(){o()}function u(){S.updateTitle(W.title)}function v(){var a=N.getNow();a.isWithin(W.intervalStart,W.intervalEnd)?S.disableButton("today"):S.enableButton("today")}function w(a,b){W.select(N.buildSelectRange.apply(N,arguments))}function x(){W&&W.unselect()}function y(){Z=W.computePrevDate(Z),i()}function z(){Z=W.computeNextDate(Z),i()}function A(){Z.add(-1,"years"),i()}function B(){Z.add(1,"years"),i()}function C(){Z=N.getNow(),i()}function D(a){Z=N.moment(a),i()}function E(a){Z.add(b.duration(a)),i()}function F(a,b){var c;b=b||"day",c=N.getViewSpec(b)||N.getUnitViewSpec(b),Z=a,i(c?c.type:null)}function G(){return Z.clone()}function H(){U.css({width:"100%",height:U.height(),overflow:"hidden"})}function I(){U.css({width:"",height:"",overflow:""})}function J(){return N}function K(){return W}function L(a,b){return void 0===b?O[a]:void(("height"==a||"contentHeight"==a||"aspectRatio"==a)&&(O[a]=b,j(!0)))}function M(a,b){var c=Array.prototype.slice.call(arguments,2);return b=b||aa,this.triggerWith(a,b,c),O[a]?O[a].apply(b,c):void 0}var N=this;N.initOptions(d||{});var O=this.options;N.render=e,N.destroy=g,N.refetchEvents=n,N.reportEvents=s,N.reportEventChange=t,N.rerenderEvents=o,N.changeView=i,N.select=w,N.unselect=x,N.prev=y,N.next=z,N.prevYear=A,N.nextYear=B,N.today=C,N.gotoDate=D,N.incrementDate=E,N.zoomTo=F,N.getDate=G,N.getCalendar=J,N.getView=K,N.option=L,N.trigger=M;var P=R(Ia(O.lang));if(O.monthNames&&(P._months=O.monthNames),O.monthNamesShort&&(P._monthsShort=O.monthNamesShort),O.dayNames&&(P._weekdays=O.dayNames),O.dayNamesShort&&(P._weekdaysShort=O.dayNamesShort),null!=O.firstDay){var Q=R(P._week);Q.dow=O.firstDay,P._week=Q}P._fullCalendar_weekCalc=function(a){return"function"==typeof a?a:"local"===a?a:"iso"===a||"ISO"===a?"ISO":void 0}(O.weekNumberCalculation),N.defaultAllDayEventDuration=b.duration(O.defaultAllDayEventDuration),N.defaultTimedEventDuration=b.duration(O.defaultTimedEventDuration),N.moment=function(){var a;return"local"===O.timezone?(a=Ma.moment.apply(null,arguments),a.hasTime()&&a.local()):a="UTC"===O.timezone?Ma.moment.utc.apply(null,arguments):Ma.moment.parseZone.apply(null,arguments),"_locale"in a?a._locale=P:a._lang=P,a},N.getIsAmbigTimezone=function(){return"local"!==O.timezone&&"UTC"!==O.timezone},N.rezoneDate=function(a){return N.moment(a.toArray())},N.getNow=function(){var a=O.now;return"function"==typeof a&&(a=a()),N.moment(a)},N.getEventEnd=function(a){return a.end?a.end.clone():N.getDefaultEventEnd(a.allDay,a.start)},N.getDefaultEventEnd=function(a,b){var c=b.clone();return a?c.stripTime().add(N.defaultAllDayEventDuration):c.add(N.defaultTimedEventDuration),N.getIsAmbigTimezone()&&c.stripZone(),c},N.humanizeDuration=function(a){return(a.locale||a.lang).call(a,O.lang).humanize()},Ka.call(N,O);var S,T,U,V,W,X,Y,Z,$=N.isFetchNeeded,_=N.fetchEvents,aa=c[0],ba={},ca=0,ea=[];Z=null!=O.defaultDate?N.moment(O.defaultDate):N.getNow(),N.getSuggestedViewHeight=function(){return void 0===X&&k(),X},N.isHeightAuto=function(){return"auto"===O.contentHeight||"auto"===O.height},N.initialize()}function Ha(b){a.each(rb,function(a,c){null==b[a]&&(b[a]=c(b))})}function Ia(a){var c=b.localeData||b.langData;return c.call(b,a)||c.call(b,"en")}function Ja(b,c){function d(){var b=c.header;return n=c.theme?"ui":"fc",b?o=a("<div class='fc-toolbar'/>").append(f("left")).append(f("right")).append(f("center")).append('<div class="fc-clear"/>'):void 0}function e(){o.remove(),o=a()}function f(d){var e=a('<div class="fc-'+d+'"/>'),f=c.header[d];return f&&a.each(f.split(" "),function(d){var f,g=a(),h=!0;a.each(this.split(","),function(d,e){var f,i,j,k,l,m,o,q,r,s;"title"==e?(g=g.add(a("<h2> </h2>")),h=!1):((f=(b.options.customButtons||{})[e])?(j=function(a){f.click&&f.click.call(s[0],a)},k="",l=f.text):(i=b.getViewSpec(e))?(j=function(){b.changeView(e)},p.push(e),k=i.buttonTextOverride,l=i.buttonTextDefault):b[e]&&(j=function(){b[e]()},k=(b.overrides.buttonText||{})[e],l=c.buttonText[e]),j&&(m=f?f.themeIcon:c.themeButtonIcons[e],o=f?f.icon:c.buttonIcons[e],q=k?Y(k):m&&c.theme?"<span class='ui-icon ui-icon-"+m+"'></span>":o&&!c.theme?"<span class='fc-icon fc-icon-"+o+"'></span>":Y(l),r=["fc-"+e+"-button",n+"-button",n+"-state-default"],s=a('<button type="button" class="'+r.join(" ")+'">'+q+"</button>").click(function(a){s.hasClass(n+"-state-disabled")||(j(a),(s.hasClass(n+"-state-active")||s.hasClass(n+"-state-disabled"))&&s.removeClass(n+"-state-hover"))}).mousedown(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-down")}).mouseup(function(){s.removeClass(n+"-state-down")}).hover(function(){s.not("."+n+"-state-active").not("."+n+"-state-disabled").addClass(n+"-state-hover")},function(){s.removeClass(n+"-state-hover").removeClass(n+"-state-down")}),g=g.add(s)))}),h&&g.first().addClass(n+"-corner-left").end().last().addClass(n+"-corner-right").end(),g.length>1?(f=a("<div/>"),h&&f.addClass("fc-button-group"),f.append(g),e.append(f)):e.append(g)}),e}function g(a){o.find("h2").text(a)}function h(a){o.find(".fc-"+a+"-button").addClass(n+"-state-active")}function i(a){o.find(".fc-"+a+"-button").removeClass(n+"-state-active")}function j(a){o.find(".fc-"+a+"-button").attr("disabled","disabled").addClass(n+"-state-disabled")}function k(a){o.find(".fc-"+a+"-button").removeAttr("disabled").removeClass(n+"-state-disabled")}function l(){return p}var m=this;m.render=d,m.removeElement=e,m.updateTitle=g,m.activateButton=h,m.deactivateButton=i,m.disableButton=j,m.enableButton=k,m.getViewsWithButtons=l;var n,o=a(),p=[]}function Ka(c){function d(a,b){return!M||a.clone().stripZone()<M.clone().stripZone()||b.clone().stripZone()>N.clone().stripZone()}function e(a,b){M=a,N=b,U=[];var c=++S,d=R.length;T=d;for(var e=0;d>e;e++)f(R[e],c)}function f(b,c){g(b,function(d){var e,f,g,h=a.isArray(b.events);if(c==S){if(d)for(e=0;e<d.length;e++)f=d[e],g=h?f:s(f,b),g&&U.push.apply(U,x(g));T--,T||O(U)}})}function g(b,d){var e,f,h=Ma.sourceFetchers;for(e=0;e<h.length;e++){if(f=h[e].call(L,b,M.clone(),N.clone(),c.timezone,d),f===!0)return;if("object"==typeof f)return void g(f,d)}var i=b.events;if(i)a.isFunction(i)?(L.pushLoading(),i.call(L,M.clone(),N.clone(),c.timezone,function(a){d(a),L.popLoading()})):a.isArray(i)?d(i):d();else{var j=b.url;if(j){var k,l=b.success,m=b.error,n=b.complete;k=a.isFunction(b.data)?b.data():b.data;var o=a.extend({},k||{}),p=X(b.startParam,c.startParam),q=X(b.endParam,c.endParam),r=X(b.timezoneParam,c.timezoneParam);p&&(o[p]=M.format()),q&&(o[q]=N.format()),c.timezone&&"local"!=c.timezone&&(o[r]=c.timezone),L.pushLoading(),a.ajax(a.extend({},sb,b,{data:o,success:function(b){b=b||[];var c=W(l,this,arguments);a.isArray(c)&&(b=c),d(b)},error:function(){W(m,this,arguments),d()},complete:function(){W(n,this,arguments),L.popLoading()}}))}else d()}}function h(a){var b=i(a);b&&(R.push(b),T++,f(b,S))}function i(b){var c,d,e=Ma.sourceNormalizers;if(a.isFunction(b)||a.isArray(b)?c={events:b}:"string"==typeof b?c={url:b}:"object"==typeof b&&(c=a.extend({},b)),c){for(c.className?"string"==typeof c.className&&(c.className=c.className.split(/\s+/)):c.className=[],a.isArray(c.events)&&(c.origArray=c.events,c.events=a.map(c.events,function(a){return s(a,c)})),d=0;d<e.length;d++)e[d].call(L,c);return c}}function j(b){R=a.grep(R,function(a){return!k(a,b)}),U=a.grep(U,function(a){return!k(a.source,b)}),O(U)}function k(a,b){return a&&b&&l(a)==l(b)}function l(a){return("object"==typeof a?a.origArray||a.googleCalendarId||a.url||a.events:null)||a}function m(a){a.start=L.moment(a.start),a.end?a.end=L.moment(a.end):a.end=null,y(a,n(a)),O(U)}function n(b){var c={};return a.each(b,function(a,b){o(a)&&void 0!==b&&V(b)&&(c[a]=b)}),c}function o(a){return!/^_|^(id|allDay|start|end)$/.test(a)}function p(a,b){var c,d,e,f=s(a);if(f){for(c=x(f),d=0;d<c.length;d++)e=c[d],e.source||(b&&(Q.events.push(e),e.source=Q),U.push(e));return O(U),c}return[]}function q(b){var c,d;for(null==b?b=function(){return!0}:a.isFunction(b)||(c=b+"",b=function(a){return a._id==c}),U=a.grep(U,b,!0),d=0;d<R.length;d++)a.isArray(R[d].events)&&(R[d].events=a.grep(R[d].events,b,!0));O(U)}function r(b){return a.isFunction(b)?a.grep(U,b):null!=b?(b+="",a.grep(U,function(a){return a._id==b})):U}function s(d,e){var f,g,h,i={};if(c.eventDataTransform&&(d=c.eventDataTransform(d)),e&&e.eventDataTransform&&(d=e.eventDataTransform(d)),a.extend(i,d),e&&(i.source=e),i._id=d._id||(void 0===d.id?"_fc"+tb++:d.id+""),d.className?"string"==typeof d.className?i.className=d.className.split(/\s+/):i.className=d.className:i.className=[],f=d.start||d.date,g=d.end,P(f)&&(f=b.duration(f)),P(g)&&(g=b.duration(g)),d.dow||b.isDuration(f)||b.isDuration(g))i.start=f?b.duration(f):null,i.end=g?b.duration(g):null,i._recurring=!0;else{if(f&&(f=L.moment(f),!f.isValid()))return!1;g&&(g=L.moment(g),g.isValid()||(g=null)),h=d.allDay,void 0===h&&(h=X(e?e.allDayDefault:void 0,c.allDayDefault)),t(f,g,h,i)}return i}function t(a,b,c,d){d.start=a,d.end=b,d.allDay=c,u(d),La(d)}function u(a){v(a),a.end&&!a.end.isAfter(a.start)&&(a.end=null),a.end||(c.forceEventDuration?a.end=L.getDefaultEventEnd(a.allDay,a.start):a.end=null)}function v(a){null==a.allDay&&(a.allDay=!(a.start.hasTime()||a.end&&a.end.hasTime())),a.allDay?(a.start.stripTime(),a.end&&a.end.stripTime()):(a.start.hasTime()||(a.start=L.rezoneDate(a.start)),a.end&&!a.end.hasTime()&&(a.end=L.rezoneDate(a.end)))}function w(b){var c;return b.end||(c=b.allDay,null==c&&(c=!b.start.hasTime()),b=a.extend({},b),b.end=L.getDefaultEventEnd(c,b.start)),b}function x(b,c,d){var e,f,g,h,i,j,k,l,m,n=[];if(c=c||M,d=d||N,b)if(b._recurring){if(f=b.dow)for(e={},g=0;g<f.length;g++)e[f[g]]=!0;for(h=c.clone().stripTime();h.isBefore(d);)(!e||e[h.day()])&&(i=b.start,j=b.end,k=h.clone(),l=null,i&&(k=k.time(i)),j&&(l=h.clone().time(j)),m=a.extend({},b),t(k,l,!i&&!j,m),n.push(m)),h.add(1,"days")}else n.push(b);return n}function y(b,c,d){function e(a,b){return d?H(a,b,d):c.allDay?G(a,b):F(a,b)}var f,g,h,i,j,k,l={};return c=c||{},c.start||(c.start=b.start.clone()),void 0===c.end&&(c.end=b.end?b.end.clone():null),null==c.allDay&&(c.allDay=b.allDay),u(c),f={start:b._start.clone(),end:b._end?b._end.clone():L.getDefaultEventEnd(b._allDay,b._start),allDay:c.allDay},u(f),g=null!==b._end&&null===c.end,h=e(c.start,f.start),c.end?(i=e(c.end,f.end),j=i.subtract(h)):j=null,a.each(c,function(a,b){o(a)&&void 0!==b&&(l[a]=b)}),k=z(r(b._id),g,c.allDay,h,j,l),{dateDelta:h,durationDelta:j,undo:k}}function z(b,c,d,e,f,g){var h=L.getIsAmbigTimezone(),i=[];return e&&!e.valueOf()&&(e=null),f&&!f.valueOf()&&(f=null),a.each(b,function(b,j){var k,l;k={start:j.start.clone(),end:j.end?j.end.clone():null,allDay:j.allDay},a.each(g,function(a){k[a]=j[a]}),l={start:j._start,end:j._end,allDay:d},u(l),c?l.end=null:f&&!l.end&&(l.end=L.getDefaultEventEnd(l.allDay,l.start)),e&&(l.start.add(e),l.end&&l.end.add(e)),f&&l.end.add(f),h&&!l.allDay&&(e||f)&&(l.start.stripZone(),l.end&&l.end.stripZone()),a.extend(j,g,l),La(j),i.push(function(){a.extend(j,k),La(j)})}),function(){for(var a=0;a<i.length;a++)i[a]()}}function A(b){var d,e=c.businessHours,f={className:"fc-nonbusiness",start:"09:00",end:"17:00",dow:[1,2,3,4,5],rendering:"inverse-background"},g=L.getView();return e&&(d=a.extend({},f,"object"==typeof e?e:{})),d?(b&&(d.start=null,d.end=null),x(s(d),g.start,g.end)):[]}function B(a,b){var d=b.source||{},e=X(b.constraint,d.constraint,c.eventConstraint),f=X(b.overlap,d.overlap,c.eventOverlap);return a=w(a),E(a,e,f,b)}function C(a){return E(a,c.selectConstraint,c.selectOverlap)}function D(b,c){var d,e;return c&&(d=a.extend({},c,b),e=x(s(d))[0]),e?B(b,e):(b=w(b),C(b))}function E(b,c,d,e){var f,g,h,i,j,k;if(b=a.extend({},b),b.start=b.start.clone().stripZone(),b.end=b.end.clone().stripZone(),null!=c){for(f=I(c),g=!1,i=0;i<f.length;i++)if(J(f[i],b)){g=!0;break}if(!g)return!1}for(h=L.getPeerEvents(e,b),i=0;i<h.length;i++)if(j=h[i],K(j,b)){if(d===!1)return!1;if("function"==typeof d&&!d(j,e))return!1;if(e){if(k=X(j.overlap,(j.source||{}).overlap),k===!1)return!1;if("function"==typeof k&&!k(e,j))return!1}}return!0}function I(a){return"businessHours"===a?A():"object"==typeof a?x(s(a)):r(a)}function J(a,b){var c=a.start.clone().stripZone(),d=L.getEventEnd(a).stripZone();return b.start>=c&&b.end<=d}function K(a,b){var c=a.start.clone().stripZone(),d=L.getEventEnd(a).stripZone();return b.start<d&&b.end>c}var L=this;L.isFetchNeeded=d,L.fetchEvents=e,L.addEventSource=h,L.removeEventSource=j,L.updateEvent=m,L.renderEvent=p,L.removeEvents=q,L.clientEvents=r,L.mutateEvent=y,L.normalizeEventRange=u,L.normalizeEventRangeTimes=v,L.ensureVisibleEventRange=w;var M,N,O=L.reportEvents,Q={events:[]},R=[Q],S=0,T=0,U=[];a.each((c.events?[c.events]:[]).concat(c.eventSources||[]),function(a,b){var c=i(b);c&&R.push(c)}),L.getBusinessHoursEvents=A,L.isEventRangeAllowed=B,L.isSelectionRangeAllowed=C,L.isExternalDropRangeAllowed=D,L.getEventCache=function(){return U}}function La(a){a._allDay=a.allDay,a._start=a.start.clone(),a._end=a.end?a.end.clone():null}var Ma=a.fullCalendar={version:"2.4.0"},Na=Ma.views={};a.fn.fullCalendar=function(b){var c=Array.prototype.slice.call(arguments,1),d=this;return this.each(function(e,f){var g,h=a(f),i=h.data("fullCalendar");"string"==typeof b?i&&a.isFunction(i[b])&&(g=i[b].apply(i,c),e||(d=g),"destroy"===b&&h.removeData("fullCalendar")):i||(i=new nb(h,b),h.data("fullCalendar",i),i.render())}),d};var Oa=["header","buttonText","buttonIcons","themeButtonIcons"];Ma.intersectionToSeg=E,Ma.applyAll=W,Ma.debounce=da,Ma.isInt=ba,Ma.htmlEscape=Y,Ma.cssToStr=$,Ma.proxy=ca,Ma.capitaliseFirstLetter=_,Ma.getClientRect=p,Ma.getContentRect=q,Ma.getScrollbarWidths=r;var Pa=null;Ma.intersectRects=w,Ma.parseFieldSpecs=A,Ma.compareByFieldSpecs=B,Ma.compareByFieldSpec=C,Ma.flexibleCompare=D,Ma.computeIntervalUnit=I,Ma.divideRangeByDuration=K,Ma.divideDurationByDuration=L,Ma.multiplyDuration=M,Ma.durationHasTime=N;var Qa=["sun","mon","tue","wed","thu","fri","sat"],Ra=["year","month","week","day","hour","minute","second","millisecond"];Ma.log=function(){var a=window.console;return a&&a.log?a.log.apply(a,arguments):void 0},Ma.warn=function(){var a=window.console;return a&&a.warn?a.warn.apply(a,arguments):Ma.log.apply(Ma,arguments)};var Sa,Ta,Ua,Va={}.hasOwnProperty,Wa=/^\s*\d{4}-\d\d$/,Xa=/^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?)?$/,Ya=b.fn,Za=a.extend({},Ya);Ma.moment=function(){return ea(arguments)},Ma.moment.utc=function(){var a=ea(arguments,!0);return a.hasTime()&&a.utc(),a},Ma.moment.parseZone=function(){return ea(arguments,!0,!0)},Ya.clone=function(){var a=Za.clone.apply(this,arguments);return ga(this,a),this._fullCalendar&&(a._fullCalendar=!0),a},Ya.week=Ya.weeks=function(a){var b=(this._locale||this._lang)._fullCalendar_weekCalc;return null==a&&"function"==typeof b?b(this):"ISO"===b?Za.isoWeek.apply(this,arguments):Za.week.apply(this,arguments)},Ya.time=function(a){if(!this._fullCalendar)return Za.time.apply(this,arguments);if(null==a)return b.duration({hours:this.hours(),minutes:this.minutes(),seconds:this.seconds(),milliseconds:this.milliseconds()});this._ambigTime=!1,b.isDuration(a)||b.isMoment(a)||(a=b.duration(a));var c=0;return b.isDuration(a)&&(c=24*Math.floor(a.asDays())),this.hours(c+a.hours()).minutes(a.minutes()).seconds(a.seconds()).milliseconds(a.milliseconds())},Ya.stripTime=function(){var a;return this._ambigTime||(a=this.toArray(),this.utc(),Ta(this,a.slice(0,3)),this._ambigTime=!0,this._ambigZone=!0),this},Ya.hasTime=function(){return!this._ambigTime},Ya.stripZone=function(){var a,b;return this._ambigZone||(a=this.toArray(),b=this._ambigTime,this.utc(),Ta(this,a),this._ambigTime=b||!1,this._ambigZone=!0),this},Ya.hasZone=function(){return!this._ambigZone},Ya.local=function(){var a=this.toArray(),b=this._ambigZone;return Za.local.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,b&&Ua(this,a),this},Ya.utc=function(){return Za.utc.apply(this,arguments),this._ambigTime=!1,this._ambigZone=!1,this},a.each(["zone","utcOffset"],function(a,b){Za[b]&&(Ya[b]=function(a){return null!=a&&(this._ambigTime=!1,this._ambigZone=!1),Za[b].apply(this,arguments)})}),Ya.format=function(){return this._fullCalendar&&arguments[0]?ja(this,arguments[0]):this._ambigTime?ia(this,"YYYY-MM-DD"):this._ambigZone?ia(this,"YYYY-MM-DD[T]HH:mm:ss"):Za.format.apply(this,arguments)},Ya.toISOString=function(){return this._ambigTime?ia(this,"YYYY-MM-DD"):this._ambigZone?ia(this,"YYYY-MM-DD[T]HH:mm:ss"):Za.toISOString.apply(this,arguments)},Ya.isWithin=function(a,b){var c=fa([this,a,b]);return c[0]>=c[1]&&c[0]<c[2]},Ya.isSame=function(a,b){var c;return this._fullCalendar?b?(c=fa([this,a],!0),Za.isSame.call(c[0],c[1],b)):(a=Ma.moment.parseZone(a),Za.isSame.call(this,a)&&Boolean(this._ambigTime)===Boolean(a._ambigTime)&&Boolean(this._ambigZone)===Boolean(a._ambigZone)):Za.isSame.apply(this,arguments)},a.each(["isBefore","isAfter"],function(a,b){Ya[b]=function(a,c){var d;return this._fullCalendar?(d=fa([this,a]),Za[b].call(d[0],d[1],c)):Za[b].apply(this,arguments)}}),Sa="_d"in b()&&"updateOffset"in b,Ta=Sa?function(a,c){a._d.setTime(Date.UTC.apply(Date,c)),b.updateOffset(a,!1)}:ha,Ua=Sa?function(a,c){a._d.setTime(+new Date(c[0]||0,c[1]||0,c[2]||0,c[3]||0,c[4]||0,c[5]||0,c[6]||0)),b.updateOffset(a,!1)}:ha;var $a={t:function(a){return ia(a,"a").charAt(0)},T:function(a){return ia(a,"A").charAt(0)}};Ma.formatRange=ma;var _a={Y:"year",M:"month",D:"day",d:"day",A:"second",a:"second",T:"second",t:"second",H:"second",h:"second",m:"second",s:"second"},ab={};Ma.Class=ra,ra.extend=function(a){var b,c=this;return a=a||{},U(a,"constructor")&&(b=a.constructor),"function"!=typeof b&&(b=a.constructor=function(){c.apply(this,arguments)}),b.prototype=R(c.prototype),S(a,b.prototype),T(a,b.prototype),S(c,b),b},ra.mixin=function(a){S(a.prototype||a,this.prototype)};var bb=Ma.Emitter=ra.extend({callbackHash:null,on:function(a,b){return this.getCallbacks(a).add(b),this},off:function(a,b){return this.getCallbacks(a).remove(b),this},trigger:function(a){var b=Array.prototype.slice.call(arguments,1);return this.triggerWith(a,this,b),this},triggerWith:function(a,b,c){var d=this.getCallbacks(a);return d.fireWith(b,c),this},getCallbacks:function(b){var c;return this.callbackHash||(this.callbackHash={}),c=this.callbackHash[b],c||(c=this.callbackHash[b]=a.Callbacks()),c}}),cb=ra.extend({isHidden:!0,options:null,el:null,documentMousedownProxy:null,margin:10,constructor:function(a){this.options=a||{}},show:function(){this.isHidden&&(this.el||this.render(),this.el.show(),this.position(),this.isHidden=!1,this.trigger("show"))},hide:function(){this.isHidden||(this.el.hide(),this.isHidden=!0,this.trigger("hide"))},render:function(){var b=this,c=this.options;this.el=a('<div class="fc-popover"/>').addClass(c.className||"").css({top:0,left:0}).append(c.content).appendTo(c.parentEl),this.el.on("click",".fc-close",function(){b.hide()}),c.autoHide&&a(document).on("mousedown",this.documentMousedownProxy=ca(this,"documentMousedown"))},documentMousedown:function(b){this.el&&!a(b.target).closest(this.el).length&&this.hide()},removeElement:function(){this.hide(),this.el&&(this.el.remove(),this.el=null),a(document).off("mousedown",this.documentMousedownProxy)},position:function(){var b,c,d,e,f,g=this.options,h=this.el.offsetParent().offset(),i=this.el.outerWidth(),j=this.el.outerHeight(),k=a(window),l=n(this.el);e=g.top||0,f=void 0!==g.left?g.left:void 0!==g.right?g.right-i:0,l.is(window)||l.is(document)?(l=k,b=0,c=0):(d=l.offset(),b=d.top,c=d.left),b+=k.scrollTop(),c+=k.scrollLeft(),g.viewportConstrain!==!1&&(e=Math.min(e,b+l.outerHeight()-j-this.margin),e=Math.max(e,b+this.margin),f=Math.min(f,c+l.outerWidth()-i-this.margin),f=Math.max(f,c+this.margin)),this.el.css({top:e-h.top,left:f-h.left})},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1));
|
7 |
+
}}),db=ra.extend({grid:null,rowCoords:null,colCoords:null,containerEl:null,bounds:null,constructor:function(a){this.grid=a},build:function(){this.grid.build(),this.rowCoords=this.grid.computeRowCoords(),this.colCoords=this.grid.computeColCoords(),this.computeBounds()},clear:function(){this.grid.clear(),this.rowCoords=null,this.colCoords=null},getCell:function(b,c){var d,e,f,g=this.rowCoords,h=g.length,i=this.colCoords,j=i.length,k=null,l=null;if(this.inBounds(b,c)){for(d=0;h>d;d++)if(e=g[d],c>=e.top&&c<e.bottom){k=d;break}for(d=0;j>d;d++)if(e=i[d],b>=e.left&&b<e.right){l=d;break}if(null!==k&&null!==l)return f=this.grid.getCell(k,l),f.grid=this.grid,a.extend(f,g[k],i[l]),f}return null},computeBounds:function(){this.bounds=this.containerEl?p(this.containerEl):null},inBounds:function(a,b){var c=this.bounds;return c?a>=c.left&&a<c.right&&b>=c.top&&b<c.bottom:!0}}),eb=ra.extend({coordMaps:null,constructor:function(a){this.coordMaps=a},build:function(){var a,b=this.coordMaps;for(a=0;a<b.length;a++)b[a].build()},getCell:function(a,b){var c,d=this.coordMaps,e=null;for(c=0;c<d.length&&!e;c++)e=d[c].getCell(a,b);return e},clear:function(){var a,b=this.coordMaps;for(a=0;a<b.length;a++)b[a].clear()}}),fb=Ma.DragListener=ra.extend({options:null,isListening:!1,isDragging:!1,originX:null,originY:null,mousemoveProxy:null,mouseupProxy:null,subjectEl:null,subjectHref:null,scrollEl:null,scrollBounds:null,scrollTopVel:null,scrollLeftVel:null,scrollIntervalId:null,scrollHandlerProxy:null,scrollSensitivity:30,scrollSpeed:200,scrollIntervalMs:50,constructor:function(a){a=a||{},this.options=a,this.subjectEl=a.subjectEl},mousedown:function(a){v(a)&&(a.preventDefault(),this.startListening(a),this.options.distance||this.startDrag(a))},startListening:function(b){var c;this.isListening||(b&&this.options.scroll&&(c=n(a(b.target)),c.is(window)||c.is(document)||(this.scrollEl=c,this.scrollHandlerProxy=da(ca(this,"scrollHandler"),100),this.scrollEl.on("scroll",this.scrollHandlerProxy))),a(document).on("mousemove",this.mousemoveProxy=ca(this,"mousemove")).on("mouseup",this.mouseupProxy=ca(this,"mouseup")).on("selectstart",this.preventDefault),b?(this.originX=b.pageX,this.originY=b.pageY):(this.originX=0,this.originY=0),this.isListening=!0,this.listenStart(b))},listenStart:function(a){this.trigger("listenStart",a)},mousemove:function(a){var b,c,d=a.pageX-this.originX,e=a.pageY-this.originY;this.isDragging||(b=this.options.distance||1,c=d*d+e*e,c>=b*b&&this.startDrag(a)),this.isDragging&&this.drag(d,e,a)},startDrag:function(a){this.isListening||this.startListening(),this.isDragging||(this.isDragging=!0,this.dragStart(a))},dragStart:function(a){var b=this.subjectEl;this.trigger("dragStart",a),(this.subjectHref=b?b.attr("href"):null)&&b.removeAttr("href")},drag:function(a,b,c){this.trigger("drag",a,b,c),this.updateScroll(c)},mouseup:function(a){this.stopListening(a)},stopDrag:function(a){this.isDragging&&(this.stopScrolling(),this.dragStop(a),this.isDragging=!1)},dragStop:function(a){var b=this;this.trigger("dragStop",a),setTimeout(function(){b.subjectHref&&b.subjectEl.attr("href",b.subjectHref)},0)},stopListening:function(b){this.stopDrag(b),this.isListening&&(this.scrollEl&&(this.scrollEl.off("scroll",this.scrollHandlerProxy),this.scrollHandlerProxy=null),a(document).off("mousemove",this.mousemoveProxy).off("mouseup",this.mouseupProxy).off("selectstart",this.preventDefault),this.mousemoveProxy=null,this.mouseupProxy=null,this.isListening=!1,this.listenStop(b))},listenStop:function(a){this.trigger("listenStop",a)},trigger:function(a){this.options[a]&&this.options[a].apply(this,Array.prototype.slice.call(arguments,1))},preventDefault:function(a){a.preventDefault()},computeScrollBounds:function(){var a=this.scrollEl;this.scrollBounds=a?o(a):null},updateScroll:function(a){var b,c,d,e,f=this.scrollSensitivity,g=this.scrollBounds,h=0,i=0;g&&(b=(f-(a.pageY-g.top))/f,c=(f-(g.bottom-a.pageY))/f,d=(f-(a.pageX-g.left))/f,e=(f-(g.right-a.pageX))/f,b>=0&&1>=b?h=b*this.scrollSpeed*-1:c>=0&&1>=c&&(h=c*this.scrollSpeed),d>=0&&1>=d?i=d*this.scrollSpeed*-1:e>=0&&1>=e&&(i=e*this.scrollSpeed)),this.setScrollVel(h,i)},setScrollVel:function(a,b){this.scrollTopVel=a,this.scrollLeftVel=b,this.constrainScrollVel(),!this.scrollTopVel&&!this.scrollLeftVel||this.scrollIntervalId||(this.scrollIntervalId=setInterval(ca(this,"scrollIntervalFunc"),this.scrollIntervalMs))},constrainScrollVel:function(){var a=this.scrollEl;this.scrollTopVel<0?a.scrollTop()<=0&&(this.scrollTopVel=0):this.scrollTopVel>0&&a.scrollTop()+a[0].clientHeight>=a[0].scrollHeight&&(this.scrollTopVel=0),this.scrollLeftVel<0?a.scrollLeft()<=0&&(this.scrollLeftVel=0):this.scrollLeftVel>0&&a.scrollLeft()+a[0].clientWidth>=a[0].scrollWidth&&(this.scrollLeftVel=0)},scrollIntervalFunc:function(){var a=this.scrollEl,b=this.scrollIntervalMs/1e3;this.scrollTopVel&&a.scrollTop(a.scrollTop()+this.scrollTopVel*b),this.scrollLeftVel&&a.scrollLeft(a.scrollLeft()+this.scrollLeftVel*b),this.constrainScrollVel(),this.scrollTopVel||this.scrollLeftVel||this.stopScrolling()},stopScrolling:function(){this.scrollIntervalId&&(clearInterval(this.scrollIntervalId),this.scrollIntervalId=null,this.scrollStop())},scrollHandler:function(){this.scrollIntervalId||this.scrollStop()},scrollStop:function(){}}),gb=fb.extend({coordMap:null,origCell:null,cell:null,coordAdjust:null,constructor:function(a,b){fb.prototype.constructor.call(this,b),this.coordMap=a},listenStart:function(a){var b,c,d,e=this.subjectEl;fb.prototype.listenStart.apply(this,arguments),this.computeCoords(),a?(c={left:a.pageX,top:a.pageY},d=c,e&&(b=o(e),d=x(d,b)),this.origCell=this.getCell(d.left,d.top),e&&this.options.subjectCenter&&(this.origCell&&(b=w(this.origCell,b)||b),d=y(b)),this.coordAdjust=z(d,c)):(this.origCell=null,this.coordAdjust=null)},computeCoords:function(){this.coordMap.build(),this.computeScrollBounds()},dragStart:function(a){var b;fb.prototype.dragStart.apply(this,arguments),b=this.getCell(a.pageX,a.pageY),b&&this.cellOver(b)},drag:function(a,b,c){var d;fb.prototype.drag.apply(this,arguments),d=this.getCell(c.pageX,c.pageY),sa(d,this.cell)||(this.cell&&this.cellOut(),d&&this.cellOver(d))},dragStop:function(){this.cellDone(),fb.prototype.dragStop.apply(this,arguments)},cellOver:function(a){this.cell=a,this.trigger("cellOver",a,sa(a,this.origCell),this.origCell)},cellOut:function(){this.cell&&(this.trigger("cellOut",this.cell),this.cellDone(),this.cell=null)},cellDone:function(){this.cell&&this.trigger("cellDone",this.cell)},listenStop:function(){fb.prototype.listenStop.apply(this,arguments),this.origCell=this.cell=null,this.coordMap.clear()},scrollStop:function(){fb.prototype.scrollStop.apply(this,arguments),this.computeCoords()},getCell:function(a,b){return this.coordAdjust&&(a+=this.coordAdjust.left,b+=this.coordAdjust.top),this.coordMap.getCell(a,b)}}),hb=ra.extend({options:null,sourceEl:null,el:null,parentEl:null,top0:null,left0:null,mouseY0:null,mouseX0:null,topDelta:null,leftDelta:null,mousemoveProxy:null,isFollowing:!1,isHidden:!1,isAnimating:!1,constructor:function(b,c){this.options=c=c||{},this.sourceEl=b,this.parentEl=c.parentEl?a(c.parentEl):b.parent()},start:function(b){this.isFollowing||(this.isFollowing=!0,this.mouseY0=b.pageY,this.mouseX0=b.pageX,this.topDelta=0,this.leftDelta=0,this.isHidden||this.updatePosition(),a(document).on("mousemove",this.mousemoveProxy=ca(this,"mousemove")))},stop:function(b,c){function d(){this.isAnimating=!1,e.removeElement(),this.top0=this.left0=null,c&&c()}var e=this,f=this.options.revertDuration;this.isFollowing&&!this.isAnimating&&(this.isFollowing=!1,a(document).off("mousemove",this.mousemoveProxy),b&&f&&!this.isHidden?(this.isAnimating=!0,this.el.animate({top:this.top0,left:this.left0},{duration:f,complete:d})):d())},getEl:function(){var a=this.el;return a||(this.sourceEl.width(),a=this.el=this.sourceEl.clone().css({position:"absolute",visibility:"",display:this.isHidden?"none":"",margin:0,right:"auto",bottom:"auto",width:this.sourceEl.width(),height:this.sourceEl.height(),opacity:this.options.opacity||"",zIndex:this.options.zIndex}).appendTo(this.parentEl)),a},removeElement:function(){this.el&&(this.el.remove(),this.el=null)},updatePosition:function(){var a,b;this.getEl(),null===this.top0&&(this.sourceEl.width(),a=this.sourceEl.offset(),b=this.el.offsetParent().offset(),this.top0=a.top-b.top,this.left0=a.left-b.left),this.el.css({top:this.top0+this.topDelta,left:this.left0+this.leftDelta})},mousemove:function(a){this.topDelta=a.pageY-this.mouseY0,this.leftDelta=a.pageX-this.mouseX0,this.isHidden||this.updatePosition()},hide:function(){this.isHidden||(this.isHidden=!0,this.el&&this.el.hide())},show:function(){this.isHidden&&(this.isHidden=!1,this.updatePosition(),this.getEl().show())}}),ib=ra.extend({view:null,isRTL:null,cellHtml:"<td/>",constructor:function(a){this.view=a,this.isRTL=a.opt("isRTL")},rowHtml:function(a,b){var c,d,e=this.getHtmlRenderer("cell",a),f="";for(b=b||0,c=0;c<this.colCnt;c++)d=this.getCell(b,c),f+=e(d);return f=this.bookendCells(f,a,b),"<tr>"+f+"</tr>"},bookendCells:function(a,b,c){var d=this.getHtmlRenderer("intro",b)(c||0),e=this.getHtmlRenderer("outro",b)(c||0),f=this.isRTL?e:d,g=this.isRTL?d:e;return"string"==typeof a?f+a+g:a.prepend(f).append(g)},getHtmlRenderer:function(a,b){var c,d,e,f,g=this.view;return c=a+"Html",b&&(d=b+_(a)+"Html"),d&&(f=g[d])?e=g:d&&(f=this[d])?e=this:(f=g[c])?e=g:(f=this[c])&&(e=this),"function"==typeof f?function(){return f.apply(e,arguments)||""}:function(){return f||""}}}),jb=Ma.Grid=ib.extend({start:null,end:null,rowCnt:0,colCnt:0,el:null,coordMap:null,elsByFill:null,externalDragStartProxy:null,colHeadFormat:null,eventTimeFormat:null,displayEventTime:null,displayEventEnd:null,cellDuration:null,largeUnit:null,constructor:function(){ib.apply(this,arguments),this.coordMap=new db(this),this.elsByFill={},this.externalDragStartProxy=ca(this,"externalDragStart")},computeColHeadFormat:function(){},computeEventTimeFormat:function(){return this.view.opt("smallTimeFormat")},computeDisplayEventTime:function(){return!0},computeDisplayEventEnd:function(){return!0},setRange:function(a){this.start=a.start.clone(),this.end=a.end.clone(),this.rangeUpdated(),this.processRangeOptions()},rangeUpdated:function(){},processRangeOptions:function(){var a,b,c=this.view;this.colHeadFormat=c.opt("columnFormat")||this.computeColHeadFormat(),this.eventTimeFormat=c.opt("eventTimeFormat")||c.opt("timeFormat")||this.computeEventTimeFormat(),a=c.opt("displayEventTime"),null==a&&(a=this.computeDisplayEventTime()),b=c.opt("displayEventEnd"),null==b&&(b=this.computeDisplayEventEnd()),this.displayEventTime=a,this.displayEventEnd=b},build:function(){},clear:function(){},rangeToSegs:function(a){},diffDates:function(a,b){return this.largeUnit?H(a,b,this.largeUnit):F(a,b)},getCell:function(b,c){var d;return null==c&&("number"==typeof b?(c=b%this.colCnt,b=Math.floor(b/this.colCnt)):(c=b.col,b=b.row)),d={row:b,col:c},a.extend(d,this.getRowData(b),this.getColData(c)),a.extend(d,this.computeCellRange(d)),d},computeCellRange:function(a){var b=this.computeCellDate(a);return{start:b,end:b.clone().add(this.cellDuration)}},computeCellDate:function(a){},getRowData:function(a){return{}},getColData:function(a){return{}},getRowEl:function(a){},getColEl:function(a){},getCellDayEl:function(a){return this.getColEl(a.col)||this.getRowEl(a.row)},computeRowCoords:function(){var a,b,c,d=[];for(a=0;a<this.rowCnt;a++)b=this.getRowEl(a),c=b.offset().top,d.push({top:c,bottom:c+b.outerHeight()});return d},computeColCoords:function(){var a,b,c,d=[];for(a=0;a<this.colCnt;a++)b=this.getColEl(a),c=b.offset().left,d.push({left:c,right:c+b.outerWidth()});return d},setElement:function(b){var c=this;this.el=b,b.on("mousedown",function(b){a(b.target).is(".fc-event-container *, .fc-more")||a(b.target).closest(".fc-popover").length||c.dayMousedown(b)}),this.bindSegHandlers(),this.bindGlobalHandlers()},removeElement:function(){this.unbindGlobalHandlers(),this.el.remove()},renderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},bindGlobalHandlers:function(){a(document).on("dragstart sortstart",this.externalDragStartProxy)},unbindGlobalHandlers:function(){a(document).off("dragstart sortstart",this.externalDragStartProxy)},dayMousedown:function(a){var b,c,d=this,e=this.view,f=e.opt("selectable"),i=new gb(this.coordMap,{scroll:e.opt("dragScroll"),dragStart:function(){e.unselect()},cellOver:function(a,e,h){h&&(b=e?a:null,f&&(c=d.computeSelection(h,a),c?d.renderSelection(c):g()))},cellOut:function(a){b=null,c=null,d.unrenderSelection(),h()},listenStop:function(a){b&&e.triggerDayClick(b,d.getCellDayEl(b),a),c&&e.reportSelection(c,a),h()}});i.mousedown(a)},renderRangeHelper:function(a,b){var c=this.fabricateHelperEvent(a,b);this.renderHelper(c,b)},fabricateHelperEvent:function(a,b){var c=b?R(b.event):{};return c.start=a.start.clone(),c.end=a.end?a.end.clone():null,c.allDay=null,this.view.calendar.normalizeEventRange(c),c.className=(c.className||[]).concat("fc-helper"),b||(c.editable=!1),c},renderHelper:function(a,b){},unrenderHelper:function(){},renderSelection:function(a){this.renderHighlight(this.selectionRangeToSegs(a))},unrenderSelection:function(){this.unrenderHighlight()},computeSelection:function(a,b){var c,d=[a.start,a.end,b.start,b.end];return d.sort(aa),c={start:d[0].clone(),end:d[3].clone()},this.view.calendar.isSelectionRangeAllowed(c)?c:null},selectionRangeToSegs:function(a){return this.rangeToSegs(a)},renderHighlight:function(a){this.renderFill("highlight",a)},unrenderHighlight:function(){this.unrenderFill("highlight")},highlightSegClasses:function(){return["fc-highlight"]},renderFill:function(a,b){},unrenderFill:function(a){var b=this.elsByFill[a];b&&(b.remove(),delete this.elsByFill[a])},renderFillSegEls:function(b,c){var d,e=this,f=this[b+"SegEl"],g="",h=[];if(c.length){for(d=0;d<c.length;d++)g+=this.fillSegHtml(b,c[d]);a(g).each(function(b,d){var g=c[b],i=a(d);f&&(i=f.call(e,g,i)),i&&(i=a(i),i.is(e.fillSegTag)&&(g.el=i,h.push(g)))})}return h},fillSegTag:"div",fillSegHtml:function(a,b){var c=this[a+"SegClasses"],d=this[a+"SegCss"],e=c?c.call(this,b):[],f=$(d?d.call(this,b):{});return"<"+this.fillSegTag+(e.length?' class="'+e.join(" ")+'"':"")+(f?' style="'+f+'"':"")+" />"},headHtml:function(){return'<div class="fc-row '+this.view.widgetHeaderClass+'"><table><thead>'+this.rowHtml("head")+"</thead></table></div>"},headCellHtml:function(a){var b=this.view,c=a.start;return'<th class="fc-day-header '+b.widgetHeaderClass+" fc-"+Qa[c.day()]+'">'+Y(c.format(this.colHeadFormat))+"</th>"},bgCellHtml:function(a){var b=this.view,c=a.start,d=this.getDayClasses(c);return d.unshift("fc-day",b.widgetContentClass),'<td class="'+d.join(" ")+'" data-date="'+c.format("YYYY-MM-DD")+'"></td>'},getDayClasses:function(a){var b=this.view,c=b.calendar.getNow().stripTime(),d=["fc-"+Qa[a.day()]];return 1==b.intervalDuration.as("months")&&a.month()!=b.intervalStart.month()&&d.push("fc-other-month"),a.isSame(c,"day")?d.push("fc-today",b.highlightStateClass):c>a?d.push("fc-past"):d.push("fc-future"),d}});jb.mixin({mousedOverSeg:null,isDraggingSeg:!1,isResizingSeg:!1,isDraggingExternal:!1,segs:null,renderEvents:function(a){var b,c,d=this.eventsToSegs(a),e=[],f=[];for(b=0;b<d.length;b++)c=d[b],ta(c.event)?e.push(c):f.push(c);e=this.renderBgSegs(e)||e,f=this.renderFgSegs(f)||f,this.segs=e.concat(f)},unrenderEvents:function(){this.triggerSegMouseout(),this.unrenderFgSegs(),this.unrenderBgSegs(),this.segs=null},getEventSegs:function(){return this.segs||[]},renderFgSegs:function(a){},unrenderFgSegs:function(){},renderFgSegEls:function(b,c){var d,e=this.view,f="",g=[];if(b.length){for(d=0;d<b.length;d++)f+=this.fgSegHtml(b[d],c);a(f).each(function(c,d){var f=b[c],h=e.resolveEventEl(f.event,a(d));h&&(h.data("fc-seg",f),f.el=h,g.push(f))})}return g},fgSegHtml:function(a,b){},renderBgSegs:function(a){return this.renderFill("bgEvent",a)},unrenderBgSegs:function(){this.unrenderFill("bgEvent")},bgEventSegEl:function(a,b){return this.view.resolveEventEl(a.event,b)},bgEventSegClasses:function(a){var b=a.event,c=b.source||{};return["fc-bgevent"].concat(b.className,c.className||[])},bgEventSegCss:function(a){var b=this.view,c=a.event,d=c.source||{};return{"background-color":c.backgroundColor||c.color||d.backgroundColor||d.color||b.opt("eventBackgroundColor")||b.opt("eventColor")}},businessHoursSegClasses:function(a){return["fc-nonbusiness","fc-bgevent"]},bindSegHandlers:function(){var b=this,c=this.view;a.each({mouseenter:function(a,c){b.triggerSegMouseover(a,c)},mouseleave:function(a,c){b.triggerSegMouseout(a,c)},click:function(a,b){return c.trigger("eventClick",this,a.event,b)},mousedown:function(d,e){a(e.target).is(".fc-resizer")&&c.isEventResizable(d.event)?b.segResizeMousedown(d,e,a(e.target).is(".fc-start-resizer")):c.isEventDraggable(d.event)&&b.segDragMousedown(d,e)}},function(c,d){b.el.on(c,".fc-event-container > *",function(c){var e=a(this).data("fc-seg");return!e||b.isDraggingSeg||b.isResizingSeg?void 0:d.call(this,e,c)})})},triggerSegMouseover:function(a,b){this.mousedOverSeg||(this.mousedOverSeg=a,this.view.trigger("eventMouseover",a.el[0],a.event,b))},triggerSegMouseout:function(a,b){b=b||{},this.mousedOverSeg&&(a=a||this.mousedOverSeg,this.mousedOverSeg=null,this.view.trigger("eventMouseout",a.el[0],a.event,b))},segDragMousedown:function(a,b){var c,d=this,e=this.view,f=e.calendar,i=a.el,j=a.event,k=new hb(a.el,{parentEl:e.el,opacity:e.opt("dragOpacity"),revertDuration:e.opt("dragRevertDuration"),zIndex:2}),l=new gb(e.coordMap,{distance:5,scroll:e.opt("dragScroll"),subjectEl:i,subjectCenter:!0,listenStart:function(a){k.hide(),k.start(a)},dragStart:function(b){d.triggerSegMouseout(a,b),d.segDragStart(a,b),e.hideEvent(j)},cellOver:function(b,h,i){a.cell&&(i=a.cell),c=d.computeEventDrop(i,b,j),c&&!f.isEventRangeAllowed(c,j)&&(g(),c=null),c&&e.renderDrag(c,a)?k.hide():k.show(),h&&(c=null)},cellOut:function(){e.unrenderDrag(),k.show(),c=null},cellDone:function(){h()},dragStop:function(b){k.stop(!c,function(){e.unrenderDrag(),e.showEvent(j),d.segDragStop(a,b),c&&e.reportEventDrop(j,c,this.largeUnit,i,b)})},listenStop:function(){k.stop()}});l.mousedown(b)},segDragStart:function(a,b){this.isDraggingSeg=!0,this.view.trigger("eventDragStart",a.el[0],a.event,b,{})},segDragStop:function(a,b){this.isDraggingSeg=!1,this.view.trigger("eventDragStop",a.el[0],a.event,b,{})},computeEventDrop:function(a,b,c){var d,e,f=this.view.calendar,g=a.start,h=b.start;return g.hasTime()===h.hasTime()?(d=this.diffDates(h,g),c.allDay&&N(d)?(e={start:c.start.clone(),end:f.getEventEnd(c),allDay:!1},f.normalizeEventRangeTimes(e)):e={start:c.start.clone(),end:c.end?c.end.clone():null,allDay:c.allDay},e.start.add(d),e.end&&e.end.add(d)):e={start:h.clone(),end:null,allDay:!h.hasTime()},e},applyDragOpacity:function(a){var b=this.view.opt("dragOpacity");null!=b&&a.each(function(a,c){c.style.opacity=b})},externalDragStart:function(b,c){var d,e,f=this.view;f.opt("droppable")&&(d=a((c?c.item:null)||b.target),e=f.opt("dropAccept"),(a.isFunction(e)?e.call(d[0],d):d.is(e))&&(this.isDraggingExternal||this.listenToExternalDrag(d,b,c)))},listenToExternalDrag:function(a,b,c){var d,e,f=this,i=ya(a);d=new gb(this.coordMap,{listenStart:function(){f.isDraggingExternal=!0},cellOver:function(a){e=f.computeExternalDrop(a,i),e?f.renderDrag(e):g()},cellOut:function(){e=null,f.unrenderDrag(),h()},dragStop:function(){f.unrenderDrag(),h(),e&&f.view.reportExternalDrop(i,e,a,b,c)},listenStop:function(){f.isDraggingExternal=!1}}),d.startDrag(b)},computeExternalDrop:function(a,b){var c={start:a.start.clone(),end:null};return b.startTime&&!c.start.hasTime()&&c.start.time(b.startTime),b.duration&&(c.end=c.start.clone().add(b.duration)),this.view.calendar.isExternalDropRangeAllowed(c,b.eventProps)?c:null},renderDrag:function(a,b){},unrenderDrag:function(){},segResizeMousedown:function(a,b,c){var d,e,f=this,i=this.view,j=i.calendar,k=a.el,l=a.event,m=j.getEventEnd(l);d=new gb(this.coordMap,{distance:5,scroll:i.opt("dragScroll"),subjectEl:k,dragStart:function(b){f.triggerSegMouseout(a,b),f.segResizeStart(a,b)},cellOver:function(b,d,h){e=c?f.computeEventStartResize(h,b,l):f.computeEventEndResize(h,b,l),e&&(j.isEventRangeAllowed(e,l)?e.start.isSame(l.start)&&e.end.isSame(m)&&(e=null):(g(),e=null)),e&&(i.hideEvent(l),f.renderEventResize(e,a))},cellOut:function(){e=null},cellDone:function(){f.unrenderEventResize(),i.showEvent(l),h()},dragStop:function(b){f.segResizeStop(a,b),e&&i.reportEventResize(l,e,this.largeUnit,k,b)}}),d.mousedown(b)},segResizeStart:function(a,b){this.isResizingSeg=!0,this.view.trigger("eventResizeStart",a.el[0],a.event,b,{})},segResizeStop:function(a,b){this.isResizingSeg=!1,this.view.trigger("eventResizeStop",a.el[0],a.event,b,{})},computeEventStartResize:function(a,b,c){return this.computeEventResize("start",a,b,c)},computeEventEndResize:function(a,b,c){return this.computeEventResize("end",a,b,c)},computeEventResize:function(a,b,c,d){var e,f,g=this.view.calendar,h=this.diffDates(c[a],b[a]);return e={start:d.start.clone(),end:g.getEventEnd(d),allDay:d.allDay},e.allDay&&N(h)&&(e.allDay=!1,g.normalizeEventRangeTimes(e)),e[a].add(h),e.start.isBefore(e.end)||(f=d.allDay?g.defaultAllDayEventDuration:g.defaultTimedEventDuration,this.cellDuration&&this.cellDuration<f&&(f=this.cellDuration),"start"==a?e.start=e.end.clone().subtract(f):e.end=e.start.clone().add(f)),e},renderEventResize:function(a,b){},unrenderEventResize:function(){},getEventTimeText:function(a,b,c){return null==b&&(b=this.eventTimeFormat),null==c&&(c=this.displayEventEnd),this.displayEventTime&&a.start.hasTime()?c&&a.end?this.view.formatRange(a,b):a.start.format(b):""},getSegClasses:function(a,b,c){var d=a.event,e=["fc-event",a.isStart?"fc-start":"fc-not-start",a.isEnd?"fc-end":"fc-not-end"].concat(d.className,d.source?d.source.className:[]);return b&&e.push("fc-draggable"),c&&e.push("fc-resizable"),e},getEventSkinCss:function(a){var b=this.view,c=a.source||{},d=a.color,e=c.color,f=b.opt("eventColor");return{"background-color":a.backgroundColor||d||c.backgroundColor||e||b.opt("eventBackgroundColor")||f,"border-color":a.borderColor||d||c.borderColor||e||b.opt("eventBorderColor")||f,color:a.textColor||c.textColor||b.opt("eventTextColor")}},eventsToSegs:function(a,b){var c,d=this.eventsToRanges(a),e=[];for(c=0;c<d.length;c++)e.push.apply(e,this.eventRangeToSegs(d[c],b));return e},eventsToRanges:function(b){var c=this,d=wa(b),e=[];return a.each(d,function(a,b){b.length&&e.push.apply(e,ua(b[0])?c.eventsToInverseRanges(b):c.eventsToNormalRanges(b))}),e},eventsToNormalRanges:function(a){var b,c,d,e,f=this.view.calendar,g=[];for(b=0;b<a.length;b++)c=a[b],d=c.start.clone().stripZone(),e=f.getEventEnd(c).stripZone(),g.push({event:c,start:d,end:e,eventStartMS:+d,eventDurationMS:e-d});return g},eventsToInverseRanges:function(a){var b,c,d=this.view,e=d.start.clone().stripZone(),f=d.end.clone().stripZone(),g=this.eventsToNormalRanges(a),h=[],i=a[0],j=e;for(g.sort(xa),b=0;b<g.length;b++)c=g[b],c.start>j&&h.push({event:i,start:j,end:c.start}),j=c.end;return f>j&&h.push({event:i,start:j,end:f}),h},eventRangeToSegs:function(a,b){var c,d,e;for(a=this.view.calendar.ensureVisibleEventRange(a),c=b?b(a):this.rangeToSegs(a),d=0;d<c.length;d++)e=c[d],e.event=a.event,e.eventStartMS=a.eventStartMS,e.eventDurationMS=a.eventDurationMS;return c},sortSegs:function(a){a.sort(ca(this,"compareSegs"))},compareSegs:function(a,b){return a.eventStartMS-b.eventStartMS||b.eventDurationMS-a.eventDurationMS||b.event.allDay-a.event.allDay||B(a.event,b.event,this.view.eventOrderSpecs)}}),Ma.dataAttrPrefix="";var kb=jb.extend({numbersVisible:!1,bottomCoordPadding:0,breakOnWeeks:null,cellDates:null,dayToCellOffsets:null,rowEls:null,dayEls:null,helperEls:null,constructor:function(){jb.apply(this,arguments),this.cellDuration=b.duration(1,"day")},renderDates:function(a){var b,c,d,e=this.view,f=this.rowCnt,g=this.colCnt,h=f*g,i="";for(b=0;f>b;b++)i+=this.dayRowHtml(b,a);for(this.el.html(i),this.rowEls=this.el.find(".fc-row"),this.dayEls=this.el.find(".fc-day"),c=0;h>c;c++)d=this.getCell(c),e.trigger("dayRender",null,d.start,this.dayEls.eq(c))},unrenderDates:function(){this.removeSegPopover()},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents(!0),b=this.eventsToSegs(a);this.renderFill("businessHours",b,"bgevent")},dayRowHtml:function(a,b){var c=this.view,d=["fc-row","fc-week",c.widgetContentClass];return b&&d.push("fc-rigid"),'<div class="'+d.join(" ")+'"><div class="fc-bg"><table>'+this.rowHtml("day",a)+'</table></div><div class="fc-content-skeleton"><table>'+(this.numbersVisible?"<thead>"+this.rowHtml("number",a)+"</thead>":"")+"</table></div></div>"},dayCellHtml:function(a){return this.bgCellHtml(a)},computeColHeadFormat:function(){return this.rowCnt>1?"ddd":this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},computeEventTimeFormat:function(){return this.view.opt("extraSmallTimeFormat")},computeDisplayEventEnd:function(){return 1==this.colCnt},rangeUpdated:function(){var a,b,c,d;if(this.updateCellDates(),a=this.cellDates,this.breakOnWeeks){for(b=a[0].day(),d=1;d<a.length&&a[d].day()!=b;d++);c=Math.ceil(a.length/d)}else c=1,d=a.length;this.rowCnt=c,this.colCnt=d},updateCellDates:function(){for(var a=this.view,b=this.start.clone(),c=[],d=-1,e=[];b.isBefore(this.end);)a.isHiddenDay(b)?e.push(d+.5):(d++,e.push(d),c.push(b.clone())),b.add(1,"days");this.cellDates=c,this.dayToCellOffsets=e},computeCellDate:function(a){var b=this.colCnt,c=a.row*b+(this.isRTL?b-a.col-1:a.col);return this.cellDates[c].clone()},getRowEl:function(a){return this.rowEls.eq(a)},getColEl:function(a){return this.dayEls.eq(a)},getCellDayEl:function(a){return this.dayEls.eq(a.row*this.colCnt+a.col)},computeRowCoords:function(){var a=jb.prototype.computeRowCoords.call(this);return a[a.length-1].bottom+=this.bottomCoordPadding,a},rangeToSegs:function(a){var b,c,d,e,f,g,h,i,j,k,l=this.isRTL,m=this.rowCnt,n=this.colCnt,o=[];for(a=this.view.computeDayRange(a),b=this.dateToCellOffset(a.start),c=this.dateToCellOffset(a.end.subtract(1,"days")),d=0;m>d;d++)e=d*n,f=e+n-1,i=Math.max(e,b),j=Math.min(f,c),i=Math.ceil(i),j=Math.floor(j),j>=i&&(g=i===b,h=j===c,i-=e,j-=e,k={row:d,isStart:g,isEnd:h},l?(k.leftCol=n-j-1,k.rightCol=n-i-1):(k.leftCol=i,k.rightCol=j),o.push(k));return o},dateToCellOffset:function(a){var b=this.dayToCellOffsets,c=a.diff(this.start,"days");return 0>c?b[0]-1:c>=b.length?b[b.length-1]+1:b[c]},renderDrag:function(a,b){return this.renderHighlight(this.eventRangeToSegs(a)),b&&!b.el.closest(this.el).length?(this.renderRangeHelper(a,b),this.applyDragOpacity(this.helperEls),!0):void 0},unrenderDrag:function(){this.unrenderHighlight(),this.unrenderHelper()},renderEventResize:function(a,b){this.renderHighlight(this.eventRangeToSegs(a)),this.renderRangeHelper(a,b)},unrenderEventResize:function(){this.unrenderHighlight(),this.unrenderHelper()},renderHelper:function(b,c){var d,e=[],f=this.eventsToSegs([b]);f=this.renderFgSegEls(f),d=this.renderSegRows(f),this.rowEls.each(function(b,f){var g,h=a(f),i=a('<div class="fc-helper-skeleton"><table/></div>');g=c&&c.row===b?c.el.position().top:h.find(".fc-content-skeleton tbody").position().top,i.css("top",g).find("table").append(d[b].tbodyEl),h.append(i),e.push(i[0])}),this.helperEls=a(e)},unrenderHelper:function(){this.helperEls&&(this.helperEls.remove(),this.helperEls=null)},fillSegTag:"td",renderFill:function(b,c,d){var e,f,g,h=[];for(c=this.renderFillSegEls(b,c),e=0;e<c.length;e++)f=c[e],g=this.renderFillRow(b,f,d),this.rowEls.eq(f.row).append(g),h.push(g[0]);return this.elsByFill[b]=a(h),c},renderFillRow:function(b,c,d){var e,f,g=this.colCnt,h=c.leftCol,i=c.rightCol+1;return d=d||b.toLowerCase(),e=a('<div class="fc-'+d+'-skeleton"><table><tr/></table></div>'),f=e.find("tr"),h>0&&f.append('<td colspan="'+h+'"/>'),f.append(c.el.attr("colspan",i-h)),g>i&&f.append('<td colspan="'+(g-i)+'"/>'),this.bookendCells(f,b),e}});kb.mixin({rowStructs:null,unrenderEvents:function(){this.removeSegPopover(),jb.prototype.unrenderEvents.apply(this,arguments)},getEventSegs:function(){return jb.prototype.getEventSegs.call(this).concat(this.popoverSegs||[])},renderBgSegs:function(b){var c=a.grep(b,function(a){return a.event.allDay});return jb.prototype.renderBgSegs.call(this,c)},renderFgSegs:function(b){var c;return b=this.renderFgSegEls(b),c=this.rowStructs=this.renderSegRows(b),this.rowEls.each(function(b,d){a(d).find(".fc-content-skeleton > table").append(c[b].tbodyEl)}),b},unrenderFgSegs:function(){for(var a,b=this.rowStructs||[];a=b.pop();)a.tbodyEl.remove();this.rowStructs=null},renderSegRows:function(a){var b,c,d=[];for(b=this.groupSegRows(a),c=0;c<b.length;c++)d.push(this.renderSegRow(c,b[c]));return d},fgSegHtml:function(a,b){var c,d,e=this.view,f=a.event,g=e.isEventDraggable(f),h=!b&&f.allDay&&a.isStart&&e.isEventResizableFromStart(f),i=!b&&f.allDay&&a.isEnd&&e.isEventResizableFromEnd(f),j=this.getSegClasses(a,g,h||i),k=$(this.getEventSkinCss(f)),l="";return j.unshift("fc-day-grid-event","fc-h-event"),a.isStart&&(c=this.getEventTimeText(f),c&&(l='<span class="fc-time">'+Y(c)+"</span>")),d='<span class="fc-title">'+(Y(f.title||"")||" ")+"</span>",'<a class="'+j.join(" ")+'"'+(f.url?' href="'+Y(f.url)+'"':"")+(k?' style="'+k+'"':"")+'><div class="fc-content">'+(this.isRTL?d+" "+l:l+" "+d)+"</div>"+(h?'<div class="fc-resizer fc-start-resizer" />':"")+(i?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},renderSegRow:function(b,c){function d(b){for(;b>g;)k=(r[e-1]||[])[g],k?k.attr("rowspan",parseInt(k.attr("rowspan")||1,10)+1):(k=a("<td/>"),h.append(k)),q[e][g]=k,r[e][g]=k,g++}var e,f,g,h,i,j,k,l=this.colCnt,m=this.buildSegLevels(c),n=Math.max(1,m.length),o=a("<tbody/>"),p=[],q=[],r=[];for(e=0;n>e;e++){if(f=m[e],g=0,h=a("<tr/>"),p.push([]),q.push([]),r.push([]),f)for(i=0;i<f.length;i++){for(j=f[i],d(j.leftCol),k=a('<td class="fc-event-container"/>').append(j.el),j.leftCol!=j.rightCol?k.attr("colspan",j.rightCol-j.leftCol+1):r[e][g]=k;g<=j.rightCol;)q[e][g]=k,p[e][g]=j,g++;h.append(k)}d(l),this.bookendCells(h,"eventSkeleton"),o.append(h)}return{row:b,tbodyEl:o,cellMatrix:q,segMatrix:p,segLevels:m,segs:c}},buildSegLevels:function(a){var b,c,d,e=[];for(this.sortSegs(a),b=0;b<a.length;b++){for(c=a[b],d=0;d<e.length&&za(c,e[d]);d++);c.level=d,(e[d]||(e[d]=[])).push(c)}for(d=0;d<e.length;d++)e[d].sort(Aa);return e},groupSegRows:function(a){var b,c=[];for(b=0;b<this.rowCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].row].push(a[b]);return c}}),kb.mixin({segPopover:null,popoverSegs:null,removeSegPopover:function(){this.segPopover&&this.segPopover.hide()},limitRows:function(a){var b,c,d=this.rowStructs||[];for(b=0;b<d.length;b++)this.unlimitRow(b),c=a?"number"==typeof a?a:this.computeRowLevelLimit(b):!1,c!==!1&&this.limitRow(b,c)},computeRowLevelLimit:function(b){function c(b,c){f=Math.max(f,a(c).outerHeight())}var d,e,f,g=this.rowEls.eq(b),h=g.height(),i=this.rowStructs[b].tbodyEl.children();for(d=0;d<i.length;d++)if(e=i.eq(d).removeClass("fc-limited"),f=0,e.find("> td > :first-child").each(c),e.position().top+f>h)return d;return!1},limitRow:function(b,c){function d(d){for(;d>x;)e=u.getCell(b,x),k=u.getCellSegs(e,c),k.length&&(n=g[c-1][x],t=u.renderMoreLink(e,k),s=a("<div/>").append(t),n.append(s),w.push(s[0])),x++}var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u=this,v=this.rowStructs[b],w=[],x=0;if(c&&c<v.segLevels.length){for(f=v.segLevels[c-1],g=v.cellMatrix,h=v.tbodyEl.children().slice(c).addClass("fc-limited").get(),i=0;i<f.length;i++){for(j=f[i],d(j.leftCol),m=[],l=0;x<=j.rightCol;)e=this.getCell(b,x),k=this.getCellSegs(e,c),m.push(k),l+=k.length,x++;if(l){for(n=g[c-1][j.leftCol],o=n.attr("rowspan")||1,p=[],q=0;q<m.length;q++)r=a('<td class="fc-more-cell"/>').attr("rowspan",o),k=m[q],e=this.getCell(b,j.leftCol+q),t=this.renderMoreLink(e,[j].concat(k)),s=a("<div/>").append(t),r.append(s),p.push(r[0]),w.push(r[0]);n.addClass("fc-limited").after(a(p)),h.push(n[0])}}d(this.colCnt),v.moreEls=a(w),v.limitedEls=a(h)}},
|
8 |
+
unlimitRow:function(a){var b=this.rowStructs[a];b.moreEls&&(b.moreEls.remove(),b.moreEls=null),b.limitedEls&&(b.limitedEls.removeClass("fc-limited"),b.limitedEls=null)},renderMoreLink:function(b,c){var d=this,e=this.view;return a('<a class="fc-more"/>').text(this.getMoreLinkText(c.length)).on("click",function(f){var g=e.opt("eventLimitClick"),h=b.start,i=a(this),j=d.getCellDayEl(b),k=d.getCellSegs(b),l=d.resliceDaySegs(k,h),m=d.resliceDaySegs(c,h);"function"==typeof g&&(g=e.trigger("eventLimitClick",null,{date:h,dayEl:j,moreEl:i,segs:l,hiddenSegs:m},f)),"popover"===g?d.showSegPopover(b,i,l):"string"==typeof g&&e.calendar.zoomTo(h,g)})},showSegPopover:function(a,b,c){var d,e,f=this,g=this.view,h=b.parent();d=1==this.rowCnt?g.el:this.rowEls.eq(a.row),e={className:"fc-more-popover",content:this.renderSegPopoverContent(a,c),parentEl:this.el,top:d.offset().top,autoHide:!0,viewportConstrain:g.opt("popoverViewportConstrain"),hide:function(){f.segPopover.removeElement(),f.segPopover=null,f.popoverSegs=null}},this.isRTL?e.right=h.offset().left+h.outerWidth()+1:e.left=h.offset().left-1,this.segPopover=new cb(e),this.segPopover.show()},renderSegPopoverContent:function(b,c){var d,e=this.view,f=e.opt("theme"),g=b.start.format(e.opt("dayPopoverFormat")),h=a('<div class="fc-header '+e.widgetHeaderClass+'"><span class="fc-close '+(f?"ui-icon ui-icon-closethick":"fc-icon fc-icon-x")+'"></span><span class="fc-title">'+Y(g)+'</span><div class="fc-clear"/></div><div class="fc-body '+e.widgetContentClass+'"><div class="fc-event-container"></div></div>'),i=h.find(".fc-event-container");for(c=this.renderFgSegEls(c,!0),this.popoverSegs=c,d=0;d<c.length;d++)c[d].cell=b,i.append(c[d].el);return h},resliceDaySegs:function(b,c){var d=a.map(b,function(a){return a.event}),e=c.clone().stripTime(),f=e.clone().add(1,"days"),g={start:e,end:f};return b=this.eventsToSegs(d,function(a){var b=E(a,g);return b?[b]:[]}),this.sortSegs(b),b},getMoreLinkText:function(a){var b=this.view.opt("eventLimitText");return"function"==typeof b?b(a):"+"+a+" "+b},getCellSegs:function(a,b){for(var c,d=this.rowStructs[a.row].segMatrix,e=b||0,f=[];e<d.length;)c=d[e][a.col],c&&f.push(c),e++;return f}});var lb=jb.extend({slotDuration:null,snapDuration:null,minTime:null,maxTime:null,colDates:null,labelFormat:null,labelInterval:null,dayEls:null,slatEls:null,slatTops:null,helperEl:null,businessHourSegs:null,constructor:function(){jb.apply(this,arguments),this.processOptions()},renderDates:function(){this.el.html(this.renderHtml()),this.dayEls=this.el.find(".fc-day"),this.slatEls=this.el.find(".fc-slats tr")},renderBusinessHours:function(){var a=this.view.calendar.getBusinessHoursEvents();this.businessHourSegs=this.renderFill("businessHours",this.eventsToSegs(a),"bgevent")},renderHtml:function(){return'<div class="fc-bg"><table>'+this.rowHtml("slotBg")+'</table></div><div class="fc-slats"><table>'+this.slatRowHtml()+"</table></div>"},slotBgCellHtml:function(a){return this.bgCellHtml(a)},slatRowHtml:function(){for(var a,c,d,e=this.view,f=this.isRTL,g="",h=b.duration(+this.minTime);h<this.maxTime;)a=this.start.clone().time(h),c=ba(L(h,this.labelInterval)),d='<td class="fc-axis fc-time '+e.widgetContentClass+'" '+e.axisStyleAttr()+">"+(c?"<span>"+Y(a.format(this.labelFormat))+"</span>":"")+"</td>",g+="<tr "+(c?"":'class="fc-minor"')+">"+(f?"":d)+'<td class="'+e.widgetContentClass+'"/>'+(f?d:"")+"</tr>",h.add(this.slotDuration);return g},processOptions:function(){var c,d=this.view,e=d.opt("slotDuration"),f=d.opt("snapDuration");e=b.duration(e),f=f?b.duration(f):e,this.slotDuration=e,this.snapDuration=f,this.cellDuration=f,this.minTime=b.duration(d.opt("minTime")),this.maxTime=b.duration(d.opt("maxTime")),c=d.opt("slotLabelFormat"),a.isArray(c)&&(c=c[c.length-1]),this.labelFormat=c||d.opt("axisFormat")||d.opt("smallTimeFormat"),c=d.opt("slotLabelInterval"),this.labelInterval=c?b.duration(c):this.computeLabelInterval(e)},computeLabelInterval:function(a){var c,d,e;for(c=yb.length-1;c>=0;c--)if(d=b.duration(yb[c]),e=L(d,a),ba(e)&&e>1)return d;return b.duration(a)},computeColHeadFormat:function(){return this.colCnt>1?this.view.opt("dayOfMonthFormat"):"dddd"},computeEventTimeFormat:function(){return this.view.opt("noMeridiemTimeFormat")},computeDisplayEventEnd:function(){return!0},rangeUpdated:function(){var a,b=this.view,c=[];for(a=this.start.clone();a.isBefore(this.end);)c.push(a.clone()),a.add(1,"day"),a=b.skipHiddenDays(a);this.isRTL&&c.reverse(),this.colDates=c,this.colCnt=c.length,this.rowCnt=Math.ceil((this.maxTime-this.minTime)/this.snapDuration)},computeCellDate:function(a){var b=this.colDates[a.col],c=this.computeSnapTime(a.row);return b=this.view.calendar.rezoneDate(b),b.time(c),b},getColEl:function(a){return this.dayEls.eq(a)},computeSnapTime:function(a){return b.duration(this.minTime+this.snapDuration*a)},rangeToSegs:function(a){var b,c,d,e,f=this.colCnt,g=[];for(a={start:a.start.clone().stripZone(),end:a.end.clone().stripZone()},c=0;f>c;c++)d=this.colDates[c],e={start:d.clone().time(this.minTime),end:d.clone().time(this.maxTime)},b=E(a,e),b&&(b.col=c,g.push(b));return g},updateSize:function(a){this.computeSlatTops(),a&&this.updateSegVerticals()},computeRowCoords:function(){var a,b,c=this.el.offset().top,d=[];for(a=0;a<this.rowCnt;a++)b={top:c+this.computeTimeTop(this.computeSnapTime(a))},a>0&&(d[a-1].bottom=b.top),d.push(b);return b.bottom=b.top+this.computeTimeTop(this.computeSnapTime(a)),d},computeDateTop:function(a,c){return this.computeTimeTop(b.duration(a.clone().stripZone()-c.clone().stripTime()))},computeTimeTop:function(a){var b,c,d,e,f=(a-this.minTime)/this.slotDuration;return f=Math.max(0,f),f=Math.min(this.slatEls.length,f),b=Math.floor(f),c=f-b,d=this.slatTops[b],c?(e=this.slatTops[b+1],d+(e-d)*c):d},computeSlatTops:function(){var b,c=[];this.slatEls.each(function(d,e){b=a(e).position().top,c.push(b)}),c.push(b+this.slatEls.last().outerHeight()),this.slatTops=c},renderDrag:function(a,b){return b?(this.renderRangeHelper(a,b),this.applyDragOpacity(this.helperEl),!0):void this.renderHighlight(this.eventRangeToSegs(a))},unrenderDrag:function(){this.unrenderHelper(),this.unrenderHighlight()},renderEventResize:function(a,b){this.renderRangeHelper(a,b)},unrenderEventResize:function(){this.unrenderHelper()},renderHelper:function(b,c){var d,e,f,g,h=this.eventsToSegs([b]);for(h=this.renderFgSegEls(h),d=this.renderSegTable(h),e=0;e<h.length;e++)f=h[e],c&&c.col===f.col&&(g=c.el,f.el.css({left:g.css("left"),right:g.css("right"),"margin-left":g.css("margin-left"),"margin-right":g.css("margin-right")}));this.helperEl=a('<div class="fc-helper-skeleton"/>').append(d).appendTo(this.el)},unrenderHelper:function(){this.helperEl&&(this.helperEl.remove(),this.helperEl=null)},renderSelection:function(a){this.view.opt("selectHelper")?this.renderRangeHelper(a):this.renderHighlight(this.selectionRangeToSegs(a))},unrenderSelection:function(){this.unrenderHelper(),this.unrenderHighlight()},renderFill:function(b,c,d){var e,f,g,h,i,j,k,l,m,n;if(c.length){for(c=this.renderFillSegEls(b,c),e=this.groupSegCols(c),d=d||b.toLowerCase(),f=a('<div class="fc-'+d+'-skeleton"><table><tr/></table></div>'),g=f.find("tr"),h=0;h<e.length;h++)if(i=e[h],j=a("<td/>").appendTo(g),i.length)for(k=a('<div class="fc-'+d+'-container"/>').appendTo(j),l=this.colDates[h],m=0;m<i.length;m++)n=i[m],k.append(n.el.css({top:this.computeDateTop(n.start,l),bottom:-this.computeDateTop(n.end,l)}));this.bookendCells(g,b),this.el.append(f),this.elsByFill[b]=f}return c}});lb.mixin({eventSkeletonEl:null,renderFgSegs:function(b){return b=this.renderFgSegEls(b),this.el.append(this.eventSkeletonEl=a('<div class="fc-content-skeleton"/>').append(this.renderSegTable(b))),b},unrenderFgSegs:function(a){this.eventSkeletonEl&&(this.eventSkeletonEl.remove(),this.eventSkeletonEl=null)},renderSegTable:function(b){var c,d,e,f,g,h,i=a("<table><tr/></table>"),j=i.find("tr");for(c=this.groupSegCols(b),this.computeSegVerticals(b),f=0;f<c.length;f++){for(g=c[f],this.placeSlotSegs(g),h=a('<div class="fc-event-container"/>'),d=0;d<g.length;d++)e=g[d],e.el.css(this.generateSegPositionCss(e)),e.bottom-e.top<30&&e.el.addClass("fc-short"),h.append(e.el);j.append(a("<td/>").append(h))}return this.bookendCells(j,"eventSkeleton"),i},placeSlotSegs:function(a){var b,c,d;if(this.sortSegs(a),b=Ba(a),Ca(b),c=b[0]){for(d=0;d<c.length;d++)Da(c[d]);for(d=0;d<c.length;d++)this.computeSlotSegCoords(c[d],0,0)}},computeSlotSegCoords:function(a,b,c){var d,e=a.forwardSegs;if(void 0===a.forwardCoord)for(e.length?(this.sortForwardSlotSegs(e),this.computeSlotSegCoords(e[0],b+1,c),a.forwardCoord=e[0].backwardCoord):a.forwardCoord=1,a.backwardCoord=a.forwardCoord-(a.forwardCoord-c)/(b+1),d=0;d<e.length;d++)this.computeSlotSegCoords(e[d],0,a.forwardCoord)},updateSegVerticals:function(){var a,b=(this.segs||[]).concat(this.businessHourSegs||[]);for(this.computeSegVerticals(b),a=0;a<b.length;a++)b[a].el.css(this.generateSegVerticalCss(b[a]))},computeSegVerticals:function(a){var b,c;for(b=0;b<a.length;b++)c=a[b],c.top=this.computeDateTop(c.start,c.start),c.bottom=this.computeDateTop(c.end,c.start)},fgSegHtml:function(a,b){var c,d,e,f=this.view,g=a.event,h=f.isEventDraggable(g),i=!b&&a.isStart&&f.isEventResizableFromStart(g),j=!b&&a.isEnd&&f.isEventResizableFromEnd(g),k=this.getSegClasses(a,h,i||j),l=$(this.getEventSkinCss(g));return k.unshift("fc-time-grid-event","fc-v-event"),f.isMultiDayEvent(g)?(a.isStart||a.isEnd)&&(c=this.getEventTimeText(a),d=this.getEventTimeText(a,"LT"),e=this.getEventTimeText(a,null,!1)):(c=this.getEventTimeText(g),d=this.getEventTimeText(g,"LT"),e=this.getEventTimeText(g,null,!1)),'<a class="'+k.join(" ")+'"'+(g.url?' href="'+Y(g.url)+'"':"")+(l?' style="'+l+'"':"")+'><div class="fc-content">'+(c?'<div class="fc-time" data-start="'+Y(e)+'" data-full="'+Y(d)+'"><span>'+Y(c)+"</span></div>":"")+(g.title?'<div class="fc-title">'+Y(g.title)+"</div>":"")+'</div><div class="fc-bg"/>'+(j?'<div class="fc-resizer fc-end-resizer" />':"")+"</a>"},generateSegPositionCss:function(a){var b,c,d=this.view.opt("slotEventOverlap"),e=a.backwardCoord,f=a.forwardCoord,g=this.generateSegVerticalCss(a);return d&&(f=Math.min(1,e+2*(f-e))),this.isRTL?(b=1-f,c=e):(b=e,c=1-f),g.zIndex=a.level+1,g.left=100*b+"%",g.right=100*c+"%",d&&a.forwardPressure&&(g[this.isRTL?"marginLeft":"marginRight"]=20),g},generateSegVerticalCss:function(a){return{top:a.top,bottom:-a.bottom}},groupSegCols:function(a){var b,c=[];for(b=0;b<this.colCnt;b++)c.push([]);for(b=0;b<a.length;b++)c[a[b].col].push(a[b]);return c},sortForwardSlotSegs:function(a){a.sort(ca(this,"compareForwardSlotSegs"))},compareForwardSlotSegs:function(a,b){return b.forwardPressure-a.forwardPressure||(a.backwardCoord||0)-(b.backwardCoord||0)||this.compareSegs(a,b)}});var mb=Ma.View=ra.extend({type:null,name:null,title:null,calendar:null,options:null,coordMap:null,el:null,displaying:null,isSkeletonRendered:!1,isEventsRendered:!1,start:null,end:null,intervalStart:null,intervalEnd:null,intervalDuration:null,intervalUnit:null,isRTL:!1,isSelected:!1,eventOrderSpecs:null,scrollerEl:null,scrollTop:null,widgetHeaderClass:null,widgetContentClass:null,highlightStateClass:null,nextDayThreshold:null,isHiddenDayHash:null,documentMousedownProxy:null,constructor:function(a,c,d,e){this.calendar=a,this.type=this.name=c,this.options=d,this.intervalDuration=e||b.duration(1,"day"),this.nextDayThreshold=b.duration(this.opt("nextDayThreshold")),this.initThemingProps(),this.initHiddenDays(),this.isRTL=this.opt("isRTL"),this.eventOrderSpecs=A(this.opt("eventOrder")),this.documentMousedownProxy=ca(this,"documentMousedown"),this.initialize()},initialize:function(){},opt:function(a){return this.options[a]},trigger:function(a,b){var c=this.calendar;return c.trigger.apply(c,[a,b||this].concat(Array.prototype.slice.call(arguments,2),[this]))},setDate:function(a){this.setRange(this.computeRange(a))},setRange:function(b){a.extend(this,b),this.updateTitle()},computeRange:function(a){var b,c,d=I(this.intervalDuration),e=a.clone().startOf(d),f=e.clone().add(this.intervalDuration);return/year|month|week|day/.test(d)?(e.stripTime(),f.stripTime()):(e.hasTime()||(e=this.calendar.rezoneDate(e)),f.hasTime()||(f=this.calendar.rezoneDate(f))),b=e.clone(),b=this.skipHiddenDays(b),c=f.clone(),c=this.skipHiddenDays(c,-1,!0),{intervalUnit:d,intervalStart:e,intervalEnd:f,start:b,end:c}},computePrevDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).subtract(this.intervalDuration),-1)},computeNextDate:function(a){return this.massageCurrentDate(a.clone().startOf(this.intervalUnit).add(this.intervalDuration))},massageCurrentDate:function(a,b){return this.intervalDuration.as("days")<=1&&this.isHiddenDay(a)&&(a=this.skipHiddenDays(a,b),a.startOf("day")),a},updateTitle:function(){this.title=this.computeTitle()},computeTitle:function(){return this.formatRange({start:this.intervalStart,end:this.intervalEnd},this.opt("titleFormat")||this.computeTitleFormat(),this.opt("titleRangeSeparator"))},computeTitleFormat:function(){return"year"==this.intervalUnit?"YYYY":"month"==this.intervalUnit?this.opt("monthYearFormat"):this.intervalDuration.as("days")>1?"ll":"LL"},formatRange:function(a,b,c){var d=a.end;return d.hasTime()||(d=d.clone().subtract(1)),ma(a.start,d,b,c,this.opt("isRTL"))},setElement:function(a){this.el=a,this.bindGlobalHandlers()},removeElement:function(){this.clear(),this.isSkeletonRendered&&(this.unrenderSkeleton(),this.isSkeletonRendered=!1),this.unbindGlobalHandlers(),this.el.remove()},display:function(b){var c=this,d=null;return this.displaying&&(d=this.queryScroll()),this.clear().then(function(){return c.displaying=a.when(c.displayView(b)).then(function(){c.forceScroll(c.computeInitialScroll(d)),c.triggerRender()})})},clear:function(){var b=this,c=this.displaying;return c?c.then(function(){return b.displaying=null,b.clearEvents(),b.clearView()}):a.when()},displayView:function(a){this.isSkeletonRendered||(this.renderSkeleton(),this.isSkeletonRendered=!0),this.setDate(a),this.render&&this.render(),this.renderDates(),this.updateSize(),this.renderBusinessHours()},clearView:function(){this.unselect(),this.triggerUnrender(),this.unrenderBusinessHours(),this.unrenderDates(),this.destroy&&this.destroy()},renderSkeleton:function(){},unrenderSkeleton:function(){},renderDates:function(){},unrenderDates:function(){},renderBusinessHours:function(){},unrenderBusinessHours:function(){},triggerRender:function(){this.trigger("viewRender",this,this,this.el)},triggerUnrender:function(){this.trigger("viewDestroy",this,this,this.el)},bindGlobalHandlers:function(){a(document).on("mousedown",this.documentMousedownProxy)},unbindGlobalHandlers:function(){a(document).off("mousedown",this.documentMousedownProxy)},initThemingProps:function(){var a=this.opt("theme")?"ui":"fc";this.widgetHeaderClass=a+"-widget-header",this.widgetContentClass=a+"-widget-content",this.highlightStateClass=a+"-state-highlight"},updateSize:function(a){var b;a&&(b=this.queryScroll()),this.updateHeight(a),this.updateWidth(a),a&&this.setScroll(b)},updateWidth:function(a){},updateHeight:function(a){var b=this.calendar;this.setHeight(b.getSuggestedViewHeight(),b.isHeightAuto())},setHeight:function(a,b){},computeScrollerHeight:function(a){var b,c,d=this.scrollerEl;return b=this.el.add(d),b.css({position:"relative",left:-1}),c=this.el.outerHeight()-d.height(),b.css({position:"",left:""}),a-c},computeInitialScroll:function(a){return 0},queryScroll:function(){return this.scrollerEl?this.scrollerEl.scrollTop():void 0},setScroll:function(a){return this.scrollerEl?this.scrollerEl.scrollTop(a):void 0},forceScroll:function(a){var b=this;this.setScroll(a),setTimeout(function(){b.setScroll(a)},0)},displayEvents:function(a){var b=this.queryScroll();this.clearEvents(),this.renderEvents(a),this.isEventsRendered=!0,this.setScroll(b),this.triggerEventRender()},clearEvents:function(){this.isEventsRendered&&(this.triggerEventUnrender(),this.destroyEvents&&this.destroyEvents(),this.unrenderEvents(),this.isEventsRendered=!1)},renderEvents:function(a){},unrenderEvents:function(){},triggerEventRender:function(){this.renderedEventSegEach(function(a){this.trigger("eventAfterRender",a.event,a.event,a.el)}),this.trigger("eventAfterAllRender")},triggerEventUnrender:function(){this.renderedEventSegEach(function(a){this.trigger("eventDestroy",a.event,a.event,a.el)})},resolveEventEl:function(b,c){var d=this.trigger("eventRender",b,b,c);return d===!1?c=null:d&&d!==!0&&(c=a(d)),c},showEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","")},a)},hideEvent:function(a){this.renderedEventSegEach(function(a){a.el.css("visibility","hidden")},a)},renderedEventSegEach:function(a,b){var c,d=this.getEventSegs();for(c=0;c<d.length;c++)b&&d[c].event._id!==b._id||d[c].el&&a.call(this,d[c])},getEventSegs:function(){return[]},isEventDraggable:function(a){var b=a.source||{};return X(a.startEditable,b.startEditable,this.opt("eventStartEditable"),a.editable,b.editable,this.opt("editable"))},reportEventDrop:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventDrop(a,g.dateDelta,h,d,e),f.reportEventChange()},triggerEventDrop:function(a,b,c,d,e){this.trigger("eventDrop",d[0],a,b,c,e,{})},reportExternalDrop:function(b,c,d,e,f){var g,h,i=b.eventProps;i&&(g=a.extend({},i,c),h=this.calendar.renderEvent(g,b.stick)[0]),this.triggerExternalDrop(h,c,d,e,f)},triggerExternalDrop:function(a,b,c,d,e){this.trigger("drop",c[0],b.start,d,e),a&&this.trigger("eventReceive",null,a)},renderDrag:function(a,b){},unrenderDrag:function(){},isEventResizableFromStart:function(a){return this.opt("eventResizableFromStart")&&this.isEventResizable(a)},isEventResizableFromEnd:function(a){return this.isEventResizable(a)},isEventResizable:function(a){var b=a.source||{};return X(a.durationEditable,b.durationEditable,this.opt("eventDurationEditable"),a.editable,b.editable,this.opt("editable"))},reportEventResize:function(a,b,c,d,e){var f=this.calendar,g=f.mutateEvent(a,b,c),h=function(){g.undo(),f.reportEventChange()};this.triggerEventResize(a,g.durationDelta,h,d,e),f.reportEventChange()},triggerEventResize:function(a,b,c,d,e){this.trigger("eventResize",d[0],a,b,c,e,{})},select:function(a,b){this.unselect(b),this.renderSelection(a),this.reportSelection(a,b)},renderSelection:function(a){},reportSelection:function(a,b){this.isSelected=!0,this.triggerSelect(a,b)},triggerSelect:function(a,b){this.trigger("select",null,a.start,a.end,b)},unselect:function(a){this.isSelected&&(this.isSelected=!1,this.destroySelection&&this.destroySelection(),this.unrenderSelection(),this.trigger("unselect",null,a))},unrenderSelection:function(){},documentMousedown:function(b){var c;this.isSelected&&this.opt("unselectAuto")&&v(b)&&(c=this.opt("unselectCancel"),c&&a(b.target).closest(c).length||this.unselect(b))},triggerDayClick:function(a,b,c){this.trigger("dayClick",b,a.start,c)},initHiddenDays:function(){var b,c=this.opt("hiddenDays")||[],d=[],e=0;for(this.opt("weekends")===!1&&c.push(0,6),b=0;7>b;b++)(d[b]=-1!==a.inArray(b,c))||e++;if(!e)throw"invalid hiddenDays";this.isHiddenDayHash=d},isHiddenDay:function(a){return b.isMoment(a)&&(a=a.day()),this.isHiddenDayHash[a]},skipHiddenDays:function(a,b,c){var d=a.clone();for(b=b||1;this.isHiddenDayHash[(d.day()+(c?b:0)+7)%7];)d.add(b,"days");return d},computeDayRange:function(a){var b,c=a.start.clone().stripTime(),d=a.end,e=null;return d&&(e=d.clone().stripTime(),b=+d.time(),b&&b>=this.nextDayThreshold&&e.add(1,"days")),(!d||c>=e)&&(e=c.clone().add(1,"days")),{start:c,end:e}},isMultiDayEvent:function(a){var b=this.computeDayRange(a);return b.end.diff(b.start,"days")>1}}),nb=Ma.Calendar=ra.extend({dirDefaults:null,langDefaults:null,overrides:null,options:null,viewSpecCache:null,view:null,header:null,loadingLevel:0,constructor:Ga,initialize:function(){},initOptions:function(a){var b,e,f,g;a=d(a),b=a.lang,e=ob[b],e||(b=nb.defaults.lang,e=ob[b]||{}),f=X(a.isRTL,e.isRTL,nb.defaults.isRTL),g=f?nb.rtlDefaults:{},this.dirDefaults=g,this.langDefaults=e,this.overrides=a,this.options=c([nb.defaults,g,e,a]),Ha(this.options),this.viewSpecCache={}},getViewSpec:function(a){var b=this.viewSpecCache;return b[a]||(b[a]=this.buildViewSpec(a))},getUnitViewSpec:function(b){var c,d,e;if(-1!=a.inArray(b,Ra))for(c=this.header.getViewsWithButtons(),a.each(Ma.views,function(a){c.push(a)}),d=0;d<c.length;d++)if(e=this.getViewSpec(c[d]),e&&e.singleUnit==b)return e},buildViewSpec:function(a){for(var d,e,f,g,h=this.overrides.views||{},i=[],j=[],k=[],l=a;l;)d=Na[l],e=h[l],l=null,"function"==typeof d&&(d={"class":d}),d&&(i.unshift(d),j.unshift(d.defaults||{}),f=f||d.duration,l=l||d.type),e&&(k.unshift(e),f=f||e.duration,l=l||e.type);return d=Q(i),d.type=a,d["class"]?(f&&(f=b.duration(f),f.valueOf()&&(d.duration=f,g=I(f),1===f.as(g)&&(d.singleUnit=g,k.unshift(h[g]||{})))),d.defaults=c(j),d.overrides=c(k),this.buildViewSpecOptions(d),this.buildViewSpecButtonText(d,a),d):!1},buildViewSpecOptions:function(a){a.options=c([nb.defaults,a.defaults,this.dirDefaults,this.langDefaults,this.overrides,a.overrides]),Ha(a.options)},buildViewSpecButtonText:function(a,b){function c(c){var d=c.buttonText||{};return d[b]||(a.singleUnit?d[a.singleUnit]:null)}a.buttonTextOverride=c(this.overrides)||a.overrides.buttonText,a.buttonTextDefault=c(this.langDefaults)||c(this.dirDefaults)||a.defaults.buttonText||c(nb.defaults)||(a.duration?this.humanizeDuration(a.duration):null)||b},instantiateView:function(a){var b=this.getViewSpec(a);return new b["class"](this,a,b.options,b.duration)},isValidViewType:function(a){return Boolean(this.getViewSpec(a))},pushLoading:function(){this.loadingLevel++||this.trigger("loading",null,!0,this.view)},popLoading:function(){--this.loadingLevel||this.trigger("loading",null,!1,this.view)},buildSelectRange:function(a,b){return a=this.moment(a),b=b?this.moment(b):a.hasTime()?a.clone().add(this.defaultTimedEventDuration):a.clone().add(this.defaultAllDayEventDuration),{start:a,end:b}}});nb.mixin(bb),nb.defaults={titleRangeSeparator:" — ",monthYearFormat:"MMMM YYYY",defaultTimedEventDuration:"02:00:00",defaultAllDayEventDuration:{days:1},forceEventDuration:!1,nextDayThreshold:"09:00:00",defaultView:"month",aspectRatio:1.35,header:{left:"title",center:"",right:"today prev,next"},weekends:!0,weekNumbers:!1,weekNumberTitle:"W",weekNumberCalculation:"local",scrollTime:"06:00:00",lazyFetching:!0,startParam:"start",endParam:"end",timezoneParam:"timezone",timezone:!1,isRTL:!1,buttonText:{prev:"prev",next:"next",prevYear:"prev year",nextYear:"next year",year:"year",today:"today",month:"month",week:"week",day:"day"},buttonIcons:{prev:"left-single-arrow",next:"right-single-arrow",prevYear:"left-double-arrow",nextYear:"right-double-arrow"},theme:!1,themeButtonIcons:{prev:"circle-triangle-w",next:"circle-triangle-e",prevYear:"seek-prev",nextYear:"seek-next"},dragOpacity:.75,dragRevertDuration:500,dragScroll:!0,unselectAuto:!0,dropAccept:"*",eventOrder:"title",eventLimit:!1,eventLimitText:"more",eventLimitClick:"popover",dayPopoverFormat:"LL",handleWindowResize:!0,windowResizeDelay:200},nb.englishDefaults={dayPopoverFormat:"dddd, MMMM D"},nb.rtlDefaults={header:{left:"next,prev today",center:"",right:"title"},buttonIcons:{prev:"right-single-arrow",next:"left-single-arrow",prevYear:"right-double-arrow",nextYear:"left-double-arrow"},themeButtonIcons:{prev:"circle-triangle-e",next:"circle-triangle-w",nextYear:"seek-prev",prevYear:"seek-next"}};var ob=Ma.langs={};Ma.datepickerLang=function(b,c,d){var e=ob[b]||(ob[b]={});e.isRTL=d.isRTL,e.weekNumberTitle=d.weekHeader,a.each(pb,function(a,b){e[a]=b(d)}),a.datepicker&&(a.datepicker.regional[c]=a.datepicker.regional[b]=d,a.datepicker.regional.en=a.datepicker.regional[""],a.datepicker.setDefaults(d))},Ma.lang=function(b,d){var e,f;e=ob[b]||(ob[b]={}),d&&(e=ob[b]=c([e,d])),f=Ia(b),a.each(qb,function(a,b){null==e[a]&&(e[a]=b(f,e))}),nb.defaults.lang=b};var pb={buttonText:function(a){return{prev:Z(a.prevText),next:Z(a.nextText),today:Z(a.currentText)}},monthYearFormat:function(a){return a.showMonthAfterYear?"YYYY["+a.yearSuffix+"] MMMM":"MMMM YYYY["+a.yearSuffix+"]"}},qb={dayOfMonthFormat:function(a,b){var c=a.longDateFormat("l");return c=c.replace(/^Y+[^\w\s]*|[^\w\s]*Y+$/g,""),b.isRTL?c+=" ddd":c="ddd "+c,c},mediumTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"a")},smallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"a")},extraSmallTimeFormat:function(a){return a.longDateFormat("LT").replace(":mm","(:mm)").replace(/(\Wmm)$/,"($1)").replace(/\s*a$/i,"t")},hourFormat:function(a){return a.longDateFormat("LT").replace(":mm","").replace(/(\Wmm)$/,"").replace(/\s*a$/i,"a")},noMeridiemTimeFormat:function(a){return a.longDateFormat("LT").replace(/\s*a$/i,"")}},rb={smallDayDateFormat:function(a){return a.isRTL?"D dd":"dd D"},weekFormat:function(a){return a.isRTL?"w[ "+a.weekNumberTitle+"]":"["+a.weekNumberTitle+" ]w"},smallWeekFormat:function(a){return a.isRTL?"w["+a.weekNumberTitle+"]":"["+a.weekNumberTitle+"]w"}};Ma.lang("en",nb.englishDefaults),Ma.sourceNormalizers=[],Ma.sourceFetchers=[];var sb={dataType:"json",cache:!1},tb=1;nb.prototype.getPeerEvents=function(a,b){var c,d,e=this.getEventCache(),f=[];for(c=0;c<e.length;c++)d=e[c],a&&a._id===d._id||f.push(d);return f};var ub=mb.extend({dayGrid:null,dayNumbersVisible:!1,weekNumbersVisible:!1,weekNumberWidth:null,headRowEl:null,initialize:function(){this.dayGrid=new kb(this),this.coordMap=this.dayGrid.coordMap},setRange:function(a){mb.prototype.setRange.call(this,a),this.dayGrid.breakOnWeeks=/year|month|week/.test(this.intervalUnit),this.dayGrid.setRange(a)},computeRange:function(a){var b=mb.prototype.computeRange.call(this,a);return/year|month/.test(b.intervalUnit)&&(b.start.startOf("week"),b.start=this.skipHiddenDays(b.start),b.end.weekday()&&(b.end.add(1,"week").startOf("week"),b.end=this.skipHiddenDays(b.end,-1,!0))),b},renderDates:function(){this.dayNumbersVisible=this.dayGrid.rowCnt>1,this.weekNumbersVisible=this.opt("weekNumbers"),this.dayGrid.numbersVisible=this.dayNumbersVisible||this.weekNumbersVisible,this.el.addClass("fc-basic-view").html(this.renderHtml()),this.headRowEl=this.el.find("thead .fc-row"),this.scrollerEl=this.el.find(".fc-day-grid-container"),this.dayGrid.coordMap.containerEl=this.scrollerEl,this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(this.hasRigidRows())},unrenderDates:function(){this.dayGrid.unrenderDates(),this.dayGrid.removeElement()},renderBusinessHours:function(){this.dayGrid.renderBusinessHours()},renderHtml:function(){return'<table><thead class="fc-head"><tr><td class="'+this.widgetHeaderClass+'">'+this.dayGrid.headHtml()+'</td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'"><div class="fc-day-grid-container"><div class="fc-day-grid"/></div></td></tr></tbody></table>'},headIntroHtml:function(){return this.weekNumbersVisible?'<th class="fc-week-number '+this.widgetHeaderClass+'" '+this.weekNumberStyleAttr()+"><span>"+Y(this.opt("weekNumberTitle"))+"</span></th>":void 0},numberIntroHtml:function(a){return this.weekNumbersVisible?'<td class="fc-week-number" '+this.weekNumberStyleAttr()+"><span>"+this.dayGrid.getCell(a,0).start.format("w")+"</span></td>":void 0},dayIntroHtml:function(){return this.weekNumbersVisible?'<td class="fc-week-number '+this.widgetContentClass+'" '+this.weekNumberStyleAttr()+"></td>":void 0},introHtml:function(){return this.weekNumbersVisible?'<td class="fc-week-number" '+this.weekNumberStyleAttr()+"></td>":void 0},numberCellHtml:function(a){var b,c=a.start;return this.dayNumbersVisible?(b=this.dayGrid.getDayClasses(c),b.unshift("fc-day-number"),'<td class="'+b.join(" ")+'" data-date="'+c.format()+'">'+c.date()+"</td>"):"<td/>"},weekNumberStyleAttr:function(){return null!==this.weekNumberWidth?'style="width:'+this.weekNumberWidth+'px"':""},hasRigidRows:function(){var a=this.opt("eventLimit");return a&&"number"!=typeof a},updateWidth:function(){this.weekNumbersVisible&&(this.weekNumberWidth=k(this.el.find(".fc-week-number")))},setHeight:function(a,b){var c,d=this.opt("eventLimit");m(this.scrollerEl),f(this.headRowEl),this.dayGrid.removeSegPopover(),d&&"number"==typeof d&&this.dayGrid.limitRows(d),c=this.computeScrollerHeight(a),this.setGridHeight(c,b),d&&"number"!=typeof d&&this.dayGrid.limitRows(d),!b&&l(this.scrollerEl,c)&&(e(this.headRowEl,r(this.scrollerEl)),c=this.computeScrollerHeight(a),this.scrollerEl.height(c))},setGridHeight:function(a,b){b?j(this.dayGrid.rowEls):i(this.dayGrid.rowEls,a,!0)},renderEvents:function(a){this.dayGrid.renderEvents(a),this.updateHeight()},getEventSegs:function(){return this.dayGrid.getEventSegs()},unrenderEvents:function(){this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return this.dayGrid.renderDrag(a,b)},unrenderDrag:function(){this.dayGrid.unrenderDrag()},renderSelection:function(a){this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.dayGrid.unrenderSelection()}}),vb=ub.extend({computeRange:function(a){var b,c=ub.prototype.computeRange.call(this,a);return this.isFixedWeeks()&&(b=Math.ceil(c.end.diff(c.start,"weeks",!0)),c.end.add(6-b,"weeks")),c},setGridHeight:function(a,b){b=b||"variable"===this.opt("weekMode"),b&&(a*=this.rowCnt/6),i(this.dayGrid.rowEls,a,!b)},isFixedWeeks:function(){var a=this.opt("weekMode");return a?"fixed"===a:this.opt("fixedWeekCount")}});Na.basic={"class":ub},Na.basicDay={type:"basic",duration:{days:1}},Na.basicWeek={type:"basic",duration:{weeks:1}},Na.month={"class":vb,duration:{months:1},defaults:{fixedWeekCount:!0}};var wb=mb.extend({timeGrid:null,dayGrid:null,axisWidth:null,noScrollRowEls:null,bottomRuleEl:null,bottomRuleHeight:null,initialize:function(){this.timeGrid=new lb(this),this.opt("allDaySlot")?(this.dayGrid=new kb(this),this.coordMap=new eb([this.dayGrid.coordMap,this.timeGrid.coordMap])):this.coordMap=this.timeGrid.coordMap},setRange:function(a){mb.prototype.setRange.call(this,a),this.timeGrid.setRange(a),this.dayGrid&&this.dayGrid.setRange(a)},renderDates:function(){this.el.addClass("fc-agenda-view").html(this.renderHtml()),this.scrollerEl=this.el.find(".fc-time-grid-container"),this.timeGrid.coordMap.containerEl=this.scrollerEl,this.timeGrid.setElement(this.el.find(".fc-time-grid")),this.timeGrid.renderDates(),this.bottomRuleEl=a('<hr class="fc-divider '+this.widgetHeaderClass+'"/>').appendTo(this.timeGrid.el),this.dayGrid&&(this.dayGrid.setElement(this.el.find(".fc-day-grid")),this.dayGrid.renderDates(),this.dayGrid.bottomCoordPadding=this.dayGrid.el.next("hr").outerHeight()),this.noScrollRowEls=this.el.find(".fc-row:not(.fc-scroller *)")},unrenderDates:function(){this.timeGrid.unrenderDates(),this.timeGrid.removeElement(),this.dayGrid&&(this.dayGrid.unrenderDates(),this.dayGrid.removeElement())},renderBusinessHours:function(){this.timeGrid.renderBusinessHours(),this.dayGrid&&this.dayGrid.renderBusinessHours()},renderHtml:function(){return'<table><thead class="fc-head"><tr><td class="'+this.widgetHeaderClass+'">'+this.timeGrid.headHtml()+'</td></tr></thead><tbody class="fc-body"><tr><td class="'+this.widgetContentClass+'">'+(this.dayGrid?'<div class="fc-day-grid"/><hr class="fc-divider '+this.widgetHeaderClass+'"/>':"")+'<div class="fc-time-grid-container"><div class="fc-time-grid"/></div></td></tr></tbody></table>'},headIntroHtml:function(){var a,b;return this.opt("weekNumbers")?(a=this.timeGrid.getCell(0).start,b=a.format(this.opt("smallWeekFormat")),'<th class="fc-axis fc-week-number '+this.widgetHeaderClass+'" '+this.axisStyleAttr()+"><span>"+Y(b)+"</span></th>"):'<th class="fc-axis '+this.widgetHeaderClass+'" '+this.axisStyleAttr()+"></th>"},dayIntroHtml:function(){return'<td class="fc-axis '+this.widgetContentClass+'" '+this.axisStyleAttr()+"><span>"+(this.opt("allDayHtml")||Y(this.opt("allDayText")))+"</span></td>"},slotBgIntroHtml:function(){return'<td class="fc-axis '+this.widgetContentClass+'" '+this.axisStyleAttr()+"></td>";
|
9 |
},introHtml:function(){return'<td class="fc-axis" '+this.axisStyleAttr()+"></td>"},axisStyleAttr:function(){return null!==this.axisWidth?'style="width:'+this.axisWidth+'px"':""},updateSize:function(a){this.timeGrid.updateSize(a),mb.prototype.updateSize.call(this,a)},updateWidth:function(){this.axisWidth=k(this.el.find(".fc-axis"))},setHeight:function(a,b){var c,d;null===this.bottomRuleHeight&&(this.bottomRuleHeight=this.bottomRuleEl.outerHeight()),this.bottomRuleEl.hide(),this.scrollerEl.css("overflow",""),m(this.scrollerEl),f(this.noScrollRowEls),this.dayGrid&&(this.dayGrid.removeSegPopover(),c=this.opt("eventLimit"),c&&"number"!=typeof c&&(c=xb),c&&this.dayGrid.limitRows(c)),b||(d=this.computeScrollerHeight(a),l(this.scrollerEl,d)?(e(this.noScrollRowEls,r(this.scrollerEl)),d=this.computeScrollerHeight(a),this.scrollerEl.height(d)):(this.scrollerEl.height(d).css("overflow","hidden"),this.bottomRuleEl.show()))},computeInitialScroll:function(){var a=b.duration(this.opt("scrollTime")),c=this.timeGrid.computeTimeTop(a);return c=Math.ceil(c),c&&c++,c},renderEvents:function(a){var b,c,d=[],e=[],f=[];for(c=0;c<a.length;c++)a[c].allDay?d.push(a[c]):e.push(a[c]);b=this.timeGrid.renderEvents(e),this.dayGrid&&(f=this.dayGrid.renderEvents(d)),this.updateHeight()},getEventSegs:function(){return this.timeGrid.getEventSegs().concat(this.dayGrid?this.dayGrid.getEventSegs():[])},unrenderEvents:function(){this.timeGrid.unrenderEvents(),this.dayGrid&&this.dayGrid.unrenderEvents()},renderDrag:function(a,b){return a.start.hasTime()?this.timeGrid.renderDrag(a,b):this.dayGrid?this.dayGrid.renderDrag(a,b):void 0},unrenderDrag:function(){this.timeGrid.unrenderDrag(),this.dayGrid&&this.dayGrid.unrenderDrag()},renderSelection:function(a){a.start.hasTime()||a.end.hasTime()?this.timeGrid.renderSelection(a):this.dayGrid&&this.dayGrid.renderSelection(a)},unrenderSelection:function(){this.timeGrid.unrenderSelection(),this.dayGrid&&this.dayGrid.unrenderSelection()}}),xb=5,yb=[{hours:1},{minutes:30},{minutes:15},{seconds:30},{seconds:15}];return Na.agenda={"class":wb,defaults:{allDaySlot:!0,allDayText:"all-day",slotDuration:"00:30:00",minTime:"00:00:00",maxTime:"24:00:00",slotEventOverlap:!0}},Na.agendaDay={type:"agenda",duration:{days:1}},Na.agendaWeek={type:"agenda",duration:{weeks:1}},Ma});
|
backend/modules/calendar/resources/js/ng-appointment_dialog.js
CHANGED
@@ -1,729 +1,982 @@
|
|
1 |
-
;(function() {
|
2 |
-
|
3 |
-
var module = angular.module('appointmentDialog', ['ui.date', 'customerDialog', 'paymentDetailsDialog']);
|
4 |
-
|
5 |
-
/**
|
6 |
-
* DataSource service.
|
7 |
-
*/
|
8 |
-
module.factory('dataSource', function($q, $rootScope, $filter) {
|
9 |
-
var ds = {
|
10 |
-
loaded : false,
|
11 |
-
data : {
|
12 |
-
staff : [],
|
13 |
-
customers : [],
|
14 |
-
start_time : [],
|
15 |
-
end_time : [],
|
16 |
-
time_interval : 900,
|
17 |
-
status : {
|
18 |
-
items: [],
|
19 |
-
default: null
|
20 |
-
}
|
21 |
-
},
|
22 |
-
form : {
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
},
|
135 |
-
|
136 |
-
var
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
start_time =
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
ds.form.
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
}
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
*
|
237 |
-
*/
|
238 |
-
$scope.
|
239 |
-
|
240 |
-
jQuery.
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
.
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
//
|
500 |
-
var
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
:
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
}
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
if ($scope.form.service) {
|
595 |
-
jQuery('#bookly-extras
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
if (
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
}
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
729 |
};
|
1 |
+
;(function() {
|
2 |
+
|
3 |
+
var module = angular.module('appointmentDialog', ['ui.date', 'customerDialog', 'paymentDetailsDialog']);
|
4 |
+
|
5 |
+
/**
|
6 |
+
* DataSource service.
|
7 |
+
*/
|
8 |
+
module.factory('dataSource', function($q, $rootScope, $filter) {
|
9 |
+
var ds = {
|
10 |
+
loaded : false,
|
11 |
+
data : {
|
12 |
+
staff : [],
|
13 |
+
customers : [],
|
14 |
+
start_time : [],
|
15 |
+
end_time : [],
|
16 |
+
time_interval : 900,
|
17 |
+
status : {
|
18 |
+
items: [],
|
19 |
+
default: null
|
20 |
+
}
|
21 |
+
},
|
22 |
+
form : {
|
23 |
+
screen : null,
|
24 |
+
id : null,
|
25 |
+
staff : null,
|
26 |
+
service : null,
|
27 |
+
date : null,
|
28 |
+
repeat : {
|
29 |
+
enabled : null,
|
30 |
+
repeat : null,
|
31 |
+
daily : { every : null },
|
32 |
+
weekly : { on : null },
|
33 |
+
biweekly : { on : null },
|
34 |
+
monthly : { on : null, day : null, weekday : null },
|
35 |
+
until : null
|
36 |
+
},
|
37 |
+
schedule : {
|
38 |
+
items : [],
|
39 |
+
edit : null,
|
40 |
+
page : null,
|
41 |
+
another_time : []
|
42 |
+
},
|
43 |
+
start_time : null,
|
44 |
+
end_time : null,
|
45 |
+
customers : [],
|
46 |
+
notification : null
|
47 |
+
},
|
48 |
+
loadData : function() {
|
49 |
+
var deferred = $q.defer();
|
50 |
+
if (!ds.loaded) {
|
51 |
+
jQuery.get(
|
52 |
+
ajaxurl,
|
53 |
+
{ action : 'bookly_get_data_for_appointment_form' },
|
54 |
+
function(data) {
|
55 |
+
ds.loaded = true;
|
56 |
+
ds.data = data;
|
57 |
+
// Add empty element to beginning of array for single-select customer form
|
58 |
+
ds.data.customers.unshift({name: ''});
|
59 |
+
|
60 |
+
if (data.staff.length) {
|
61 |
+
ds.form.staff = data.staff[0];
|
62 |
+
}
|
63 |
+
ds.form.start_time = data.start_time[0];
|
64 |
+
ds.form.end_time = data.end_time[1];
|
65 |
+
deferred.resolve();
|
66 |
+
},
|
67 |
+
'json'
|
68 |
+
);
|
69 |
+
} else {
|
70 |
+
deferred.resolve();
|
71 |
+
}
|
72 |
+
|
73 |
+
return deferred.promise;
|
74 |
+
},
|
75 |
+
findStaff : function(id) {
|
76 |
+
var result = null;
|
77 |
+
jQuery.each(ds.data.staff, function(key, item) {
|
78 |
+
if (item.id == id) {
|
79 |
+
result = item;
|
80 |
+
return false;
|
81 |
+
}
|
82 |
+
});
|
83 |
+
return result;
|
84 |
+
},
|
85 |
+
findService : function(staff_id, id) {
|
86 |
+
var result = null,
|
87 |
+
staff = ds.findStaff(staff_id);
|
88 |
+
|
89 |
+
if (staff !== null) {
|
90 |
+
jQuery.each(staff.services, function(key, item) {
|
91 |
+
if (item.id == id) {
|
92 |
+
result = item;
|
93 |
+
return false;
|
94 |
+
}
|
95 |
+
});
|
96 |
+
}
|
97 |
+
return result;
|
98 |
+
},
|
99 |
+
findTime : function(source, date) {
|
100 |
+
var result = null,
|
101 |
+
value_to_find = $filter('date')(date, 'HH:mm'),
|
102 |
+
time = source == 'start' ? ds.data.start_time : ds.data.end_time;
|
103 |
+
|
104 |
+
jQuery.each(time, function(key, item) {
|
105 |
+
if (item.value >= value_to_find) {
|
106 |
+
result = item;
|
107 |
+
return false;
|
108 |
+
}
|
109 |
+
});
|
110 |
+
return result;
|
111 |
+
},
|
112 |
+
findCustomer : function(id) {
|
113 |
+
var result = null;
|
114 |
+
jQuery.each(ds.data.customers, function(key, item) {
|
115 |
+
if (item.id == id) {
|
116 |
+
result = item;
|
117 |
+
return false;
|
118 |
+
}
|
119 |
+
});
|
120 |
+
return result;
|
121 |
+
},
|
122 |
+
resetCustomers : function() {
|
123 |
+
ds.data.customers.forEach(function(customer) {
|
124 |
+
customer.custom_fields = [];
|
125 |
+
customer.extras = [];
|
126 |
+
customer.status = ds.data.status.default;
|
127 |
+
customer.number_of_persons = 1;
|
128 |
+
customer.compound_token = null;
|
129 |
+
customer.location_id = null;
|
130 |
+
customer.payment_id = null;
|
131 |
+
customer.payment_type = null;
|
132 |
+
customer.payment_title = null;
|
133 |
+
});
|
134 |
+
},
|
135 |
+
getDataForEndTime : function() {
|
136 |
+
var result = [];
|
137 |
+
if (ds.form.start_time) {
|
138 |
+
var start_time = ds.form.start_time.value.split(':'),
|
139 |
+
end = (24 + parseInt(start_time[0])) + ':' + start_time[1];
|
140 |
+
jQuery.each(ds.data.end_time, function(key, item) {
|
141 |
+
if (item.value > end) {
|
142 |
+
return false;
|
143 |
+
}
|
144 |
+
if (item.value > ds.form.start_time.value) {
|
145 |
+
result.push(item);
|
146 |
+
}
|
147 |
+
});
|
148 |
+
}
|
149 |
+
return result;
|
150 |
+
},
|
151 |
+
setEndTimeBasedOnService : function() {
|
152 |
+
var i = jQuery.inArray(ds.form.start_time, ds.data.start_time),
|
153 |
+
d = ds.form.service ? ds.form.service.duration : ds.data.time_interval;
|
154 |
+
if (ds.form.service && ds.form.service.duration == 86400) {
|
155 |
+
ds.form.start_time = ds.data.start_time[0];
|
156 |
+
ds.form.end_time = ds.data.end_time[ 86400 / ds.data.time_interval ];
|
157 |
+
} else {
|
158 |
+
if (i !== -1) {
|
159 |
+
for (; i < ds.data.end_time.length; ++i) {
|
160 |
+
d -= ds.data.time_interval;
|
161 |
+
if (d < 0) {
|
162 |
+
break;
|
163 |
+
}
|
164 |
+
}
|
165 |
+
ds.form.end_time = ds.data.end_time[i];
|
166 |
+
}
|
167 |
+
}
|
168 |
+
},
|
169 |
+
getStartAndEndDates : function() {
|
170 |
+
var start_date = new Date(ds.form.date.getTime()),
|
171 |
+
start_time = ds.form.start_time.value.split(':'),
|
172 |
+
end_date = new Date(ds.form.date.getTime()),
|
173 |
+
end_time = ds.form.end_time.value.split(':');
|
174 |
+
start_date.setHours(start_time[0]);
|
175 |
+
start_date.setMinutes(start_time[1]);
|
176 |
+
end_date.setHours(end_time[0]);
|
177 |
+
end_date.setMinutes(end_time[1]);
|
178 |
+
|
179 |
+
return {
|
180 |
+
start_date : $filter('date')(start_date, 'yyyy-MM-dd HH:mm:00'),
|
181 |
+
end_date : $filter('date')(end_date, 'yyyy-MM-dd HH:mm:00')
|
182 |
+
};
|
183 |
+
},
|
184 |
+
getTotalNumberOfPersons : function () {
|
185 |
+
var result = 0;
|
186 |
+
ds.form.customers.forEach(function (item) {
|
187 |
+
result += parseInt(item.number_of_persons);
|
188 |
+
});
|
189 |
+
|
190 |
+
return result;
|
191 |
+
},
|
192 |
+
getTotalNumberOfNotCancelledPersons: function () {
|
193 |
+
var result = 0;
|
194 |
+
ds.form.customers.forEach(function (item) {
|
195 |
+
if (item.status != 'cancelled') {
|
196 |
+
result += parseInt(item.number_of_persons);
|
197 |
+
}
|
198 |
+
});
|
199 |
+
|
200 |
+
return result;
|
201 |
+
},
|
202 |
+
getTotalNumberOfCancelledPersons: function () {
|
203 |
+
var result = 0;
|
204 |
+
ds.form.customers.forEach(function (item) {
|
205 |
+
if (item.status == 'cancelled') {
|
206 |
+
result += parseInt(item.number_of_persons);
|
207 |
+
}
|
208 |
+
});
|
209 |
+
|
210 |
+
return result;
|
211 |
+
}
|
212 |
+
};
|
213 |
+
|
214 |
+
return ds;
|
215 |
+
});
|
216 |
+
|
217 |
+
/**
|
218 |
+
* Controller for 'create/edit appointment' dialog form.
|
219 |
+
*/
|
220 |
+
module.controller('appointmentDialogCtrl', function($scope, $element, dataSource, $filter) {
|
221 |
+
// Set up initial data.
|
222 |
+
$scope.$calendar = null;
|
223 |
+
// Set up data source.
|
224 |
+
$scope.dataSource = dataSource;
|
225 |
+
$scope.form = dataSource.form; // shortcut
|
226 |
+
// Error messages.
|
227 |
+
$scope.errors = {};
|
228 |
+
// Callback to be called after editing appointment.
|
229 |
+
var callback = null;
|
230 |
+
|
231 |
+
/**
|
232 |
+
* Prepare the form for new event.
|
233 |
+
*
|
234 |
+
* @param int staff_id
|
235 |
+
* @param moment start_date
|
236 |
+
* @param function _callback
|
237 |
+
*/
|
238 |
+
$scope.configureNewForm = function(staff_id, start_date, _callback) {
|
239 |
+
var weekday = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][start_date.format('d')];
|
240 |
+
jQuery.extend($scope.form, {
|
241 |
+
screen : 'main',
|
242 |
+
id : null,
|
243 |
+
staff : dataSource.findStaff(staff_id),
|
244 |
+
service : null,
|
245 |
+
date : start_date.clone().local().toDate(),
|
246 |
+
start_time : dataSource.findTime('start', start_date.format('HH:mm')),
|
247 |
+
end_time : null,
|
248 |
+
repeat : {
|
249 |
+
enabled : 0,
|
250 |
+
repeat : 'daily',
|
251 |
+
daily : { every: 1 },
|
252 |
+
weekly : { on : [weekday] },
|
253 |
+
biweekly : { on : [weekday] },
|
254 |
+
monthly : { on : 'day', day : start_date.format('D'), weekday : weekday },
|
255 |
+
until : start_date.clone().add(1, 'month').format('YYYY-MM-DD')
|
256 |
+
},
|
257 |
+
schedule : {
|
258 |
+
items : [],
|
259 |
+
edit : 0,
|
260 |
+
page : 0,
|
261 |
+
another_time : []
|
262 |
+
},
|
263 |
+
customers : [],
|
264 |
+
notification : 'no',
|
265 |
+
internal_note : null
|
266 |
+
});
|
267 |
+
$scope.errors = {};
|
268 |
+
dataSource.setEndTimeBasedOnService();
|
269 |
+
callback = _callback;
|
270 |
+
|
271 |
+
$scope.reInitChosen();
|
272 |
+
$scope.prepareExtras();
|
273 |
+
$scope.prepareCustomFields();
|
274 |
+
$scope.dataSource.resetCustomers();
|
275 |
+
};
|
276 |
+
|
277 |
+
/**
|
278 |
+
* Prepare the form for editing an event.
|
279 |
+
*/
|
280 |
+
$scope.configureEditForm = function(appointment_id, _callback) {
|
281 |
+
$scope.loading = true;
|
282 |
+
jQuery.post(
|
283 |
+
ajaxurl,
|
284 |
+
{action: 'bookly_get_data_for_appointment', id: appointment_id},
|
285 |
+
function(response) {
|
286 |
+
$scope.$apply(function($scope) {
|
287 |
+
if (response.success) {
|
288 |
+
var start_date = moment(response.data.start_date),
|
289 |
+
end_date = moment(response.data.end_date);
|
290 |
+
jQuery.extend($scope.form, {
|
291 |
+
screen : 'main',
|
292 |
+
id : appointment_id,
|
293 |
+
staff : $scope.dataSource.findStaff(response.data.staff_id),
|
294 |
+
service : $scope.dataSource.findService(response.data.staff_id, response.data.service_id),
|
295 |
+
date : start_date.clone().local().toDate(),
|
296 |
+
start_time : $scope.dataSource.findTime('start', start_date.format('HH:mm')),
|
297 |
+
end_time : start_date.format('YYYY-MM-DD') == end_date.format('YYYY-MM-DD')
|
298 |
+
? $scope.dataSource.findTime('end', end_date.format('HH:mm'))
|
299 |
+
: $scope.dataSource.findTime('end', (24 + end_date.hour()) + end_date.format(':mm')),
|
300 |
+
repeat : {
|
301 |
+
enabled : 0,
|
302 |
+
repeat : 'daily',
|
303 |
+
daily : { every: 1 },
|
304 |
+
weekly : { on : [] },
|
305 |
+
biweekly : { on : [] },
|
306 |
+
monthly : { on : 'day', day : '1', weekday : 'mon' },
|
307 |
+
until : start_date.clone().add(1, 'month').format('YYYY-MM-DD')
|
308 |
+
},
|
309 |
+
schedule : {
|
310 |
+
items : [],
|
311 |
+
edit : 0,
|
312 |
+
page : 0,
|
313 |
+
another_time : []
|
314 |
+
},
|
315 |
+
customers : [],
|
316 |
+
notification : 'no',
|
317 |
+
internal_note : response.data.internal_note
|
318 |
+
});
|
319 |
+
|
320 |
+
$scope.reInitChosen();
|
321 |
+
$scope.prepareExtras();
|
322 |
+
$scope.prepareCustomFields();
|
323 |
+
$scope.dataSource.resetCustomers();
|
324 |
+
|
325 |
+
var customers_ids = [];
|
326 |
+
response.data.customers.forEach(function (item, i, arr) {
|
327 |
+
var customer = $scope.dataSource.findCustomer(item.id),
|
328 |
+
clone = {};
|
329 |
+
if (customers_ids.indexOf(item.id) === -1) {
|
330 |
+
customers_ids.push(item.id);
|
331 |
+
clone = customer;
|
332 |
+
} else {
|
333 |
+
// For Error: ngRepeat:dupes & chosen directive
|
334 |
+
angular.copy(customer, clone);
|
335 |
+
}
|
336 |
+
clone.ca_id = item.ca_id;
|
337 |
+
clone.extras = item.extras;
|
338 |
+
clone.status = item.status;
|
339 |
+
clone.custom_fields = item.custom_fields;
|
340 |
+
clone.number_of_persons = item.number_of_persons;
|
341 |
+
clone.location_id = item.location_id;
|
342 |
+
clone.payment_id = item.payment_id;
|
343 |
+
clone.payment_type = item.payment_type;
|
344 |
+
clone.payment_title = item.payment_title;
|
345 |
+
clone.compound_token = item.compound_token;
|
346 |
+
clone.compound_service = item.compound_service;
|
347 |
+
$scope.form.customers.push(clone);
|
348 |
+
});
|
349 |
+
}
|
350 |
+
$scope.loading = false;
|
351 |
+
});
|
352 |
+
},
|
353 |
+
'json'
|
354 |
+
);
|
355 |
+
$scope.errors = {};
|
356 |
+
callback = _callback;
|
357 |
+
};
|
358 |
+
|
359 |
+
var checkTimeInterval = function() {
|
360 |
+
var dates = $scope.dataSource.getStartAndEndDates();
|
361 |
+
jQuery.post(
|
362 |
+
ajaxurl,
|
363 |
+
{
|
364 |
+
action : 'bookly_check_appointment_date_selection',
|
365 |
+
start_date : dates.start_date,
|
366 |
+
end_date : dates.end_date,
|
367 |
+
appointment_id : $scope.form.id,
|
368 |
+
staff_id : $scope.form.staff ? $scope.form.staff.id : null,
|
369 |
+
service_id : $scope.form.service ? $scope.form.service.id : null
|
370 |
+
},
|
371 |
+
function (response) {
|
372 |
+
$scope.$apply(function ($scope) {
|
373 |
+
$scope.errors = response;
|
374 |
+
});
|
375 |
+
},
|
376 |
+
'json'
|
377 |
+
);
|
378 |
+
};
|
379 |
+
|
380 |
+
$scope.onServiceChange = function() {
|
381 |
+
$scope.dataSource.setEndTimeBasedOnService();
|
382 |
+
$scope.reInitChosen();
|
383 |
+
$scope.prepareExtras();
|
384 |
+
$scope.prepareCustomFields();
|
385 |
+
checkTimeInterval();
|
386 |
+
};
|
387 |
+
|
388 |
+
$scope.onStaffChange = function() {
|
389 |
+
$scope.form.service = null;
|
390 |
+
};
|
391 |
+
|
392 |
+
$scope.onStartTimeChange = function() {
|
393 |
+
$scope.dataSource.setEndTimeBasedOnService();
|
394 |
+
checkTimeInterval();
|
395 |
+
};
|
396 |
+
|
397 |
+
$scope.onEndTimeChange = function() {
|
398 |
+
checkTimeInterval();
|
399 |
+
};
|
400 |
+
|
401 |
+
$scope.processForm = function() {
|
402 |
+
$scope.loading = true;
|
403 |
+
|
404 |
+
var dates = $scope.dataSource.getStartAndEndDates(),
|
405 |
+
schedule = [],
|
406 |
+
customers = []
|
407 |
+
;
|
408 |
+
|
409 |
+
angular.forEach($scope.form.schedule.items, function (item) {
|
410 |
+
if (!item.deleted) {
|
411 |
+
schedule.push(item.slots);
|
412 |
+
}
|
413 |
+
});
|
414 |
+
|
415 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
416 |
+
var customer_extras = {};
|
417 |
+
if ($scope.form.service) {
|
418 |
+
jQuery('#bookly-extras .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
419 |
+
var extra_id = jQuery(this).data('id');
|
420 |
+
if (item.extras[extra_id] !== undefined) {
|
421 |
+
customer_extras[extra_id] = item.extras[extra_id];
|
422 |
+
}
|
423 |
+
});
|
424 |
+
}
|
425 |
+
customers.push({
|
426 |
+
id : item.id,
|
427 |
+
ca_id : item.ca_id,
|
428 |
+
custom_fields : item.custom_fields,
|
429 |
+
extras : customer_extras,
|
430 |
+
location_id : item.location_id,
|
431 |
+
number_of_persons : item.number_of_persons,
|
432 |
+
status : item.status
|
433 |
+
});
|
434 |
+
});
|
435 |
+
|
436 |
+
jQuery.post(
|
437 |
+
ajaxurl,
|
438 |
+
{
|
439 |
+
action : 'bookly_save_appointment_form',
|
440 |
+
id : $scope.form.id,
|
441 |
+
staff_id : $scope.form.staff ? $scope.form.staff.id : null,
|
442 |
+
service_id : $scope.form.service ? $scope.form.service.id : null,
|
443 |
+
start_date : dates.start_date,
|
444 |
+
end_date : dates.end_date,
|
445 |
+
repeat : JSON.stringify($scope.form.repeat),
|
446 |
+
schedule : schedule,
|
447 |
+
customers : JSON.stringify(customers),
|
448 |
+
notification : $scope.form.notification,
|
449 |
+
internal_note : $scope.form.internal_note
|
450 |
+
},
|
451 |
+
function (response) {
|
452 |
+
$scope.$apply(function($scope) {
|
453 |
+
if (response.success) {
|
454 |
+
if (callback) {
|
455 |
+
// Call callback.
|
456 |
+
callback(response.data);
|
457 |
+
}
|
458 |
+
// Close the dialog.
|
459 |
+
$element.children().modal('hide');
|
460 |
+
} else {
|
461 |
+
$scope.errors = response.errors;
|
462 |
+
}
|
463 |
+
$scope.loading = false;
|
464 |
+
});
|
465 |
+
},
|
466 |
+
'json'
|
467 |
+
);
|
468 |
+
};
|
469 |
+
|
470 |
+
// On 'Cancel' button click.
|
471 |
+
$scope.closeDialog = function () {
|
472 |
+
// Close the dialog.
|
473 |
+
$element.children().modal('hide');
|
474 |
+
};
|
475 |
+
|
476 |
+
$scope.reInitChosen = function () {
|
477 |
+
jQuery('#bookly-chosen')
|
478 |
+
.chosen('destroy')
|
479 |
+
.chosen({
|
480 |
+
search_contains : true,
|
481 |
+
width : '100%',
|
482 |
+
max_selected_options: dataSource.form.service ? dataSource.form.service.capacity + dataSource.getTotalNumberOfCancelledPersons() : 0
|
483 |
+
});
|
484 |
+
};
|
485 |
+
|
486 |
+
$scope.statusToString = function (status) {
|
487 |
+
return dataSource.data.status.items[status];
|
488 |
+
};
|
489 |
+
|
490 |
+
/**************************************************************************************************************
|
491 |
+
* New customer *
|
492 |
+
**************************************************************************************************************/
|
493 |
+
|
494 |
+
/**
|
495 |
+
* Create new customer.
|
496 |
+
* @param customer
|
497 |
+
*/
|
498 |
+
$scope.createCustomer = function(customer) {
|
499 |
+
// Add new customer to the list.
|
500 |
+
var new_customer = {
|
501 |
+
id : customer.id.toString(),
|
502 |
+
name : customer.name,
|
503 |
+
custom_fields : customer.custom_fields,
|
504 |
+
extras : customer.extras,
|
505 |
+
status : customer.status,
|
506 |
+
number_of_persons : 1,
|
507 |
+
compound_token : null,
|
508 |
+
location_id : null,
|
509 |
+
payment_id : null,
|
510 |
+
payment_type : null,
|
511 |
+
payment_title : null
|
512 |
+
};
|
513 |
+
|
514 |
+
if (customer.email || customer.phone){
|
515 |
+
new_customer.name += ' (' + [customer.email, customer.phone].filter(Boolean).join(', ') + ')';
|
516 |
+
}
|
517 |
+
|
518 |
+
dataSource.data.customers.push(new_customer);
|
519 |
+
|
520 |
+
// Make it selected.
|
521 |
+
if (!dataSource.form.service || dataSource.form.customers.length < dataSource.form.service.capacity) {
|
522 |
+
dataSource.form.customers.push(new_customer);
|
523 |
+
}
|
524 |
+
|
525 |
+
setTimeout(function() { jQuery('#bookly-chosen').trigger('chosen:updated'); }, 0);
|
526 |
+
};
|
527 |
+
|
528 |
+
$scope.removeCustomer = function(customer) {
|
529 |
+
$scope.form.customers.splice($scope.form.customers.indexOf(customer), 1);
|
530 |
+
};
|
531 |
+
|
532 |
+
/**************************************************************************************************************
|
533 |
+
* Customer Details *
|
534 |
+
**************************************************************************************************************/
|
535 |
+
|
536 |
+
$scope.editCustomerDetails = function(customer) {
|
537 |
+
var $dialog = jQuery('#bookly-customer-details-dialog');
|
538 |
+
$dialog.find('input.ab-custom-field:text, textarea.ab-custom-field, select.ab-custom-field').val('');
|
539 |
+
$dialog.find('input.ab-custom-field:checkbox, input.ab-custom-field:radio').prop('checked', false);
|
540 |
+
$dialog.find('#bookly-extras :checkbox').prop('checked', false);
|
541 |
+
|
542 |
+
customer.custom_fields.forEach(function (field) {
|
543 |
+
var $custom_field = $dialog.find('#ab--custom-fields > *[data-id="' + field.id + '"]');
|
544 |
+
switch ($custom_field.data('type')) {
|
545 |
+
case 'checkboxes':
|
546 |
+
field.value.forEach(function (value) {
|
547 |
+
$custom_field.find('.ab-custom-field').filter(function () {
|
548 |
+
return this.value == value;
|
549 |
+
}).prop('checked', true);
|
550 |
+
});
|
551 |
+
break;
|
552 |
+
case 'radio-buttons':
|
553 |
+
$custom_field.find('.ab-custom-field').filter(function () {
|
554 |
+
return this.value == field.value;
|
555 |
+
}).prop('checked', true);
|
556 |
+
break;
|
557 |
+
default:
|
558 |
+
$custom_field.find('.ab-custom-field').val(field.value);
|
559 |
+
break;
|
560 |
+
}
|
561 |
+
});
|
562 |
+
|
563 |
+
$dialog.find('#bookly-extras .extras-count').val(0);
|
564 |
+
angular.forEach(customer.extras, function (extra_count, extra_id) {
|
565 |
+
$dialog.find('#bookly-extras .extras-count[data-id="' + extra_id + '"]').val(extra_count);
|
566 |
+
});
|
567 |
+
|
568 |
+
// Prepare select for number of persons.
|
569 |
+
var $number_of_persons = $dialog.find('#ab-edit-number-of-persons');
|
570 |
+
|
571 |
+
var max = $scope.form.service
|
572 |
+
? parseInt($scope.form.service.capacity) - $scope.dataSource.getTotalNumberOfNotCancelledPersons() + ( customer.status != 'cancelled' ? parseInt(customer.number_of_persons) : 0 )
|
573 |
+
: 1;
|
574 |
+
$number_of_persons.empty();
|
575 |
+
for (var i = 1; i <= max; ++i) {
|
576 |
+
$number_of_persons.append('<option value="' + i + '">' + i + '</option>');
|
577 |
+
}
|
578 |
+
if (customer.number_of_persons > max) {
|
579 |
+
$number_of_persons.append('<option value="' + customer.number_of_persons + '">' + customer.number_of_persons + '</option>');
|
580 |
+
}
|
581 |
+
$number_of_persons.val(customer.number_of_persons);
|
582 |
+
$dialog.find('#ab-appointment-status').val(customer.status);
|
583 |
+
$dialog.find('#ab-appointment-location').val(customer.location_id);
|
584 |
+
$dialog.find('#ab-deposit-due').val(customer.due);
|
585 |
+
$scope.edit_customer = customer;
|
586 |
+
|
587 |
+
$dialog.modal({show: true, backdrop: false})
|
588 |
+
.on('hidden.bs.modal', function () {
|
589 |
+
jQuery('body').addClass('modal-open');
|
590 |
+
});
|
591 |
+
};
|
592 |
+
|
593 |
+
$scope.prepareExtras = function () {
|
594 |
+
if ($scope.form.service) {
|
595 |
+
jQuery('#bookly-extras > *').hide();
|
596 |
+
var $service_extras = jQuery('#bookly-extras .service_' + $scope.form.service.id);
|
597 |
+
if ($service_extras.length) {
|
598 |
+
$service_extras.show();
|
599 |
+
jQuery('#bookly-extras').show();
|
600 |
+
} else {
|
601 |
+
jQuery('#bookly-extras').hide();
|
602 |
+
}
|
603 |
+
} else {
|
604 |
+
jQuery('#bookly-extras').hide();
|
605 |
+
}
|
606 |
+
};
|
607 |
+
|
608 |
+
// Hide or unhide custom fields for current service
|
609 |
+
$scope.prepareCustomFields = function () {
|
610 |
+
if (BooklyL10nAppDialog.cf_per_service == 1) {
|
611 |
+
var show = false;
|
612 |
+
jQuery('#ab--custom-fields div[data-services]').each(function() {
|
613 |
+
var $this = jQuery(this);
|
614 |
+
if (dataSource.form.service !== null) {
|
615 |
+
var services = $this.data('services');
|
616 |
+
if (services && jQuery.inArray(dataSource.form.service.id, services) > -1) {
|
617 |
+
$this.show();
|
618 |
+
show = true;
|
619 |
+
} else {
|
620 |
+
$this.hide();
|
621 |
+
}
|
622 |
+
} else {
|
623 |
+
$this.hide();
|
624 |
+
}
|
625 |
+
});
|
626 |
+
if (show) {
|
627 |
+
jQuery('#ab--custom-fields').show();
|
628 |
+
} else {
|
629 |
+
jQuery('#ab--custom-fields').hide();
|
630 |
+
}
|
631 |
+
}
|
632 |
+
};
|
633 |
+
|
634 |
+
$scope.saveCustomFields = function() {
|
635 |
+
var result = [],
|
636 |
+
extras = {},
|
637 |
+
$fields = jQuery('#ab--custom-fields > *'),
|
638 |
+
$number_of_persons = jQuery('#bookly-customer-details-dialog #ab-edit-number-of-persons')
|
639 |
+
;
|
640 |
+
|
641 |
+
$fields.each(function () {
|
642 |
+
var $this = jQuery(this),
|
643 |
+
value;
|
644 |
+
if ($this.is(':visible')) {
|
645 |
+
switch ($this.data('type')) {
|
646 |
+
case 'checkboxes':
|
647 |
+
value = [];
|
648 |
+
$this.find('.ab-custom-field:checked').each(function () {
|
649 |
+
value.push(this.value);
|
650 |
+
});
|
651 |
+
break;
|
652 |
+
case 'radio-buttons':
|
653 |
+
value = $this.find('.ab-custom-field:checked').val();
|
654 |
+
break;
|
655 |
+
default:
|
656 |
+
value = $this.find('.ab-custom-field').val();
|
657 |
+
break;
|
658 |
+
}
|
659 |
+
result.push({id: $this.data('id'), value: value});
|
660 |
+
}
|
661 |
+
});
|
662 |
+
|
663 |
+
if ($scope.form.service) {
|
664 |
+
jQuery('#bookly-extras .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
665 |
+
if (this.value > 0) {
|
666 |
+
extras[jQuery(this).data('id')] = this.value;
|
667 |
+
}
|
668 |
+
});
|
669 |
+
}
|
670 |
+
|
671 |
+
$scope.edit_customer.custom_fields = result;
|
672 |
+
$scope.edit_customer.number_of_persons = $number_of_persons.val();
|
673 |
+
$scope.edit_customer.location_id = jQuery('#bookly-customer-details-dialog #ab-appointment-location').val();
|
674 |
+
$scope.edit_customer.extras = extras;
|
675 |
+
$scope.edit_customer.status = jQuery('#bookly-customer-details-dialog #ab-appointment-status').val();
|
676 |
+
|
677 |
+
jQuery('#bookly-customer-details-dialog').modal('hide');
|
678 |
+
};
|
679 |
+
|
680 |
+
/**************************************************************************************************************
|
681 |
+
* Payment Details *
|
682 |
+
**************************************************************************************************************/
|
683 |
+
|
684 |
+
$scope.completePayment = function(payment_id, payment_title) {
|
685 |
+
jQuery.each($scope.dataSource.data.customers, function(key, item) {
|
686 |
+
if (item.payment_id == payment_id) {
|
687 |
+
item.payment_type = 'full';
|
688 |
+
item.payment_title = payment_title;
|
689 |
+
}
|
690 |
+
});
|
691 |
+
};
|
692 |
+
|
693 |
+
/**************************************************************************************************************
|
694 |
+
* Schedule of Recurring Appointments *
|
695 |
+
**************************************************************************************************************/
|
696 |
+
|
697 |
+
$scope.schSchedule = function ($event) {
|
698 |
+
var extras = [];
|
699 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
700 |
+
extras.push(item.extras);
|
701 |
+
});
|
702 |
+
|
703 |
+
if (
|
704 |
+
($scope.form.repeat.repeat == 'weekly' || $scope.form.repeat.repeat == 'biweekly') &&
|
705 |
+
$scope.form.repeat[$scope.form.repeat.repeat].on.length == 0
|
706 |
+
) {
|
707 |
+
$scope.errors.repeat_weekdays_empty = true;
|
708 |
+
} else {
|
709 |
+
delete $scope.errors.repeat_weekdays_empty;
|
710 |
+
var ladda = Ladda.create($event.currentTarget);
|
711 |
+
ladda.start();
|
712 |
+
var dates = $scope.dataSource.getStartAndEndDates();
|
713 |
+
jQuery.post(
|
714 |
+
ajaxurl,
|
715 |
+
{
|
716 |
+
action : 'bookly_recurring_appointments_get_schedule',
|
717 |
+
staff_id : $scope.form.staff.id,
|
718 |
+
service_id : $scope.form.service.id,
|
719 |
+
datetime : dates.start_date,
|
720 |
+
until : $scope.form.repeat.until,
|
721 |
+
repeat : $scope.form.repeat.repeat,
|
722 |
+
params : $scope.form.repeat[$scope.form.repeat.repeat],
|
723 |
+
extras : extras
|
724 |
+
},
|
725 |
+
function (response) {
|
726 |
+
$scope.$apply(function($scope) {
|
727 |
+
$scope.form.schedule.items = response.data;
|
728 |
+
$scope.form.schedule.page = 0;
|
729 |
+
$scope.form.schedule.another_time = [];
|
730 |
+
angular.forEach($scope.form.schedule.items, function (item) {
|
731 |
+
if (item.another_time) {
|
732 |
+
var page = parseInt( ( item.index - 1 ) / 10 ) + 1;
|
733 |
+
if ($scope.form.schedule.another_time.indexOf(page) < 0) {
|
734 |
+
$scope.form.schedule.another_time.push(page);
|
735 |
+
}
|
736 |
+
}
|
737 |
+
});
|
738 |
+
$scope.form.screen = 'schedule';
|
739 |
+
ladda.stop();
|
740 |
+
});
|
741 |
+
},
|
742 |
+
'json'
|
743 |
+
);
|
744 |
+
}
|
745 |
+
};
|
746 |
+
$scope.schFormatDate = function(date) {
|
747 |
+
var m = moment(date),
|
748 |
+
weekday = m.format('d'),
|
749 |
+
month = m.format('M'),
|
750 |
+
day = m.format('DD');
|
751 |
+
|
752 |
+
return BooklyL10nAppDialog.calendar.shortDays[weekday] + ', ' + BooklyL10nAppDialog.calendar.shortMonths[month-1] + ' ' + day;
|
753 |
+
};
|
754 |
+
$scope.schFormatTime = function(slots, options) {
|
755 |
+
for (var i = 0; i < options.length; ++ i) {
|
756 |
+
if (slots == options[i].value) {
|
757 |
+
return options[i].title;
|
758 |
+
}
|
759 |
+
}
|
760 |
+
};
|
761 |
+
$scope.schFirstPage = function() {
|
762 |
+
return $scope.form.schedule.page == 0;
|
763 |
+
};
|
764 |
+
$scope.schLastPage = function() {
|
765 |
+
var lastPageNum = Math.ceil($scope.form.schedule.items.length / 10 - 1);
|
766 |
+
return $scope.form.schedule.page == lastPageNum;
|
767 |
+
};
|
768 |
+
$scope.schNumberOfPages = function() {
|
769 |
+
return Math.ceil($scope.form.schedule.items.length / 10);
|
770 |
+
};
|
771 |
+
$scope.schStartingItem = function() {
|
772 |
+
return $scope.form.schedule.page * 10;
|
773 |
+
};
|
774 |
+
$scope.schPageBack = function() {
|
775 |
+
$scope.form.schedule.page = $scope.form.schedule.page - 1;
|
776 |
+
};
|
777 |
+
$scope.schPageForward = function() {
|
778 |
+
$scope.form.schedule.page = $scope.form.schedule.page + 1;
|
779 |
+
};
|
780 |
+
$scope.schOnWeekdayClick = function (weekday) {
|
781 |
+
var idx = $scope.form.repeat.weekly.on.indexOf(weekday);
|
782 |
+
|
783 |
+
// is currently selected
|
784 |
+
if (idx > -1) {
|
785 |
+
$scope.form.repeat.weekly.on.splice(idx, 1);
|
786 |
+
}
|
787 |
+
// is newly selected
|
788 |
+
else {
|
789 |
+
$scope.form.repeat.weekly.on.push(weekday);
|
790 |
+
}
|
791 |
+
// copy weekly to biweekly
|
792 |
+
$scope.form.repeat.biweekly.on = $scope.form.repeat.weekly.on.slice();
|
793 |
+
};
|
794 |
+
$scope.schOnDateChange = function(item) {
|
795 |
+
var extras = [];
|
796 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
797 |
+
extras.push(item.extras);
|
798 |
+
});
|
799 |
+
|
800 |
+
var exclude = [];
|
801 |
+
angular.forEach($scope.form.schedule.items, function (_item) {
|
802 |
+
if (item.slots != _item.slots && !_item.deleted) {
|
803 |
+
exclude.push(_item.slots);
|
804 |
+
}
|
805 |
+
});
|
806 |
+
jQuery.post(
|
807 |
+
ajaxurl,
|
808 |
+
{
|
809 |
+
action : 'bookly_recurring_appointments_get_schedule',
|
810 |
+
staff_id : $scope.form.staff.id,
|
811 |
+
service_id : $scope.form.service.id,
|
812 |
+
datetime : item.date + ' 00:00',
|
813 |
+
until : item.date,
|
814 |
+
repeat : 'daily',
|
815 |
+
params : {every: 1},
|
816 |
+
with_options : 1,
|
817 |
+
exclude : exclude,
|
818 |
+
extras : extras
|
819 |
+
},
|
820 |
+
function (response) {
|
821 |
+
$scope.$apply(function($scope) {
|
822 |
+
if (response.data.length) {
|
823 |
+
item.options = response.data[0].options;
|
824 |
+
var found = false;
|
825 |
+
jQuery.each(item.options, function (key, option) {
|
826 |
+
if ( option.value == item.slots ) {
|
827 |
+
found = true;
|
828 |
+
return false;
|
829 |
+
}
|
830 |
+
});
|
831 |
+
if (!found) {
|
832 |
+
item.slots = item.options[0].value;
|
833 |
+
}
|
834 |
+
} else {
|
835 |
+
item.options = [];
|
836 |
+
}
|
837 |
+
});
|
838 |
+
},
|
839 |
+
'json'
|
840 |
+
);
|
841 |
+
};
|
842 |
+
$scope.schIsScheduleEmpty = function () {
|
843 |
+
return $scope.form.schedule.items.every(function(item) {
|
844 |
+
return item.deleted;
|
845 |
+
});
|
846 |
+
};
|
847 |
+
$scope.schDateOptions = {
|
848 |
+
dateFormat : 'D, M dd, yy',
|
849 |
+
dayNamesMin : BooklyL10nAppDialog.calendar.shortDays,
|
850 |
+
dayNamesShort : BooklyL10nAppDialog.calendar.shortDays,
|
851 |
+
monthNames : BooklyL10nAppDialog.calendar.longMonths,
|
852 |
+
monthNamesShort : BooklyL10nAppDialog.calendar.shortMonths,
|
853 |
+
firstDay : BooklyL10nAppDialog.startOfWeek
|
854 |
+
};
|
855 |
+
|
856 |
+
/**
|
857 |
+
* Datepicker options.
|
858 |
+
*/
|
859 |
+
$scope.dateOptions = {
|
860 |
+
dateFormat : BooklyL10nAppDialog.dpDateFormat,
|
861 |
+
dayNamesMin : BooklyL10nAppDialog.calendar.shortDays,
|
862 |
+
monthNames : BooklyL10nAppDialog.calendar.longMonths,
|
863 |
+
monthNamesShort : BooklyL10nAppDialog.calendar.shortMonths,
|
864 |
+
firstDay : BooklyL10nAppDialog.startOfWeek
|
865 |
+
};
|
866 |
+
});
|
867 |
+
|
868 |
+
/**
|
869 |
+
* Directive for slide up/down.
|
870 |
+
*/
|
871 |
+
module.directive('mySlideUp', function() {
|
872 |
+
return function(scope, element, attrs) {
|
873 |
+
element.hide();
|
874 |
+
// watch the expression, and update the UI on change.
|
875 |
+
scope.$watch(attrs.mySlideUp, function(value) {
|
876 |
+
if (value) {
|
877 |
+
element.delay(0).slideDown();
|
878 |
+
} else {
|
879 |
+
element.slideUp();
|
880 |
+
}
|
881 |
+
});
|
882 |
+
};
|
883 |
+
});
|
884 |
+
|
885 |
+
/**
|
886 |
+
* Directive for chosen.
|
887 |
+
*/
|
888 |
+
module.directive('chosen',function($timeout) {
|
889 |
+
var linker = function(scope,element,attrs) {
|
890 |
+
scope.$watch(attrs['chosen'], function() {
|
891 |
+
element.trigger('chosen:updated');
|
892 |
+
});
|
893 |
+
|
894 |
+
scope.$watchCollection(attrs['ngModel'], function() {
|
895 |
+
$timeout(function() {
|
896 |
+
element.trigger('chosen:updated');
|
897 |
+
});
|
898 |
+
});
|
899 |
+
|
900 |
+
scope.reInitChosen();
|
901 |
+
};
|
902 |
+
|
903 |
+
return {
|
904 |
+
restrict:'A',
|
905 |
+
link: linker
|
906 |
+
};
|
907 |
+
});
|
908 |
+
|
909 |
+
/**
|
910 |
+
* Directive for Popover jQuery plugin.
|
911 |
+
*/
|
912 |
+
module.directive('popover', function() {
|
913 |
+
return function(scope, element, attrs) {
|
914 |
+
element.popover({
|
915 |
+
trigger : 'hover',
|
916 |
+
content : function() { return this.getAttribute('popover'); },
|
917 |
+
html : true,
|
918 |
+
placement: 'top',
|
919 |
+
template: '<div class="popover bookly-font-xs" style="width: 220px" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
920 |
+
});
|
921 |
+
};
|
922 |
+
});
|
923 |
+
|
924 |
+
/**
|
925 |
+
* Filters for pagination in Schedule.
|
926 |
+
*/
|
927 |
+
module.filter('startFrom', function() {
|
928 |
+
return function(input, start){
|
929 |
+
start = +start;
|
930 |
+
return input.slice(start);
|
931 |
+
}
|
932 |
+
});
|
933 |
+
module.filter('range', function() {
|
934 |
+
return function(input, total) {
|
935 |
+
total = parseInt(total);
|
936 |
+
|
937 |
+
for (var i = 1; i <= total; ++ i) {
|
938 |
+
input.push(i);
|
939 |
+
}
|
940 |
+
|
941 |
+
return input;
|
942 |
+
};
|
943 |
+
});
|
944 |
+
})();
|
945 |
+
|
946 |
+
/**
|
947 |
+
* @param int appointment_id
|
948 |
+
* @param int staff_id
|
949 |
+
* @param moment start_date
|
950 |
+
* @param function callback
|
951 |
+
*/
|
952 |
+
var showAppointmentDialog = function (appointment_id, staff_id, start_date, callback) {
|
953 |
+
var $dialog = jQuery('#bookly-appointment-dialog');
|
954 |
+
var $scope = angular.element($dialog[0]).scope();
|
955 |
+
$scope.$apply(function ($scope) {
|
956 |
+
$scope.loading = true;
|
957 |
+
$dialog
|
958 |
+
.find('.modal-title')
|
959 |
+
.text(appointment_id ? BooklyL10nAppDialog.title.edit_appointment : BooklyL10nAppDialog.title.new_appointment);
|
960 |
+
// Populate data source.
|
961 |
+
$scope.dataSource.loadData().then(function() {
|
962 |
+
$scope.loading = false;
|
963 |
+
if (appointment_id) {
|
964 |
+
$scope.configureEditForm(appointment_id, callback);
|
965 |
+
} else {
|
966 |
+
$scope.configureNewForm(staff_id, start_date, callback);
|
967 |
+
}
|
968 |
+
});
|
969 |
+
});
|
970 |
+
|
971 |
+
// hide customer details dialog, if it remained opened.
|
972 |
+
if (jQuery('#bookly-customer-details-dialog').hasClass('in')) {
|
973 |
+
jQuery('#bookly-customer-details-dialog').modal('hide');
|
974 |
+
}
|
975 |
+
|
976 |
+
// hide new customer dialog, if it remained opened.
|
977 |
+
if (jQuery('#bookly-customer-dialog').hasClass('in')) {
|
978 |
+
jQuery('#bookly-customer-dialog').modal('hide');
|
979 |
+
}
|
980 |
+
|
981 |
+
$dialog.modal('show');
|
982 |
};
|
backend/modules/calendar/templates/_appointment_dialog.php
CHANGED
@@ -11,7 +11,7 @@
|
|
11 |
<div ng-show=loading class="modal-body">
|
12 |
<div class="bookly-loading"></div>
|
13 |
</div>
|
14 |
-
<div ng-hide=loading class="modal-body">
|
15 |
<div class=form-group>
|
16 |
<label for="ab_provider"><?php _e( 'Provider', 'bookly' ) ?></label>
|
17 |
<select id="ab_provider" class="field form-control" ng-model="form.staff" ng-options="s.full_name for s in dataSource.data.staff" ng-change="onStaffChange()"></select>
|
@@ -59,16 +59,16 @@
|
|
59 |
<?php _e( 'Selected period doesn\'t match service duration', 'bookly' ) ?>
|
60 |
</p>
|
61 |
<p class="text-success" my-slide-up="errors.time_interval" ng-bind="errors.time_interval"></p>
|
62 |
-
<p class="text-
|
63 |
<?php _e( 'The selected period is occupied by another appointment', 'bookly' ) ?>
|
64 |
</p>
|
65 |
</div>
|
66 |
</div>
|
67 |
</div>
|
68 |
</div>
|
69 |
-
|
70 |
<div class=form-group>
|
71 |
-
<label for="chosen"><?php _e( 'Customers', 'bookly' ) ?></label>
|
72 |
<span ng-show="form.service" title="<?php esc_attr_e( 'Selected / maximum', 'bookly' ) ?>">
|
73 |
({{dataSource.getTotalNumberOfPersons()}}/{{form.service.capacity}})
|
74 |
</span>
|
@@ -76,24 +76,24 @@
|
|
76 |
<li ng-repeat="customer in form.customers">
|
77 |
{{customer.number_of_persons}}×<i class="glyphicon glyphicon-user"></i>
|
78 |
<a ng-click="editCustomerDetails(customer)" title="<?php esc_attr_e( 'Edit booking details', 'bookly' ) ?>" href="#">{{customer.name}}</a>
|
79 |
-
<span ng-class="{'
|
80 |
popover="<?php esc_attr_e( 'Status', 'bookly' ) ?>: {{statusToString(customer.status)}}"></span>
|
81 |
<span ng-show="customer.payment_id"
|
82 |
popover="<?php esc_attr_e( 'Payment', 'bookly' ) ?>: {{customer.payment_title}}">
|
83 |
<a data-toggle="modal"
|
84 |
href="#bookly-payment-details-modal"
|
85 |
data-payment_id="{{customer.payment_id}}"
|
86 |
-
ng-class="{'bookly-js-toggle-popover
|
87 |
</span>
|
88 |
-
<a ng-click="removeCustomer(customer)" class="
|
89 |
popover="<?php esc_attr_e( 'Remove customer', 'bookly' ) ?>"></a>
|
90 |
</li>
|
91 |
</ul>
|
92 |
|
93 |
-
<div ng-show="!form.service || dataSource.
|
94 |
<div class="form-group">
|
95 |
<div class="input-group">
|
96 |
-
<select id="chosen" multiple data-placeholder="<?php esc_attr_e( '-- Search customers --', 'bookly' ) ?>"
|
97 |
class="field chzn-select form-control" chosen="dataSource.data.customers"
|
98 |
ng-model="form.customers" ng-options="c.name for c in dataSource.data.customers">
|
99 |
</select>
|
@@ -115,7 +115,7 @@
|
|
115 |
<div class=form-group>
|
116 |
<label for="ab_notification"><?php _e( 'Send notifications', 'bookly' ) ?></label>
|
117 |
<p class="help-block"><?php _e( 'If email or SMS notifications are enabled and you want customers or staff member to be notified about this appointment after saving, select appropriate option before clicking Save. With "If status changed" the notifications are sent to those customers whose status has just been changed. With "To all customers" the notifications are sent to everyone in the list.', 'bookly' ) ?></p>
|
118 |
-
<select class="form-control
|
119 |
<option value="no"><?php _e( 'Don\'t send', 'bookly' ) ?></option>
|
120 |
<option value="changed_status"><?php _e( 'If status changed', 'bookly' ) ?></option>
|
121 |
<option value="all"><?php _e( 'To all customers', 'bookly' ) ?></option>
|
@@ -127,12 +127,12 @@
|
|
127 |
<textarea class="form-control" ng-model=form.internal_note id="ab_internal_note"></textarea>
|
128 |
</div>
|
129 |
</div>
|
|
|
130 |
<div class="modal-footer">
|
131 |
<div ng-hide=loading>
|
132 |
-
<?php
|
133 |
-
|
134 |
-
|
135 |
-
</button>
|
136 |
</div>
|
137 |
</div>
|
138 |
</form>
|
11 |
<div ng-show=loading class="modal-body">
|
12 |
<div class="bookly-loading"></div>
|
13 |
</div>
|
14 |
+
<div ng-hide="loading || form.screen != 'main'" class="modal-body">
|
15 |
<div class=form-group>
|
16 |
<label for="ab_provider"><?php _e( 'Provider', 'bookly' ) ?></label>
|
17 |
<select id="ab_provider" class="field form-control" ng-model="form.staff" ng-options="s.full_name for s in dataSource.data.staff" ng-change="onStaffChange()"></select>
|
59 |
<?php _e( 'Selected period doesn\'t match service duration', 'bookly' ) ?>
|
60 |
</p>
|
61 |
<p class="text-success" my-slide-up="errors.time_interval" ng-bind="errors.time_interval"></p>
|
62 |
+
<p class="text-danger" my-slide-up=errors.date_interval_not_available id=date_interval_not_available_msg>
|
63 |
<?php _e( 'The selected period is occupied by another appointment', 'bookly' ) ?>
|
64 |
</p>
|
65 |
</div>
|
66 |
</div>
|
67 |
</div>
|
68 |
</div>
|
69 |
+
<?php do_action( 'bookly_recurring_appointments_render_appointment_dialog_repeat' ) ?>
|
70 |
<div class=form-group>
|
71 |
+
<label for="bookly-chosen"><?php _e( 'Customers', 'bookly' ) ?></label>
|
72 |
<span ng-show="form.service" title="<?php esc_attr_e( 'Selected / maximum', 'bookly' ) ?>">
|
73 |
({{dataSource.getTotalNumberOfPersons()}}/{{form.service.capacity}})
|
74 |
</span>
|
76 |
<li ng-repeat="customer in form.customers">
|
77 |
{{customer.number_of_persons}}×<i class="glyphicon glyphicon-user"></i>
|
78 |
<a ng-click="editCustomerDetails(customer)" title="<?php esc_attr_e( 'Edit booking details', 'bookly' ) ?>" href="#">{{customer.name}}</a>
|
79 |
+
<span ng-class="{'dashicons': true, 'dashicons-clock': customer.status == 'pending', 'dashicons-yes': customer.status == 'approved', 'dashicons-no': customer.status == 'cancelled', 'dashicons-dismiss': customer.status == 'rejected'}"
|
80 |
popover="<?php esc_attr_e( 'Status', 'bookly' ) ?>: {{statusToString(customer.status)}}"></span>
|
81 |
<span ng-show="customer.payment_id"
|
82 |
popover="<?php esc_attr_e( 'Payment', 'bookly' ) ?>: {{customer.payment_title}}">
|
83 |
<a data-toggle="modal"
|
84 |
href="#bookly-payment-details-modal"
|
85 |
data-payment_id="{{customer.payment_id}}"
|
86 |
+
ng-class="{'bookly-js-toggle-popover dashicons': true, 'dashicons-thumbs-up': customer.payment_type == 'full', 'dashicons-warning': customer.payment_type == 'partial'}"></a>
|
87 |
</span>
|
88 |
+
<a ng-click="removeCustomer(customer)" class="dashicons dashicons-trash text-danger" href="#"
|
89 |
popover="<?php esc_attr_e( 'Remove customer', 'bookly' ) ?>"></a>
|
90 |
</li>
|
91 |
</ul>
|
92 |
|
93 |
+
<div ng-show="!form.service || dataSource.getTotalNumberOfNotCancelledPersons() < form.service.capacity">
|
94 |
<div class="form-group">
|
95 |
<div class="input-group">
|
96 |
+
<select id="bookly-chosen" multiple data-placeholder="<?php esc_attr_e( '-- Search customers --', 'bookly' ) ?>"
|
97 |
class="field chzn-select form-control" chosen="dataSource.data.customers"
|
98 |
ng-model="form.customers" ng-options="c.name for c in dataSource.data.customers">
|
99 |
</select>
|
115 |
<div class=form-group>
|
116 |
<label for="ab_notification"><?php _e( 'Send notifications', 'bookly' ) ?></label>
|
117 |
<p class="help-block"><?php _e( 'If email or SMS notifications are enabled and you want customers or staff member to be notified about this appointment after saving, select appropriate option before clicking Save. With "If status changed" the notifications are sent to those customers whose status has just been changed. With "To all customers" the notifications are sent to everyone in the list.', 'bookly' ) ?></p>
|
118 |
+
<select class="form-control" style="margin-top: 0" ng-model=form.notification id="ab_notification">
|
119 |
<option value="no"><?php _e( 'Don\'t send', 'bookly' ) ?></option>
|
120 |
<option value="changed_status"><?php _e( 'If status changed', 'bookly' ) ?></option>
|
121 |
<option value="all"><?php _e( 'To all customers', 'bookly' ) ?></option>
|
127 |
<textarea class="form-control" ng-model=form.internal_note id="ab_internal_note"></textarea>
|
128 |
</div>
|
129 |
</div>
|
130 |
+
<?php do_action( 'bookly_recurring_appointments_render_appointment_dialog_schedule' ) ?>
|
131 |
<div class="modal-footer">
|
132 |
<div ng-hide=loading>
|
133 |
+
<?php do_action( 'bookly_recurring_appointments_render_appointment_dialog_next_button' ) ?>
|
134 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( 'bookly-save', 'btn-lg btn-success', null, array( 'ng-hide' => 'form.repeat.enabled && form.screen == \'main\'', 'ng-disabled' => 'form.repeat.enabled && schIsScheduleEmpty()' ), 'submit' ) ?>
|
135 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'ng-click' => 'closeDialog()', 'data-dismiss' => 'modal' ) ) ?>
|
|
|
136 |
</div>
|
137 |
</div>
|
138 |
</form>
|
backend/modules/calendar/templates/_customer_details_dialog.php
CHANGED
@@ -1,98 +1,99 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use BooklyLite\Lib\Entities\CustomerAppointment;
|
3 |
-
?>
|
4 |
-
<div id="bookly-customer-details-dialog" class="modal fade" tabindex=-1 role="dialog">
|
5 |
-
<div class="modal-dialog">
|
6 |
-
<div class="modal-content">
|
7 |
-
<div class="modal-header">
|
8 |
-
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
9 |
-
<div class="modal-title h2"><?php _e( 'Edit booking details', 'bookly' ) ?></div>
|
10 |
-
</div>
|
11 |
-
<form ng-hide=loading style="z-index: 1050">
|
12 |
-
<div class="modal-body">
|
13 |
-
<div class="form-group">
|
14 |
-
<label for="ab-appointment-status"><?php _e( 'Status', 'bookly' ) ?></label>
|
15 |
-
<select class="ab-custom-field form-control" id="ab-appointment-status">
|
16 |
-
<option value="<?php echo CustomerAppointment::STATUS_PENDING ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?></option>
|
17 |
-
<option value="<?php echo CustomerAppointment::STATUS_APPROVED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?></option>
|
18 |
-
<option value="<?php echo CustomerAppointment::STATUS_CANCELLED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?></option>
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
<
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
<
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
<?php echo $item ?>
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
<?php echo $item ?>
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
<input type="button" class="ab-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
98 |
</div><!-- /.modal -->
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Entities\CustomerAppointment;
|
3 |
+
?>
|
4 |
+
<div id="bookly-customer-details-dialog" class="modal fade" tabindex=-1 role="dialog">
|
5 |
+
<div class="modal-dialog">
|
6 |
+
<div class="modal-content">
|
7 |
+
<div class="modal-header">
|
8 |
+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
9 |
+
<div class="modal-title h2"><?php _e( 'Edit booking details', 'bookly' ) ?></div>
|
10 |
+
</div>
|
11 |
+
<form ng-hide=loading style="z-index: 1050">
|
12 |
+
<div class="modal-body">
|
13 |
+
<div class="form-group">
|
14 |
+
<label for="ab-appointment-status"><?php _e( 'Status', 'bookly' ) ?></label>
|
15 |
+
<select class="ab-custom-field form-control" id="ab-appointment-status">
|
16 |
+
<option value="<?php echo CustomerAppointment::STATUS_PENDING ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?></option>
|
17 |
+
<option value="<?php echo CustomerAppointment::STATUS_APPROVED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?></option>
|
18 |
+
<option value="<?php echo CustomerAppointment::STATUS_CANCELLED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?></option>
|
19 |
+
<option value="<?php echo CustomerAppointment::STATUS_REJECTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ) ?></option>
|
20 |
+
</select>
|
21 |
+
</div>
|
22 |
+
<div class="form-group">
|
23 |
+
<label for="ab-edit-number-of-persons"><?php _e( 'Number of persons', 'bookly' ) ?></label>
|
24 |
+
<select class="ab-custom-field form-control" id="ab-edit-number-of-persons"></select>
|
25 |
+
</div>
|
26 |
+
<?php do_action( 'bookly_render_customer_details_dialog' ) ?>
|
27 |
+
<h3 class="bookly-block-head bookly-color-gray">
|
28 |
+
<?php _e( 'Custom Fields', 'bookly' ) ?>
|
29 |
+
</h3>
|
30 |
+
<div id="ab--custom-fields">
|
31 |
+
<?php foreach ( $custom_fields as $custom_field ) : ?>
|
32 |
+
<div class="form-group" data-type="<?php echo esc_attr( $custom_field->type )?>" data-id="<?php echo esc_attr( $custom_field->id ) ?>" data-services="<?php echo esc_attr( json_encode( $custom_field->services ) ) ?>">
|
33 |
+
<label for="custom_field_<?php echo esc_attr( $custom_field->id ) ?>"><?php echo $custom_field->label ?></label>
|
34 |
+
<div>
|
35 |
+
<?php if ( $custom_field->type == 'text-field' ) : ?>
|
36 |
+
<input id="custom_field_<?php echo esc_attr( $custom_field->id ) ?>" type="text" class="ab-custom-field form-control" />
|
37 |
+
|
38 |
+
<?php elseif ( $custom_field->type == 'textarea' ) : ?>
|
39 |
+
<textarea id="custom_field_<?php echo esc_attr( $custom_field->id ) ?>" rows="3" class="ab-custom-field form-control"></textarea>
|
40 |
+
|
41 |
+
<?php elseif ( $custom_field->type == 'checkboxes' ) : ?>
|
42 |
+
<?php foreach ( $custom_field->items as $item ) : ?>
|
43 |
+
<div class="checkbox">
|
44 |
+
<label>
|
45 |
+
<input class="ab-custom-field" type="checkbox" value="<?php echo esc_attr( $item ) ?>" />
|
46 |
+
<?php echo $item ?>
|
47 |
+
</label>
|
48 |
+
</div>
|
49 |
+
<?php endforeach ?>
|
50 |
+
|
51 |
+
<?php elseif ( $custom_field->type == 'radio-buttons' ) : ?>
|
52 |
+
<?php foreach ( $custom_field->items as $item ) : ?>
|
53 |
+
<div class="radio">
|
54 |
+
<label>
|
55 |
+
<input type="radio" name="<?php echo $custom_field->id ?>" class="ab-custom-field" value="<?php echo esc_attr( $item ) ?>" />
|
56 |
+
<?php echo $item ?>
|
57 |
+
</label>
|
58 |
+
</div>
|
59 |
+
<?php endforeach ?>
|
60 |
+
|
61 |
+
<?php elseif ( $custom_field->type == 'drop-down' ) : ?>
|
62 |
+
<select id="custom_field_<?php echo esc_attr( $custom_field->id ) ?>" class="ab-custom-field form-control">
|
63 |
+
<option value=""></option>
|
64 |
+
<?php foreach ( $custom_field->items as $item ) : ?>
|
65 |
+
<option value="<?php echo esc_attr( $item ) ?>"><?php echo $item ?></option>
|
66 |
+
<?php endforeach ?>
|
67 |
+
</select>
|
68 |
+
<?php endif ?>
|
69 |
+
</div>
|
70 |
+
</div>
|
71 |
+
<?php endforeach ?>
|
72 |
+
</div>
|
73 |
+
|
74 |
+
<?php if ( $extras = apply_filters( 'bookly_service_extras_find_all', array() ) ) : ?>
|
75 |
+
<h3 class="bookly-block-head bookly-color-gray">
|
76 |
+
<?php _e( 'Extras', 'bookly' ) ?>
|
77 |
+
</h3>
|
78 |
+
<div id="bookly-extras" class="bookly-flexbox">
|
79 |
+
<?php foreach ( $extras as $extra ) : ?>
|
80 |
+
<div class="bookly-flex-row service_<?php echo $extra->get( 'service_id' ) ?> bookly-margin-bottom-sm">
|
81 |
+
<div class="bookly-flex-cell bookly-padding-bottom-sm" style="width:5em">
|
82 |
+
<input class="extras-count form-control" data-id="<?php echo $extra->get( 'id' ) ?>" type="number" min="0" name="extra[<?php echo $extra->get( 'id' ) ?>]" value="0" />
|
83 |
+
</div>
|
84 |
+
<div class="bookly-flex-cell bookly-padding-bottom-sm bookly-vertical-middle">
|
85 |
+
× <b><?php echo $extra->getTitle() ?></b> (<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $extra->get( 'price' ) ) ?>)
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
<?php endforeach ?>
|
89 |
+
</div>
|
90 |
+
<?php endif ?>
|
91 |
+
</div>
|
92 |
+
<div class="modal-footer">
|
93 |
+
<input type="button" data-customer="" ng-click=saveCustomFields() class="ab-popup-save btn btn-lg btn-success" value="<?php _e( 'Apply', 'bookly' ) ?>">
|
94 |
+
<input type="button" class="btn btn-lg btn-default" data-dismiss=modal value="<?php _e( 'Cancel', 'bookly' ) ?>" aria-hidden=true>
|
95 |
+
</div>
|
96 |
+
</form>
|
97 |
+
</div><!-- /.modal-content -->
|
98 |
+
</div><!-- /.modal-dialog -->
|
99 |
</div><!-- /.modal -->
|
backend/modules/calendar/templates/_delete_dialog.php
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Template for delete appointment dialog
|
4 |
+
*/
|
5 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
6 |
+
?>
|
7 |
+
|
8 |
+
<div id="bookly-delete-dialog" class="modal fade" tabindex=-1 role="dialog">
|
9 |
+
<div class="modal-dialog">
|
10 |
+
<div class="modal-content">
|
11 |
+
<div class="modal-header">
|
12 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
13 |
+
<div class="modal-title h2"><?php _e( 'Delete', 'bookly' ) ?></div>
|
14 |
+
</div>
|
15 |
+
<div class="modal-body">
|
16 |
+
<div class="checkbox">
|
17 |
+
<label>
|
18 |
+
<input id="bookly-delete-notify" type="checkbox" />
|
19 |
+
<?php _e( 'Send notifications', 'bookly' ) ?>
|
20 |
+
</label>
|
21 |
+
</div>
|
22 |
+
<div class="form-group" style="display: none;" id="bookly-delete-reason-cover">
|
23 |
+
<input class="form-control" type="text" id="bookly-delete-reason" placeholder="<?php _e( 'Cancellation reason (optional)', 'bookly' ) ?>" />
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
<div class="modal-footer">
|
27 |
+
<?php \BooklyLite\Lib\Utils\Common::deleteButton(); ?>
|
28 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn-default', __( 'Cancel', 'bookly' ), array( 'ng-click' => 'closeDialog()', 'data-dismiss' => 'modal' ) ) ?>
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</div>
|
backend/modules/calendar/templates/calendar.php
CHANGED
@@ -1,92 +1,94 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
<div
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
<?php
|
14 |
-
|
15 |
-
</div>
|
16 |
-
<div class="panel panel-default bookly-main bookly-fc-inner">
|
17 |
-
<div class="panel-body">
|
18 |
-
<?php if ( $staff_members ) : ?>
|
19 |
-
<ul class="bookly-nav bookly-nav-tabs">
|
20 |
-
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
21 |
-
<li class="bookly-nav-item bookly-js-calendar-tab" data-staff_id="0">
|
22 |
-
<?php _e( 'All', 'bookly' ) ?>
|
23 |
-
</li>
|
24 |
-
<?php endif ?>
|
25 |
-
<?php foreach ( $staff_members as $
|
26 |
-
<li class="bookly-nav-item bookly-js-calendar-tab" data-staff_id="<?php echo $staff->id ?>" style="display: none">
|
27 |
-
<?php echo $staff->full_name ?>
|
28 |
-
</li>
|
29 |
-
<?php endforeach ?>
|
30 |
-
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
31 |
-
<div class="btn-group pull-right" style="margin-top: 5px;">
|
32 |
-
<button class="btn btn-default dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
33 |
-
<div class="bookly-flex-cell"><i class="dashicons dashicons-admin-users bookly-margin-right-md"></i></div>
|
34 |
-
<div class="bookly-flex-cell text-left"><span id="ab-staff-button"></span></div>
|
35 |
-
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
36 |
-
</button>
|
37 |
-
<ul class="dropdown-menu bookly-entity-selector">
|
38 |
-
<li>
|
39 |
-
<a class="checkbox" href="javascript:void(0)">
|
40 |
-
<label><input type="checkbox" id="bookly-check-all-entities"><?php _e( 'All staff', 'bookly' ) ?></label>
|
41 |
-
</a>
|
42 |
-
</li>
|
43 |
-
<?php foreach ( $staff_members as $
|
44 |
-
<li>
|
45 |
-
<a class="checkbox" href="javascript:void(0)">
|
46 |
-
<label>
|
47 |
-
<input type="checkbox" id="ab-filter-staff-<?php echo $staff->id ?>" value="<?php echo $staff->id ?>" data-staff_name="<?php echo esc_attr( $staff->full_name ) ?>" class="bookly-js-check-entity">
|
48 |
-
<?php echo $staff->full_name ?>
|
49 |
-
</label>
|
50 |
-
</a>
|
51 |
-
</li>
|
52 |
-
<?php endforeach ?>
|
53 |
-
</ul>
|
54 |
-
</div>
|
55 |
-
<?php endif ?>
|
56 |
-
</ul>
|
57 |
-
<?php endif ?>
|
58 |
-
<div class="bookly-margin-top-xlg">
|
59 |
-
<div style="display: none;" class="bookly-loading bookly-js-loading"></div>
|
60 |
-
<?php if ( $staff_members ) : ?>
|
61 |
-
<div class="fc-loading-inner" style="display: none">
|
62 |
-
<div class="fc-loading"></div>
|
63 |
-
</div>
|
64 |
-
<div id="bookly-fc-wrapper" class="bookly-calendar">
|
65 |
-
<div class="bookly-js-calendar-element"></div>
|
66 |
-
</div>
|
67 |
-
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderAppointmentDialog() ?>
|
68 |
-
<?php do_action( 'bookly_render_component_calendar' ) ?>
|
69 |
-
<?php else : ?>
|
70 |
-
<div class="well">
|
71 |
-
<div class="h1"><?php _e( 'Welcome to Bookly!',
|
72 |
-
<h3><?php _e( 'Thank you for purchasing our product.', 'bookly' ) ?></h3>
|
73 |
-
<h3><?php _e( 'Bookly offers a simple solution for making appointments. With our plugin you will be able to easily manage your availability time and handle the flow of your clients.', 'bookly' ) ?></h3>
|
74 |
-
<p><?php _e( 'To start using Bookly, you need to follow these steps which are the minimum requirements to get it running!', 'bookly' ) ?></p>
|
75 |
-
<ol>
|
76 |
-
<li><?php _e( 'Add staff members.', 'bookly' ) ?></li>
|
77 |
-
<li><?php _e( 'Add services and assign them to staff members.', 'bookly' ) ?></li>
|
78 |
-
</ol>
|
79 |
-
<hr>
|
80 |
-
<a class="btn btn-success" href="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( BooklyLite\Backend\Modules\Staff\Controller::page_slug ) ?>">
|
81 |
-
<?php _e( 'Add Staff Members', 'bookly' ) ?>
|
82 |
-
</a>
|
83 |
-
<a class="btn btn-success" href="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( BooklyLite\Backend\Modules\Services\Controller::page_slug ) ?>">
|
84 |
-
<?php _e( 'Add Services', 'bookly' ) ?>
|
85 |
-
</a>
|
86 |
-
</div>
|
87 |
-
<?php endif ?>
|
88 |
-
</div>
|
89 |
-
</div>
|
90 |
-
</div>
|
91 |
-
|
|
|
|
|
92 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<style>
|
3 |
+
.fc-slats tr { height: <?php echo max( 21, (int) ( 0.43 * get_option( 'bookly_gen_time_slot_length' ) ) ) ?>px; }
|
4 |
+
.fc-time-grid-event.fc-short .fc-time::after { content: '' !important; }
|
5 |
+
</style>
|
6 |
+
<div id="bookly-tbs" class="wrap">
|
7 |
+
<div class="bookly-tbs-body">
|
8 |
+
<div class="page-header text-right clearfix">
|
9 |
+
<div class="bookly-page-title">
|
10 |
+
<?php _e( 'Calendar', 'bookly' ) ?>
|
11 |
+
</div>
|
12 |
+
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
13 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
14 |
+
<?php endif ?>
|
15 |
+
</div>
|
16 |
+
<div class="panel panel-default bookly-main bookly-fc-inner">
|
17 |
+
<div class="panel-body">
|
18 |
+
<?php if ( $staff_members ) : ?>
|
19 |
+
<ul class="bookly-nav bookly-nav-tabs">
|
20 |
+
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
21 |
+
<li class="bookly-nav-item bookly-js-calendar-tab" data-staff_id="0">
|
22 |
+
<?php _e( 'All', 'bookly' ) ?>
|
23 |
+
</li>
|
24 |
+
<?php endif ?>
|
25 |
+
<?php foreach ( $staff_members as $staff ) : ?>
|
26 |
+
<li class="bookly-nav-item bookly-js-calendar-tab" data-staff_id="<?php echo $staff->id ?>" style="display: none">
|
27 |
+
<?php echo $staff->full_name ?>
|
28 |
+
</li>
|
29 |
+
<?php endforeach ?>
|
30 |
+
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
31 |
+
<div class="btn-group pull-right" style="margin-top: 5px;">
|
32 |
+
<button class="btn btn-default dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
33 |
+
<div class="bookly-flex-cell"><i class="dashicons dashicons-admin-users bookly-margin-right-md"></i></div>
|
34 |
+
<div class="bookly-flex-cell text-left"><span id="ab-staff-button"></span></div>
|
35 |
+
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
36 |
+
</button>
|
37 |
+
<ul class="dropdown-menu bookly-entity-selector">
|
38 |
+
<li>
|
39 |
+
<a class="checkbox" href="javascript:void(0)">
|
40 |
+
<label><input type="checkbox" id="bookly-check-all-entities"><?php _e( 'All staff', 'bookly' ) ?></label>
|
41 |
+
</a>
|
42 |
+
</li>
|
43 |
+
<?php foreach ( $staff_members as $staff ) : ?>
|
44 |
+
<li>
|
45 |
+
<a class="checkbox" href="javascript:void(0)">
|
46 |
+
<label>
|
47 |
+
<input type="checkbox" id="ab-filter-staff-<?php echo $staff->id ?>" value="<?php echo $staff->id ?>" data-staff_name="<?php echo esc_attr( $staff->full_name ) ?>" class="bookly-js-check-entity">
|
48 |
+
<?php echo $staff->full_name ?>
|
49 |
+
</label>
|
50 |
+
</a>
|
51 |
+
</li>
|
52 |
+
<?php endforeach ?>
|
53 |
+
</ul>
|
54 |
+
</div>
|
55 |
+
<?php endif ?>
|
56 |
+
</ul>
|
57 |
+
<?php endif ?>
|
58 |
+
<div class="bookly-margin-top-xlg">
|
59 |
+
<div style="display: none;" class="bookly-loading bookly-js-loading"></div>
|
60 |
+
<?php if ( $staff_members ) : ?>
|
61 |
+
<div class="fc-loading-inner" style="display: none">
|
62 |
+
<div class="fc-loading"></div>
|
63 |
+
</div>
|
64 |
+
<div id="bookly-fc-wrapper" class="bookly-calendar">
|
65 |
+
<div class="bookly-js-calendar-element"></div>
|
66 |
+
</div>
|
67 |
+
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderAppointmentDialog() ?>
|
68 |
+
<?php do_action( 'bookly_render_component_calendar' ) ?>
|
69 |
+
<?php else : ?>
|
70 |
+
<div class="well">
|
71 |
+
<div class="h1"><?php _e( 'Welcome to Bookly!', 'bookly' ) ?></div>
|
72 |
+
<h3><?php _e( 'Thank you for purchasing our product.', 'bookly' ) ?></h3>
|
73 |
+
<h3><?php _e( 'Bookly offers a simple solution for making appointments. With our plugin you will be able to easily manage your availability time and handle the flow of your clients.', 'bookly' ) ?></h3>
|
74 |
+
<p><?php _e( 'To start using Bookly, you need to follow these steps which are the minimum requirements to get it running!', 'bookly' ) ?></p>
|
75 |
+
<ol>
|
76 |
+
<li><?php _e( 'Add staff members.', 'bookly' ) ?></li>
|
77 |
+
<li><?php _e( 'Add services and assign them to staff members.', 'bookly' ) ?></li>
|
78 |
+
</ol>
|
79 |
+
<hr>
|
80 |
+
<a class="btn btn-success" href="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( BooklyLite\Backend\Modules\Staff\Controller::page_slug ) ?>">
|
81 |
+
<?php _e( 'Add Staff Members', 'bookly' ) ?>
|
82 |
+
</a>
|
83 |
+
<a class="btn btn-success" href="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( BooklyLite\Backend\Modules\Services\Controller::page_slug ) ?>">
|
84 |
+
<?php _e( 'Add Services', 'bookly' ) ?>
|
85 |
+
</a>
|
86 |
+
</div>
|
87 |
+
<?php endif ?>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderDeleteDialog(); ?>
|
93 |
+
</div>
|
94 |
</div>
|
backend/modules/coupons/Controller.php
CHANGED
@@ -1,64 +1,66 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Coupons;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Coupons
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
'js/
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
'
|
39 |
-
'
|
40 |
-
'
|
41 |
-
|
42 |
-
|
43 |
-
'
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
*
|
57 |
-
*
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
|
|
|
|
64 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Coupons;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Coupons
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-coupons';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Default action
|
16 |
+
*/
|
17 |
+
public function index()
|
18 |
+
{
|
19 |
+
$this->enqueueStyles( array(
|
20 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
21 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
22 |
+
) );
|
23 |
+
|
24 |
+
$this->enqueueScripts( array(
|
25 |
+
'backend' => array(
|
26 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
27 |
+
'js/datatables.min.js' => array( 'jquery' ),
|
28 |
+
'js/alert.js' => array( 'jquery' ),
|
29 |
+
),
|
30 |
+
'frontend' => array(
|
31 |
+
'js/spin.min.js' => array( 'jquery' ),
|
32 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
33 |
+
),
|
34 |
+
'module' => array( 'js/coupons.js' => array( 'jquery' ) )
|
35 |
+
) );
|
36 |
+
|
37 |
+
wp_localize_script( 'bookly-coupons.js', 'BooklyL10n', array(
|
38 |
+
'edit' => __( 'Edit', 'bookly' ),
|
39 |
+
'zeroRecords' => __( 'No coupons found.', 'bookly' ),
|
40 |
+
'processing' => __( 'Processing...', 'bookly' ),
|
41 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
42 |
+
'selector' => array(
|
43 |
+
'all_selected' => __( 'All services', 'bookly' ),
|
44 |
+
'nothing_selected' => __( 'No service selected', 'bookly' ),
|
45 |
+
'collection' => array(),
|
46 |
+
),
|
47 |
+
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
48 |
+
) );
|
49 |
+
|
50 |
+
$this->render( 'index' );
|
51 |
+
}
|
52 |
+
|
53 |
+
// Protected methods.
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
57 |
+
* so current 'execute*' methods look nicer.
|
58 |
+
*
|
59 |
+
* @param string $prefix
|
60 |
+
*/
|
61 |
+
protected function registerWpActions( $prefix = '' )
|
62 |
+
{
|
63 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
64 |
+
}
|
65 |
+
|
66 |
}
|
backend/modules/coupons/forms/Coupon.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Coupons\Forms;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Coupon
|
8 |
-
* @package BooklyLite\Backend\Modules\Coupons\Forms
|
9 |
-
*/
|
10 |
-
class Coupon extends Lib\Base\Form
|
11 |
-
{
|
12 |
-
protected static $entity_class = 'Coupon';
|
13 |
-
|
14 |
-
public function configure()
|
15 |
-
{
|
16 |
-
$this->setFields( array( 'id', 'code', 'discount', 'deduction', 'usage_limit' ) );
|
17 |
-
}
|
18 |
-
|
19 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Coupons\Forms;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Coupon
|
8 |
+
* @package BooklyLite\Backend\Modules\Coupons\Forms
|
9 |
+
*/
|
10 |
+
class Coupon extends Lib\Base\Form
|
11 |
+
{
|
12 |
+
protected static $entity_class = 'Coupon';
|
13 |
+
|
14 |
+
public function configure()
|
15 |
+
{
|
16 |
+
$this->setFields( array( 'id', 'code', 'discount', 'deduction', 'usage_limit' ) );
|
17 |
+
}
|
18 |
+
|
19 |
}
|
backend/modules/coupons/resources/js/coupons.js
CHANGED
@@ -1,64 +1,63 @@
|
|
1 |
-
jQuery(function($) {
|
2 |
-
|
3 |
-
var
|
4 |
-
$coupons_list = $('#bookly-coupons-list'),
|
5 |
-
$coupon_modal = $('#bookly-coupon-modal'),
|
6 |
-
$save_button = $('#bookly-coupon-save')
|
7 |
-
;
|
8 |
-
|
9 |
-
/**
|
10 |
-
* Init DataTables.
|
11 |
-
*/
|
12 |
-
var dt = $coupons_list.DataTable({
|
13 |
-
order: [[ 0, "asc" ]],
|
14 |
-
paging: false,
|
15 |
-
info: false,
|
16 |
-
searching: false,
|
17 |
-
processing: true,
|
18 |
-
responsive: true,
|
19 |
-
data: [],
|
20 |
-
|
21 |
-
|
22 |
-
{ data: "
|
23 |
-
{ data: "
|
24 |
-
{ data:
|
25 |
-
{ data:
|
26 |
-
{ data: "
|
27 |
-
{
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
});
|
1 |
+
jQuery(function($) {
|
2 |
+
|
3 |
+
var
|
4 |
+
$coupons_list = $('#bookly-coupons-list'),
|
5 |
+
$coupon_modal = $('#bookly-coupon-modal'),
|
6 |
+
$save_button = $('#bookly-coupon-save')
|
7 |
+
;
|
8 |
+
|
9 |
+
/**
|
10 |
+
* Init DataTables.
|
11 |
+
*/
|
12 |
+
var dt = $coupons_list.DataTable({
|
13 |
+
order: [[ 0, "asc" ]],
|
14 |
+
paging: false,
|
15 |
+
info: false,
|
16 |
+
searching: false,
|
17 |
+
processing: true,
|
18 |
+
responsive: true,
|
19 |
+
data: [],
|
20 |
+
columns: [
|
21 |
+
{ data: "code" },
|
22 |
+
{ data: "discount" },
|
23 |
+
{ data: "deduction" },
|
24 |
+
{ data: 'service_ids'},
|
25 |
+
{ data: "usage_limit" },
|
26 |
+
{ data: "used" },
|
27 |
+
{
|
28 |
+
responsivePriority: 1,
|
29 |
+
orderable: false,
|
30 |
+
searchable: false,
|
31 |
+
render: function ( data, type, row, meta ) {
|
32 |
+
return '<button type="button" class="btn btn-default" data-toggle="modal" data-target="#bookly-coupon-modal"><i class="glyphicon glyphicon-edit"></i> ' + BooklyL10n.edit + '</button>';
|
33 |
+
}
|
34 |
+
},
|
35 |
+
{
|
36 |
+
responsivePriority: 1,
|
37 |
+
orderable: false,
|
38 |
+
searchable: false,
|
39 |
+
render: function ( data, type, row, meta ) {
|
40 |
+
return '<input type="checkbox" value="' + row.id + '">';
|
41 |
+
}
|
42 |
+
}
|
43 |
+
],
|
44 |
+
language: {
|
45 |
+
zeroRecords: BooklyL10n.zeroRecords,
|
46 |
+
processing: BooklyL10n.processing
|
47 |
+
}
|
48 |
+
});
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Save coupon.
|
52 |
+
*/
|
53 |
+
$save_button.on('click', function (e) {
|
54 |
+
e.preventDefault();
|
55 |
+
$coupon_modal.modal('hide');
|
56 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
57 |
+
});
|
58 |
+
$('#bookly-add,#bookly-delete').on('click', function (e) {
|
59 |
+
e.preventDefault();
|
60 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
61 |
+
});
|
62 |
+
|
63 |
+
});
|
|
backend/modules/coupons/templates/_modal.php
CHANGED
@@ -1 +1,66 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="modal fade" id="bookly-coupon-modal" tabindex="-1">
|
3 |
+
<div class="modal-dialog">
|
4 |
+
<div class="modal-content">
|
5 |
+
<form>
|
6 |
+
<div class="modal-header">
|
7 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
8 |
+
<h4 class="modal-title" id="bookly-new-coupon-title"><?php _e( 'New coupon', 'bookly' ) ?></h4>
|
9 |
+
<h4 class="modal-title" id="bookly-edit-coupon-title"><?php _e( 'Edit coupon', 'bookly' ) ?></h4>
|
10 |
+
</div>
|
11 |
+
<div class="modal-body">
|
12 |
+
<div class="row">
|
13 |
+
<div class="col-sm-12">
|
14 |
+
<div class=form-group>
|
15 |
+
<label for="bookly-coupon-code"><?php _e( 'Code', 'bookly' ) ?></label>
|
16 |
+
<input type="text" id="bookly-coupon-code" class="form-control" name="code" />
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
<div class="col-sm-6">
|
20 |
+
<div class=form-group>
|
21 |
+
<label for="bookly-coupon-discount"><?php _e( 'Discount (%)', 'bookly' ) ?></label>
|
22 |
+
<input type="number" id="bookly-coupon-discount" class="form-control" name="discount" />
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
<div class="col-sm-6">
|
26 |
+
<div class=form-group>
|
27 |
+
<label for="bookly-coupon-deduction"><?php _e( 'Deduction', 'bookly' ) ?></label>
|
28 |
+
<input type="text" id="bookly-coupon-deduction" class="form-control" name="deduction" />
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
<div class="col-sm-12">
|
32 |
+
<div class=form-group>
|
33 |
+
<label for="bookly-coupon-usage-limit"><?php _e( 'Usage limit', 'bookly' ) ?></label>
|
34 |
+
<input type="number" id="bookly-coupon-usage-limit" class="form-control" name="usage_limit" min="0" step="1" />
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
<div class="col-sm-12">
|
38 |
+
<div class="btn-group">
|
39 |
+
<button class="btn btn-default dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
40 |
+
<div class="bookly-flex-cell"><i class="glyphicon glyphicon-tag bookly-margin-right-md"></i></div>
|
41 |
+
<div class="bookly-flex-cell text-left"><span id="bookly-entity-counter"></span></div>
|
42 |
+
<div class="bookly-flex-cell">
|
43 |
+
<div class="bookly-margin-left-md"><span class="caret"></span></div>
|
44 |
+
</div>
|
45 |
+
</button>
|
46 |
+
<ul class="dropdown-menu bookly-entity-selector">
|
47 |
+
<li>
|
48 |
+
<a class="checkbox" href="javascript:void(0)">
|
49 |
+
<label><input type="checkbox" id="bookly-check-all-entities"/><?php _e( 'All Services', 'bookly' ) ?></label>
|
50 |
+
</a>
|
51 |
+
</li>
|
52 |
+
</ul>
|
53 |
+
</div>
|
54 |
+
</div>
|
55 |
+
</div>
|
56 |
+
</div>
|
57 |
+
<div class="modal-footer">
|
58 |
+
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'bookly-coupon-save' ) ?>
|
59 |
+
<button class="btn btn-lg btn-default" data-dismiss="modal">
|
60 |
+
<?php _e( 'Cancel', 'bookly' ) ?>
|
61 |
+
</button>
|
62 |
+
</div>
|
63 |
+
</form>
|
64 |
+
</div>
|
65 |
+
</div>
|
66 |
+
</div>
|
backend/modules/coupons/templates/index.php
CHANGED
@@ -1,45 +1,44 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-tbs" class="wrap">
|
3 |
-
<div class="bookly-tbs-body">
|
4 |
-
<div class="page-header text-right clearfix">
|
5 |
-
<div class="bookly-page-title">
|
6 |
-
<?php _e( 'Coupons', 'bookly' ) ?>
|
7 |
-
</div>
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
<th><?php _e( '
|
27 |
-
<th><?php _e( '
|
28 |
-
<th><?php _e( '
|
29 |
-
<th><?php _e( '
|
30 |
-
<th><?php _e( '
|
31 |
-
<th
|
32 |
-
<th></th>
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
<?php include '_modal.php' ?>
|
45 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-tbs" class="wrap">
|
3 |
+
<div class="bookly-tbs-body">
|
4 |
+
<div class="page-header text-right clearfix">
|
5 |
+
<div class="bookly-page-title">
|
6 |
+
<?php _e( 'Coupons', 'bookly' ) ?>
|
7 |
+
</div>
|
8 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
9 |
+
</div>
|
10 |
+
<div class="panel panel-default bookly-main">
|
11 |
+
<div class="panel-body">
|
12 |
+
<div class="form-inline bookly-margin-bottom-lg text-right">
|
13 |
+
<div class="form-group">
|
14 |
+
<button type="button"
|
15 |
+
id="bookly-add"
|
16 |
+
class="btn btn-success">
|
17 |
+
<i class="glyphicon glyphicon-plus"></i> <?php _e( 'Add Coupon', 'bookly' ) ?>
|
18 |
+
</button>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<table class="table table-striped" id="bookly-coupons-list" width="100%">
|
23 |
+
<thead>
|
24 |
+
<tr>
|
25 |
+
<th><?php _e( 'Code', 'bookly' ) ?></th>
|
26 |
+
<th><?php _e( 'Discount (%)', 'bookly' ) ?></th>
|
27 |
+
<th><?php _e( 'Deduction', 'bookly' ) ?></th>
|
28 |
+
<th><?php _e( 'Services', 'bookly' ) ?></th>
|
29 |
+
<th><?php _e( 'Usage limit', 'bookly' ) ?></th>
|
30 |
+
<th><?php _e( 'Number of times used', 'bookly' ) ?></th>
|
31 |
+
<th></th>
|
32 |
+
<th width="16"><input type="checkbox" id="bookly-check-all"></th>
|
33 |
+
</tr>
|
34 |
+
</thead>
|
35 |
+
</table>
|
36 |
+
|
37 |
+
<div class="text-right bookly-margin-top-lg">
|
38 |
+
<?php \BooklyLite\Lib\Utils\Common::deleteButton() ?>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
<?php include '_modal.php' ?>
|
|
|
44 |
</div>
|
backend/modules/custom_fields/Controller.php
CHANGED
@@ -1,88 +1,90 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\CustomFields;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\CustomFields
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
'
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
case '
|
59 |
-
case '
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
case '
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
*
|
81 |
-
*
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
|
|
|
|
88 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\CustomFields;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\CustomFields
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-custom-fields';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Default Action
|
16 |
+
*/
|
17 |
+
public function index()
|
18 |
+
{
|
19 |
+
$this->enqueueStyles( array(
|
20 |
+
'frontend' => array( 'css/ladda.min.css' ),
|
21 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
22 |
+
) );
|
23 |
+
|
24 |
+
$this->enqueueScripts( array(
|
25 |
+
'module' => array( 'js/custom_fields.js' => array( 'jquery-ui-sortable' ) ),
|
26 |
+
'frontend' => array(
|
27 |
+
'js/spin.min.js' => array( 'jquery' ),
|
28 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
29 |
+
),
|
30 |
+
'backend' => array(
|
31 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
32 |
+
'js/alert.js' => array( 'jquery' ),
|
33 |
+
),
|
34 |
+
) );
|
35 |
+
|
36 |
+
wp_localize_script( 'bookly-custom_fields.js', 'BooklyL10n', array(
|
37 |
+
'custom_fields' => get_option( 'bookly_custom_fields' ),
|
38 |
+
'saved' => __( 'Settings saved.', 'bookly' ),
|
39 |
+
'selector' => array(
|
40 |
+
'all_selected' => __( 'All services', 'bookly' ),
|
41 |
+
'nothing_selected' => __( 'No service selected', 'bookly' ),
|
42 |
+
),
|
43 |
+
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
44 |
+
) );
|
45 |
+
|
46 |
+
$services = $this->render( '_services', array( 'services' => Lib\Entities\Service::query()->select( 'id, title' )->where( 'type', Lib\Entities\Service::TYPE_SIMPLE )->fetchArray() ), false );
|
47 |
+
$this->render( 'index', array( 'services_html' => $services ) );
|
48 |
+
}
|
49 |
+
|
50 |
+
/**
|
51 |
+
* Save custom fields.
|
52 |
+
*/
|
53 |
+
public function executeSaveCustomFields()
|
54 |
+
{
|
55 |
+
$custom_fields = $this->getParameter( 'fields' );
|
56 |
+
foreach ( json_decode( $custom_fields ) as $custom_field ) {
|
57 |
+
switch ( $custom_field->type ) {
|
58 |
+
case 'textarea':
|
59 |
+
case 'text-content':
|
60 |
+
case 'text-field':
|
61 |
+
case 'captcha':
|
62 |
+
do_action( 'wpml_register_single_string', 'bookly', 'custom_field_' . $custom_field->id . '_' .sanitize_title( $custom_field->label ), $custom_field->label );
|
63 |
+
break;
|
64 |
+
case 'checkboxes':
|
65 |
+
case 'radio-buttons':
|
66 |
+
case 'drop-down':
|
67 |
+
do_action( 'wpml_register_single_string', 'bookly', 'custom_field_' . $custom_field->id . '_' . sanitize_title( $custom_field->label ), $custom_field->label );
|
68 |
+
foreach ( $custom_field->items as $label ) {
|
69 |
+
do_action( 'wpml_register_single_string', 'bookly', 'custom_field_' . $custom_field->id . '_' . sanitize_title( $custom_field->label ) . '=' . sanitize_title( $label ), $label );
|
70 |
+
}
|
71 |
+
break;
|
72 |
+
}
|
73 |
+
}
|
74 |
+
update_option( 'bookly_custom_fields', $custom_fields );
|
75 |
+
update_option( 'bookly_custom_fields_per_service', '0' );
|
76 |
+
wp_send_json_success();
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
81 |
+
* so current 'execute*' methods look nicer.
|
82 |
+
*
|
83 |
+
* @param string $prefix
|
84 |
+
*/
|
85 |
+
protected function registerWpActions( $prefix = '' )
|
86 |
+
{
|
87 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
88 |
+
}
|
89 |
+
|
90 |
}
|
backend/modules/custom_fields/resources/js/custom_fields.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
jQuery(function($) {
|
2 |
|
3 |
var $fields = $("#ab-custom-fields"),
|
4 |
-
$cf_per_service = $('#
|
5 |
|
6 |
$fields.sortable({
|
7 |
axis : 'y',
|
@@ -81,7 +81,7 @@ jQuery(function($) {
|
|
81 |
type : 'POST',
|
82 |
url : ajaxurl,
|
83 |
xhrFields : { withCredentials: true },
|
84 |
-
data : { action: '
|
85 |
complete : function() {
|
86 |
ladda.stop();
|
87 |
booklyAlert({success : [BooklyL10n.saved]});
|
1 |
jQuery(function($) {
|
2 |
|
3 |
var $fields = $("#ab-custom-fields"),
|
4 |
+
$cf_per_service = $('#bookly_custom_fields_per_service');
|
5 |
|
6 |
$fields.sortable({
|
7 |
axis : 'y',
|
81 |
type : 'POST',
|
82 |
url : ajaxurl,
|
83 |
xhrFields : { withCredentials: true },
|
84 |
+
data : { action: 'bookly_save_custom_fields', fields: JSON.stringify(data), cf_per_service: $cf_per_service.val() },
|
85 |
complete : function() {
|
86 |
ladda.stop();
|
87 |
booklyAlert({success : [BooklyL10n.saved]});
|
backend/modules/custom_fields/templates/_services.php
CHANGED
@@ -1,32 +1,32 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div class="btn-group ab--services-holder bookly-margin-top-screenxs-sm" style="display: none;">
|
3 |
-
<button class="btn btn-default btn-block dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
4 |
-
<div class="bookly-flex-cell">
|
5 |
-
<i class="glyphicon glyphicon-tag bookly-margin-right-md"></i>
|
6 |
-
</div>
|
7 |
-
<div class="bookly-flex-cell text-left" style="width: 100%">
|
8 |
-
<span class="ab-count"></span>
|
9 |
-
</div>
|
10 |
-
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
11 |
-
</button>
|
12 |
-
<ul class="dropdown-menu bookly-entity-selector">
|
13 |
-
<li>
|
14 |
-
<a class="checkbox" href="javascript:void(0)">
|
15 |
-
<label>
|
16 |
-
<input type="checkbox" class="bookly-check-all-entities">
|
17 |
-
<?php _e( 'All services', 'bookly' ) ?>
|
18 |
-
</label>
|
19 |
-
</a>
|
20 |
-
</li>
|
21 |
-
<?php foreach ( $services as $service ) : ?>
|
22 |
-
<li>
|
23 |
-
<a class="checkbox" href="javascript:void(0)">
|
24 |
-
<label>
|
25 |
-
<input type="checkbox" class="bookly-js-check-entity" value="<?php echo $service['id'] ?>" data-title="<?php echo esc_attr( $service['title'] ) ?>">
|
26 |
-
<?php echo $service['title'] ?>
|
27 |
-
</label>
|
28 |
-
</a>
|
29 |
-
</li>
|
30 |
-
<?php endforeach ?>
|
31 |
-
</ul>
|
32 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div class="btn-group ab--services-holder bookly-margin-top-screenxs-sm" style="display: none;">
|
3 |
+
<button class="btn btn-default btn-block dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
4 |
+
<div class="bookly-flex-cell">
|
5 |
+
<i class="glyphicon glyphicon-tag bookly-margin-right-md"></i>
|
6 |
+
</div>
|
7 |
+
<div class="bookly-flex-cell text-left" style="width: 100%">
|
8 |
+
<span class="ab-count"></span>
|
9 |
+
</div>
|
10 |
+
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
11 |
+
</button>
|
12 |
+
<ul class="dropdown-menu bookly-entity-selector">
|
13 |
+
<li>
|
14 |
+
<a class="checkbox" href="javascript:void(0)">
|
15 |
+
<label>
|
16 |
+
<input type="checkbox" class="bookly-check-all-entities">
|
17 |
+
<?php _e( 'All services', 'bookly' ) ?>
|
18 |
+
</label>
|
19 |
+
</a>
|
20 |
+
</li>
|
21 |
+
<?php foreach ( $services as $service ) : ?>
|
22 |
+
<li>
|
23 |
+
<a class="checkbox" href="javascript:void(0)">
|
24 |
+
<label>
|
25 |
+
<input type="checkbox" class="bookly-js-check-entity" value="<?php echo $service['id'] ?>" data-title="<?php echo esc_attr( $service['title'] ) ?>">
|
26 |
+
<?php echo $service['title'] ?>
|
27 |
+
</label>
|
28 |
+
</a>
|
29 |
+
</li>
|
30 |
+
<?php endforeach ?>
|
31 |
+
</ul>
|
32 |
</div>
|
backend/modules/custom_fields/templates/index.php
CHANGED
@@ -5,18 +5,13 @@
|
|
5 |
<div class="bookly-page-title">
|
6 |
<?php _e( 'Custom Fields', 'bookly' ) ?>
|
7 |
</div>
|
|
|
8 |
</div>
|
9 |
<div class="panel panel-default bookly-main">
|
10 |
<div class="panel-body">
|
11 |
<div class="row">
|
12 |
<div class="col-md-4">
|
13 |
-
|
14 |
-
<label for="ab_custom_fields_per_service">
|
15 |
-
<?php _e( 'Bind fields to services', 'bookly' ) ?>
|
16 |
-
</label>
|
17 |
-
<p class="help-block"><?php _e( 'When this setting is enabled you will be able to create service specific custom fields.', 'bookly' ) ?></p>
|
18 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'ab_custom_fields_per_service' ) ?>
|
19 |
-
</div>
|
20 |
</div>
|
21 |
</div>
|
22 |
|
5 |
<div class="bookly-page-title">
|
6 |
<?php _e( 'Custom Fields', 'bookly' ) ?>
|
7 |
</div>
|
8 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
9 |
</div>
|
10 |
<div class="panel panel-default bookly-main">
|
11 |
<div class="panel-body">
|
12 |
<div class="row">
|
13 |
<div class="col-md-4">
|
14 |
+
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_custom_fields_per_service', __( 'Bind fields to services', 'bookly' ), __( 'When this setting is enabled you will be able to create service specific custom fields.', 'bookly' ) ) ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
</div>
|
16 |
</div>
|
17 |
|
backend/modules/customers/Components.php
CHANGED
@@ -16,25 +16,25 @@ class Components extends Lib\Base\Components
|
|
16 |
public function renderCustomerDialog()
|
17 |
{
|
18 |
$this->enqueueStyles( array(
|
19 |
-
'frontend' => get_option( '
|
20 |
? array()
|
21 |
: array( 'css/intlTelInput.css' ),
|
22 |
) );
|
23 |
|
24 |
$this->enqueueScripts( array(
|
25 |
'backend' => array( 'js/angular.min.js' => array( 'jquery' ), ),
|
26 |
-
'frontend' => get_option( '
|
27 |
? array()
|
28 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) ),
|
29 |
-
'module' => array( 'js/ng-customer_dialog.js' => array( '
|
30 |
) );
|
31 |
|
32 |
-
wp_localize_script( '
|
33 |
-
'default_status' => get_option( '
|
34 |
'intlTelInput' => array(
|
35 |
-
'enabled' =>
|
36 |
'utils' => plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
37 |
-
'country' => get_option( '
|
38 |
),
|
39 |
) );
|
40 |
|
16 |
public function renderCustomerDialog()
|
17 |
{
|
18 |
$this->enqueueStyles( array(
|
19 |
+
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
20 |
? array()
|
21 |
: array( 'css/intlTelInput.css' ),
|
22 |
) );
|
23 |
|
24 |
$this->enqueueScripts( array(
|
25 |
'backend' => array( 'js/angular.min.js' => array( 'jquery' ), ),
|
26 |
+
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
27 |
? array()
|
28 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) ),
|
29 |
+
'module' => array( 'js/ng-customer_dialog.js' => array( 'bookly-angular.min.js' ), )
|
30 |
) );
|
31 |
|
32 |
+
wp_localize_script( 'bookly-ng-customer_dialog.js', 'BooklyL10nCustDialog', array(
|
33 |
+
'default_status' => get_option( 'bookly_gen_default_appointment_status' ),
|
34 |
'intlTelInput' => array(
|
35 |
+
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
36 |
'utils' => plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
37 |
+
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
38 |
),
|
39 |
) );
|
40 |
|
backend/modules/customers/Controller.php
CHANGED
@@ -1,235 +1,235 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Customers;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Customers
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
const page_slug = '
|
13 |
-
|
14 |
-
protected function getPermissions()
|
15 |
-
{
|
16 |
-
return array(
|
17 |
-
'executeSaveCustomer' => 'user',
|
18 |
-
);
|
19 |
-
}
|
20 |
-
|
21 |
-
public function index()
|
22 |
-
{
|
23 |
-
if ( $this->hasParameter( 'import-customers' ) ) {
|
24 |
-
$this->importCustomers();
|
25 |
-
}
|
26 |
-
|
27 |
-
$this->enqueueStyles( array(
|
28 |
-
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
29 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
30 |
-
) );
|
31 |
-
|
32 |
-
$this->enqueueScripts( array(
|
33 |
-
'backend' => array(
|
34 |
-
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
35 |
-
'js/datatables.min.js' => array( 'jquery' ),
|
36 |
-
'js/alert.js' => array( 'jquery' ),
|
37 |
-
),
|
38 |
-
'frontend' => array(
|
39 |
-
'js/spin.min.js' => array( 'jquery' ),
|
40 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
41 |
-
),
|
42 |
-
'module' => array(
|
43 |
-
'js/customers.js' => array( '
|
44 |
-
),
|
45 |
-
) );
|
46 |
-
|
47 |
-
wp_localize_script( '
|
48 |
-
'edit' => __( 'Edit', 'bookly' ),
|
49 |
-
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
50 |
-
'wp_users' => get_users( array( 'fields' => array( 'ID', 'display_name' ), 'orderby' => 'display_name' ) ),
|
51 |
-
'zeroRecords' => __( 'No customers found.', 'bookly' ),
|
52 |
-
'processing' => __( 'Processing...', 'bookly' ),
|
53 |
-
'edit_customer' => __( 'Edit customer', 'bookly' ),
|
54 |
-
'new_customer' => __( 'New customer', 'bookly' ),
|
55 |
-
'create_customer' => __( 'Create customer', 'bookly' ),
|
56 |
-
'save' => __( 'Save', 'bookly' ),
|
57 |
-
'search' => __( 'Quick search customer', 'bookly' ),
|
58 |
-
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
59 |
-
) );
|
60 |
-
|
61 |
-
$this->render( 'index' );
|
62 |
-
}
|
63 |
-
|
64 |
-
/**
|
65 |
-
* Get list of customers.
|
66 |
-
*/
|
67 |
-
public function executeGetCustomers()
|
68 |
-
{
|
69 |
-
global $wpdb;
|
70 |
-
|
71 |
-
$columns = $this->getParameter( 'columns' );
|
72 |
-
$order = $this->getParameter( 'order' );
|
73 |
-
$filter = $this->getParameter( 'filter' );
|
74 |
-
|
75 |
-
$query = Lib\Entities\Customer::query( 'c' );
|
76 |
-
|
77 |
-
$total = $query->count();
|
78 |
-
|
79 |
-
$query
|
80 |
-
->select( 'SQL_CALC_FOUND_ROWS c.*,
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
}
|
203 |
-
}
|
204 |
-
}
|
205 |
-
|
206 |
-
/**
|
207 |
-
* Delete customers.
|
208 |
-
*/
|
209 |
-
public function executeDeleteCustomers()
|
210 |
-
{
|
211 |
-
foreach ( $this->getParameter( 'data', array() ) as $id ) {
|
212 |
-
$customer = new Lib\Entities\Customer();
|
213 |
-
$customer->load( $id );
|
214 |
-
$customer->deleteWithWPUser( (bool) $this->getParameter( 'with_wp_user' ) );
|
215 |
-
}
|
216 |
-
wp_send_json_success();
|
217 |
-
}
|
218 |
-
|
219 |
-
/**
|
220 |
-
* Export Customers to CSV
|
221 |
-
*/
|
222 |
-
public function executeExportCustomers() { exit; }
|
223 |
-
|
224 |
-
/**
|
225 |
-
* Override parent method to add '
|
226 |
-
* so current 'execute*' methods look nicer.
|
227 |
-
*
|
228 |
-
* @param string $prefix
|
229 |
-
*/
|
230 |
-
protected function registerWpActions( $prefix = '' )
|
231 |
-
{
|
232 |
-
parent::registerWpActions( '
|
233 |
-
}
|
234 |
-
|
235 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Customers;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Customers
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-customers';
|
13 |
+
|
14 |
+
protected function getPermissions()
|
15 |
+
{
|
16 |
+
return array(
|
17 |
+
'executeSaveCustomer' => 'user',
|
18 |
+
);
|
19 |
+
}
|
20 |
+
|
21 |
+
public function index()
|
22 |
+
{
|
23 |
+
if ( $this->hasParameter( 'import-customers' ) ) {
|
24 |
+
$this->importCustomers();
|
25 |
+
}
|
26 |
+
|
27 |
+
$this->enqueueStyles( array(
|
28 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
29 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
30 |
+
) );
|
31 |
+
|
32 |
+
$this->enqueueScripts( array(
|
33 |
+
'backend' => array(
|
34 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
35 |
+
'js/datatables.min.js' => array( 'jquery' ),
|
36 |
+
'js/alert.js' => array( 'jquery' ),
|
37 |
+
),
|
38 |
+
'frontend' => array(
|
39 |
+
'js/spin.min.js' => array( 'jquery' ),
|
40 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
41 |
+
),
|
42 |
+
'module' => array(
|
43 |
+
'js/customers.js' => array( 'bookly-datatables.min.js', 'bookly-ng-customer_dialog.js' ),
|
44 |
+
),
|
45 |
+
) );
|
46 |
+
|
47 |
+
wp_localize_script( 'bookly-customers.js', 'BooklyL10n', array(
|
48 |
+
'edit' => __( 'Edit', 'bookly' ),
|
49 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
50 |
+
'wp_users' => get_users( array( 'fields' => array( 'ID', 'display_name' ), 'orderby' => 'display_name' ) ),
|
51 |
+
'zeroRecords' => __( 'No customers found.', 'bookly' ),
|
52 |
+
'processing' => __( 'Processing...', 'bookly' ),
|
53 |
+
'edit_customer' => __( 'Edit customer', 'bookly' ),
|
54 |
+
'new_customer' => __( 'New customer', 'bookly' ),
|
55 |
+
'create_customer' => __( 'Create customer', 'bookly' ),
|
56 |
+
'save' => __( 'Save', 'bookly' ),
|
57 |
+
'search' => __( 'Quick search customer', 'bookly' ),
|
58 |
+
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
59 |
+
) );
|
60 |
+
|
61 |
+
$this->render( 'index' );
|
62 |
+
}
|
63 |
+
|
64 |
+
/**
|
65 |
+
* Get list of customers.
|
66 |
+
*/
|
67 |
+
public function executeGetCustomers()
|
68 |
+
{
|
69 |
+
global $wpdb;
|
70 |
+
|
71 |
+
$columns = $this->getParameter( 'columns' );
|
72 |
+
$order = $this->getParameter( 'order' );
|
73 |
+
$filter = $this->getParameter( 'filter' );
|
74 |
+
|
75 |
+
$query = Lib\Entities\Customer::query( 'c' );
|
76 |
+
|
77 |
+
$total = $query->count();
|
78 |
+
|
79 |
+
$query
|
80 |
+
->select( 'SQL_CALC_FOUND_ROWS c.*,
|
81 |
+
(
|
82 |
+
SELECT MAX(a.start_date) FROM ' . Lib\Entities\Appointment::getTableName() . ' a
|
83 |
+
LEFT JOIN ' . Lib\Entities\CustomerAppointment::getTableName() . ' ca ON ca.appointment_id = a.id
|
84 |
+
WHERE ca.customer_id = c.id
|
85 |
+
) AS last_appointment,
|
86 |
+
(
|
87 |
+
SELECT COUNT(DISTINCT ca.appointment_id) FROM ' . Lib\Entities\CustomerAppointment::getTableName() . ' ca
|
88 |
+
WHERE ca.customer_id = c.id
|
89 |
+
) AS total_appointments,
|
90 |
+
(
|
91 |
+
SELECT SUM(p.total) FROM ' . Lib\Entities\Payment::getTableName() . ' p
|
92 |
+
WHERE p.id IN (
|
93 |
+
SELECT DISTINCT ca.payment_id FROM ' . Lib\Entities\CustomerAppointment::getTableName() . ' ca
|
94 |
+
WHERE ca.customer_id = c.id
|
95 |
+
)
|
96 |
+
) AS payments,
|
97 |
+
wpu.display_name AS wp_user' )
|
98 |
+
->tableJoin( $wpdb->users, 'wpu', 'wpu.ID = c.wp_user_id' )
|
99 |
+
->groupBy( 'c.id' );
|
100 |
+
|
101 |
+
if ( $filter != '' ) {
|
102 |
+
$search_value = Lib\Query::escape( $filter );
|
103 |
+
$query
|
104 |
+
->whereLike( 'c.name', "%{$search_value}%" )
|
105 |
+
->whereLike( 'c.phone', "%{$search_value}%", 'OR' )
|
106 |
+
->whereLike( 'c.email', "%{$search_value}%", 'OR' );
|
107 |
+
}
|
108 |
+
|
109 |
+
foreach ( $order as $sort_by ) {
|
110 |
+
$query->sortBy( str_replace( '.', '_', $columns[ $sort_by['column'] ]['data'] ) )
|
111 |
+
->order( $sort_by['dir'] == 'desc' ? Lib\Query::ORDER_DESCENDING : Lib\Query::ORDER_ASCENDING );
|
112 |
+
}
|
113 |
+
|
114 |
+
$query->limit( $this->getParameter( 'length' ) )->offset( $this->getParameter( 'start' ) );
|
115 |
+
|
116 |
+
$data = array();
|
117 |
+
foreach ( $query->fetchArray() as $row ) {
|
118 |
+
$data[] = array(
|
119 |
+
'id' => $row['id'],
|
120 |
+
'name' => $row['name'],
|
121 |
+
'wp_user' => $row['wp_user'],
|
122 |
+
'wp_user_id' => $row['wp_user_id'],
|
123 |
+
'phone' => $row['phone'],
|
124 |
+
'email' => $row['email'],
|
125 |
+
'notes' => $row['notes'],
|
126 |
+
'last_appointment' => $row['last_appointment'] ? Lib\Utils\DateTime::formatDateTime( $row['last_appointment'] ) : '',
|
127 |
+
'total_appointments' => $row['total_appointments'],
|
128 |
+
'payments' => Lib\Utils\Common::formatPrice( $row['payments'] ),
|
129 |
+
);
|
130 |
+
}
|
131 |
+
|
132 |
+
wp_send_json( array(
|
133 |
+
'draw' => ( int ) $this->getParameter( 'draw' ),
|
134 |
+
'recordsTotal' => $total,
|
135 |
+
'recordsFiltered' => ( int ) $wpdb->get_var( 'SELECT FOUND_ROWS()' ),
|
136 |
+
'data' => $data,
|
137 |
+
) );
|
138 |
+
}
|
139 |
+
|
140 |
+
/**
|
141 |
+
* Create or edit a customer.
|
142 |
+
*/
|
143 |
+
public function executeSaveCustomer()
|
144 |
+
{
|
145 |
+
$response = array();
|
146 |
+
$form = new Forms\Customer();
|
147 |
+
|
148 |
+
do {
|
149 |
+
if ( $this->getParameter( 'name' ) !== '' ) {
|
150 |
+
$params = $this->getPostParameters();
|
151 |
+
if ( ! $params['wp_user_id'] ) {
|
152 |
+
$params['wp_user_id'] = null;
|
153 |
+
}
|
154 |
+
$form->bind( $params );
|
155 |
+
/** @var Lib\Entities\Customer $customer */
|
156 |
+
$customer = $form->save();
|
157 |
+
if ( $customer ) {
|
158 |
+
$response['success'] = true;
|
159 |
+
$response['customer'] = array(
|
160 |
+
'id' => $customer->get( 'id' ),
|
161 |
+
'name' => $customer->get( 'name' ),
|
162 |
+
'phone' => $customer->get( 'phone' ),
|
163 |
+
'email' => $customer->get( 'email' ),
|
164 |
+
'notes' => $customer->get( 'notes' ),
|
165 |
+
'wp_user_id' => $customer->get( 'wp_user_id' ),
|
166 |
+
'jsonString' => json_encode( array(
|
167 |
+
'name' => $customer->get( 'name' ),
|
168 |
+
'phone' => $customer->get( 'phone' ),
|
169 |
+
'email' => $customer->get( 'email' ),
|
170 |
+
'notes' => $customer->get( 'notes' )
|
171 |
+
) )
|
172 |
+
);
|
173 |
+
break;
|
174 |
+
}
|
175 |
+
}
|
176 |
+
$response['success'] = false;
|
177 |
+
$response['errors'] = array( 'name' => array( 'required' ) );
|
178 |
+
} while ( 0 );
|
179 |
+
|
180 |
+
wp_send_json( $response );
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Import customers from CSV.
|
185 |
+
*/
|
186 |
+
private function importCustomers()
|
187 |
+
{
|
188 |
+
@ini_set( 'auto_detect_line_endings', true );
|
189 |
+
|
190 |
+
$file = fopen( $_FILES['import_customers_file']['tmp_name'], 'r' );
|
191 |
+
while ( $line = fgetcsv( $file, null, $this->getParameter( 'import_customers_delimiter' ) ) ) {
|
192 |
+
if ( $line[0] != '' ) {
|
193 |
+
$customer = new Lib\Entities\Customer();
|
194 |
+
$customer->set( 'name', $line[0] );
|
195 |
+
if ( isset( $line[1] ) ) {
|
196 |
+
$customer->set( 'phone', $line[1] );
|
197 |
+
}
|
198 |
+
if ( isset( $line[2] ) ) {
|
199 |
+
$customer->set( 'email', $line[2] );
|
200 |
+
}
|
201 |
+
$customer->save();
|
202 |
+
}
|
203 |
+
}
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Delete customers.
|
208 |
+
*/
|
209 |
+
public function executeDeleteCustomers()
|
210 |
+
{
|
211 |
+
foreach ( $this->getParameter( 'data', array() ) as $id ) {
|
212 |
+
$customer = new Lib\Entities\Customer();
|
213 |
+
$customer->load( $id );
|
214 |
+
$customer->deleteWithWPUser( (bool) $this->getParameter( 'with_wp_user' ) );
|
215 |
+
}
|
216 |
+
wp_send_json_success();
|
217 |
+
}
|
218 |
+
|
219 |
+
/**
|
220 |
+
* Export Customers to CSV
|
221 |
+
*/
|
222 |
+
public function executeExportCustomers() { exit; }
|
223 |
+
|
224 |
+
/**
|
225 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
226 |
+
* so current 'execute*' methods look nicer.
|
227 |
+
*
|
228 |
+
* @param string $prefix
|
229 |
+
*/
|
230 |
+
protected function registerWpActions( $prefix = '' )
|
231 |
+
{
|
232 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
233 |
+
}
|
234 |
+
|
235 |
}
|
backend/modules/customers/forms/Customer.php
CHANGED
@@ -1,25 +1,25 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Customers\Forms;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Customer
|
8 |
-
* @package BooklyLite\Backend\Modules\Customers\Forms
|
9 |
-
*/
|
10 |
-
class Customer extends Lib\Base\Form
|
11 |
-
{
|
12 |
-
protected static $entity_class = 'Customer';
|
13 |
-
|
14 |
-
public function configure()
|
15 |
-
{
|
16 |
-
$this->setFields( array(
|
17 |
-
'name',
|
18 |
-
'wp_user_id',
|
19 |
-
'phone',
|
20 |
-
'email',
|
21 |
-
'notes'
|
22 |
-
) );
|
23 |
-
}
|
24 |
-
|
25 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Customers\Forms;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Customer
|
8 |
+
* @package BooklyLite\Backend\Modules\Customers\Forms
|
9 |
+
*/
|
10 |
+
class Customer extends Lib\Base\Form
|
11 |
+
{
|
12 |
+
protected static $entity_class = 'Customer';
|
13 |
+
|
14 |
+
public function configure()
|
15 |
+
{
|
16 |
+
$this->setFields( array(
|
17 |
+
'name',
|
18 |
+
'wp_user_id',
|
19 |
+
'phone',
|
20 |
+
'email',
|
21 |
+
'notes'
|
22 |
+
) );
|
23 |
+
}
|
24 |
+
|
25 |
+
}
|
backend/modules/customers/resources/js/customers.js
CHANGED
@@ -32,17 +32,17 @@ jQuery(function($) {
|
|
32 |
url: ajaxurl,
|
33 |
data: function (d) {
|
34 |
return $.extend({}, d, {
|
35 |
-
action: '
|
36 |
filter: $filter.val()
|
37 |
});
|
38 |
}
|
39 |
},
|
40 |
columns: [
|
41 |
-
{ data: 'name' },
|
42 |
-
{ data: 'wp_user' },
|
43 |
-
{ data: 'phone' },
|
44 |
-
{ data: 'email' },
|
45 |
-
{ data: 'notes' },
|
46 |
{ data: 'last_appointment' },
|
47 |
{ data: 'total_appointments' },
|
48 |
{ data: 'payments' },
|
@@ -177,7 +177,7 @@ jQuery(function($) {
|
|
177 |
url : ajaxurl,
|
178 |
type : 'POST',
|
179 |
data : {
|
180 |
-
action : '
|
181 |
data : data,
|
182 |
with_wp_user : with_wp_user
|
183 |
},
|
32 |
url: ajaxurl,
|
33 |
data: function (d) {
|
34 |
return $.extend({}, d, {
|
35 |
+
action: 'bookly_get_customers',
|
36 |
filter: $filter.val()
|
37 |
});
|
38 |
}
|
39 |
},
|
40 |
columns: [
|
41 |
+
{ data: 'name', render: $.fn.dataTable.render.text() },
|
42 |
+
{ data: 'wp_user', render: $.fn.dataTable.render.text() },
|
43 |
+
{ data: 'phone', render: $.fn.dataTable.render.text() },
|
44 |
+
{ data: 'email', render: $.fn.dataTable.render.text() },
|
45 |
+
{ data: 'notes', render: $.fn.dataTable.render.text() },
|
46 |
{ data: 'last_appointment' },
|
47 |
{ data: 'total_appointments' },
|
48 |
{ data: 'payments' },
|
177 |
url : ajaxurl,
|
178 |
type : 'POST',
|
179 |
data : {
|
180 |
+
action : 'bookly_delete_customers',
|
181 |
data : data,
|
182 |
with_wp_user : with_wp_user
|
183 |
},
|
backend/modules/customers/resources/js/ng-customer_dialog.js
CHANGED
@@ -1,122 +1,122 @@
|
|
1 |
-
;(function() {
|
2 |
-
|
3 |
-
angular.module('customerDialog', []).directive('customerDialog', function() {
|
4 |
-
return {
|
5 |
-
restrict : 'A',
|
6 |
-
replace : true,
|
7 |
-
scope : {
|
8 |
-
callback : '&customerDialog',
|
9 |
-
form : '=customer'
|
10 |
-
},
|
11 |
-
templateUrl : 'bookly-customer-dialog.tpl',
|
12 |
-
// The linking function will add behavior to the template.
|
13 |
-
link: function(scope, element, attrs) {
|
14 |
-
// Init properties.
|
15 |
-
var init = function() {
|
16 |
-
// Form fields.
|
17 |
-
if (!scope.form) {
|
18 |
-
scope.form = {
|
19 |
-
id : '',
|
20 |
-
wp_user_id : '',
|
21 |
-
name : '',
|
22 |
-
phone : '',
|
23 |
-
email : '',
|
24 |
-
notes : ''
|
25 |
-
};
|
26 |
-
}
|
27 |
-
if (BooklyL10nCustDialog.intlTelInput.enabled) {
|
28 |
-
element.find('#phone').intlTelInput({
|
29 |
-
preferredCountries: [BooklyL10nCustDialog.intlTelInput.country],
|
30 |
-
defaultCountry: BooklyL10nCustDialog.intlTelInput.country,
|
31 |
-
geoIpLookup: function (callback) {
|
32 |
-
jQuery.get(ajaxurl, {action: '
|
33 |
-
}, 'json').always(function (resp) {
|
34 |
-
var countryCode = (resp && resp.country) ? resp.country : '';
|
35 |
-
callback(countryCode);
|
36 |
-
});
|
37 |
-
},
|
38 |
-
utilsScript: BooklyL10nCustDialog.intlTelInput.utils
|
39 |
-
});
|
40 |
-
}
|
41 |
-
// Form errors.
|
42 |
-
scope.errors = {
|
43 |
-
name: {required: false}
|
44 |
-
};
|
45 |
-
// Loading indicator.
|
46 |
-
scope.loading = false;
|
47 |
-
|
48 |
-
jQuery('#bookly-customer-dialog').modal('hide')
|
49 |
-
.on('hidden.bs.modal', function () {
|
50 |
-
if (jQuery('#bookly-appointment-dialog').length) {
|
51 |
-
jQuery('body').addClass('modal-open');
|
52 |
-
}
|
53 |
-
});
|
54 |
-
};
|
55 |
-
|
56 |
-
// Run init.
|
57 |
-
init();
|
58 |
-
|
59 |
-
// On 'Cancel' button click.
|
60 |
-
scope.closeDialog = function () {
|
61 |
-
// Close the dialog.
|
62 |
-
jQuery('#bookly-customer-dialog').modal('hide');
|
63 |
-
// Re-init all properties.
|
64 |
-
init();
|
65 |
-
};
|
66 |
-
|
67 |
-
/**
|
68 |
-
* Send form to server.
|
69 |
-
*/
|
70 |
-
scope.processForm = function() {
|
71 |
-
scope.errors = {};
|
72 |
-
scope.loading = true;
|
73 |
-
scope.form.phone = BooklyL10nCustDialog.intlTelInput.enabled
|
74 |
-
? element.find('#phone').intlTelInput('getNumber')
|
75 |
-
: element.find('#phone').val();
|
76 |
-
jQuery.ajax({
|
77 |
-
url : ajaxurl,
|
78 |
-
type : 'POST',
|
79 |
-
data : jQuery.extend({ action : '
|
80 |
-
dataType : 'json',
|
81 |
-
success : function ( response ) {
|
82 |
-
scope.$apply(function(scope) {
|
83 |
-
if (response.success) {
|
84 |
-
response.customer.custom_fields = [];
|
85 |
-
response.customer.extras = [];
|
86 |
-
response.customer.status = BooklyL10nCustDialog.default_status;
|
87 |
-
// Send new customer to the parent scope.
|
88 |
-
scope.callback({customer : response.customer});
|
89 |
-
scope.form = {
|
90 |
-
id : '',
|
91 |
-
wp_user_id : '',
|
92 |
-
name : '',
|
93 |
-
phone : '',
|
94 |
-
email : '',
|
95 |
-
notes : ''
|
96 |
-
};
|
97 |
-
// Close the dialog.
|
98 |
-
scope.closeDialog();
|
99 |
-
} else {
|
100 |
-
// Set errors.
|
101 |
-
jQuery.each(response.errors, function(field, errors) {
|
102 |
-
scope.errors[field] = {};
|
103 |
-
jQuery.each(errors, function(key, error) {
|
104 |
-
scope.errors[field][error] = true;
|
105 |
-
});
|
106 |
-
});
|
107 |
-
}
|
108 |
-
scope.loading = false;
|
109 |
-
});
|
110 |
-
},
|
111 |
-
error : function() {
|
112 |
-
scope.$apply(function(scope) {
|
113 |
-
scope.loading = false;
|
114 |
-
});
|
115 |
-
}
|
116 |
-
});
|
117 |
-
};
|
118 |
-
}
|
119 |
-
};
|
120 |
-
});
|
121 |
-
|
122 |
})();
|
1 |
+
;(function() {
|
2 |
+
|
3 |
+
angular.module('customerDialog', []).directive('customerDialog', function() {
|
4 |
+
return {
|
5 |
+
restrict : 'A',
|
6 |
+
replace : true,
|
7 |
+
scope : {
|
8 |
+
callback : '&customerDialog',
|
9 |
+
form : '=customer'
|
10 |
+
},
|
11 |
+
templateUrl : 'bookly-customer-dialog.tpl',
|
12 |
+
// The linking function will add behavior to the template.
|
13 |
+
link: function(scope, element, attrs) {
|
14 |
+
// Init properties.
|
15 |
+
var init = function() {
|
16 |
+
// Form fields.
|
17 |
+
if (!scope.form) {
|
18 |
+
scope.form = {
|
19 |
+
id : '',
|
20 |
+
wp_user_id : '',
|
21 |
+
name : '',
|
22 |
+
phone : '',
|
23 |
+
email : '',
|
24 |
+
notes : ''
|
25 |
+
};
|
26 |
+
}
|
27 |
+
if (BooklyL10nCustDialog.intlTelInput.enabled) {
|
28 |
+
element.find('#phone').intlTelInput({
|
29 |
+
preferredCountries: [BooklyL10nCustDialog.intlTelInput.country],
|
30 |
+
defaultCountry: BooklyL10nCustDialog.intlTelInput.country,
|
31 |
+
geoIpLookup: function (callback) {
|
32 |
+
jQuery.get(ajaxurl, {action: 'bookly_ip_info'}, function () {
|
33 |
+
}, 'json').always(function (resp) {
|
34 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
35 |
+
callback(countryCode);
|
36 |
+
});
|
37 |
+
},
|
38 |
+
utilsScript: BooklyL10nCustDialog.intlTelInput.utils
|
39 |
+
});
|
40 |
+
}
|
41 |
+
// Form errors.
|
42 |
+
scope.errors = {
|
43 |
+
name: {required: false}
|
44 |
+
};
|
45 |
+
// Loading indicator.
|
46 |
+
scope.loading = false;
|
47 |
+
|
48 |
+
jQuery('#bookly-customer-dialog').modal('hide')
|
49 |
+
.on('hidden.bs.modal', function () {
|
50 |
+
if (jQuery('#bookly-appointment-dialog').length) {
|
51 |
+
jQuery('body').addClass('modal-open');
|
52 |
+
}
|
53 |
+
});
|
54 |
+
};
|
55 |
+
|
56 |
+
// Run init.
|
57 |
+
init();
|
58 |
+
|
59 |
+
// On 'Cancel' button click.
|
60 |
+
scope.closeDialog = function () {
|
61 |
+
// Close the dialog.
|
62 |
+
jQuery('#bookly-customer-dialog').modal('hide');
|
63 |
+
// Re-init all properties.
|
64 |
+
init();
|
65 |
+
};
|
66 |
+
|
67 |
+
/**
|
68 |
+
* Send form to server.
|
69 |
+
*/
|
70 |
+
scope.processForm = function() {
|
71 |
+
scope.errors = {};
|
72 |
+
scope.loading = true;
|
73 |
+
scope.form.phone = BooklyL10nCustDialog.intlTelInput.enabled
|
74 |
+
? element.find('#phone').intlTelInput('getNumber')
|
75 |
+
: element.find('#phone').val();
|
76 |
+
jQuery.ajax({
|
77 |
+
url : ajaxurl,
|
78 |
+
type : 'POST',
|
79 |
+
data : jQuery.extend({ action : 'bookly_save_customer' }, scope.form),
|
80 |
+
dataType : 'json',
|
81 |
+
success : function ( response ) {
|
82 |
+
scope.$apply(function(scope) {
|
83 |
+
if (response.success) {
|
84 |
+
response.customer.custom_fields = [];
|
85 |
+
response.customer.extras = [];
|
86 |
+
response.customer.status = BooklyL10nCustDialog.default_status;
|
87 |
+
// Send new customer to the parent scope.
|
88 |
+
scope.callback({customer : response.customer});
|
89 |
+
scope.form = {
|
90 |
+
id : '',
|
91 |
+
wp_user_id : '',
|
92 |
+
name : '',
|
93 |
+
phone : '',
|
94 |
+
email : '',
|
95 |
+
notes : ''
|
96 |
+
};
|
97 |
+
// Close the dialog.
|
98 |
+
scope.closeDialog();
|
99 |
+
} else {
|
100 |
+
// Set errors.
|
101 |
+
jQuery.each(response.errors, function(field, errors) {
|
102 |
+
scope.errors[field] = {};
|
103 |
+
jQuery.each(errors, function(key, error) {
|
104 |
+
scope.errors[field][error] = true;
|
105 |
+
});
|
106 |
+
});
|
107 |
+
}
|
108 |
+
scope.loading = false;
|
109 |
+
});
|
110 |
+
},
|
111 |
+
error : function() {
|
112 |
+
scope.$apply(function(scope) {
|
113 |
+
scope.loading = false;
|
114 |
+
});
|
115 |
+
}
|
116 |
+
});
|
117 |
+
};
|
118 |
+
}
|
119 |
+
};
|
120 |
+
});
|
121 |
+
|
122 |
})();
|
backend/modules/customers/templates/_customer_dialog.php
CHANGED
@@ -46,12 +46,8 @@
|
|
46 |
</div>
|
47 |
<div class="modal-footer">
|
48 |
<div ng-hide=loading>
|
49 |
-
|
50 |
-
|
51 |
-
</button>
|
52 |
-
<button type="button" class="ab-reset-form btn btn-lg btn-default" data-dismiss="modal">
|
53 |
-
<?php _e( 'Cancel', 'bookly' ) ?>
|
54 |
-
</button>
|
55 |
</div>
|
56 |
</div>
|
57 |
</div>
|
46 |
</div>
|
47 |
<div class="modal-footer">
|
48 |
<div ng-hide=loading>
|
49 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn-success btn-lg', __( 'Create customer', 'bookly' ), array( 'ng-click' => 'processForm()' ) ) ?>
|
50 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn-default btn-lg', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
|
|
|
|
|
|
|
|
51 |
</div>
|
52 |
</div>
|
53 |
</div>
|
backend/modules/customers/templates/_import.php
CHANGED
@@ -1,36 +1,36 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-import-customers-dialog" class="modal fade" tabindex=-1 role="dialog">
|
3 |
-
<div class="modal-dialog">
|
4 |
-
<form enctype="multipart/form-data" action="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Customers\Controller::page_slug ) ?>" method="POST">
|
5 |
-
<div class="modal-content">
|
6 |
-
<div class="modal-header">
|
7 |
-
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
8 |
-
<div class="modal-title h2"><?php _e( 'Import', 'bookly' ) ?></div>
|
9 |
-
</div>
|
10 |
-
<div class="modal-body">
|
11 |
-
<h4><?php _e( 'Note', 'bookly' ) ?></h4>
|
12 |
-
<p>
|
13 |
-
<?php _e( 'You may import list of clients in CSV format. The file needs to have three columns: Name, Phone and Email.', 'bookly' ) ?>
|
14 |
-
</p>
|
15 |
-
<div class="form-group">
|
16 |
-
<label for="import_customers_file"><?php _e( 'Select file', 'bookly' ) ?></label>
|
17 |
-
<input name="import_customers_file" id="import_customers_file" type="file">
|
18 |
-
</div>
|
19 |
-
<div class="form-group">
|
20 |
-
<label for="import_customers_delimiter"><?php _e( 'Delimiter', 'bookly' ) ?></label>
|
21 |
-
<select name="import_customers_delimiter" id="import_customers_delimiter" class="form-control">
|
22 |
-
<option value=","><?php _e( 'Comma (,)', 'bookly' ) ?></option>
|
23 |
-
<option value=";"><?php _e( 'Semicolon (;)', 'bookly' ) ?></option>
|
24 |
-
</select>
|
25 |
-
</div>
|
26 |
-
<input type="hidden" name="import">
|
27 |
-
</div>
|
28 |
-
<div class="modal-footer">
|
29 |
-
<button type="submit" class="btn btn-lg btn-success ab-popup-save" name="import-customers">
|
30 |
-
<?php _e( 'Import', 'bookly' ) ?>
|
31 |
-
</button>
|
32 |
-
</div>
|
33 |
-
</div>
|
34 |
-
</form>
|
35 |
-
</div>
|
36 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-import-customers-dialog" class="modal fade" tabindex=-1 role="dialog">
|
3 |
+
<div class="modal-dialog">
|
4 |
+
<form enctype="multipart/form-data" action="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Customers\Controller::page_slug ) ?>" method="POST">
|
5 |
+
<div class="modal-content">
|
6 |
+
<div class="modal-header">
|
7 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
8 |
+
<div class="modal-title h2"><?php _e( 'Import', 'bookly' ) ?></div>
|
9 |
+
</div>
|
10 |
+
<div class="modal-body">
|
11 |
+
<h4><?php _e( 'Note', 'bookly' ) ?></h4>
|
12 |
+
<p>
|
13 |
+
<?php _e( 'You may import list of clients in CSV format. The file needs to have three columns: Name, Phone and Email.', 'bookly' ) ?>
|
14 |
+
</p>
|
15 |
+
<div class="form-group">
|
16 |
+
<label for="import_customers_file"><?php _e( 'Select file', 'bookly' ) ?></label>
|
17 |
+
<input name="import_customers_file" id="import_customers_file" type="file">
|
18 |
+
</div>
|
19 |
+
<div class="form-group">
|
20 |
+
<label for="import_customers_delimiter"><?php _e( 'Delimiter', 'bookly' ) ?></label>
|
21 |
+
<select name="import_customers_delimiter" id="import_customers_delimiter" class="form-control">
|
22 |
+
<option value=","><?php _e( 'Comma (,)', 'bookly' ) ?></option>
|
23 |
+
<option value=";"><?php _e( 'Semicolon (;)', 'bookly' ) ?></option>
|
24 |
+
</select>
|
25 |
+
</div>
|
26 |
+
<input type="hidden" name="import">
|
27 |
+
</div>
|
28 |
+
<div class="modal-footer">
|
29 |
+
<button type="submit" class="btn btn-lg btn-success ab-popup-save" name="import-customers">
|
30 |
+
<?php _e( 'Import', 'bookly' ) ?>
|
31 |
+
</button>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
+
</form>
|
35 |
+
</div>
|
36 |
</div>
|
backend/modules/customers/templates/index.php
CHANGED
@@ -5,25 +5,25 @@
|
|
5 |
<div class="bookly-page-title">
|
6 |
<?php _e( 'Customers', 'bookly' ) ?>
|
7 |
</div>
|
|
|
8 |
</div>
|
9 |
<div class="panel panel-default bookly-main">
|
10 |
<div class="panel-body">
|
11 |
<div class="row">
|
12 |
-
<div class="
|
13 |
<div class="form-group">
|
14 |
-
<
|
15 |
</div>
|
|
|
|
|
16 |
<div class="form-group">
|
17 |
-
<button type="button" class="btn btn-default bookly-btn-block-xs" data-toggle="modal" data-target="#bookly-
|
18 |
</div>
|
19 |
<div class="form-group">
|
20 |
-
<button type="button" class="btn btn-
|
21 |
</div>
|
22 |
-
</div>
|
23 |
-
|
24 |
-
<div class="col-md-4">
|
25 |
<div class="form-group">
|
26 |
-
<
|
27 |
</div>
|
28 |
</div>
|
29 |
</div>
|
@@ -31,10 +31,10 @@
|
|
31 |
<table id="bookly-customers-list" class="table table-striped" width="100%">
|
32 |
<thead>
|
33 |
<tr>
|
34 |
-
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( '
|
35 |
<th><?php _e( 'User', 'bookly' ) ?></th>
|
36 |
-
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( '
|
37 |
-
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( '
|
38 |
<th><?php _e( 'Notes', 'bookly' ) ?></th>
|
39 |
<th><?php _e( 'Last appointment', 'bookly' ) ?></th>
|
40 |
<th><?php _e( 'Total appointments', 'bookly' ) ?></th>
|
5 |
<div class="bookly-page-title">
|
6 |
<?php _e( 'Customers', 'bookly' ) ?>
|
7 |
</div>
|
8 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
9 |
</div>
|
10 |
<div class="panel panel-default bookly-main">
|
11 |
<div class="panel-body">
|
12 |
<div class="row">
|
13 |
+
<div class="col-md-4">
|
14 |
<div class="form-group">
|
15 |
+
<input class="form-control" type="text" id="bookly-filter" placeholder="<?php esc_attr_e( 'Quick search customer', 'bookly' ) ?>" />
|
16 |
</div>
|
17 |
+
</div>
|
18 |
+
<div class="col-md-8 form-inline bookly-margin-bottom-lg text-right">
|
19 |
<div class="form-group">
|
20 |
+
<button type="button" class="btn btn-default bookly-btn-block-xs bookly-limitation" data-toggle="modal" data-target="#bookly-export-customers-dialog"><i class="glyphicon glyphicon-export"></i> <?php _e( 'Export to CSV', 'bookly' ) ?></button>
|
21 |
</div>
|
22 |
<div class="form-group">
|
23 |
+
<button type="button" class="btn btn-default bookly-btn-block-xs" data-toggle="modal" data-target="#bookly-import-customers-dialog"><i class="glyphicon glyphicon-import"></i> <?php _e( 'Import', 'bookly' ) ?></button>
|
24 |
</div>
|
|
|
|
|
|
|
25 |
<div class="form-group">
|
26 |
+
<button type="button" class="btn btn-success bookly-btn-block-xs" id="bookly-add" data-toggle="modal" data-target="#bookly-customer-dialog"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'New customer', 'bookly' ) ?></button>
|
27 |
</div>
|
28 |
</div>
|
29 |
</div>
|
31 |
<table id="bookly-customers-list" class="table table-striped" width="100%">
|
32 |
<thead>
|
33 |
<tr>
|
34 |
+
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_name' ) ?></th>
|
35 |
<th><?php _e( 'User', 'bookly' ) ?></th>
|
36 |
+
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_phone' ) ?></th>
|
37 |
+
<th><?php echo \BooklyLite\Lib\Utils\Common::getTranslatedOption( 'bookly_l10n_label_email' ) ?></th>
|
38 |
<th><?php _e( 'Notes', 'bookly' ) ?></th>
|
39 |
<th><?php _e( 'Last appointment', 'bookly' ) ?></th>
|
40 |
<th><?php _e( 'Total appointments', 'bookly' ) ?></th>
|
backend/modules/debug/Controller.php
CHANGED
@@ -9,6 +9,7 @@ use BooklyLite\Lib;
|
|
9 |
*/
|
10 |
class Controller extends Lib\Base\Controller
|
11 |
{
|
|
|
12 |
|
13 |
const TABLE_STATUS_OK = 1;
|
14 |
const TABLE_STATUS_ERROR = 0;
|
@@ -30,67 +31,187 @@ class Controller extends Lib\Base\Controller
|
|
30 |
) );
|
31 |
|
32 |
$debug = array();
|
33 |
-
/** @var Lib\Base\
|
34 |
-
foreach (
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
56 |
}
|
57 |
-
}
|
58 |
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
|
|
68 |
}
|
69 |
-
}
|
70 |
|
71 |
-
|
72 |
-
|
|
|
73 |
}
|
74 |
}
|
75 |
-
|
|
|
|
|
76 |
}
|
77 |
|
78 |
/**
|
79 |
-
*
|
80 |
-
*
|
81 |
-
* @return array
|
82 |
*/
|
83 |
-
public function
|
84 |
{
|
|
|
|
|
|
|
85 |
$result = array();
|
86 |
-
|
87 |
-
|
88 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
89 |
}
|
90 |
-
$result[] = '\\BooklyLite\\Lib\\Entities\\' . basename( $filename, '.php' );
|
91 |
}
|
92 |
|
93 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
|
96 |
/**
|
@@ -99,7 +220,7 @@ class Controller extends Lib\Base\Controller
|
|
99 |
* @param string $tableName
|
100 |
* @return array
|
101 |
*/
|
102 |
-
|
103 |
{
|
104 |
global $wpdb;
|
105 |
|
@@ -120,7 +241,7 @@ class Controller extends Lib\Base\Controller
|
|
120 |
* @param string $tableName
|
121 |
* @return array
|
122 |
*/
|
123 |
-
|
124 |
{
|
125 |
global $wpdb;
|
126 |
|
@@ -158,7 +279,7 @@ class Controller extends Lib\Base\Controller
|
|
158 |
* @param string $tableName
|
159 |
* @return int
|
160 |
*/
|
161 |
-
|
162 |
{
|
163 |
global $wpdb;
|
164 |
|
@@ -168,14 +289,14 @@ class Controller extends Lib\Base\Controller
|
|
168 |
// Protected methods.
|
169 |
|
170 |
/**
|
171 |
-
* Override parent method to add '
|
172 |
* so current 'execute*' methods look nicer.
|
173 |
*
|
174 |
* @param string $prefix
|
175 |
*/
|
176 |
protected function registerWpActions( $prefix = '' )
|
177 |
{
|
178 |
-
parent::registerWpActions( '
|
179 |
}
|
180 |
|
181 |
}
|
9 |
*/
|
10 |
class Controller extends Lib\Base\Controller
|
11 |
{
|
12 |
+
const page_slug = 'bookly-debug';
|
13 |
|
14 |
const TABLE_STATUS_OK = 1;
|
15 |
const TABLE_STATUS_ERROR = 0;
|
31 |
) );
|
32 |
|
33 |
$debug = array();
|
34 |
+
/** @var Lib\Base\Plugin $plugin */
|
35 |
+
foreach ( apply_filters( 'bookly_plugins', array() ) as $plugin ) {
|
36 |
+
foreach ( $plugin::getEntityClasses() as $entity_class ) {
|
37 |
+
$tableName = $entity_class::getTableName();
|
38 |
+
$debug[ $tableName ] = array(
|
39 |
+
'fields' => null,
|
40 |
+
'constraints' => null,
|
41 |
+
'status' => null,
|
42 |
+
);
|
43 |
+
if ( $this->_tableExists( $tableName ) ) {
|
44 |
+
$tableStructure = $this->_getTableStructure( $tableName );
|
45 |
+
$tableConstraints = $this->_getTableConstraints( $tableName );
|
46 |
+
$entitySchema = $entity_class::getSchema();
|
47 |
+
$entityConstraints = $entity_class::getConstraints();
|
48 |
+
$debug[ $tableName ]['status'] = self::TABLE_STATUS_OK;
|
49 |
+
$debug[ $tableName ]['fields'] = array();
|
50 |
+
|
51 |
+
// Comparing model schema with real DB schema
|
52 |
+
foreach ( $entitySchema as $field => $data ) {
|
53 |
+
if ( in_array( $field, $tableStructure ) ) {
|
54 |
+
$debug[ $tableName ]['fields'][ $field ] = 1;
|
55 |
+
} else {
|
56 |
+
$debug[ $tableName ]['fields'][ $field ] = 0;
|
57 |
+
$debug[ $tableName ]['status'] = self::TABLE_STATUS_WARNING;
|
58 |
+
}
|
59 |
}
|
|
|
60 |
|
61 |
+
// Comparing model constraints with real DB constraints
|
62 |
+
foreach ( $entityConstraints as $constraint ) {
|
63 |
+
$key = $constraint['column_name'] . $constraint['referenced_table_name'] . $constraint['referenced_column_name'];
|
64 |
+
$debug[ $tableName ]['constraints'][ $key ] = $constraint;
|
65 |
+
if ( array_key_exists ( $key, $tableConstraints ) ) {
|
66 |
+
$debug[ $tableName ]['constraints'][ $key ]['status'] = 1;
|
67 |
+
} else {
|
68 |
+
$debug[ $tableName ]['constraints'][ $key ]['status'] = 0;
|
69 |
+
$debug[ $tableName ]['status'] = self::TABLE_STATUS_WARNING;
|
70 |
+
}
|
71 |
}
|
|
|
72 |
|
73 |
+
} else {
|
74 |
+
$debug[ $tableName ]['status'] = self::TABLE_STATUS_ERROR;
|
75 |
+
}
|
76 |
}
|
77 |
}
|
78 |
+
|
79 |
+
$import_status = $this->getParameter( 'status' );
|
80 |
+
$this->render( 'index', compact( 'debug', 'import_status' ) );
|
81 |
}
|
82 |
|
83 |
/**
|
84 |
+
* Export database data.
|
|
|
|
|
85 |
*/
|
86 |
+
public function executeExportData()
|
87 |
{
|
88 |
+
/** @var \wpdb $wpdb */
|
89 |
+
global $wpdb;
|
90 |
+
|
91 |
$result = array();
|
92 |
+
|
93 |
+
foreach ( apply_filters( 'bookly_plugins', array() ) as $plugin ) {
|
94 |
+
/** @var Lib\Base\Plugin $plugin */
|
95 |
+
$installer_class = $plugin::getRootNamespace() . '\Lib\Installer';
|
96 |
+
/** @var Lib\Base\Installer $installer */
|
97 |
+
$installer = new $installer_class();
|
98 |
+
|
99 |
+
foreach ( $plugin::getEntityClasses() as $entity_class ) {
|
100 |
+
$table_name = $entity_class::getTableName();
|
101 |
+
$result['entities'][ $entity_class ] = array(
|
102 |
+
'fields' => $this->_getTableStructure( $table_name ),
|
103 |
+
'values' => $wpdb->get_results( 'SELECT * FROM ' . $table_name, ARRAY_N )
|
104 |
+
);
|
105 |
+
}
|
106 |
+
$plugin_prefix = $plugin::getPrefix();
|
107 |
+
$options_postfix = array( 'data_loaded', 'grace_start', 'db_version', 'installation_time' );
|
108 |
+
if ( $plugin_prefix != 'bookly_' ) {
|
109 |
+
$options_postfix[] = 'enabled';
|
110 |
+
}
|
111 |
+
foreach ( $options_postfix as $option ) {
|
112 |
+
$option_name = $plugin_prefix . $option;
|
113 |
+
$result['options'][ $option_name ] = get_option( $option_name );
|
114 |
+
}
|
115 |
+
|
116 |
+
$result['options'][ $plugin::getPurchaseCodeOption() ] = $plugin::getPurchaseCode();
|
117 |
+
foreach ( $installer->getOptions() as $option_name => $option_value ) {
|
118 |
+
$result['options'][ $option_name ] = get_option( $option_name );
|
119 |
}
|
|
|
120 |
}
|
121 |
|
122 |
+
header( 'Content-type: application/json' );
|
123 |
+
header( 'Content-Disposition: attachment; filename=bookly_db_export_' . date( 'YmdHis' ) . '.json' );
|
124 |
+
echo json_encode( $result );
|
125 |
+
|
126 |
+
exit ( 0 );
|
127 |
+
}
|
128 |
+
|
129 |
+
/**
|
130 |
+
* Import database data.
|
131 |
+
*/
|
132 |
+
public function executeImportData()
|
133 |
+
{
|
134 |
+
/** @var \wpdb $wpdb */
|
135 |
+
global $wpdb;
|
136 |
+
|
137 |
+
if ( $file = $_FILES['import']['name'] ) {
|
138 |
+
$json = file_get_contents( $_FILES['import']['tmp_name'] );
|
139 |
+
if ( $json !== false) {
|
140 |
+
$wpdb->query( 'SET FOREIGN_KEY_CHECKS = 0' );
|
141 |
+
|
142 |
+
$data = json_decode( $json, true );
|
143 |
+
|
144 |
+
foreach ( apply_filters( 'bookly_plugins', array() ) as $plugin ) {
|
145 |
+
/** @var Lib\Base\Plugin $plugin */
|
146 |
+
$installer_class = $plugin::getRootNamespace() . '\Lib\Installer';
|
147 |
+
/** @var Lib\Base\Installer $installer */
|
148 |
+
$installer = new $installer_class();
|
149 |
+
|
150 |
+
// Drop all data and options.
|
151 |
+
$installer->removeData();
|
152 |
+
$installer->dropTables();
|
153 |
+
$installer->createTables();
|
154 |
+
|
155 |
+
// Insert tables data.
|
156 |
+
foreach ( $plugin::getEntityClasses() as $entity_class ) {
|
157 |
+
if ( isset ( $data['entities'][ $entity_class ]['values'][0] ) ) {
|
158 |
+
$table_name = $entity_class::getTableName();
|
159 |
+
$query = sprintf(
|
160 |
+
'INSERT INTO `%s` (`%s`) VALUES (%%s)',
|
161 |
+
$table_name,
|
162 |
+
implode( '`,`', $data['entities'][ $entity_class ]['fields'] )
|
163 |
+
);
|
164 |
+
$placeholders = array();
|
165 |
+
$values = array();
|
166 |
+
$counter = 0;
|
167 |
+
foreach ( $data['entities'][ $entity_class ]['values'] as $row ) {
|
168 |
+
$params = array();
|
169 |
+
foreach ( $row as $value ) {
|
170 |
+
if ( $value === null ) {
|
171 |
+
$params[] = 'NULL';
|
172 |
+
} else {
|
173 |
+
$params[] = '%s';
|
174 |
+
$values[] = $value;
|
175 |
+
}
|
176 |
+
}
|
177 |
+
$placeholders[] = implode( ',', $params );
|
178 |
+
if ( ++ $counter > 50 ) {
|
179 |
+
// Flush.
|
180 |
+
$wpdb->query( $wpdb->prepare( sprintf( $query, implode( '),(', $placeholders ) ), $values ) );
|
181 |
+
$placeholders = array();
|
182 |
+
$values = array();
|
183 |
+
$counter = 0;
|
184 |
+
}
|
185 |
+
}
|
186 |
+
if ( ! empty ( $placeholders ) ) {
|
187 |
+
$wpdb->query( $wpdb->prepare( sprintf( $query, implode( '),(', $placeholders ) ), $values ) );
|
188 |
+
}
|
189 |
+
}
|
190 |
+
}
|
191 |
+
|
192 |
+
// Insert options data.
|
193 |
+
foreach ( $installer->getOptions() as $option_name => $option_value ) {
|
194 |
+
add_option( $option_name, $data['options'][ $option_name ] );
|
195 |
+
}
|
196 |
+
|
197 |
+
$plugin_prefix = $plugin::getPrefix();
|
198 |
+
$options_postfix = array( 'data_loaded', 'grace_start', 'db_version' );
|
199 |
+
if ( $plugin_prefix != 'bookly_' ) {
|
200 |
+
$options_postfix[] = 'enabled';
|
201 |
+
}
|
202 |
+
foreach ( $options_postfix as $option ) {
|
203 |
+
$option_name = $plugin_prefix . $option;
|
204 |
+
add_option( $option_name, $data['options'][ $option_name ] );
|
205 |
+
}
|
206 |
+
}
|
207 |
+
|
208 |
+
header( 'Location: ' . admin_url( 'admin.php?page=bookly-debug&status=imported' ) );
|
209 |
+
}
|
210 |
+
}
|
211 |
+
|
212 |
+
header( 'Location: ' . admin_url( 'admin.php?page=bookly-debug' ) );
|
213 |
+
|
214 |
+
exit ( 0 );
|
215 |
}
|
216 |
|
217 |
/**
|
220 |
* @param string $tableName
|
221 |
* @return array
|
222 |
*/
|
223 |
+
private function _getTableStructure( $tableName )
|
224 |
{
|
225 |
global $wpdb;
|
226 |
|
241 |
* @param string $tableName
|
242 |
* @return array
|
243 |
*/
|
244 |
+
private function _getTableConstraints( $tableName )
|
245 |
{
|
246 |
global $wpdb;
|
247 |
|
279 |
* @param string $tableName
|
280 |
* @return int
|
281 |
*/
|
282 |
+
private function _tableExists( $tableName )
|
283 |
{
|
284 |
global $wpdb;
|
285 |
|
289 |
// Protected methods.
|
290 |
|
291 |
/**
|
292 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
293 |
* so current 'execute*' methods look nicer.
|
294 |
*
|
295 |
* @param string $prefix
|
296 |
*/
|
297 |
protected function registerWpActions( $prefix = '' )
|
298 |
{
|
299 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
300 |
}
|
301 |
|
302 |
}
|
backend/modules/debug/resources/css/style.css
CHANGED
@@ -9,4 +9,26 @@
|
|
9 |
|
10 |
.list-group-item{
|
11 |
padding: 5px 10px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
}
|
9 |
|
10 |
.list-group-item{
|
11 |
padding: 5px 10px;
|
12 |
+
}
|
13 |
+
.btn-file {
|
14 |
+
position: relative;
|
15 |
+
overflow: hidden;
|
16 |
+
}
|
17 |
+
.btn-file input[type=file] {
|
18 |
+
position: absolute;
|
19 |
+
top: 0;
|
20 |
+
right: 0;
|
21 |
+
min-width: 100%;
|
22 |
+
min-height: 100%;
|
23 |
+
font-size: 100px;
|
24 |
+
text-align: right;
|
25 |
+
filter: alpha(opacity=0);
|
26 |
+
opacity: 0;
|
27 |
+
outline: none;
|
28 |
+
background: white;
|
29 |
+
cursor: inherit;
|
30 |
+
display: block;
|
31 |
+
}
|
32 |
+
.bookly-data-button {
|
33 |
+
display: inline-block;
|
34 |
}
|
backend/modules/debug/resources/js/debug.js
CHANGED
@@ -1,3 +1,9 @@
|
|
1 |
jQuery(function($) {
|
2 |
$('.collapse').collapse('hide');
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
});
|
1 |
jQuery(function($) {
|
2 |
$('.collapse').collapse('hide');
|
3 |
+
|
4 |
+
$('#bookly_import_file').change(function() {
|
5 |
+
if($(this).val()) {
|
6 |
+
$('#bookly_import').submit();
|
7 |
+
}
|
8 |
+
});
|
9 |
});
|
backend/modules/debug/templates/index.php
CHANGED
@@ -1,6 +1,34 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<div id="bookly-tbs" class="wrap">
|
3 |
<div class="bookly-tbs-body">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
<div class="page-header text-right clearfix">
|
5 |
<div class="bookly-page-title">
|
6 |
Database Integrity
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<div id="bookly-tbs" class="wrap">
|
3 |
<div class="bookly-tbs-body">
|
4 |
+
<div class="page-header text-right clearfix">
|
5 |
+
<div class="bookly-page-title">
|
6 |
+
Data management
|
7 |
+
</div>
|
8 |
+
</div>
|
9 |
+
<?php if ( $import_status ) : ?>
|
10 |
+
<div class="alert alert-success">
|
11 |
+
Data successfully imported
|
12 |
+
</div>
|
13 |
+
<?php endif ?>
|
14 |
+
|
15 |
+
<div class="panel-group" id="data-management">
|
16 |
+
<div class="bookly-data-button">
|
17 |
+
<form action="<?php echo admin_url( 'admin-ajax.php?action=bookly_export_data' ) ?>" method="POST">
|
18 |
+
<button id="bookly-export" type="submit" class="btn btn-lg btn-success">
|
19 |
+
<span class="ladda-label">Export data</span>
|
20 |
+
</button>
|
21 |
+
</form>
|
22 |
+
</div>
|
23 |
+
<div class="bookly-data-button">
|
24 |
+
<form id="bookly_import" action="<?php echo admin_url( 'admin-ajax.php?action=bookly_import_data' ) ?>" method="POST" enctype="multipart/form-data">
|
25 |
+
<div id="bookly-import" class="btn btn-lg btn-primary btn-file">
|
26 |
+
<span class="ladda-label">Import data</span>
|
27 |
+
<input type="file" id="bookly_import_file" name="import">
|
28 |
+
</div>
|
29 |
+
</form>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
<div class="page-header text-right clearfix">
|
33 |
<div class="bookly-page-title">
|
34 |
Database Integrity
|
backend/modules/notifications/Controller.php
CHANGED
@@ -1,108 +1,110 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Notifications;
|
3 |
-
|
4 |
-
use
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Notifications
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
'js/
|
24 |
-
'js/
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
$
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
$
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
)
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
$
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
*
|
101 |
-
*
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
|
|
|
|
108 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Notifications;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Notifications
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-notifications';
|
13 |
+
|
14 |
+
public function index()
|
15 |
+
{
|
16 |
+
$this->enqueueStyles( array(
|
17 |
+
'frontend' => array( 'css/ladda.min.css' ),
|
18 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
19 |
+
) );
|
20 |
+
|
21 |
+
$this->enqueueScripts( array(
|
22 |
+
'backend' => array(
|
23 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
24 |
+
'js/angular.min.js',
|
25 |
+
'js/help.js' => array( 'jquery' ),
|
26 |
+
'js/alert.js' => array( 'jquery' ),
|
27 |
+
),
|
28 |
+
'module' => array(
|
29 |
+
'js/notification.js' => array( 'jquery' ),
|
30 |
+
'js/ng-app.js' => array( 'jquery', 'bookly-angular.min.js' ),
|
31 |
+
),
|
32 |
+
'frontend' => array(
|
33 |
+
'js/spin.min.js' => array( 'jquery' ),
|
34 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
35 |
+
)
|
36 |
+
) );
|
37 |
+
$cron_reminder = (array) get_option( 'bookly_cron_reminder_times' );
|
38 |
+
$form = new Forms\Notifications( 'email' );
|
39 |
+
$alert = array( 'success' => array() );
|
40 |
+
// Save action.
|
41 |
+
if ( ! empty ( $_POST ) ) {
|
42 |
+
$form->bind( $this->getPostParameters() );
|
43 |
+
$form->save();
|
44 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
45 |
+
update_option( 'bookly_email_send_as', $this->getParameter( 'bookly_email_send_as' ) );
|
46 |
+
update_option( 'bookly_email_reply_to_customers', $this->getParameter( 'bookly_email_reply_to_customers' ) );
|
47 |
+
update_option( 'bookly_email_sender', $this->getParameter( 'bookly_email_sender' ) );
|
48 |
+
update_option( 'bookly_email_sender_name', $this->getParameter( 'bookly_email_sender_name' ) );
|
49 |
+
foreach ( array( 'staff_agenda', 'client_follow_up', 'client_reminder' ) as $type ) {
|
50 |
+
$cron_reminder[ $type ] = $this->getParameter( $type . '_cron_hour' );
|
51 |
+
}
|
52 |
+
update_option( 'bookly_cron_reminder_times', $cron_reminder );
|
53 |
+
}
|
54 |
+
$cron_path = realpath( Lib\Plugin::getDirectory() . '/lib/utils/send_notifications_cron.php' );
|
55 |
+
wp_localize_script( 'bookly-alert.js', 'BooklyL10n', array(
|
56 |
+
'alert' => $alert,
|
57 |
+
'sent_successfully' => __( 'Sent successfully.', 'bookly' ),
|
58 |
+
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
59 |
+
) );
|
60 |
+
$this->render( 'index', compact( 'form', 'cron_path', 'cron_reminder' ) );
|
61 |
+
}
|
62 |
+
|
63 |
+
public function executeGetEmailNotificationsData()
|
64 |
+
{
|
65 |
+
$form = new Forms\Notifications( 'email' );
|
66 |
+
|
67 |
+
$bookly_email_sender_name = get_option( 'bookly_email_sender_name' ) == '' ?
|
68 |
+
get_option( 'blogname' ) : get_option( 'bookly_email_sender_name' );
|
69 |
+
|
70 |
+
$bookly_email_sender = get_option( 'bookly_email_sender' ) == '' ?
|
71 |
+
get_option( 'admin_email' ) : get_option( 'bookly_email_sender' );
|
72 |
+
|
73 |
+
$notifications = array();
|
74 |
+
foreach ( $form->getData() as $notification ) {
|
75 |
+
$notifications[] = array(
|
76 |
+
'type' => $notification['type'],
|
77 |
+
'name' => $notification['name'],
|
78 |
+
'active' => $notification['active'],
|
79 |
+
);
|
80 |
+
}
|
81 |
+
|
82 |
+
$result = array(
|
83 |
+
'notifications' => $notifications,
|
84 |
+
'sender_email' => $bookly_email_sender,
|
85 |
+
'sender_name' => $bookly_email_sender_name,
|
86 |
+
'send_as' => get_option( 'bookly_email_send_as' ),
|
87 |
+
'reply_to_customers' => get_option( 'bookly_email_reply_to_customers' ),
|
88 |
+
);
|
89 |
+
|
90 |
+
wp_send_json_success( $result );
|
91 |
+
}
|
92 |
+
|
93 |
+
public function executeTestEmailNotifications()
|
94 |
+
{
|
95 |
+
}
|
96 |
+
|
97 |
+
// Protected methods.
|
98 |
+
|
99 |
+
/**
|
100 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
101 |
+
* so current 'execute*' methods look nicer.
|
102 |
+
*
|
103 |
+
* @param string $prefix
|
104 |
+
*/
|
105 |
+
protected function registerWpActions( $prefix = '' )
|
106 |
+
{
|
107 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
108 |
+
}
|
109 |
+
|
110 |
}
|
backend/modules/notifications/forms/Notifications.php
CHANGED
@@ -1,213 +1,215 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Notifications\Forms;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Notifications
|
8 |
-
* @package BooklyLite\Backend\Modules\Notifications\Forms
|
9 |
-
*/
|
10 |
-
class Notifications extends Lib\Base\Form
|
11 |
-
{
|
12 |
-
public $types = array(
|
13 |
-
'single' => array(
|
14 |
-
'client_pending_appointment',
|
15 |
-
'staff_pending_appointment',
|
16 |
-
'client_approved_appointment',
|
17 |
-
'staff_approved_appointment',
|
18 |
-
'client_cancelled_appointment',
|
19 |
-
'staff_cancelled_appointment',
|
20 |
-
'
|
21 |
-
'
|
22 |
-
'
|
23 |
-
'
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
*
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
->
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
'
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
echo '
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
*
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
*
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
<
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
|
|
|
|
213 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Notifications\Forms;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Notifications
|
8 |
+
* @package BooklyLite\Backend\Modules\Notifications\Forms
|
9 |
+
*/
|
10 |
+
class Notifications extends Lib\Base\Form
|
11 |
+
{
|
12 |
+
public $types = array(
|
13 |
+
'single' => array(
|
14 |
+
'client_pending_appointment',
|
15 |
+
'staff_pending_appointment',
|
16 |
+
'client_approved_appointment',
|
17 |
+
'staff_approved_appointment',
|
18 |
+
'client_cancelled_appointment',
|
19 |
+
'staff_cancelled_appointment',
|
20 |
+
'client_rejected_appointment',
|
21 |
+
'staff_rejected_appointment',
|
22 |
+
'client_new_wp_user',
|
23 |
+
'client_reminder',
|
24 |
+
'client_follow_up',
|
25 |
+
'staff_agenda',
|
26 |
+
),
|
27 |
+
'combined' => array(
|
28 |
+
'client_pending_appointment_cart',
|
29 |
+
'client_approved_appointment_cart',
|
30 |
+
),
|
31 |
+
);
|
32 |
+
|
33 |
+
public $gateway;
|
34 |
+
|
35 |
+
/**
|
36 |
+
* Constructor.
|
37 |
+
*
|
38 |
+
* @param string $gateway
|
39 |
+
*/
|
40 |
+
public function __construct( $gateway = 'email' )
|
41 |
+
{
|
42 |
+
/*
|
43 |
+
* make Visual Mode as default (instead of Text Mode)
|
44 |
+
* allowed: tinymce - Visual Mode, html - Text Mode, test - no one Mode selected
|
45 |
+
*/
|
46 |
+
add_filter( 'wp_default_editor', create_function( '', 'return \'tinymce\';' ) );
|
47 |
+
$this->types = apply_filters( 'bookly_prepare_notification_types', $this->types );
|
48 |
+
$this->gateway = $gateway;
|
49 |
+
if ( ! Lib\Config::areCombinedNotificationsEnabled() ) {
|
50 |
+
$this->types['combined'] = array();
|
51 |
+
}
|
52 |
+
$this->setFields( array( 'active', 'subject', 'message', 'copy', ) );
|
53 |
+
$this->load();
|
54 |
+
}
|
55 |
+
|
56 |
+
public function bind( array $_post = array(), array $files = array() )
|
57 |
+
{
|
58 |
+
foreach ( $this->types as $group ) {
|
59 |
+
foreach ( $group as $type ) {
|
60 |
+
foreach ( $this->fields as $field ) {
|
61 |
+
if ( isset ( $_post[ $type ] [ $field ] ) ) {
|
62 |
+
$this->data[ $type ][ $field ] = $_post[ $type ][ $field ];
|
63 |
+
}
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
/**
|
70 |
+
* Save form.
|
71 |
+
*/
|
72 |
+
public function save()
|
73 |
+
{
|
74 |
+
/** @var Lib\Entities\Notification[] $notifications */
|
75 |
+
$notifications = Lib\Entities\Notification::query( 'n' )
|
76 |
+
->where( 'gateway', $this->gateway )
|
77 |
+
->indexBy( 'type' )
|
78 |
+
->find();
|
79 |
+
foreach ( $this->types as $group ) {
|
80 |
+
foreach ( $group as $type ) {
|
81 |
+
$notifications[ $type ]->setFields( $this->data[ $type ] );
|
82 |
+
$notifications[ $type ]->save();
|
83 |
+
}
|
84 |
+
}
|
85 |
+
}
|
86 |
+
|
87 |
+
public function load()
|
88 |
+
{
|
89 |
+
$notifications = Lib\Entities\Notification::query( 'n' )
|
90 |
+
->select( 'active, subject, message, copy, type' )
|
91 |
+
->where( 'gateway', $this->gateway )
|
92 |
+
->indexBy( 'type' )
|
93 |
+
->fetchArray();
|
94 |
+
foreach ( $this->types as $group ) {
|
95 |
+
foreach ( $group as $type ) {
|
96 |
+
$notifications[ $type ]['name'] = Lib\Entities\Notification::getName( $type );
|
97 |
+
$this->data[ $type ] = $notifications[ $type ];
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
101 |
+
|
102 |
+
/**
|
103 |
+
* Render subject.
|
104 |
+
*
|
105 |
+
* @param string $type
|
106 |
+
*/
|
107 |
+
public function renderSubject( $type )
|
108 |
+
{
|
109 |
+
printf(
|
110 |
+
'<div class="form-group">
|
111 |
+
<label for="%1$s">%2$s</label>
|
112 |
+
<input type="text" class="form-control" id="%1$s" name="%3$s" value="%4$s" />
|
113 |
+
</div>',
|
114 |
+
$type . '_subject',
|
115 |
+
__( 'Subject', 'bookly' ),
|
116 |
+
$type . '[subject]',
|
117 |
+
esc_attr( $this->data[ $type ]['subject'] )
|
118 |
+
);
|
119 |
+
}
|
120 |
+
|
121 |
+
/**
|
122 |
+
* Render message editor.
|
123 |
+
*
|
124 |
+
* @param string $type
|
125 |
+
*/
|
126 |
+
public function renderEditor( $type )
|
127 |
+
{
|
128 |
+
$id = $type . '_message';
|
129 |
+
$name = $type . '[message]';
|
130 |
+
$value = $this->data[ $type ]['message'];
|
131 |
+
|
132 |
+
if ( $this->gateway == 'sms' ) {
|
133 |
+
printf(
|
134 |
+
'<div class="form-group">
|
135 |
+
<label for="%1$s">%2$s</label>
|
136 |
+
<textarea rows="6" id="%1$s" name="%3$s" class="form-control">%4$s</textarea>
|
137 |
+
</div>',
|
138 |
+
$id,
|
139 |
+
__( 'Message', 'bookly' ),
|
140 |
+
$name,
|
141 |
+
esc_textarea( $value )
|
142 |
+
);
|
143 |
+
} else {
|
144 |
+
$settings = array(
|
145 |
+
'textarea_name' => $name,
|
146 |
+
'media_buttons' => false,
|
147 |
+
'editor_height' => 384,
|
148 |
+
'tinymce' => array(
|
149 |
+
'theme_advanced_buttons1' => 'formatselect,|,bold,italic,underline,|,'.
|
150 |
+
'bullist,blockquote,|,justifyleft,justifycenter'.
|
151 |
+
',justifyright,justifyfull,|,link,unlink,|'.
|
152 |
+
',spellchecker,wp_fullscreen,wp_adv'
|
153 |
+
)
|
154 |
+
);
|
155 |
+
|
156 |
+
echo '<div class="form-group"><label>' . __( 'Message', 'bookly' ) . '</label>';
|
157 |
+
wp_editor( $value, $id, $settings );
|
158 |
+
echo '</div>';
|
159 |
+
}
|
160 |
+
}
|
161 |
+
|
162 |
+
/**
|
163 |
+
* Render copy.
|
164 |
+
*
|
165 |
+
* @param string $type
|
166 |
+
*/
|
167 |
+
public function renderCopy( $type )
|
168 |
+
{
|
169 |
+
if ( in_array( $type, array( 'staff_pending_appointment', 'staff_approved_appointment', 'staff_cancelled_appointment', 'staff_rejected_appointment', 'staff_pending_recurring_appointment', 'staff_approved_recurring_appointment', 'staff_cancelled_recurring_appointment' ) ) ) {
|
170 |
+
printf(
|
171 |
+
'<div class="form-group">
|
172 |
+
<input name="%1$s" type="hidden" value="0">
|
173 |
+
<div class="checkbox"><label for="%2$s"><input id="%2$s" name="%1$s" type="checkbox" value="1" %3$s> %4$s</label></div>
|
174 |
+
</div>',
|
175 |
+
$type . '[copy]',
|
176 |
+
$type . '_copy',
|
177 |
+
checked( $this->data[ $type ]['copy'], true, false ),
|
178 |
+
__( 'Send copy to administrators', 'bookly' )
|
179 |
+
);
|
180 |
+
}
|
181 |
+
}
|
182 |
+
|
183 |
+
/**
|
184 |
+
* Render sending time.
|
185 |
+
*
|
186 |
+
* @param string $type
|
187 |
+
*/
|
188 |
+
public function renderSendingTime( $type )
|
189 |
+
{
|
190 |
+
if ( in_array( $type, array( 'staff_agenda', 'client_follow_up', 'client_reminder' ) ) ) {
|
191 |
+
$cron_reminder = (array) get_option( 'bookly_cron_reminder_times' );
|
192 |
+
printf(
|
193 |
+
'<div class="form-group">
|
194 |
+
<label for="%1$s">%2$s</label>
|
195 |
+
<p class="help-block">%3$s</p>
|
196 |
+
<select class="form-control" name="%1$s" id="%1$s">
|
197 |
+
%4$s
|
198 |
+
</select>
|
199 |
+
</div>',
|
200 |
+
$type . '_cron_hour',
|
201 |
+
__( 'Sending time', 'bookly' ),
|
202 |
+
__( 'Set the time you want the notification to be sent.', 'bookly' ),
|
203 |
+
implode( '', array_map( function ( $hour ) use ( $type, $cron_reminder ) {
|
204 |
+
return sprintf(
|
205 |
+
'<option value="%s" %s>%s</option>',
|
206 |
+
$hour,
|
207 |
+
selected( $cron_reminder[ $type ], $hour, false ),
|
208 |
+
Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false )
|
209 |
+
);
|
210 |
+
}, range( 0, 23 ) ) )
|
211 |
+
);
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
}
|
backend/modules/notifications/resources/js/ng-app.js
CHANGED
@@ -3,25 +3,25 @@
|
|
3 |
|
4 |
module.factory('dataSource', function($q, $rootScope) {
|
5 |
var ds = {
|
6 |
-
|
7 |
-
|
8 |
reply_to_customers : false,
|
9 |
-
|
10 |
notifications : [],
|
11 |
loadData : function(params) {
|
12 |
var deferred = $q.defer();
|
13 |
jQuery.ajax({
|
14 |
url : ajaxurl,
|
15 |
type : 'POST',
|
16 |
-
data : jQuery.extend({ action : '
|
17 |
dataType : 'json',
|
18 |
success : function(response) {
|
19 |
if (response.success) {
|
20 |
-
ds.
|
21 |
-
ds.
|
22 |
ds.reply_to_customers = response.data.reply_to_customers;
|
23 |
-
ds.
|
24 |
-
ds.notifications = response.data.
|
25 |
}
|
26 |
$rootScope.$apply(deferred.resolve);
|
27 |
},
|
3 |
|
4 |
module.factory('dataSource', function($q, $rootScope) {
|
5 |
var ds = {
|
6 |
+
sender_name : '',
|
7 |
+
sender_email : '',
|
8 |
reply_to_customers : false,
|
9 |
+
send_as : 'html',
|
10 |
notifications : [],
|
11 |
loadData : function(params) {
|
12 |
var deferred = $q.defer();
|
13 |
jQuery.ajax({
|
14 |
url : ajaxurl,
|
15 |
type : 'POST',
|
16 |
+
data : jQuery.extend({ action : 'bookly_get_email_notifications_data' }, params),
|
17 |
dataType : 'json',
|
18 |
success : function(response) {
|
19 |
if (response.success) {
|
20 |
+
ds.sender_name = response.data.sender_name;
|
21 |
+
ds.sender_email = response.data.sender_email;
|
22 |
ds.reply_to_customers = response.data.reply_to_customers;
|
23 |
+
ds.send_as = response.data.send_as;
|
24 |
+
ds.notifications = response.data.notifications;
|
25 |
}
|
26 |
$rootScope.$apply(deferred.resolve);
|
27 |
},
|
backend/modules/notifications/resources/js/notification.js
CHANGED
@@ -1,34 +1,34 @@
|
|
1 |
-
jQuery(function($) {
|
2 |
-
|
3 |
-
Ladda.bind( 'button[type=submit]' );
|
4 |
-
|
5 |
-
// menu fix for WP 3.8.1
|
6 |
-
$('#toplevel_page_ab-system > ul').css('margin-left', '0px');
|
7 |
-
|
8 |
-
/* exclude checkboxes in form */
|
9 |
-
var $checkboxes = $('.bookly-js-collapse .panel-title > input:checkbox');
|
10 |
-
|
11 |
-
$checkboxes.change(function () {
|
12 |
-
$(this).parents('.panel-heading').next().collapse(this.checked ? 'show' : 'hide');
|
13 |
-
});
|
14 |
-
|
15 |
-
$('[data-toggle="popover"]').popover({
|
16 |
-
html: true,
|
17 |
-
placement: 'top',
|
18 |
-
trigger: 'hover',
|
19 |
-
template: '<div class="popover bookly-font-xs" style="width: 220px" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
20 |
-
});
|
21 |
-
|
22 |
-
booklyAlert(BooklyL10n.alert);
|
23 |
-
|
24 |
-
$(':checkbox').on('change', function () {
|
25 |
-
if ($(this).prop('checked')) {
|
26 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
27 |
-
$(this).prop('checked', false).prop('readonly', true);
|
28 |
-
}
|
29 |
-
});
|
30 |
-
|
31 |
-
$('.ab-test-email-notifications').on('click',function () {
|
32 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
33 |
-
});
|
34 |
});
|
1 |
+
jQuery(function($) {
|
2 |
+
|
3 |
+
Ladda.bind( 'button[type=submit]' );
|
4 |
+
|
5 |
+
// menu fix for WP 3.8.1
|
6 |
+
$('#toplevel_page_ab-system > ul').css('margin-left', '0px');
|
7 |
+
|
8 |
+
/* exclude checkboxes in form */
|
9 |
+
var $checkboxes = $('.bookly-js-collapse .panel-title > input:checkbox');
|
10 |
+
|
11 |
+
$checkboxes.change(function () {
|
12 |
+
$(this).parents('.panel-heading').next().collapse(this.checked ? 'show' : 'hide');
|
13 |
+
});
|
14 |
+
|
15 |
+
$('[data-toggle="popover"]').popover({
|
16 |
+
html: true,
|
17 |
+
placement: 'top',
|
18 |
+
trigger: 'hover',
|
19 |
+
template: '<div class="popover bookly-font-xs" style="width: 220px" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
20 |
+
});
|
21 |
+
|
22 |
+
booklyAlert(BooklyL10n.alert);
|
23 |
+
|
24 |
+
$(':checkbox').on('change', function () {
|
25 |
+
if ($(this).prop('checked')) {
|
26 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
27 |
+
$(this).prop('checked', false).prop('readonly', true);
|
28 |
+
}
|
29 |
+
});
|
30 |
+
|
31 |
+
$('.ab-test-email-notifications').on('click',function () {
|
32 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
33 |
+
});
|
34 |
});
|
backend/modules/notifications/templates/_codes.php
CHANGED
@@ -6,6 +6,7 @@ $codes = array(
|
|
6 |
array( 'code' => 'approve_appointment_url', 'description' => esc_html__( 'URL of approve appointment link (to use inside <a> tag)', 'bookly' ) ),
|
7 |
array( 'code' => 'cancel_appointment', 'description' => __( 'cancel appointment link', 'bookly' ) ),
|
8 |
array( 'code' => 'cancel_appointment_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) ),
|
|
|
9 |
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
10 |
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
11 |
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
@@ -30,4 +31,4 @@ $codes = array(
|
|
30 |
array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) ),
|
31 |
array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) ),
|
32 |
);
|
33 |
-
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( '
|
6 |
array( 'code' => 'approve_appointment_url', 'description' => esc_html__( 'URL of approve appointment link (to use inside <a> tag)', 'bookly' ) ),
|
7 |
array( 'code' => 'cancel_appointment', 'description' => __( 'cancel appointment link', 'bookly' ) ),
|
8 |
array( 'code' => 'cancel_appointment_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) ),
|
9 |
+
array( 'code' => 'cancellation_reason', 'description' => __( 'reason you mentioned while deleting appointment', 'bookly' ) ),
|
10 |
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
11 |
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
12 |
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
31 |
array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) ),
|
32 |
array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) ),
|
33 |
);
|
34 |
+
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( 'bookly_prepare_notification_short_codes', $codes ) );
|
backend/modules/notifications/templates/_codes_cart.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'cart_info', 'description' => __( 'cart information', 'bookly' ) ),
|
4 |
-
array( 'code' => 'cart_info_c', 'description' => __( 'cart information with cancel', 'bookly' ) ),
|
5 |
-
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
6 |
-
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
7 |
-
array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) ),
|
8 |
-
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
9 |
-
array( 'code' => 'company_logo', 'description' => __( 'company logo', 'bookly' ) ),
|
10 |
-
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
11 |
-
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
12 |
-
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
13 |
-
array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) ),
|
14 |
-
array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) ),
|
15 |
-
);
|
16 |
-
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( '
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
$codes = array(
|
3 |
+
array( 'code' => 'cart_info', 'description' => __( 'cart information', 'bookly' ) ),
|
4 |
+
array( 'code' => 'cart_info_c', 'description' => __( 'cart information with cancel', 'bookly' ) ),
|
5 |
+
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
6 |
+
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
7 |
+
array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) ),
|
8 |
+
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
9 |
+
array( 'code' => 'company_logo', 'description' => __( 'company logo', 'bookly' ) ),
|
10 |
+
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
11 |
+
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
12 |
+
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
13 |
+
array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) ),
|
14 |
+
array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) ),
|
15 |
+
);
|
16 |
+
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( 'bookly_prepare_cart_notification_short_codes', $codes ) );
|
backend/modules/notifications/templates/_test_email_notifications_modal.php
CHANGED
@@ -13,34 +13,40 @@
|
|
13 |
</div>
|
14 |
<div class="modal-body">
|
15 |
<div class="form-group">
|
16 |
-
<label for="
|
17 |
-
<input id="
|
18 |
</div>
|
19 |
<div class="row">
|
20 |
<div class="col-sm-6">
|
21 |
<div class="form-group">
|
22 |
-
<label for="
|
23 |
-
<input id="
|
24 |
</div>
|
25 |
</div>
|
26 |
<div class="col-sm-6">
|
27 |
<div class="form-group">
|
28 |
-
<label for="
|
29 |
-
<input id="
|
30 |
</div>
|
31 |
</div>
|
32 |
</div>
|
33 |
<div class="row">
|
34 |
<div class="col-sm-6">
|
35 |
<div class="form-group">
|
36 |
-
<label><?php _e( 'Reply directly to customers', 'bookly' ) ?></label>
|
37 |
-
|
|
|
|
|
|
|
38 |
</div>
|
39 |
</div>
|
40 |
<div class="col-sm-6">
|
41 |
<div class="form-group">
|
42 |
-
<label><?php _e( 'Send emails as', 'bookly' ) ?></label>
|
43 |
-
|
|
|
|
|
|
|
44 |
</div>
|
45 |
</div>
|
46 |
</div>
|
@@ -56,7 +62,7 @@
|
|
56 |
<li class="bookly-padding-horizontal-md">
|
57 |
<div class="checkbox">
|
58 |
<label>
|
59 |
-
<input type="checkbox" id="bookly-check-all-entities" ng-model="allNotifications" ng-change="toggleAllNotifications()"
|
60 |
<?php _e( 'All templates', 'bookly' ) ?>
|
61 |
</label>
|
62 |
</div>
|
@@ -66,12 +72,11 @@
|
|
66 |
<li class="bookly-padding-horizontal-md" ng-repeat="notification in dataSource.notifications">
|
67 |
<div class="checkbox">
|
68 |
<label>
|
69 |
-
<input type="checkbox"
|
70 |
-
ng-
|
71 |
{{notification.name}}
|
72 |
</label>
|
73 |
</div>
|
74 |
-
|
75 |
</li>
|
76 |
</ul>
|
77 |
</div>
|
13 |
</div>
|
14 |
<div class="modal-body">
|
15 |
<div class="form-group">
|
16 |
+
<label for="bookly_test_to_email"><?php _e( 'To email', 'bookly' ) ?></label>
|
17 |
+
<input id="bookly_test_to_email" class="form-control" type="text" ng-model="toEmail"/>
|
18 |
</div>
|
19 |
<div class="row">
|
20 |
<div class="col-sm-6">
|
21 |
<div class="form-group">
|
22 |
+
<label for="bookly_test_sender_name"><?php _e( 'Sender name', 'bookly' ) ?></label>
|
23 |
+
<input id="bookly_test_sender_name" class="form-control" type="text" ng-model="dataSource.sender_name" />
|
24 |
</div>
|
25 |
</div>
|
26 |
<div class="col-sm-6">
|
27 |
<div class="form-group">
|
28 |
+
<label for="bookly_test_sender_email"><?php _e( 'Sender email', 'bookly' ) ?></label>
|
29 |
+
<input id="bookly_test_sender_email" class="form-control" type="text" ng-model="dataSource.sender_email" />
|
30 |
</div>
|
31 |
</div>
|
32 |
</div>
|
33 |
<div class="row">
|
34 |
<div class="col-sm-6">
|
35 |
<div class="form-group">
|
36 |
+
<label for="bookly_test_reply_to_customers"><?php _e( 'Reply directly to customers', 'bookly' ) ?></label>
|
37 |
+
<select id="bookly_test_reply_to_customers" class="form-control" ng-model="dataSource.reply_to_customers">
|
38 |
+
<option value="0"><?php _e( 'Disabled', 'bookly' ) ?></option>
|
39 |
+
<option value="1"><?php _e( 'Enabled', 'bookly' ) ?></option>
|
40 |
+
</select>
|
41 |
</div>
|
42 |
</div>
|
43 |
<div class="col-sm-6">
|
44 |
<div class="form-group">
|
45 |
+
<label for="bookly_test_send_as"><?php _e( 'Send emails as', 'bookly' ) ?></label>
|
46 |
+
<select id="bookly_test_send_as" class="form-control" ng-model="dataSource.send_as">
|
47 |
+
<option value="html"><?php _e( 'HTML', 'bookly' ) ?></option>
|
48 |
+
<option value="text"><?php _e( 'Text', 'bookly' ) ?></option>
|
49 |
+
</select>
|
50 |
</div>
|
51 |
</div>
|
52 |
</div>
|
62 |
<li class="bookly-padding-horizontal-md">
|
63 |
<div class="checkbox">
|
64 |
<label>
|
65 |
+
<input type="checkbox" id="bookly-check-all-entities" ng-model="allNotifications" ng-change="toggleAllNotifications()" />
|
66 |
<?php _e( 'All templates', 'bookly' ) ?>
|
67 |
</label>
|
68 |
</div>
|
72 |
<li class="bookly-padding-horizontal-md" ng-repeat="notification in dataSource.notifications">
|
73 |
<div class="checkbox">
|
74 |
<label>
|
75 |
+
<input type="checkbox" ng-model="notification.active"
|
76 |
+
ng-true-value="'1'" ng-false-value="'0'" ng-change="notificationChecked()" />
|
77 |
{{notification.name}}
|
78 |
</label>
|
79 |
</div>
|
|
|
80 |
</li>
|
81 |
</ul>
|
82 |
</div>
|
backend/modules/notifications/templates/index.php
CHANGED
@@ -1,151 +1,143 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$
|
3 |
-
get_option( 'blogname' ) : get_option( '
|
4 |
-
$
|
5 |
-
get_option( 'admin_email' ) : get_option( '
|
6 |
-
$collapse_id = 0;
|
7 |
-
$form_data = $form->getData();
|
8 |
-
?>
|
9 |
-
<div id="bookly-tbs" class="wrap">
|
10 |
-
<div class="bookly-tbs-body" ng-app="notifications">
|
11 |
-
<div class="page-header text-right clearfix">
|
12 |
-
<div class="bookly-page-title">
|
13 |
-
<?php _e( 'Email Notifications', 'bookly' ) ?>
|
14 |
-
</div>
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
<
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
<
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
<div class="col-md-6">
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
</button>
|
144 |
-
</div>
|
145 |
-
</div>
|
146 |
-
</div>
|
147 |
-
</form>
|
148 |
-
|
149 |
-
<?php include '_test_email_notifications_modal.php' ?>
|
150 |
-
</div>
|
151 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
$bookly_email_sender_name = get_option( 'bookly_email_sender_name' ) == '' ?
|
3 |
+
get_option( 'blogname' ) : get_option( 'bookly_email_sender_name' );
|
4 |
+
$bookly_email_sender = get_option( 'bookly_email_sender' ) == '' ?
|
5 |
+
get_option( 'admin_email' ) : get_option( 'bookly_email_sender' );
|
6 |
+
$collapse_id = 0;
|
7 |
+
$form_data = $form->getData();
|
8 |
+
?>
|
9 |
+
<div id="bookly-tbs" class="wrap">
|
10 |
+
<div class="bookly-tbs-body" ng-app="notifications">
|
11 |
+
<div class="page-header text-right clearfix">
|
12 |
+
<div class="bookly-page-title">
|
13 |
+
<?php _e( 'Email Notifications', 'bookly' ) ?>
|
14 |
+
</div>
|
15 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
16 |
+
</div>
|
17 |
+
<form method="post" action="">
|
18 |
+
<div class="panel panel-default bookly-main" ng-controller="emailNotifications">
|
19 |
+
<div class="panel-body">
|
20 |
+
<div class="row">
|
21 |
+
<div class="col-md-6">
|
22 |
+
<div class="form-group">
|
23 |
+
<label for="sender_name"><?php _e( 'Sender name', 'bookly' ) ?></label>
|
24 |
+
<input id="sender_name" name="bookly_email_sender_name" class="form-control" type="text" value="<?php echo esc_attr( $bookly_email_sender_name ) ?>">
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
<div class="col-md-6">
|
28 |
+
<div class="form-group">
|
29 |
+
<label for="sender_email"><?php _e( 'Sender email', 'bookly' ) ?></label>
|
30 |
+
<input id="sender_email" name="bookly_email_sender" class="form-control ab-sender" type="text" value="<?php echo esc_attr( $bookly_email_sender ) ?>">
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="col-md-6">
|
34 |
+
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_email_send_as', __( 'Send emails as', 'bookly' ), __( 'HTML allows formatting, colors, fonts, positioning, etc. With Text you must use Text mode of rich-text editors below. On some servers only text emails are sent successfully.', 'bookly' ),
|
35 |
+
array( array( 'html', __( 'HTML', 'bookly' ) ), array( 'text', __( 'Text', 'bookly' ) ) )
|
36 |
+
) ?>
|
37 |
+
</div>
|
38 |
+
<div class="col-md-6">
|
39 |
+
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_email_reply_to_customers', __( 'Reply directly to customers', 'bookly' ), __( 'If this option is enabled then the email address of the customer is used as a sender email address for notifications sent to staff members and administrators.', 'bookly' ) ) ?>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
<?php if ( $form->types['combined'] || \BooklyLite\Lib\Utils\Common::isPluginActive( 'bookly-addon-recurring-appointments/main.php' ) ) : ?>
|
43 |
+
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Single', 'bookly' ) ?></h4>
|
44 |
+
<?php endif ?>
|
45 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="single">
|
46 |
+
<?php foreach ( $form->types['single'] as $type ) : ?>
|
47 |
+
<div class="panel panel-default bookly-js-collapse">
|
48 |
+
<div class="panel-heading" role="tab">
|
49 |
+
<div class="checkbox bookly-margin-remove">
|
50 |
+
<label>
|
51 |
+
<input name="<?php echo $type ?>[active]" value="0" type="checkbox" checked="checked" class="hidden">
|
52 |
+
<input id="<?php echo $type ?>_active" name="<?php echo $type ?>[active]" value="1" type="checkbox" <?php checked( $form_data[ $type ]['active'] ) ?>>
|
53 |
+
<a href="#collapse_<?php echo ++ $collapse_id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#single">
|
54 |
+
<?php echo $form_data[ $type ]['name'] ?>
|
55 |
+
</a>
|
56 |
+
</label>
|
57 |
+
</div>
|
58 |
+
</div>
|
59 |
+
<div id="collapse_<?php echo $collapse_id ?>" class="panel-collapse collapse">
|
60 |
+
<div class="panel-body">
|
61 |
+
|
62 |
+
<?php $form->renderSendingTime( $type ) ?>
|
63 |
+
<?php $form->renderSubject( $type ) ?>
|
64 |
+
<?php $form->renderEditor( $type ) ?>
|
65 |
+
<?php $form->renderCopy( $type ) ?>
|
66 |
+
|
67 |
+
<div class="form-group">
|
68 |
+
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
69 |
+
<?php switch ( $type ) :
|
70 |
+
case 'staff_agenda': include '_codes_staff_agenda.php'; break;
|
71 |
+
case 'client_new_wp_user': include '_codes_client_new_wp_user.php'; break;
|
72 |
+
default: include '_codes.php';
|
73 |
+
endswitch ?>
|
74 |
+
</div>
|
75 |
+
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
</div>
|
79 |
+
<?php endforeach ?>
|
80 |
+
</div>
|
81 |
+
|
82 |
+
<?php if ( $form->types['combined'] ) : ?>
|
83 |
+
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Combined', 'bookly' ) ?></h4>
|
84 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="combined">
|
85 |
+
<?php foreach ( $form->types['combined'] as $type ) : ?>
|
86 |
+
<div class="panel panel-default bookly-js-collapse">
|
87 |
+
<div class="panel-heading" role="tab">
|
88 |
+
<div class="checkbox bookly-margin-remove">
|
89 |
+
<label>
|
90 |
+
<input name="<?php echo $type ?>[active]" value="0" type="checkbox" checked="checked" class="hidden">
|
91 |
+
<input id="<?php echo $type ?>_active" name="<?php echo $type ?>[active]" value="1" type="checkbox" <?php checked( $form_data[ $type ]['active'] ) ?>>
|
92 |
+
<a href="#collapse_<?php echo ++ $collapse_id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#combined">
|
93 |
+
<?php echo $form_data[ $type ]['name'] ?>
|
94 |
+
</a>
|
95 |
+
</label>
|
96 |
+
</div>
|
97 |
+
</div>
|
98 |
+
<div id="collapse_<?php echo $collapse_id ?>" class="panel-collapse collapse">
|
99 |
+
<div class="panel-body">
|
100 |
+
<?php $form->renderSubject( $type ) ?>
|
101 |
+
<?php $form->renderEditor( $type ) ?>
|
102 |
+
<?php $form->renderCopy( $type ) ?>
|
103 |
+
|
104 |
+
<div class="form-group">
|
105 |
+
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
106 |
+
<?php include '_codes_cart.php' ?>
|
107 |
+
|
108 |
+
</div>
|
109 |
+
</div>
|
110 |
+
</div>
|
111 |
+
</div>
|
112 |
+
<?php endforeach ?>
|
113 |
+
</div>
|
114 |
+
<?php endif ?>
|
115 |
+
|
116 |
+
<?php do_action( 'bookly_render_email_notifications', $form ) ?>
|
117 |
+
|
118 |
+
<div class="alert alert-info">
|
119 |
+
<?php if ( is_multisite() ) : ?>
|
120 |
+
<p><?php printf( __( 'To send scheduled notifications please refer to <a href="%1$s">Bookly Multisite</a> add-on <a href="%2$s">message</a>.', 'bookly' ), 'http://codecanyon.net/item/bookly-multisite-addon/13903524?ref=ladela', network_admin_url( 'admin.php?page=bookly-multisite-network' ) ) ?></p>
|
121 |
+
<?php else : ?>
|
122 |
+
<p><?php _e( 'To send scheduled notifications please execute the following script hourly with your cron:', 'bookly' ) ?></p><br />
|
123 |
+
<code class="bookly-text-wrap">php -f <?php echo $cron_path ?></code>
|
124 |
+
<?php endif ?>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
+
|
128 |
+
<div class="panel-footer">
|
129 |
+
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
130 |
+
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
131 |
+
|
132 |
+
<div class="pull-left">
|
133 |
+
<button type="button" class="btn btn-default ab-test-email-notifications btn-lg">
|
134 |
+
<?php _e( 'Test Email Notifications', 'bookly' ) ?>
|
135 |
+
</button>
|
136 |
+
</div>
|
137 |
+
</div>
|
138 |
+
</div>
|
139 |
+
</form>
|
140 |
+
|
141 |
+
<?php include '_test_email_notifications_modal.php' ?>
|
142 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
143 |
</div>
|
backend/modules/payments/Components.php
CHANGED
@@ -25,7 +25,7 @@ class Components extends Lib\Base\Components
|
|
25 |
'js/spin.min.js' => array( 'jquery' ),
|
26 |
'js/ladda.min.js' => array( 'jquery' ),
|
27 |
),
|
28 |
-
'module' => array( 'js/ng-payment_details_dialog.js' => array( '
|
29 |
) );
|
30 |
|
31 |
$this->render( '_payment_details_dialog' );
|
25 |
'js/spin.min.js' => array( 'jquery' ),
|
26 |
'js/ladda.min.js' => array( 'jquery' ),
|
27 |
),
|
28 |
+
'module' => array( 'js/ng-payment_details_dialog.js' => array( 'bookly-angular.min.js' ), ),
|
29 |
) );
|
30 |
|
31 |
$this->render( '_payment_details_dialog' );
|
backend/modules/payments/Controller.php
CHANGED
@@ -1,263 +1,266 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Payments;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Payments
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
$
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
'js/
|
41 |
-
'js/
|
42 |
-
'js/
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
'
|
55 |
-
'
|
56 |
-
'
|
57 |
-
'
|
58 |
-
'
|
59 |
-
'
|
60 |
-
'
|
61 |
-
'
|
62 |
-
'
|
63 |
-
'
|
64 |
-
|
65 |
-
|
66 |
-
'
|
67 |
-
'
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
'
|
72 |
-
'
|
73 |
-
'
|
74 |
-
'
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
Lib\Entities\Payment::
|
81 |
-
Lib\Entities\Payment::
|
82 |
-
Lib\Entities\Payment::
|
83 |
-
Lib\Entities\Payment::
|
84 |
-
Lib\Entities\Payment::
|
85 |
-
Lib\Entities\Payment::
|
86 |
-
Lib\Entities\Payment::
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
$
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
$
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
->
|
108 |
-
->leftJoin( '
|
109 |
-
->leftJoin( '
|
110 |
-
->
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
$
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
$
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
'
|
155 |
-
'
|
156 |
-
'
|
157 |
-
'
|
158 |
-
|
159 |
-
|
160 |
-
'
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
'
|
173 |
-
'
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
p.
|
191 |
-
p.
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
->
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
'
|
205 |
-
'
|
206 |
-
'
|
207 |
-
'
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
$
|
243 |
-
'
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
*
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
|
|
|
|
|
|
263 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Payments;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Payments
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-payments';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* @return array
|
16 |
+
*/
|
17 |
+
protected function getPermissions()
|
18 |
+
{
|
19 |
+
return array(
|
20 |
+
'executeGetPaymentDetails' => 'user',
|
21 |
+
'executeCompletePayment' => 'user',
|
22 |
+
);
|
23 |
+
}
|
24 |
+
|
25 |
+
public function index()
|
26 |
+
{
|
27 |
+
/** @var \WP_Locale $wp_locale */
|
28 |
+
global $wp_locale;
|
29 |
+
|
30 |
+
$this->enqueueStyles( array(
|
31 |
+
'backend' => array(
|
32 |
+
'bootstrap/css/bootstrap-theme.min.css',
|
33 |
+
'css/daterangepicker.css',
|
34 |
+
),
|
35 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
36 |
+
) );
|
37 |
+
|
38 |
+
$this->enqueueScripts( array(
|
39 |
+
'backend' => array(
|
40 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
41 |
+
'js/datatables.min.js' => array( 'jquery' ),
|
42 |
+
'js/moment.min.js',
|
43 |
+
'js/daterangepicker.js' => array( 'jquery' ),
|
44 |
+
'js/chosen.jquery.min.js' => array( 'jquery' ),
|
45 |
+
),
|
46 |
+
'frontend' => array(
|
47 |
+
'js/spin.min.js' => array( 'jquery' ),
|
48 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
49 |
+
),
|
50 |
+
'module' => array( 'js/payments.js' => array( 'bookly-datatables.min.js', 'bookly-ng-payment_details_dialog.js' ) ),
|
51 |
+
) );
|
52 |
+
|
53 |
+
wp_localize_script( 'bookly-daterangepicker.js', 'BooklyL10n', array(
|
54 |
+
'today' => __( 'Today', 'bookly' ),
|
55 |
+
'yesterday' => __( 'Yesterday', 'bookly' ),
|
56 |
+
'last_7' => __( 'Last 7 Days', 'bookly' ),
|
57 |
+
'last_30' => __( 'Last 30 Days', 'bookly' ),
|
58 |
+
'this_month' => __( 'This Month', 'bookly' ),
|
59 |
+
'last_month' => __( 'Last Month', 'bookly' ),
|
60 |
+
'custom_range' => __( 'Custom Range', 'bookly' ),
|
61 |
+
'apply' => __( 'Apply', 'bookly' ),
|
62 |
+
'cancel' => __( 'Cancel', 'bookly' ),
|
63 |
+
'to' => __( 'To', 'bookly' ),
|
64 |
+
'from' => __( 'From', 'bookly' ),
|
65 |
+
'calendar' => array(
|
66 |
+
'longMonths' => array_values( $wp_locale->month ),
|
67 |
+
'shortMonths' => array_values( $wp_locale->month_abbrev ),
|
68 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
69 |
+
'shortDays' => array_values( $wp_locale->weekday_abbrev ),
|
70 |
+
),
|
71 |
+
'startOfWeek' => (int) get_option( 'start_of_week' ),
|
72 |
+
'mjsDateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_MOMENT_JS ),
|
73 |
+
'zeroRecords' => __( 'No payments for selected period and criteria.', 'bookly' ),
|
74 |
+
'processing' => __( 'Processing...', 'bookly' ),
|
75 |
+
'details' => __( 'Details', 'bookly' ),
|
76 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
77 |
+
) );
|
78 |
+
|
79 |
+
$types = array(
|
80 |
+
Lib\Entities\Payment::TYPE_LOCAL,
|
81 |
+
Lib\Entities\Payment::TYPE_2CHECKOUT,
|
82 |
+
Lib\Entities\Payment::TYPE_PAYPAL,
|
83 |
+
Lib\Entities\Payment::TYPE_AUTHORIZENET,
|
84 |
+
Lib\Entities\Payment::TYPE_STRIPE,
|
85 |
+
Lib\Entities\Payment::TYPE_PAYULATAM,
|
86 |
+
Lib\Entities\Payment::TYPE_PAYSON,
|
87 |
+
Lib\Entities\Payment::TYPE_MOLLIE,
|
88 |
+
Lib\Entities\Payment::TYPE_COUPON,
|
89 |
+
Lib\Entities\Payment::WOO_COMMERCE,
|
90 |
+
);
|
91 |
+
$providers = Lib\Entities\Staff::query()->select( 'id, full_name' )->sortBy( 'full_name' )->fetchArray();
|
92 |
+
$services = Lib\Entities\Service::query()->select( 'id, title' )->sortBy( 'title' )->fetchArray();
|
93 |
+
|
94 |
+
$this->render( 'index', compact( 'types', 'providers', 'services' ) );
|
95 |
+
}
|
96 |
+
|
97 |
+
/**
|
98 |
+
* Get payments.
|
99 |
+
*/
|
100 |
+
public function executeGetPayments()
|
101 |
+
{
|
102 |
+
$columns = $this->getParameter( 'columns' );
|
103 |
+
$order = $this->getParameter( 'order' );
|
104 |
+
$filter = $this->getParameter( 'filter' );
|
105 |
+
|
106 |
+
$query = Lib\Entities\Payment::query( 'p' )
|
107 |
+
->select( 'p.id, p.created, p.type, p.paid, p.total, p.status, p.details, c.name customer, st.full_name provider, s.title service, a.start_date' )
|
108 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.payment_id = p.id' )
|
109 |
+
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
110 |
+
->leftJoin( 'Appointment', 'a', 'a.id = ca.appointment_id' )
|
111 |
+
->leftJoin( 'Service', 's', 's.id = COALESCE(ca.compound_service_id, a.service_id)' )
|
112 |
+
->leftJoin( 'Staff', 'st', 'st.id = a.staff_id' )
|
113 |
+
->groupBy( 'p.id' );
|
114 |
+
|
115 |
+
// Filters.
|
116 |
+
list ( $start, $end ) = explode( ' - ', $filter['created'], 2 );
|
117 |
+
$end = date( 'Y-m-d', strtotime( '+1 day', strtotime( $end ) ) );
|
118 |
+
|
119 |
+
$query->whereBetween( 'p.created', $start, $end );
|
120 |
+
|
121 |
+
if ( $filter['type'] != -1 ) {
|
122 |
+
$query->where( 'p.type', $filter['type'] );
|
123 |
+
}
|
124 |
+
|
125 |
+
if ( $filter['staff'] != -1 ) {
|
126 |
+
$query->where( 'st.id', $filter['staff'] );
|
127 |
+
}
|
128 |
+
|
129 |
+
if ( $filter['service'] != -1 ) {
|
130 |
+
$query->where( 's.id', $filter['service'] );
|
131 |
+
}
|
132 |
+
|
133 |
+
foreach ( $order as $sort_by ) {
|
134 |
+
$query->sortBy( $columns[ $sort_by['column'] ]['data'] )
|
135 |
+
->order( $sort_by['dir'] == 'desc' ? Lib\Query::ORDER_DESCENDING : Lib\Query::ORDER_ASCENDING );
|
136 |
+
}
|
137 |
+
|
138 |
+
$payments = $query->fetchArray();
|
139 |
+
|
140 |
+
$data = array();
|
141 |
+
$total = 0;
|
142 |
+
foreach ( $payments as $payment ) {
|
143 |
+
$details = json_decode( $payment['details'], true );
|
144 |
+
$multiple = count( $details['items'] ) > 1
|
145 |
+
? ' <span class="glyphicon glyphicon-shopping-cart" title="' . esc_attr( __( 'See details for more items', 'bookly' ) ) . '"></span>'
|
146 |
+
: '' ;
|
147 |
+
|
148 |
+
$paid_title = Lib\Utils\Common::formatPrice( $payment['paid'] );
|
149 |
+
if ( $payment['paid'] != $payment['total'] ) {
|
150 |
+
$paid_title = sprintf( __( '%s of %s', 'bookly' ), $paid_title, Lib\Utils\Common::formatPrice( $payment['total'] ) );
|
151 |
+
}
|
152 |
+
|
153 |
+
$data[] = array(
|
154 |
+
'id' => $payment['id'],
|
155 |
+
'created' => Lib\Utils\DateTime::formatDateTime( $payment['created'] ),
|
156 |
+
'type' => Lib\Entities\Payment::typeToString( $payment['type'] ),
|
157 |
+
'customer' => $payment['customer'] ?: $details['customer'],
|
158 |
+
'provider' => ( $payment['provider'] ?: $details['items'][0]['staff_name'] ) . $multiple,
|
159 |
+
'service' => ( $payment['service'] ?: $details['items'][0]['service_name'] ) . $multiple,
|
160 |
+
'start_date' => ( $payment['start_date']
|
161 |
+
? Lib\Utils\DateTime::formatDateTime( $payment['start_date'] )
|
162 |
+
: Lib\Utils\DateTime::formatDateTime( $details['items'][0]['appointment_date'] ) ) . $multiple,
|
163 |
+
'paid' => $paid_title,
|
164 |
+
'status' => Lib\Entities\Payment::statusToString( $payment['status'] ),
|
165 |
+
|
166 |
+
);
|
167 |
+
|
168 |
+
$total += $payment['paid'];
|
169 |
+
}
|
170 |
+
|
171 |
+
wp_send_json( array(
|
172 |
+
'draw' => ( int ) $this->getParameter( 'draw' ),
|
173 |
+
'recordsTotal' => count( $data ),
|
174 |
+
'recordsFiltered' => count( $data ),
|
175 |
+
'data' => $data,
|
176 |
+
'total' => Lib\Utils\Common::formatPrice( $total ),
|
177 |
+
) );
|
178 |
+
}
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Get payment details.
|
182 |
+
*
|
183 |
+
* @throws \Exception
|
184 |
+
*/
|
185 |
+
public function executeGetPaymentDetails()
|
186 |
+
{
|
187 |
+
$data = array();
|
188 |
+
$payment = Lib\Entities\Payment::query( 'p' )
|
189 |
+
->select( 'p.total,
|
190 |
+
p.status,
|
191 |
+
p.created AS created,
|
192 |
+
p.type,
|
193 |
+
p.details,
|
194 |
+
p.paid,
|
195 |
+
c.name AS customer' )
|
196 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.payment_id = p.id' )
|
197 |
+
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
198 |
+
->where( 'p.id', $this->getParameter( 'payment_id' ) )
|
199 |
+
->fetchRow();
|
200 |
+
if ( $payment ) {
|
201 |
+
$details = json_decode( $payment['details'], true );
|
202 |
+
$data = array(
|
203 |
+
'payment' => array(
|
204 |
+
'status' => $payment['status'],
|
205 |
+
'type' => $payment['type'],
|
206 |
+
'coupon' => $details['coupon'],
|
207 |
+
'created' => $payment['created'],
|
208 |
+
'customer' => empty ( $payment['customer'] ) ? $details['customer'] : $payment['customer'],
|
209 |
+
'total' => $payment['total'],
|
210 |
+
'paid' => $payment['paid'],
|
211 |
+
),
|
212 |
+
'items' => $details['items'],
|
213 |
+
'deposit_enabled' => Lib\Config::isDepositPaymentsEnabled()
|
214 |
+
);
|
215 |
+
}
|
216 |
+
|
217 |
+
wp_send_json_success( array( 'html' => $this->render( 'details', $data, false ) ) );
|
218 |
+
}
|
219 |
+
|
220 |
+
/**
|
221 |
+
* Delete payments.
|
222 |
+
*/
|
223 |
+
public function executeDeletePayments()
|
224 |
+
{
|
225 |
+
$payment_ids = array_map( 'intval', $this->getParameter( 'data', array() ) );
|
226 |
+
Lib\Entities\Payment::query()->delete()->whereIn( 'id', $payment_ids )->execute();
|
227 |
+
wp_send_json_success();
|
228 |
+
}
|
229 |
+
|
230 |
+
/**
|
231 |
+
* Complete payment.
|
232 |
+
*/
|
233 |
+
public function executeCompletePayment()
|
234 |
+
{
|
235 |
+
$payment = Lib\Entities\Payment::find( $this->getParameter( 'payment_id' ) );
|
236 |
+
$payment
|
237 |
+
->set( 'paid', $payment->get( 'total' ) )
|
238 |
+
->set( 'status', Lib\Entities\Payment::STATUS_COMPLETED )
|
239 |
+
->save();
|
240 |
+
|
241 |
+
$payment_title = Lib\Utils\Common::formatPrice( $payment->get( 'paid' ) );
|
242 |
+
if ( $payment->get( 'paid' ) != $payment->get( 'total' ) ) {
|
243 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Common::formatPrice( $payment->get( 'total' ) ) );
|
244 |
+
}
|
245 |
+
$payment_title .= sprintf(
|
246 |
+
' %s <span%s>%s</span>',
|
247 |
+
Lib\Entities\Payment::typeToString( $payment->get( 'type' ) ),
|
248 |
+
$payment->get( 'status' ) == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
249 |
+
Lib\Entities\Payment::statusToString( $payment->get( 'status' ) )
|
250 |
+
);
|
251 |
+
|
252 |
+
wp_send_json_success( array( 'payment_title' => $payment_title ) );
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
257 |
+
* so current 'execute*' methods look nicer.
|
258 |
+
*
|
259 |
+
* @param string $prefix
|
260 |
+
*/
|
261 |
+
protected function registerWpActions( $prefix = '' )
|
262 |
+
{
|
263 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
264 |
+
}
|
265 |
+
|
266 |
}
|
backend/modules/payments/resources/js/ng-payment_details_dialog.js
CHANGED
@@ -16,11 +16,11 @@
|
|
16 |
element
|
17 |
.on('show.bs.modal', function (e, payment_id) {
|
18 |
if (payment_id === undefined) {
|
19 |
-
payment_id =
|
20 |
}
|
21 |
jQuery.ajax({
|
22 |
url: ajaxurl,
|
23 |
-
data: {action: '
|
24 |
dataType: 'json',
|
25 |
success: function (response) {
|
26 |
if (response.success) {
|
@@ -30,7 +30,7 @@
|
|
30 |
ladda.start();
|
31 |
jQuery.ajax({
|
32 |
url: ajaxurl,
|
33 |
-
data: {action: '
|
34 |
dataType: 'json',
|
35 |
type: 'POST',
|
36 |
success: function (response) {
|
16 |
element
|
17 |
.on('show.bs.modal', function (e, payment_id) {
|
18 |
if (payment_id === undefined) {
|
19 |
+
payment_id = e.relatedTarget.getAttribute('data-payment_id');
|
20 |
}
|
21 |
jQuery.ajax({
|
22 |
url: ajaxurl,
|
23 |
+
data: {action: 'bookly_get_payment_details', payment_id: payment_id},
|
24 |
dataType: 'json',
|
25 |
success: function (response) {
|
26 |
if (response.success) {
|
30 |
ladda.start();
|
31 |
jQuery.ajax({
|
32 |
url: ajaxurl,
|
33 |
+
data: {action: 'bookly_complete_payment', payment_id: payment_id},
|
34 |
dataType: 'json',
|
35 |
type: 'POST',
|
36 |
success: function (response) {
|
backend/modules/payments/resources/js/payments.js
CHANGED
@@ -1,184 +1,184 @@
|
|
1 |
-
jQuery(function($) {
|
2 |
-
|
3 |
-
var
|
4 |
-
$payments_list = $('#bookly-payments-list'),
|
5 |
-
$check_all_button = $('#bookly-check-all'),
|
6 |
-
$date_filter = $('#bookly-filter-date'),
|
7 |
-
$type_filter = $('#bookly-filter-type'),
|
8 |
-
$staff_filter = $('#bookly-filter-staff'),
|
9 |
-
$service_filter = $('#bookly-filter-service'),
|
10 |
-
$payment_total = $('#bookly-payment-total'),
|
11 |
-
$delete_button = $('#bookly-delete')
|
12 |
-
;
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Init DataTables.
|
16 |
-
*/
|
17 |
-
var dt = $payments_list.DataTable({
|
18 |
-
order: [[ 0, 'asc' ]],
|
19 |
-
paging: false,
|
20 |
-
info: false,
|
21 |
-
searching: false,
|
22 |
-
processing: true,
|
23 |
-
responsive: true,
|
24 |
-
serverSide: true,
|
25 |
-
ajax: {
|
26 |
-
url: ajaxurl,
|
27 |
-
data: function ( d ) {
|
28 |
-
return $.extend( {}, d, {
|
29 |
-
action: '
|
30 |
-
filter: {
|
31 |
-
created: $date_filter.data('date'),
|
32 |
-
type: $type_filter.val(),
|
33 |
-
staff: $staff_filter.val(),
|
34 |
-
service: $service_filter.val()
|
35 |
-
}
|
36 |
-
} );
|
37 |
-
},
|
38 |
-
dataSrc: function (json) {
|
39 |
-
$payment_total.html(json.total);
|
40 |
-
|
41 |
-
return json.data;
|
42 |
-
}
|
43 |
-
},
|
44 |
-
columns: [
|
45 |
-
{ data: 'created' },
|
46 |
-
{ data: 'type' },
|
47 |
-
{ data: 'customer' },
|
48 |
-
{ data: 'provider' },
|
49 |
-
{ data: 'service' },
|
50 |
-
{ data: 'start_date' },
|
51 |
-
{ data: 'paid' },
|
52 |
-
{ data: 'status' },
|
53 |
-
{
|
54 |
-
responsivePriority: 1,
|
55 |
-
orderable: false,
|
56 |
-
searchable: false,
|
57 |
-
render: function ( data, type, row, meta ) {
|
58 |
-
return '<button type="button" class="btn btn-default" data-toggle="modal" data-target="#bookly-payment-details-modal" data-payment_id="' + row.id + '"><i class="glyphicon glyphicon-list-alt"></i> ' + BooklyL10n.details + '</a>';
|
59 |
-
}
|
60 |
-
},
|
61 |
-
{
|
62 |
-
responsivePriority: 1,
|
63 |
-
orderable: false,
|
64 |
-
searchable: false,
|
65 |
-
render: function ( data, type, row, meta ) {
|
66 |
-
return '<input type="checkbox" value="' + row.id + '">';
|
67 |
-
}
|
68 |
-
}
|
69 |
-
],
|
70 |
-
language: {
|
71 |
-
zeroRecords: BooklyL10n.zeroRecords,
|
72 |
-
processing: BooklyL10n.processing
|
73 |
-
}
|
74 |
-
});
|
75 |
-
|
76 |
-
/**
|
77 |
-
* Select all coupons.
|
78 |
-
*/
|
79 |
-
$check_all_button.on('change', function () {
|
80 |
-
$payments_list.find('tbody input:checkbox').prop('checked', this.checked);
|
81 |
-
});
|
82 |
-
|
83 |
-
/**
|
84 |
-
* On coupon select.
|
85 |
-
*/
|
86 |
-
$payments_list.on('change', 'tbody input:checkbox', function () {
|
87 |
-
$check_all_button.prop('checked', $payments_list.find('tbody input:not(:checked)').length == 0);
|
88 |
-
});
|
89 |
-
/**
|
90 |
-
* Init date range picker.
|
91 |
-
*/
|
92 |
-
moment.locale('en', {
|
93 |
-
months: BooklyL10n.calendar.longMonths,
|
94 |
-
monthsShort: BooklyL10n.calendar.shortMonths,
|
95 |
-
weekdays: BooklyL10n.calendar.longDays,
|
96 |
-
weekdaysShort: BooklyL10n.calendar.shortDays,
|
97 |
-
weekdaysMin: BooklyL10n.calendar.shortDays
|
98 |
-
});
|
99 |
-
|
100 |
-
var picker_ranges = {};
|
101 |
-
picker_ranges[BooklyL10n.yesterday] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
|
102 |
-
picker_ranges[BooklyL10n.today] = [moment(), moment()];
|
103 |
-
picker_ranges[BooklyL10n.last_7] = [moment().subtract(7, 'days'), moment()];
|
104 |
-
picker_ranges[BooklyL10n.last_30] = [moment().subtract(30, 'days'), moment()];
|
105 |
-
picker_ranges[BooklyL10n.this_month] = [moment().startOf('month'), moment().endOf('month')];
|
106 |
-
picker_ranges[BooklyL10n.last_month] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
|
107 |
-
|
108 |
-
$date_filter.daterangepicker(
|
109 |
-
{
|
110 |
-
parentEl: $date_filter.parent(),
|
111 |
-
startDate: moment().subtract(30, 'days'), // by default selected is "Last 30 days"
|
112 |
-
ranges: picker_ranges,
|
113 |
-
locale: {
|
114 |
-
applyLabel: BooklyL10n.apply,
|
115 |
-
cancelLabel: BooklyL10n.cancel,
|
116 |
-
fromLabel: BooklyL10n.from,
|
117 |
-
toLabel: BooklyL10n.to,
|
118 |
-
customRangeLabel: BooklyL10n.custom_range,
|
119 |
-
daysOfWeek: BooklyL10n.calendar.shortDays,
|
120 |
-
monthNames: BooklyL10n.calendar.longMonths,
|
121 |
-
firstDay: parseInt(BooklyL10n.startOfWeek),
|
122 |
-
format: BooklyL10n.mjsDateFormat
|
123 |
-
}
|
124 |
-
},
|
125 |
-
function(start, end) {
|
126 |
-
var format = 'YYYY-MM-DD';
|
127 |
-
$date_filter
|
128 |
-
.data('date', start.format(format) + ' - ' + end.format(format))
|
129 |
-
.find('span')
|
130 |
-
.html(start.format(BooklyL10n.mjsDateFormat) + ' - ' + end.format(BooklyL10n.mjsDateFormat));
|
131 |
-
}
|
132 |
-
);
|
133 |
-
|
134 |
-
/**
|
135 |
-
* On filters change.
|
136 |
-
*/
|
137 |
-
$('.bookly-js-chosen-select').chosen({
|
138 |
-
allow_single_deselect: true,
|
139 |
-
disable_search_threshold: 10
|
140 |
-
});
|
141 |
-
$date_filter.on('apply.daterangepicker', function () { dt.ajax.reload(); });
|
142 |
-
$type_filter.on('change', function () { dt.ajax.reload(); });
|
143 |
-
$staff_filter.on('change', function () { dt.ajax.reload(); });
|
144 |
-
$service_filter.on('change', function () { dt.ajax.reload(); });
|
145 |
-
|
146 |
-
/**
|
147 |
-
* Delete payments.
|
148 |
-
*/
|
149 |
-
$delete_button.on('click', function () {
|
150 |
-
if (confirm(BooklyL10n.are_you_sure)) {
|
151 |
-
var ladda = Ladda.create(this);
|
152 |
-
ladda.start();
|
153 |
-
|
154 |
-
var data = [];
|
155 |
-
var $checkboxes = $payments_list.find('tbody input:checked');
|
156 |
-
$checkboxes.each(function () {
|
157 |
-
data.push(this.value);
|
158 |
-
});
|
159 |
-
|
160 |
-
$.ajax({
|
161 |
-
url : ajaxurl,
|
162 |
-
type : 'POST',
|
163 |
-
data : {
|
164 |
-
action : '
|
165 |
-
data : data
|
166 |
-
},
|
167 |
-
dataType : 'json',
|
168 |
-
success : function(response) {
|
169 |
-
ladda.stop();
|
170 |
-
if (response.success) {
|
171 |
-
dt.rows($checkboxes.closest('td')).remove().draw();
|
172 |
-
} else {
|
173 |
-
alert(response.data.message);
|
174 |
-
}
|
175 |
-
}
|
176 |
-
});
|
177 |
-
}
|
178 |
-
});
|
179 |
-
});
|
180 |
-
|
181 |
-
(function() {
|
182 |
-
var module = angular.module('paymentDetails', ['paymentDetailsDialog']);
|
183 |
-
module.controller('paymentDetailsCtrl', function($scope) {});
|
184 |
})();
|
1 |
+
jQuery(function($) {
|
2 |
+
|
3 |
+
var
|
4 |
+
$payments_list = $('#bookly-payments-list'),
|
5 |
+
$check_all_button = $('#bookly-check-all'),
|
6 |
+
$date_filter = $('#bookly-filter-date'),
|
7 |
+
$type_filter = $('#bookly-filter-type'),
|
8 |
+
$staff_filter = $('#bookly-filter-staff'),
|
9 |
+
$service_filter = $('#bookly-filter-service'),
|
10 |
+
$payment_total = $('#bookly-payment-total'),
|
11 |
+
$delete_button = $('#bookly-delete')
|
12 |
+
;
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Init DataTables.
|
16 |
+
*/
|
17 |
+
var dt = $payments_list.DataTable({
|
18 |
+
order: [[ 0, 'asc' ]],
|
19 |
+
paging: false,
|
20 |
+
info: false,
|
21 |
+
searching: false,
|
22 |
+
processing: true,
|
23 |
+
responsive: true,
|
24 |
+
serverSide: true,
|
25 |
+
ajax: {
|
26 |
+
url: ajaxurl,
|
27 |
+
data: function ( d ) {
|
28 |
+
return $.extend( {}, d, {
|
29 |
+
action: 'bookly_get_payments',
|
30 |
+
filter: {
|
31 |
+
created: $date_filter.data('date'),
|
32 |
+
type: $type_filter.val(),
|
33 |
+
staff: $staff_filter.val(),
|
34 |
+
service: $service_filter.val()
|
35 |
+
}
|
36 |
+
} );
|
37 |
+
},
|
38 |
+
dataSrc: function (json) {
|
39 |
+
$payment_total.html(json.total);
|
40 |
+
|
41 |
+
return json.data;
|
42 |
+
}
|
43 |
+
},
|
44 |
+
columns: [
|
45 |
+
{ data: 'created' },
|
46 |
+
{ data: 'type' },
|
47 |
+
{ data: 'customer', render: $.fn.dataTable.render.text() },
|
48 |
+
{ data: 'provider' },
|
49 |
+
{ data: 'service' },
|
50 |
+
{ data: 'start_date' },
|
51 |
+
{ data: 'paid' },
|
52 |
+
{ data: 'status' },
|
53 |
+
{
|
54 |
+
responsivePriority: 1,
|
55 |
+
orderable: false,
|
56 |
+
searchable: false,
|
57 |
+
render: function ( data, type, row, meta ) {
|
58 |
+
return '<button type="button" class="btn btn-default" data-toggle="modal" data-target="#bookly-payment-details-modal" data-payment_id="' + row.id + '"><i class="glyphicon glyphicon-list-alt"></i> ' + BooklyL10n.details + '</a>';
|
59 |
+
}
|
60 |
+
},
|
61 |
+
{
|
62 |
+
responsivePriority: 1,
|
63 |
+
orderable: false,
|
64 |
+
searchable: false,
|
65 |
+
render: function ( data, type, row, meta ) {
|
66 |
+
return '<input type="checkbox" value="' + row.id + '">';
|
67 |
+
}
|
68 |
+
}
|
69 |
+
],
|
70 |
+
language: {
|
71 |
+
zeroRecords: BooklyL10n.zeroRecords,
|
72 |
+
processing: BooklyL10n.processing
|
73 |
+
}
|
74 |
+
});
|
75 |
+
|
76 |
+
/**
|
77 |
+
* Select all coupons.
|
78 |
+
*/
|
79 |
+
$check_all_button.on('change', function () {
|
80 |
+
$payments_list.find('tbody input:checkbox').prop('checked', this.checked);
|
81 |
+
});
|
82 |
+
|
83 |
+
/**
|
84 |
+
* On coupon select.
|
85 |
+
*/
|
86 |
+
$payments_list.on('change', 'tbody input:checkbox', function () {
|
87 |
+
$check_all_button.prop('checked', $payments_list.find('tbody input:not(:checked)').length == 0);
|
88 |
+
});
|
89 |
+
/**
|
90 |
+
* Init date range picker.
|
91 |
+
*/
|
92 |
+
moment.locale('en', {
|
93 |
+
months: BooklyL10n.calendar.longMonths,
|
94 |
+
monthsShort: BooklyL10n.calendar.shortMonths,
|
95 |
+
weekdays: BooklyL10n.calendar.longDays,
|
96 |
+
weekdaysShort: BooklyL10n.calendar.shortDays,
|
97 |
+
weekdaysMin: BooklyL10n.calendar.shortDays
|
98 |
+
});
|
99 |
+
|
100 |
+
var picker_ranges = {};
|
101 |
+
picker_ranges[BooklyL10n.yesterday] = [moment().subtract(1, 'days'), moment().subtract(1, 'days')];
|
102 |
+
picker_ranges[BooklyL10n.today] = [moment(), moment()];
|
103 |
+
picker_ranges[BooklyL10n.last_7] = [moment().subtract(7, 'days'), moment()];
|
104 |
+
picker_ranges[BooklyL10n.last_30] = [moment().subtract(30, 'days'), moment()];
|
105 |
+
picker_ranges[BooklyL10n.this_month] = [moment().startOf('month'), moment().endOf('month')];
|
106 |
+
picker_ranges[BooklyL10n.last_month] = [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')];
|
107 |
+
|
108 |
+
$date_filter.daterangepicker(
|
109 |
+
{
|
110 |
+
parentEl: $date_filter.parent(),
|
111 |
+
startDate: moment().subtract(30, 'days'), // by default selected is "Last 30 days"
|
112 |
+
ranges: picker_ranges,
|
113 |
+
locale: {
|
114 |
+
applyLabel: BooklyL10n.apply,
|
115 |
+
cancelLabel: BooklyL10n.cancel,
|
116 |
+
fromLabel: BooklyL10n.from,
|
117 |
+
toLabel: BooklyL10n.to,
|
118 |
+
customRangeLabel: BooklyL10n.custom_range,
|
119 |
+
daysOfWeek: BooklyL10n.calendar.shortDays,
|
120 |
+
monthNames: BooklyL10n.calendar.longMonths,
|
121 |
+
firstDay: parseInt(BooklyL10n.startOfWeek),
|
122 |
+
format: BooklyL10n.mjsDateFormat
|
123 |
+
}
|
124 |
+
},
|
125 |
+
function(start, end) {
|
126 |
+
var format = 'YYYY-MM-DD';
|
127 |
+
$date_filter
|
128 |
+
.data('date', start.format(format) + ' - ' + end.format(format))
|
129 |
+
.find('span')
|
130 |
+
.html(start.format(BooklyL10n.mjsDateFormat) + ' - ' + end.format(BooklyL10n.mjsDateFormat));
|
131 |
+
}
|
132 |
+
);
|
133 |
+
|
134 |
+
/**
|
135 |
+
* On filters change.
|
136 |
+
*/
|
137 |
+
$('.bookly-js-chosen-select').chosen({
|
138 |
+
allow_single_deselect: true,
|
139 |
+
disable_search_threshold: 10
|
140 |
+
});
|
141 |
+
$date_filter.on('apply.daterangepicker', function () { dt.ajax.reload(); });
|
142 |
+
$type_filter.on('change', function () { dt.ajax.reload(); });
|
143 |
+
$staff_filter.on('change', function () { dt.ajax.reload(); });
|
144 |
+
$service_filter.on('change', function () { dt.ajax.reload(); });
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Delete payments.
|
148 |
+
*/
|
149 |
+
$delete_button.on('click', function () {
|
150 |
+
if (confirm(BooklyL10n.are_you_sure)) {
|
151 |
+
var ladda = Ladda.create(this);
|
152 |
+
ladda.start();
|
153 |
+
|
154 |
+
var data = [];
|
155 |
+
var $checkboxes = $payments_list.find('tbody input:checked');
|
156 |
+
$checkboxes.each(function () {
|
157 |
+
data.push(this.value);
|
158 |
+
});
|
159 |
+
|
160 |
+
$.ajax({
|
161 |
+
url : ajaxurl,
|
162 |
+
type : 'POST',
|
163 |
+
data : {
|
164 |
+
action : 'bookly_delete_payments',
|
165 |
+
data : data
|
166 |
+
},
|
167 |
+
dataType : 'json',
|
168 |
+
success : function(response) {
|
169 |
+
ladda.stop();
|
170 |
+
if (response.success) {
|
171 |
+
dt.rows($checkboxes.closest('td')).remove().draw();
|
172 |
+
} else {
|
173 |
+
alert(response.data.message);
|
174 |
+
}
|
175 |
+
}
|
176 |
+
});
|
177 |
+
}
|
178 |
+
});
|
179 |
+
});
|
180 |
+
|
181 |
+
(function() {
|
182 |
+
var module = angular.module('paymentDetails', ['paymentDetailsDialog']);
|
183 |
+
module.controller('paymentDetailsCtrl', function($scope) {});
|
184 |
})();
|
backend/modules/payments/templates/_payment_details_dialog.php
CHANGED
@@ -1,21 +1,19 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<script type="text/ng-template" id="bookly-payment-details-dialog.tpl">
|
3 |
-
<div class="modal fade" id="bookly-payment-details-modal" tabindex="-1" role="dialog">
|
4 |
-
<div class="modal-dialog" role="document">
|
5 |
-
<div class="modal-content">
|
6 |
-
<div class="modal-header">
|
7 |
-
<button type="button" class="close" data-dismiss="modal" aria-label="<?php esc_attr_e( 'Close', 'bookly' ) ?>"><span aria-hidden="true">×</span></button>
|
8 |
-
<div class="modal-title h2"><?php _e( 'Payment', 'bookly' ) ?></div>
|
9 |
-
</div>
|
10 |
-
<div class="modal-body">
|
11 |
-
<div class="bookly-loading"></div>
|
12 |
-
</div>
|
13 |
-
<div class="modal-footer">
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
</script>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<script type="text/ng-template" id="bookly-payment-details-dialog.tpl">
|
3 |
+
<div class="modal fade" id="bookly-payment-details-modal" tabindex="-1" role="dialog">
|
4 |
+
<div class="modal-dialog" role="document">
|
5 |
+
<div class="modal-content">
|
6 |
+
<div class="modal-header">
|
7 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="<?php esc_attr_e( 'Close', 'bookly' ) ?>"><span aria-hidden="true">×</span></button>
|
8 |
+
<div class="modal-title h2"><?php _e( 'Payment', 'bookly' ) ?></div>
|
9 |
+
</div>
|
10 |
+
<div class="modal-body">
|
11 |
+
<div class="bookly-loading"></div>
|
12 |
+
</div>
|
13 |
+
<div class="modal-footer">
|
14 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn-lg btn-default', __( 'Close', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
15 |
+
</div>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
+
</div>
|
|
|
|
|
19 |
</script>
|
backend/modules/payments/templates/details.php
CHANGED
@@ -1,132 +1,132 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$subtotal = 0;
|
3 |
-
$subtotal_deposit = 0;
|
4 |
-
?>
|
5 |
-
<?php if ( $payment ) : ?>
|
6 |
-
<div class="table-responsive">
|
7 |
-
<table class="table table-bordered">
|
8 |
-
<thead>
|
9 |
-
<tr>
|
10 |
-
<th width="50%"><?php _e( 'Customer', 'bookly' ) ?></th>
|
11 |
-
<th width="50%"><?php _e( 'Payment', 'bookly' ) ?></th>
|
12 |
-
</tr>
|
13 |
-
</thead>
|
14 |
-
<tbody>
|
15 |
-
<tr>
|
16 |
-
<td><?php echo $payment['customer'] ?></td>
|
17 |
-
<td>
|
18 |
-
<div><?php _e( 'Date', 'bookly' ) ?>: <?php echo \BooklyLite\Lib\Utils\DateTime::formatDateTime( $payment['created'] ) ?></div>
|
19 |
-
<div><?php _e( 'Type', 'bookly' ) ?>: <?php echo \BooklyLite\Lib\Entities\Payment::typeToString( $payment['type'] ) ?></div>
|
20 |
-
<div><?php _e( 'Status', 'bookly' ) ?>: <?php echo \BooklyLite\Lib\Entities\Payment::statusToString( $payment['status'] ) ?></div>
|
21 |
-
</td>
|
22 |
-
</tr>
|
23 |
-
</tbody>
|
24 |
-
</table>
|
25 |
-
</div>
|
26 |
-
|
27 |
-
<div class="table-responsive">
|
28 |
-
<table class="table table-bordered">
|
29 |
-
<thead>
|
30 |
-
<tr>
|
31 |
-
<th><?php _e( 'Service', 'bookly' ) ?></th>
|
32 |
-
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
33 |
-
<th><?php _e( 'Provider', 'bookly' ) ?></th>
|
34 |
-
<?php if ( $deposit_enabled ): ?>
|
35 |
-
<th class="text-right"><?php _e( 'Deposit', 'bookly' ) ?></th>
|
36 |
-
<?php endif ?>
|
37 |
-
<th class="text-right"><?php _e( 'Price', 'bookly' ) ?></th>
|
38 |
-
</tr>
|
39 |
-
</thead>
|
40 |
-
<tbody>
|
41 |
-
<?php foreach ( $items as $item ) :
|
42 |
-
$extras_price = 0; ?>
|
43 |
-
<tr>
|
44 |
-
<td>
|
45 |
-
<?php if ( $item['number_of_persons'] > 1 ) echo $item['number_of_persons'] . ' × ' ?><?php echo $item['service_name'] ?>
|
46 |
-
<?php if ( ! empty ( $item['extras'] ) ) : ?>
|
47 |
-
<ul class="bookly-list list-dots">
|
48 |
-
<?php foreach ( $item['extras'] as $extra ) : ?>
|
49 |
-
<li><?php if ( $extra['quantity'] > 1 ) echo $extra['quantity'] . ' × ' ?><?php echo $extra['title'] ?></li>
|
50 |
-
<?php $extras_price += $extra['price'] * $extra['quantity'] ?>
|
51 |
-
<?php endforeach ?>
|
52 |
-
</ul>
|
53 |
-
<?php endif ?>
|
54 |
-
</td>
|
55 |
-
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDateTime( $item['appointment_date'] ) ?></td>
|
56 |
-
<td><?php echo $item['staff_name'] ?></td>
|
57 |
-
<?php $deposit = apply_filters( '
|
58 |
-
<?php if ( $deposit_enabled ) : ?>
|
59 |
-
<td class="text-right"><?php echo apply_filters( '
|
60 |
-
<?php endif ?>
|
61 |
-
<td class="text-right">
|
62 |
-
<?php $service_price = \BooklyLite\Lib\Utils\Common::formatPrice( $item['service_price'] ) ?>
|
63 |
-
<?php if ( $item['number_of_persons'] > 1 ) $service_price = $item['number_of_persons'] . ' × ' . $service_price ?>
|
64 |
-
<?php echo $service_price ?>
|
65 |
-
<ul class="bookly-list">
|
66 |
-
<?php foreach ( $item['extras'] as $extra ) : ?>
|
67 |
-
<li>
|
68 |
-
<?php printf( '%s%s%s',
|
69 |
-
( $item['number_of_persons'] > 1 ) ? $item['number_of_persons'] . ' × ' : '',
|
70 |
-
( $extra['quantity'] > 1 ) ? $extra['quantity'] . ' × ' : '',
|
71 |
-
\BooklyLite\Lib\Utils\Common::formatPrice( $extra['price'] )
|
72 |
-
) ?>
|
73 |
-
</li>
|
74 |
-
<?php $subtotal += $item['number_of_persons'] * $extra['price'] * $extra['quantity'] ?>
|
75 |
-
<?php endforeach ?>
|
76 |
-
</ul>
|
77 |
-
</td>
|
78 |
-
</tr>
|
79 |
-
<?php $subtotal += $item['number_of_persons'] * $item['service_price'] ?>
|
80 |
-
<?php $subtotal_deposit += $deposit ?>
|
81 |
-
<?php endforeach ?>
|
82 |
-
</tbody>
|
83 |
-
<tfoot>
|
84 |
-
<tr>
|
85 |
-
<th rowspan="3" style="border-left-color: white; border-bottom-color: white;"></th>
|
86 |
-
<th colspan="2"><?php _e( 'Subtotal', 'bookly' ) ?></th>
|
87 |
-
<?php if ( $deposit_enabled ) : ?>
|
88 |
-
<th class="text-right"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $subtotal_deposit ) ?></th>
|
89 |
-
<?php endif ?>
|
90 |
-
<th class="text-right"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $subtotal ) ?></th>
|
91 |
-
</tr>
|
92 |
-
<tr>
|
93 |
-
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>">
|
94 |
-
<?php _e( 'Discount', 'bookly' ) ?>
|
95 |
-
<?php if ( $payment['coupon'] ) : ?><div><small>(<?php echo $payment['coupon']['code'] ?>)</small></div><?php endif ?>
|
96 |
-
</th>
|
97 |
-
<th class="text-right">
|
98 |
-
<?php if ( $payment['coupon'] ) : ?>
|
99 |
-
<?php if ( $payment['coupon']['discount'] ) : ?>
|
100 |
-
<div>-<?php echo $payment['coupon']['discount'] ?>%</div>
|
101 |
-
<?php endif ?>
|
102 |
-
<?php if ( $payment['coupon']['deduction'] ) : ?>
|
103 |
-
<div><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( - $payment['coupon']['deduction'] ) ?></div>
|
104 |
-
<?php endif ?>
|
105 |
-
<?php else : ?>
|
106 |
-
<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 0 ) ?>
|
107 |
-
<?php endif ?>
|
108 |
-
</th>
|
109 |
-
</tr>
|
110 |
-
<tr>
|
111 |
-
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>"><?php _e( 'Total', 'bookly' ) ?></th>
|
112 |
-
<th class="text-right"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $payment['total'] ) ?></th>
|
113 |
-
</tr>
|
114 |
-
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
115 |
-
<tr>
|
116 |
-
<td rowspan="2" style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
117 |
-
<td colspan="<?php echo 2 + (int) $deposit_enabled ?>"><i><?php _e( 'Paid', 'bookly' ) ?></i></td>
|
118 |
-
<td class="text-right"><i><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $payment['paid'] ) ?></i></td>
|
119 |
-
</tr>
|
120 |
-
<tr>
|
121 |
-
<td colspan="<?php echo 2 + (int) $deposit_enabled ?>"><i><?php _e( 'Due', 'bookly' ) ?></i></td>
|
122 |
-
<td class="text-right"><i><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $payment['total'] - $payment['paid'] ) ?></i></td>
|
123 |
-
</tr>
|
124 |
-
<tr>
|
125 |
-
<td style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
126 |
-
<td colspan="<?php echo 3 + (int) $deposit_enabled ?>" class="text-right"><button type="button" class="btn btn-success ladda-button" id="bookly-complete-payment" data-spinner-size="40" data-style="zoom-in"><i><?php _e( 'Complete payment', 'bookly' ) ?></i></button></td>
|
127 |
-
</tr>
|
128 |
-
<?php endif ?>
|
129 |
-
</tfoot>
|
130 |
-
</table>
|
131 |
-
</div>
|
132 |
<?php endif ?>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
$subtotal = 0;
|
3 |
+
$subtotal_deposit = 0;
|
4 |
+
?>
|
5 |
+
<?php if ( $payment ) : ?>
|
6 |
+
<div class="table-responsive">
|
7 |
+
<table class="table table-bordered">
|
8 |
+
<thead>
|
9 |
+
<tr>
|
10 |
+
<th width="50%"><?php _e( 'Customer', 'bookly' ) ?></th>
|
11 |
+
<th width="50%"><?php _e( 'Payment', 'bookly' ) ?></th>
|
12 |
+
</tr>
|
13 |
+
</thead>
|
14 |
+
<tbody>
|
15 |
+
<tr>
|
16 |
+
<td><?php echo $payment['customer'] ?></td>
|
17 |
+
<td>
|
18 |
+
<div><?php _e( 'Date', 'bookly' ) ?>: <?php echo \BooklyLite\Lib\Utils\DateTime::formatDateTime( $payment['created'] ) ?></div>
|
19 |
+
<div><?php _e( 'Type', 'bookly' ) ?>: <?php echo \BooklyLite\Lib\Entities\Payment::typeToString( $payment['type'] ) ?></div>
|
20 |
+
<div><?php _e( 'Status', 'bookly' ) ?>: <?php echo \BooklyLite\Lib\Entities\Payment::statusToString( $payment['status'] ) ?></div>
|
21 |
+
</td>
|
22 |
+
</tr>
|
23 |
+
</tbody>
|
24 |
+
</table>
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<div class="table-responsive">
|
28 |
+
<table class="table table-bordered">
|
29 |
+
<thead>
|
30 |
+
<tr>
|
31 |
+
<th><?php _e( 'Service', 'bookly' ) ?></th>
|
32 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
33 |
+
<th><?php _e( 'Provider', 'bookly' ) ?></th>
|
34 |
+
<?php if ( $deposit_enabled ): ?>
|
35 |
+
<th class="text-right"><?php _e( 'Deposit', 'bookly' ) ?></th>
|
36 |
+
<?php endif ?>
|
37 |
+
<th class="text-right"><?php _e( 'Price', 'bookly' ) ?></th>
|
38 |
+
</tr>
|
39 |
+
</thead>
|
40 |
+
<tbody>
|
41 |
+
<?php foreach ( $items as $item ) :
|
42 |
+
$extras_price = 0; ?>
|
43 |
+
<tr>
|
44 |
+
<td>
|
45 |
+
<?php if ( $item['number_of_persons'] > 1 ) echo $item['number_of_persons'] . ' × ' ?><?php echo $item['service_name'] ?>
|
46 |
+
<?php if ( ! empty ( $item['extras'] ) ) : ?>
|
47 |
+
<ul class="bookly-list list-dots">
|
48 |
+
<?php foreach ( $item['extras'] as $extra ) : ?>
|
49 |
+
<li><?php if ( $extra['quantity'] > 1 ) echo $extra['quantity'] . ' × ' ?><?php echo $extra['title'] ?></li>
|
50 |
+
<?php $extras_price += $extra['price'] * $extra['quantity'] ?>
|
51 |
+
<?php endforeach ?>
|
52 |
+
</ul>
|
53 |
+
<?php endif ?>
|
54 |
+
</td>
|
55 |
+
<td><?php echo \BooklyLite\Lib\Utils\DateTime::formatDateTime( $item['appointment_date'] ) ?></td>
|
56 |
+
<td><?php echo $item['staff_name'] ?></td>
|
57 |
+
<?php $deposit = apply_filters( 'bookly_deposit_payments_get_deposit_amount', $item['number_of_persons'] * ( $item['service_price'] + $extras_price ), $item['deposit'], $item['number_of_persons'] ) ?>
|
58 |
+
<?php if ( $deposit_enabled ) : ?>
|
59 |
+
<td class="text-right"><?php echo apply_filters( 'bookly_deposit_payments_format_deposit', $deposit, $item['deposit'] ) ?></td>
|
60 |
+
<?php endif ?>
|
61 |
+
<td class="text-right">
|
62 |
+
<?php $service_price = \BooklyLite\Lib\Utils\Common::formatPrice( $item['service_price'] ) ?>
|
63 |
+
<?php if ( $item['number_of_persons'] > 1 ) $service_price = $item['number_of_persons'] . ' × ' . $service_price ?>
|
64 |
+
<?php echo $service_price ?>
|
65 |
+
<ul class="bookly-list">
|
66 |
+
<?php foreach ( $item['extras'] as $extra ) : ?>
|
67 |
+
<li>
|
68 |
+
<?php printf( '%s%s%s',
|
69 |
+
( $item['number_of_persons'] > 1 ) ? $item['number_of_persons'] . ' × ' : '',
|
70 |
+
( $extra['quantity'] > 1 ) ? $extra['quantity'] . ' × ' : '',
|
71 |
+
\BooklyLite\Lib\Utils\Common::formatPrice( $extra['price'] )
|
72 |
+
) ?>
|
73 |
+
</li>
|
74 |
+
<?php $subtotal += $item['number_of_persons'] * $extra['price'] * $extra['quantity'] ?>
|
75 |
+
<?php endforeach ?>
|
76 |
+
</ul>
|
77 |
+
</td>
|
78 |
+
</tr>
|
79 |
+
<?php $subtotal += $item['number_of_persons'] * $item['service_price'] ?>
|
80 |
+
<?php $subtotal_deposit += $deposit ?>
|
81 |
+
<?php endforeach ?>
|
82 |
+
</tbody>
|
83 |
+
<tfoot>
|
84 |
+
<tr>
|
85 |
+
<th rowspan="3" style="border-left-color: white; border-bottom-color: white;"></th>
|
86 |
+
<th colspan="2"><?php _e( 'Subtotal', 'bookly' ) ?></th>
|
87 |
+
<?php if ( $deposit_enabled ) : ?>
|
88 |
+
<th class="text-right"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $subtotal_deposit ) ?></th>
|
89 |
+
<?php endif ?>
|
90 |
+
<th class="text-right"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $subtotal ) ?></th>
|
91 |
+
</tr>
|
92 |
+
<tr>
|
93 |
+
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>">
|
94 |
+
<?php _e( 'Discount', 'bookly' ) ?>
|
95 |
+
<?php if ( $payment['coupon'] ) : ?><div><small>(<?php echo $payment['coupon']['code'] ?>)</small></div><?php endif ?>
|
96 |
+
</th>
|
97 |
+
<th class="text-right">
|
98 |
+
<?php if ( $payment['coupon'] ) : ?>
|
99 |
+
<?php if ( $payment['coupon']['discount'] ) : ?>
|
100 |
+
<div>-<?php echo $payment['coupon']['discount'] ?>%</div>
|
101 |
+
<?php endif ?>
|
102 |
+
<?php if ( $payment['coupon']['deduction'] ) : ?>
|
103 |
+
<div><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( - $payment['coupon']['deduction'] ) ?></div>
|
104 |
+
<?php endif ?>
|
105 |
+
<?php else : ?>
|
106 |
+
<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( 0 ) ?>
|
107 |
+
<?php endif ?>
|
108 |
+
</th>
|
109 |
+
</tr>
|
110 |
+
<tr>
|
111 |
+
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>"><?php _e( 'Total', 'bookly' ) ?></th>
|
112 |
+
<th class="text-right"><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $payment['total'] ) ?></th>
|
113 |
+
</tr>
|
114 |
+
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
115 |
+
<tr>
|
116 |
+
<td rowspan="2" style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
117 |
+
<td colspan="<?php echo 2 + (int) $deposit_enabled ?>"><i><?php _e( 'Paid', 'bookly' ) ?></i></td>
|
118 |
+
<td class="text-right"><i><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $payment['paid'] ) ?></i></td>
|
119 |
+
</tr>
|
120 |
+
<tr>
|
121 |
+
<td colspan="<?php echo 2 + (int) $deposit_enabled ?>"><i><?php _e( 'Due', 'bookly' ) ?></i></td>
|
122 |
+
<td class="text-right"><i><?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $payment['total'] - $payment['paid'] ) ?></i></td>
|
123 |
+
</tr>
|
124 |
+
<tr>
|
125 |
+
<td style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
126 |
+
<td colspan="<?php echo 3 + (int) $deposit_enabled ?>" class="text-right"><button type="button" class="btn btn-success ladda-button" id="bookly-complete-payment" data-spinner-size="40" data-style="zoom-in"><i><?php _e( 'Complete payment', 'bookly' ) ?></i></button></td>
|
127 |
+
</tr>
|
128 |
+
<?php endif ?>
|
129 |
+
</tfoot>
|
130 |
+
</table>
|
131 |
+
</div>
|
132 |
<?php endif ?>
|
backend/modules/payments/templates/index.php
CHANGED
@@ -1,89 +1,90 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-tbs" class="wrap">
|
3 |
-
<div class="bookly-tbs-body">
|
4 |
-
<div class="page-header text-right clearfix">
|
5 |
-
<div class="bookly-page-title">
|
6 |
-
<?php _e( 'Payments', 'bookly' ) ?>
|
7 |
-
</div>
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
<
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
<th><?php _e( '
|
61 |
-
<th><?php _e( '
|
62 |
-
<th><?php _e( '
|
63 |
-
<th><?php _e( '
|
64 |
-
<th><?php _e( '
|
65 |
-
<th><?php _e( '
|
66 |
-
<th><?php _e( '
|
67 |
-
<th
|
68 |
-
<th
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
<th colspan="
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
</div>
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-tbs" class="wrap">
|
3 |
+
<div class="bookly-tbs-body">
|
4 |
+
<div class="page-header text-right clearfix">
|
5 |
+
<div class="bookly-page-title">
|
6 |
+
<?php _e( 'Payments', 'bookly' ) ?>
|
7 |
+
</div>
|
8 |
+
<?php \BooklyLite\Backend\Modules\Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
9 |
+
</div>
|
10 |
+
<div class="panel panel-default bookly-main">
|
11 |
+
<div class="panel-body">
|
12 |
+
<div class="row">
|
13 |
+
<div class="col-md-4 col-lg-3">
|
14 |
+
<div class="bookly-margin-bottom-lg bookly-relative">
|
15 |
+
<button type="button" class="btn btn-block btn-default" id="bookly-filter-date" data-date="<?php echo date( 'Y-m-d', strtotime( '-30 day' ) ) ?> - <?php echo date( 'Y-m-d' ) ?>">
|
16 |
+
<i class="dashicons dashicons-calendar-alt"></i>
|
17 |
+
<span>
|
18 |
+
<?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( '-30 days' ) ?> - <?php echo \BooklyLite\Lib\Utils\DateTime::formatDate( 'today' ) ?>
|
19 |
+
</span>
|
20 |
+
</button>
|
21 |
+
</div>
|
22 |
+
</div>
|
23 |
+
<div class="col-md-2 col-lg-2">
|
24 |
+
<div class="form-group">
|
25 |
+
<select id="bookly-filter-type" class="form-control bookly-js-chosen-select" data-placeholder="<?php esc_attr_e( 'Type', 'bookly' ) ?>">
|
26 |
+
<option value="-1"></option>
|
27 |
+
<?php foreach ( $types as $type ) : ?>
|
28 |
+
<option value="<?php echo esc_attr( $type ) ?>">
|
29 |
+
<?php echo \BooklyLite\Lib\Entities\Payment::typeToString( $type ) ?>
|
30 |
+
</option>
|
31 |
+
<?php endforeach ?>
|
32 |
+
</select>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
<div class="col-md-3 col-lg-2">
|
36 |
+
<div class="form-group">
|
37 |
+
<select id="bookly-filter-staff" class="form-control bookly-js-chosen-select" data-placeholder="<?php esc_attr_e( 'Provider', 'bookly' ) ?>">
|
38 |
+
<option value="-1"></option>
|
39 |
+
<?php foreach ( $providers as $provider ) : ?>
|
40 |
+
<option value="<?php echo $provider['id'] ?>"><?php echo esc_html( $provider['full_name'] ) ?></option>
|
41 |
+
<?php endforeach ?>
|
42 |
+
</select>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
<div class="col-md-3 col-lg-2">
|
46 |
+
<div class="form-group">
|
47 |
+
<select id="bookly-filter-service" class="form-control bookly-js-chosen-select" data-placeholder="<?php esc_attr_e( 'Service', 'bookly' ) ?>">
|
48 |
+
<option value="-1"></option>
|
49 |
+
<?php foreach ( $services as $service ) : ?>
|
50 |
+
<option value="<?php echo $service['id'] ?>"><?php echo esc_html( $service['title'] ) ?></option>
|
51 |
+
<?php endforeach ?>
|
52 |
+
</select>
|
53 |
+
</div>
|
54 |
+
</div>
|
55 |
+
</div>
|
56 |
+
|
57 |
+
<table id="bookly-payments-list" class="table table-striped" width="100%">
|
58 |
+
<thead>
|
59 |
+
<tr>
|
60 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
61 |
+
<th><?php _e( 'Type', 'bookly' ) ?></th>
|
62 |
+
<th><?php _e( 'Customer', 'bookly' ) ?></th>
|
63 |
+
<th><?php _e( 'Provider', 'bookly' ) ?></th>
|
64 |
+
<th><?php _e( 'Service', 'bookly' ) ?></th>
|
65 |
+
<th><?php _e( 'Appointment Date', 'bookly' ) ?></th>
|
66 |
+
<th><?php _e( 'Amount', 'bookly' ) ?></th>
|
67 |
+
<th><?php _e( 'Status', 'bookly' ) ?></th>
|
68 |
+
<th></th>
|
69 |
+
<th width="16"><input type="checkbox" id="bookly-check-all"></th>
|
70 |
+
</tr>
|
71 |
+
</thead>
|
72 |
+
<tfoot>
|
73 |
+
<tr>
|
74 |
+
<th colspan="6"><div class="pull-right"><?php _e( 'Total', 'bookly' ) ?>:</div></th>
|
75 |
+
<th colspan="4"><span id="bookly-payment-total"></span></th>
|
76 |
+
</tr>
|
77 |
+
</tfoot>
|
78 |
+
</table>
|
79 |
+
<div class="text-right bookly-margin-top-lg">
|
80 |
+
<?php \BooklyLite\Lib\Utils\Common::deleteButton() ?>
|
81 |
+
</div>
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
|
85 |
+
<div ng-app="paymentDetails" ng-controller="paymentDetailsCtrl">
|
86 |
+
<div payment-details-dialog></div>
|
87 |
+
<?php \BooklyLite\Backend\Modules\Payments\Components::getInstance()->renderPaymentDetailsDialog() ?>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
backend/modules/services/Controller.php
CHANGED
@@ -1,288 +1,293 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Services;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Controller
|
8 |
-
* @package BooklyLite\Backend\Modules\Services
|
9 |
-
*/
|
10 |
-
class Controller extends Lib\Base\Controller
|
11 |
-
{
|
12 |
-
const page_slug = '
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Index page.
|
16 |
-
*/
|
17 |
-
public function index()
|
18 |
-
{
|
19 |
-
wp_enqueue_media();
|
20 |
-
$this->enqueueStyles( array(
|
21 |
-
'wp' => array( 'wp-color-picker' ),
|
22 |
-
'frontend' => array( 'css/ladda.min.css' ),
|
23 |
-
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css' ),
|
24 |
-
) );
|
25 |
-
|
26 |
-
$this->enqueueScripts( array(
|
27 |
-
'wp' => array( 'wp-color-picker' ),
|
28 |
-
'backend' => array(
|
29 |
-
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
30 |
-
'js/help.js' => array( 'jquery' ),
|
31 |
-
'js/alert.js' => array( 'jquery' ),
|
32 |
-
|
33 |
-
|
34 |
-
'
|
35 |
-
|
36 |
-
'js/
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
'
|
43 |
-
'
|
44 |
-
'
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
$
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
$
|
166 |
-
|
167 |
-
$
|
168 |
-
}
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
$staff_service
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
$
|
192 |
-
|
193 |
-
foreach ( $
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
}
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
$
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
->
|
263 |
-
->
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
|
|
|
|
|
|
|
|
|
|
288 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Services;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Services
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-services';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Index page.
|
16 |
+
*/
|
17 |
+
public function index()
|
18 |
+
{
|
19 |
+
wp_enqueue_media();
|
20 |
+
$this->enqueueStyles( array(
|
21 |
+
'wp' => array( 'wp-color-picker' ),
|
22 |
+
'frontend' => array( 'css/ladda.min.css' ),
|
23 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css' ),
|
24 |
+
) );
|
25 |
+
|
26 |
+
$this->enqueueScripts( array(
|
27 |
+
'wp' => array( 'wp-color-picker' ),
|
28 |
+
'backend' => array(
|
29 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
30 |
+
'js/help.js' => array( 'jquery' ),
|
31 |
+
'js/alert.js' => array( 'jquery' ),
|
32 |
+
'js/range_tools.js' => array( 'jquery' ),
|
33 |
+
),
|
34 |
+
'module' => array( 'js/service.js' => array( 'jquery-ui-sortable', 'jquery' ) ),
|
35 |
+
'frontend' => array(
|
36 |
+
'js/spin.min.js' => array( 'jquery' ),
|
37 |
+
'js/ladda.min.js' => array( 'bookly-spin.min.js', 'jquery' ),
|
38 |
+
)
|
39 |
+
) );
|
40 |
+
|
41 |
+
wp_localize_script( 'bookly-service.js', 'BooklyL10n', array(
|
42 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
43 |
+
'saved' => __( 'Settings saved.', 'bookly' ),
|
44 |
+
'selector' => array( 'nothing_selected' => __( 'No staff selected', 'bookly' ), ),
|
45 |
+
'limitations' => __( '<b class="h4">This function is disabled in the Lite version of Bookly.</b><br><br>If you find the plugin useful for your business please consider buying a licence for the full version.<br>It costs just $59 and for this money you will get many useful functions, lifetime free updates and excellent support!<br>More information can be found here', 'bookly' ) . ': <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
46 |
+
) );
|
47 |
+
|
48 |
+
// Allow add-ons to enqueue their assets.
|
49 |
+
do_action( 'bookly_enqueue_assets_for_services' );
|
50 |
+
|
51 |
+
$staff_collection = $this->getStaffCollection();
|
52 |
+
$category_collection = $this->getCategoryCollection();
|
53 |
+
$service_collection = $this->getServiceCollection();
|
54 |
+
$this->render( 'index', compact( 'staff_collection', 'category_collection', 'service_collection' ) );
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
*
|
59 |
+
*/
|
60 |
+
public function executeGetCategoryServices()
|
61 |
+
{
|
62 |
+
$this->setDataForServiceList();
|
63 |
+
wp_send_json_success( $this->render( '_list', array(), false ) );
|
64 |
+
}
|
65 |
+
|
66 |
+
/**
|
67 |
+
*
|
68 |
+
*/
|
69 |
+
public function executeCategoryForm()
|
70 |
+
{
|
71 |
+
if ( ! empty ( $_POST ) ) {
|
72 |
+
$form = new Forms\Category();
|
73 |
+
$form->bind( $this->getPostParameters() );
|
74 |
+
if ( $category = $form->save() ) {
|
75 |
+
$this->render( '_category_item', array( 'category' => $category->getFields() ) );
|
76 |
+
}
|
77 |
+
}
|
78 |
+
exit;
|
79 |
+
}
|
80 |
+
|
81 |
+
/**
|
82 |
+
* Update category.
|
83 |
+
*/
|
84 |
+
public function executeUpdateCategory()
|
85 |
+
{
|
86 |
+
$form = new Forms\Category();
|
87 |
+
$form->bind( $this->getPostParameters() );
|
88 |
+
$form->save();
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Update category position.
|
93 |
+
*/
|
94 |
+
public function executeUpdateCategoryPosition()
|
95 |
+
{
|
96 |
+
$category_sorts = $this->getParameter( 'position' );
|
97 |
+
foreach ( $category_sorts as $position => $category_id ) {
|
98 |
+
$category_sort = new Lib\Entities\Category();
|
99 |
+
$category_sort->load( $category_id );
|
100 |
+
$category_sort->set( 'position', $position );
|
101 |
+
$category_sort->save();
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
/**
|
106 |
+
* Update services position.
|
107 |
+
*/
|
108 |
+
public function executeUpdateServicesPosition()
|
109 |
+
{
|
110 |
+
$services_sorts = $this->getParameter( 'position' );
|
111 |
+
foreach ( $services_sorts as $position => $service_ids ) {
|
112 |
+
$services_sort = new Lib\Entities\Service();
|
113 |
+
$services_sort->load( $service_ids );
|
114 |
+
$services_sort->set( 'position', $position );
|
115 |
+
$services_sort->save();
|
116 |
+
}
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Delete category.
|
121 |
+
*/
|
122 |
+
public function executeDeleteCategory()
|
123 |
+
{
|
124 |
+
$category = new Lib\Entities\Category();
|
125 |
+
$category->set( 'id', $this->getParameter( 'id', 0 ) );
|
126 |
+
$category->delete();
|
127 |
+
}
|
128 |
+
|
129 |
+
public function executeAddService()
|
130 |
+
{
|
131 |
+
$form = new Forms\Service();
|
132 |
+
$form->bind( $this->getPostParameters() );
|
133 |
+
$form->getObject()->set( 'duration', Lib\Config::getTimeSlotLength() );
|
134 |
+
$service = $form->save();
|
135 |
+
$this->setDataForServiceList( $service->get( 'category_id' ) );
|
136 |
+
do_action( 'bookly_service_created', $service, $this->getPostParameters() );
|
137 |
+
wp_send_json_success( array( 'html' => $this->render( '_list', array(), false ), 'service_id' => $service->get( 'id' ) ) );
|
138 |
+
}
|
139 |
+
|
140 |
+
public function executeRemoveServices()
|
141 |
+
{
|
142 |
+
$service_ids = $this->getParameter( 'service_ids', array() );
|
143 |
+
if ( is_array( $service_ids ) && ! empty ( $service_ids ) ) {
|
144 |
+
Lib\Entities\Service::query( 's' )->delete()->whereIn( 's.id', $service_ids )->execute();
|
145 |
+
}
|
146 |
+
}
|
147 |
+
|
148 |
+
/**
|
149 |
+
* Update service parameters and assign staff
|
150 |
+
*/
|
151 |
+
public function executeUpdateService()
|
152 |
+
{
|
153 |
+
/** @var \wpdb $wpdb */
|
154 |
+
global $wpdb;
|
155 |
+
|
156 |
+
$form = new Forms\Service();
|
157 |
+
$form->bind( $this->getPostParameters() );
|
158 |
+
$service = $form->save();
|
159 |
+
|
160 |
+
$staff_ids = $this->getParameter( 'staff_ids', array() );
|
161 |
+
if ( empty( $staff_ids ) ) {
|
162 |
+
Lib\Entities\StaffService::query()->delete()->where( 'service_id', $service->get( 'id' ) )->execute();
|
163 |
+
} else {
|
164 |
+
Lib\Entities\StaffService::query()->delete()->where( 'service_id', $service->get( 'id' ) )->whereNotIn( 'staff_id', $staff_ids )->execute();
|
165 |
+
if ( $this->getParameter( 'update_staff', false ) ) {
|
166 |
+
$wpdb->update( Lib\Entities\StaffService::getTableName(), array( 'price' => $this->getParameter( 'price' ) ), array( 'service_id' => $this->getParameter( 'id' ) ) );
|
167 |
+
$wpdb->update( Lib\Entities\StaffService::getTableName(), array( 'capacity' => 1 ), array( 'service_id' => $this->getParameter( 'id' ) ) );
|
168 |
+
}
|
169 |
+
$service_staff_exists = Lib\Entities\StaffService::query()->select( 'staff_id' )->where( 'service_id', $service->get( 'id' ) )->fetchArray();
|
170 |
+
$service_staff = array();
|
171 |
+
foreach ( $service_staff_exists as $staff ) {
|
172 |
+
$service_staff[] = $staff['staff_id'];
|
173 |
+
}
|
174 |
+
foreach ( $staff_ids as $staff_id ) {
|
175 |
+
if ( ! in_array( $staff_id, $service_staff ) ) {
|
176 |
+
$staff_service = new Lib\Entities\StaffService();
|
177 |
+
$staff_service->set( 'staff_id', 1 );
|
178 |
+
$staff_service->set( 'service_id', $service->get( 'id' ) );
|
179 |
+
$staff_service->set( 'price', $service->get( 'price' ) );
|
180 |
+
$staff_service->set( 'capacity', 1 );
|
181 |
+
$staff_service->save();
|
182 |
+
}
|
183 |
+
}
|
184 |
+
}
|
185 |
+
|
186 |
+
do_action( 'bookly_update_service', $service, $this->getPostParameters() );
|
187 |
+
|
188 |
+
/** @var \BooklyServiceExtras\Lib\Entities\ServiceExtra[] $service_extras
|
189 |
+
* @var \BooklyServiceExtras\Lib\Entities\ServiceExtra[] $db_extras
|
190 |
+
*/
|
191 |
+
$service_extras = apply_filters( 'bookly_service_extras_find_by_service_id', array(), $service->get( 'id' ) );
|
192 |
+
$db_extras = array();
|
193 |
+
foreach ( $service_extras as $extra ) {
|
194 |
+
$db_extras[ $extra->get( 'id' ) ] = $extra;
|
195 |
+
}
|
196 |
+
$new_extras = array();
|
197 |
+
// Find id for new extras.
|
198 |
+
foreach ( $this->getParameter( 'extras', array() ) as $_post_id => $_post_extra ) {
|
199 |
+
if ( isset( $db_extras[ $_post_id ] ) ) {
|
200 |
+
unset( $db_extras[ $_post_id ] );
|
201 |
+
} else {
|
202 |
+
foreach ( $db_extras as $id => $extra ) {
|
203 |
+
if ( $extra->get( 'title' ) == $_post_extra['title']
|
204 |
+
&& $extra->get( 'price' ) == $_post_extra['price']
|
205 |
+
&& $extra->get( 'duration' ) == $_post_extra['duration']
|
206 |
+
) {
|
207 |
+
$new_extras[ $_post_id ] = $id;
|
208 |
+
unset( $db_extras[ $id ] );
|
209 |
+
break;
|
210 |
+
}
|
211 |
+
}
|
212 |
+
}
|
213 |
+
}
|
214 |
+
|
215 |
+
$price = Lib\Utils\Common::formatPrice( $service->get( 'price' ) );
|
216 |
+
if ( $service->get( 'type' ) == Lib\Entities\Service::TYPE_SIMPLE ) {
|
217 |
+
$nice_duration = Lib\Utils\DateTime::secondsToInterval( $service->get( 'duration' ) );
|
218 |
+
} else {
|
219 |
+
$nice_duration = sprintf( _n( '%d service', '%d services', count( json_decode( $service->get( 'sub_services' ), true ) ), 'bookly' ), count( json_decode( $service->get( 'sub_services' ), true ) ) );
|
220 |
+
}
|
221 |
+
|
222 |
+
wp_send_json_success( array( 'title' => $service->get( 'title' ), 'price' => $price, 'color' => $service->get( 'color' ), 'nice_duration' => $nice_duration, 'new_extras' => $new_extras ) );
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* @param int $category_id
|
227 |
+
*/
|
228 |
+
private function setDataForServiceList( $category_id = 0 )
|
229 |
+
{
|
230 |
+
if ( ! $category_id ) {
|
231 |
+
$category_id = $this->getParameter( 'category_id', 0 );
|
232 |
+
}
|
233 |
+
|
234 |
+
$this->service_collection = $this->getServiceCollection( $category_id );
|
235 |
+
$this->staff_collection = $this->getStaffCollection();
|
236 |
+
$this->category_collection = $this->getCategoryCollection();
|
237 |
+
}
|
238 |
+
|
239 |
+
/**
|
240 |
+
* @return array
|
241 |
+
*/
|
242 |
+
private function getCategoryCollection()
|
243 |
+
{
|
244 |
+
return Lib\Entities\Category::query()->sortBy( 'position' )->fetchArray();
|
245 |
+
}
|
246 |
+
|
247 |
+
/**
|
248 |
+
* @return array
|
249 |
+
*/
|
250 |
+
private function getStaffCollection()
|
251 |
+
{
|
252 |
+
return Lib\Entities\Staff::query()->fetchArray();
|
253 |
+
}
|
254 |
+
|
255 |
+
/**
|
256 |
+
* @param int $id
|
257 |
+
* @return array
|
258 |
+
*/
|
259 |
+
private function getServiceCollection( $id = 0 )
|
260 |
+
{
|
261 |
+
$services = Lib\Entities\Service::query( 's' )
|
262 |
+
->select( 's.*, COUNT(staff.id) AS total_staff, GROUP_CONCAT(DISTINCT staff.id) AS staff_ids' )
|
263 |
+
->leftJoin( 'StaffService', 'ss', 'ss.service_id = s.id' )
|
264 |
+
->leftJoin( 'Staff', 'staff', 'staff.id = ss.staff_id' )
|
265 |
+
->whereRaw( 's.category_id = %d OR !%d', array( $id, $id ) )
|
266 |
+
->groupBy( 's.id' )
|
267 |
+
->indexBy( 'id' )
|
268 |
+
->sortBy( 's.position' );
|
269 |
+
|
270 |
+
return $services->fetchArray();
|
271 |
+
}
|
272 |
+
|
273 |
+
public function executeUpdateExtraPosition()
|
274 |
+
{
|
275 |
+
do_action( 'bookly_service_extras_reorder', $this->getParameter( 'position' ) );
|
276 |
+
|
277 |
+
wp_send_json_success();
|
278 |
+
}
|
279 |
+
|
280 |
+
// Protected methods.
|
281 |
+
|
282 |
+
/**
|
283 |
+
* Override parent method to add 'wp_ajax_bookly_' prefix
|
284 |
+
* so current 'execute*' methods look nicer.
|
285 |
+
*
|
286 |
+
* @param string $prefix
|
287 |
+
*/
|
288 |
+
protected function registerWpActions( $prefix = '' )
|
289 |
+
{
|
290 |
+
parent::registerWpActions( 'wp_ajax_bookly_' );
|
291 |
+
}
|
292 |
+
|
293 |
}
|
backend/modules/services/forms/Category.php
CHANGED
@@ -1,22 +1,22 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Services\Forms;
|
3 |
-
|
4 |
-
use
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Category
|
8 |
-
* @package BooklyLite\Backend\Modules\Services\Forms
|
9 |
-
*/
|
10 |
-
class Category extends Lib\Base\Form
|
11 |
-
{
|
12 |
-
protected static $entity_class = 'Category';
|
13 |
-
|
14 |
-
/**
|
15 |
-
* Configure the form.
|
16 |
-
*/
|
17 |
-
public function configure()
|
18 |
-
{
|
19 |
-
$this->setFields( array( 'name' ) );
|
20 |
-
}
|
21 |
-
|
22 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Services\Forms;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Category
|
8 |
+
* @package BooklyLite\Backend\Modules\Services\Forms
|
9 |
+
*/
|
10 |
+
class Category extends Lib\Base\Form
|
11 |
+
{
|
12 |
+
protected static $entity_class = 'Category';
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Configure the form.
|
16 |
+
*/
|
17 |
+
public function configure()
|
18 |
+
{
|
19 |
+
$this->setFields( array( 'name' ) );
|
20 |
+
}
|
21 |
+
|
22 |
+
}
|
backend/modules/services/forms/Service.php
CHANGED
@@ -1,52 +1,75 @@
|
|
1 |
-
<?php
|
2 |
-
namespace BooklyLite\Backend\Modules\Services\Forms;
|
3 |
-
|
4 |
-
use BooklyLite\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Service
|
8 |
-
* @package BooklyLite\Backend\Modules\Services\Forms
|
9 |
-
*/
|
10 |
-
class Service extends Lib\Base\Form
|
11 |
-
{
|
12 |
-
protected static $entity_class = 'Service';
|
13 |
-
|
14 |
-
public function configure()
|
15 |
-
{
|
16 |
-
$
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
}
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Services\Forms;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Service
|
8 |
+
* @package BooklyLite\Backend\Modules\Services\Forms
|
9 |
+
*/
|
10 |
+
class Service extends Lib\Base\Form
|
11 |
+
{
|
12 |
+
protected static $entity_class = 'Service';
|
13 |
+
|
14 |
+
public function configure()
|
15 |
+
{
|
16 |
+
$fields = array(
|
17 |
+
'id',
|
18 |
+
'title',
|
19 |
+
'duration',
|
20 |
+
'price',
|
21 |
+
'category_id',
|
22 |
+
'color',
|
23 |
+
'capacity',
|
24 |
+
'padding_left',
|
25 |
+
'padding_right',
|
26 |
+
'info',
|
27 |
+
'type',
|
28 |
+
'sub_services',
|
29 |
+
'visibility',
|
30 |
+
);
|
31 |
+
if ( Lib\Config::isServiceScheduleEnabled() ) {
|
32 |
+
$fields[] = 'start_time';
|
33 |
+
$fields[] = 'end_time';
|
34 |
+
}
|
35 |
+
|
36 |
+
$this->setFields( $fields );
|
37 |
+
}
|
38 |
+
|
39 |
+
/**
|
40 |
+
* Bind values to form.
|
41 |
+
*
|
42 |
+
* @param array $_post
|
43 |
+
* @param array $files
|
44 |
+
*/
|
45 |
+
public function bind( array $_post, array $files = array() )
|
46 |
+
{
|
47 |
+
// Fields with NULL
|
48 |
+
foreach ( array( 'category_id', 'start_time', 'end_time' ) as $field_name ) {
|
49 |
+
if ( array_key_exists( $field_name, $_post ) && ! $_post[ $field_name ] ) {
|
50 |
+
$_post[ $field_name ] = null;
|
51 |
+
}
|
52 |
+
}
|
53 |
+
parent::bind( $_post, $files );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* @return \BooklyLite\Lib\Entities\Service
|
58 |
+
*/
|
59 |
+
public function save()
|
60 |
+
{
|
61 |
+
if ( $this->isNew() ) {
|
62 |
+
// When adding new service - set its color randomly.
|
63 |
+
$this->data['color'] = sprintf( '#%06X', mt_rand( 0, 0x64FFFF ) );
|
64 |
+
}
|
65 |
+
|
66 |
+
if ( $this->data['type'] == Lib\Entities\Service::TYPE_SIMPLE || ! array_key_exists( 'sub_services', $this->data ) || empty( $this->data['sub_services'] ) ) {
|
67 |
+
$this->data['sub_services'] = '[]';
|
68 |
+
} elseif ( is_array( $this->data['sub_services'] ) ) {
|
69 |
+
$this->data['sub_services'] = json_encode( (array) $this->data['sub_services'] );
|
70 |
+
}
|
71 |
+
|
72 |
+
return parent::save();
|
73 |
+
}
|
74 |
+
|
75 |
}
|
backend/modules/services/resources/js/service.js
CHANGED
@@ -1,511 +1,511 @@
|
|
1 |
-
jQuery(function($) {
|
2 |
-
var $no_result = $('#bookly-services-wrapper .no-result');
|
3 |
-
// Remember user choice in the modal dialog.
|
4 |
-
var update_staff_choice = null,
|
5 |
-
$new_category_popover = $('#bookly-new-category'),
|
6 |
-
$new_category_form = $('#new-category-form'),
|
7 |
-
$new_category_name = $('#bookly-category-name');
|
8 |
-
|
9 |
-
$new_category_popover.popover({
|
10 |
-
html: true,
|
11 |
-
placement: 'bottom',
|
12 |
-
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
13 |
-
content: $new_category_form.show().detach(),
|
14 |
-
trigger: 'manual'
|
15 |
-
}).on('click', function () {
|
16 |
-
$(this).popover('toggle');
|
17 |
-
}).on('shown.bs.popover', function () {
|
18 |
-
// focus input
|
19 |
-
$new_category_name.focus();
|
20 |
-
}).on('hidden.bs.popover', function (e) {
|
21 |
-
//clear input
|
22 |
-
$new_category_name.val('');
|
23 |
-
});
|
24 |
-
|
25 |
-
// Save new category.
|
26 |
-
$new_category_form.on('submit', function() {
|
27 |
-
var data = $(this).serialize();
|
28 |
-
|
29 |
-
$.post(ajaxurl, data, function(response) {
|
30 |
-
$('#bookly-category-item-list').append(response);
|
31 |
-
var $new_category = $('.bookly-category-item:last');
|
32 |
-
// add created category to services
|
33 |
-
$('select[name="category_id"]').append('<option value="' + $new_category.data('category-id') + '">' + $new_category.find('input').val() + '</option>');
|
34 |
-
});
|
35 |
-
$new_category_popover.popover('hide');
|
36 |
-
return false;
|
37 |
-
});
|
38 |
-
|
39 |
-
// Cancel button.
|
40 |
-
$new_category_form.on('click', 'button[type="button"]', function (e) {
|
41 |
-
$new_category_popover.popover('hide');
|
42 |
-
});
|
43 |
-
|
44 |
-
// Categories list delegated events.
|
45 |
-
$('#bookly-categories-list')
|
46 |
-
|
47 |
-
// On category item click.
|
48 |
-
.on('click', '.bookly-category-item', function(e) {
|
49 |
-
if ($(e.target).is('.bookly-js-handle')) return;
|
50 |
-
$('#ab-services-list').html('<div class="bookly-loading"></div>');
|
51 |
-
var $clicked = $(this);
|
52 |
-
|
53 |
-
$.get(ajaxurl, {action:'
|
54 |
-
if ( response.success ) {
|
55 |
-
$('.bookly-category-item').not($clicked).removeClass('active');
|
56 |
-
$clicked.addClass('active');
|
57 |
-
$('.bookly-category-title').text($clicked.text());
|
58 |
-
refreshList(response.data, 0);
|
59 |
-
}
|
60 |
-
});
|
61 |
-
})
|
62 |
-
|
63 |
-
// On edit category click.
|
64 |
-
.on('click', '.bookly-js-edit', function(e) {
|
65 |
-
// Keep category item click from being executed.
|
66 |
-
e.stopPropagation();
|
67 |
-
// Prevent navigating to '#'.
|
68 |
-
e.preventDefault();
|
69 |
-
var $this = $(this).closest('.bookly-category-item');
|
70 |
-
$this.find('.displayed-value').hide();
|
71 |
-
$this.find('input').show().focus();
|
72 |
-
})
|
73 |
-
|
74 |
-
// On blur save changes.
|
75 |
-
.on('blur', 'input', function() {
|
76 |
-
var $this = $(this),
|
77 |
-
$item = $this.closest('.bookly-category-item'),
|
78 |
-
field = $this.attr('name'),
|
79 |
-
value = $this.val(),
|
80 |
-
id = $item.data('category-id'),
|
81 |
-
data = { action: '
|
82 |
-
data[field] = value;
|
83 |
-
$.post(ajaxurl, data, function(response) {
|
84 |
-
// Hide input field.
|
85 |
-
$item.find('input').hide();
|
86 |
-
$item.find('.displayed-value').show();
|
87 |
-
// Show modified category name.
|
88 |
-
$item.find('.displayed-value').text(value);
|
89 |
-
// update edited category's name for services
|
90 |
-
$('select[name="category_id"] option[value="' + id + '"]').text(value);
|
91 |
-
});
|
92 |
-
})
|
93 |
-
|
94 |
-
// On press Enter save changes.
|
95 |
-
.on('keypress', 'input', function (e) {
|
96 |
-
var code = e.keyCode || e.which;
|
97 |
-
if (code == 13) {
|
98 |
-
$(this).blur();
|
99 |
-
}
|
100 |
-
})
|
101 |
-
|
102 |
-
// On delete category click.
|
103 |
-
.on('click', '.bookly-js-delete', function(e) {
|
104 |
-
// Keep category item click from being executed.
|
105 |
-
e.stopPropagation();
|
106 |
-
// Prevent navigating to '#'.
|
107 |
-
e.preventDefault();
|
108 |
-
// Ask user if he is sure.
|
109 |
-
if (confirm(BooklyL10n.are_you_sure)) {
|
110 |
-
var $item = $(this).closest('.bookly-category-item');
|
111 |
-
var data = { action: '
|
112 |
-
$.post(ajaxurl, data, function(response) {
|
113 |
-
// Remove category item from Services
|
114 |
-
$('select[name="category_id"] option[value="' + $item.data('category-id') + '"]').remove();
|
115 |
-
// Remove category item from DOM.
|
116 |
-
$item.remove();
|
117 |
-
if ($item.is('.active')) {
|
118 |
-
$('.bookly-js-all-services').click();
|
119 |
-
}
|
120 |
-
});
|
121 |
-
}
|
122 |
-
})
|
123 |
-
|
124 |
-
.on('click', 'input', function(e) {
|
125 |
-
e.stopPropagation();
|
126 |
-
});
|
127 |
-
|
128 |
-
// Services list delegated events.
|
129 |
-
$('#bookly-services-wrapper')
|
130 |
-
// On click on 'Add Service' button.
|
131 |
-
.on('click', '.add-service', function(e) {
|
132 |
-
e.preventDefault();
|
133 |
-
var ladda =
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
$panel.find('.bookly-
|
177 |
-
}
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
$
|
208 |
-
}
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
});
|
246 |
-
}
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
$panel.find('.bookly-js-service-
|
256 |
-
$
|
257 |
-
$
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
$('
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
data
|
303 |
-
});
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
data
|
329 |
-
});
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
}
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
$
|
410 |
-
|
411 |
-
|
412 |
-
$
|
413 |
-
|
414 |
-
|
415 |
-
$panel.
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
$
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
});
|
497 |
-
|
498 |
-
$(document).on('click', '.bookly-js-collapse .extra-delete', function (e) {
|
499 |
-
e.preventDefault();
|
500 |
-
e.stopPropagation();
|
501 |
-
if (confirm(BooklyL10n.are_you_sure)) {
|
502 |
-
var extra = $(this).parents('.extra');
|
503 |
-
if (!extra.hasClass('new')) {
|
504 |
-
$.post(ajaxurl, {action: 'bookly_service_extras_delete_service_extra', id: extra.data('extra-id')}, function () {
|
505 |
-
});
|
506 |
-
}
|
507 |
-
extra.remove();
|
508 |
-
}
|
509 |
-
});
|
510 |
-
/*</Extras>*/
|
511 |
-
});
|
1 |
+
jQuery(function($) {
|
2 |
+
var $no_result = $('#bookly-services-wrapper .no-result');
|
3 |
+
// Remember user choice in the modal dialog.
|
4 |
+
var update_staff_choice = null,
|
5 |
+
$new_category_popover = $('#bookly-new-category'),
|
6 |
+
$new_category_form = $('#new-category-form'),
|
7 |
+
$new_category_name = $('#bookly-category-name');
|
8 |
+
|
9 |
+
$new_category_popover.popover({
|
10 |
+
html: true,
|
11 |
+
placement: 'bottom',
|
12 |
+
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
13 |
+
content: $new_category_form.show().detach(),
|
14 |
+
trigger: 'manual'
|
15 |
+
}).on('click', function () {
|
16 |
+
$(this).popover('toggle');
|
17 |
+
}).on('shown.bs.popover', function () {
|
18 |
+
// focus input
|
19 |
+
$new_category_name.focus();
|
20 |
+
}).on('hidden.bs.popover', function (e) {
|
21 |
+
//clear input
|
22 |
+
$new_category_name.val('');
|
23 |
+
});
|
24 |
+
|
25 |
+
// Save new category.
|
26 |
+
$new_category_form.on('submit', function() {
|
27 |
+
var data = $(this).serialize();
|
28 |
+
|
29 |
+
$.post(ajaxurl, data, function(response) {
|
30 |
+
$('#bookly-category-item-list').append(response);
|
31 |
+
var $new_category = $('.bookly-category-item:last');
|
32 |
+
// add created category to services
|
33 |
+
$('select[name="category_id"]').append('<option value="' + $new_category.data('category-id') + '">' + $new_category.find('input').val() + '</option>');
|
34 |
+
});
|
35 |
+
$new_category_popover.popover('hide');
|
36 |
+
return false;
|
37 |
+
});
|
38 |
+
|
39 |
+
// Cancel button.
|
40 |
+
$new_category_form.on('click', 'button[type="button"]', function (e) {
|
41 |
+
$new_category_popover.popover('hide');
|
42 |
+
});
|
43 |
+
|
44 |
+
// Categories list delegated events.
|
45 |
+
$('#bookly-categories-list')
|
46 |
+
|
47 |
+
// On category item click.
|
48 |
+
.on('click', '.bookly-category-item', function(e) {
|
49 |
+
if ($(e.target).is('.bookly-js-handle')) return;
|
50 |
+
$('#ab-services-list').html('<div class="bookly-loading"></div>');
|
51 |
+
var $clicked = $(this);
|
52 |
+
|
53 |
+
$.get(ajaxurl, {action:'bookly_get_category_services', category_id: $clicked.data('category-id')}, function(response) {
|
54 |
+
if ( response.success ) {
|
55 |
+
$('.bookly-category-item').not($clicked).removeClass('active');
|
56 |
+
$clicked.addClass('active');
|
57 |
+
$('.bookly-category-title').text($clicked.text());
|
58 |
+
refreshList(response.data, 0);
|
59 |
+
}
|
60 |
+
});
|
61 |
+
})
|
62 |
+
|
63 |
+
// On edit category click.
|
64 |
+
.on('click', '.bookly-js-edit', function(e) {
|
65 |
+
// Keep category item click from being executed.
|
66 |
+
e.stopPropagation();
|
67 |
+
// Prevent navigating to '#'.
|
68 |
+
e.preventDefault();
|
69 |
+
var $this = $(this).closest('.bookly-category-item');
|
70 |
+
$this.find('.displayed-value').hide();
|
71 |
+
$this.find('input').show().focus();
|
72 |
+
})
|
73 |
+
|
74 |
+
// On blur save changes.
|
75 |
+
.on('blur', 'input', function() {
|
76 |
+
var $this = $(this),
|
77 |
+
$item = $this.closest('.bookly-category-item'),
|
78 |
+
field = $this.attr('name'),
|
79 |
+
value = $this.val(),
|
80 |
+
id = $item.data('category-id'),
|
81 |
+
data = { action: 'bookly_update_category', id: id };
|
82 |
+
data[field] = value;
|
83 |
+
$.post(ajaxurl, data, function(response) {
|
84 |
+
// Hide input field.
|
85 |
+
$item.find('input').hide();
|
86 |
+
$item.find('.displayed-value').show();
|
87 |
+
// Show modified category name.
|
88 |
+
$item.find('.displayed-value').text(value);
|
89 |
+
// update edited category's name for services
|
90 |
+
$('select[name="category_id"] option[value="' + id + '"]').text(value);
|
91 |
+
});
|
92 |
+
})
|
93 |
+
|
94 |
+
// On press Enter save changes.
|
95 |
+
.on('keypress', 'input', function (e) {
|
96 |
+
var code = e.keyCode || e.which;
|
97 |
+
if (code == 13) {
|
98 |
+
$(this).blur();
|
99 |
+
}
|
100 |
+
})
|
101 |
+
|
102 |
+
// On delete category click.
|
103 |
+
.on('click', '.bookly-js-delete', function(e) {
|
104 |
+
// Keep category item click from being executed.
|
105 |
+
e.stopPropagation();
|
106 |
+
// Prevent navigating to '#'.
|
107 |
+
e.preventDefault();
|
108 |
+
// Ask user if he is sure.
|
109 |
+
if (confirm(BooklyL10n.are_you_sure)) {
|
110 |
+
var $item = $(this).closest('.bookly-category-item');
|
111 |
+
var data = { action: 'bookly_delete_category', id: $item.data('category-id') };
|
112 |
+
$.post(ajaxurl, data, function(response) {
|
113 |
+
// Remove category item from Services
|
114 |
+
$('select[name="category_id"] option[value="' + $item.data('category-id') + '"]').remove();
|
115 |
+
// Remove category item from DOM.
|
116 |
+
$item.remove();
|
117 |
+
if ($item.is('.active')) {
|
118 |
+
$('.bookly-js-all-services').click();
|
119 |
+
}
|
120 |
+
});
|
121 |
+
}
|
122 |
+
})
|
123 |
+
|
124 |
+
.on('click', 'input', function(e) {
|
125 |
+
e.stopPropagation();
|
126 |
+
});
|
127 |
+
|
128 |
+
// Services list delegated events.
|
129 |
+
$('#bookly-services-wrapper')
|
130 |
+
// On click on 'Add Service' button.
|
131 |
+
.on('click', '.add-service', function(e) {
|
132 |
+
e.preventDefault();
|
133 |
+
var ladda = rangeTools.ladda(this);
|
134 |
+
var selected_category_id = $('#bookly-categories-list .active').data('category-id'),
|
135 |
+
data = { action: 'bookly_add_service' };
|
136 |
+
if (selected_category_id) {
|
137 |
+
data['category_id'] = selected_category_id;
|
138 |
+
}
|
139 |
+
$.post(ajaxurl, data, function(response) {
|
140 |
+
refreshList(response.data.html, response.data.service_id);
|
141 |
+
ladda.stop();
|
142 |
+
});
|
143 |
+
})
|
144 |
+
// On click on 'Delete' button.
|
145 |
+
.on('click', '#bookly-delete', function(e) {
|
146 |
+
if (confirm(BooklyL10n.are_you_sure)) {
|
147 |
+
var ladda = rangeTools.ladda(this);
|
148 |
+
|
149 |
+
var $for_delete = $('.service-checker:checked'),
|
150 |
+
data = { action: 'bookly_remove_services' },
|
151 |
+
services = [],
|
152 |
+
$panels = [];
|
153 |
+
|
154 |
+
$for_delete.each(function(){
|
155 |
+
var panel = $(this).parents('.bookly-js-collapse');
|
156 |
+
$panels.push(panel);
|
157 |
+
services.push(this.value);
|
158 |
+
});
|
159 |
+
data['service_ids[]'] = services;
|
160 |
+
$.post(ajaxurl, data, function() {
|
161 |
+
ladda.stop();
|
162 |
+
$.each($panels.reverse(), function (index) {
|
163 |
+
$(this).delay(500 * index).fadeOut(200, function () {
|
164 |
+
$(this).remove();
|
165 |
+
});
|
166 |
+
});
|
167 |
+
});
|
168 |
+
}
|
169 |
+
})
|
170 |
+
|
171 |
+
.on('change', 'input.bookly-check-all-entities, input.bookly-js-check-entity', function () {
|
172 |
+
var $panel = $(this).parents('.bookly-js-collapse');
|
173 |
+
if ($(this).hasClass('bookly-check-all-entities')) {
|
174 |
+
$panel.find('.bookly-js-check-entity').prop('checked', $(this).prop('checked'));
|
175 |
+
} else {
|
176 |
+
$panel.find('.bookly-check-all-entities').prop('checked', $panel.find('.bookly-js-check-entity:not(:checked)').length == 0);
|
177 |
+
}
|
178 |
+
updateStaffButton($panel);
|
179 |
+
});
|
180 |
+
|
181 |
+
// Modal window events.
|
182 |
+
var $modal = $('#ab-staff-update');
|
183 |
+
$modal
|
184 |
+
.on('click', '.ab-yes', function() {
|
185 |
+
$modal.modal('hide');
|
186 |
+
if ( $('#ab-remember-my-choice').prop('checked') ) {
|
187 |
+
update_staff_choice = true;
|
188 |
+
}
|
189 |
+
submitServiceFrom($modal.data('input'),true);
|
190 |
+
})
|
191 |
+
.on('click', '.ab-no', function() {
|
192 |
+
if ( $('#ab-remember-my-choice').prop('checked') ) {
|
193 |
+
update_staff_choice = false;
|
194 |
+
}
|
195 |
+
submitServiceFrom($modal.data('input'),false);
|
196 |
+
});
|
197 |
+
|
198 |
+
function refreshList(response,service_id) {
|
199 |
+
var $list = $('#ab-services-list');
|
200 |
+
$list.html(response);
|
201 |
+
if (response.indexOf('panel') >= 0) {
|
202 |
+
$no_result.hide();
|
203 |
+
makeServicesSortable();
|
204 |
+
onCollapseInitChildren();
|
205 |
+
$list.booklyHelp();
|
206 |
+
} else {
|
207 |
+
$no_result.show();
|
208 |
+
}
|
209 |
+
$('#service_' + service_id).collapse('show');
|
210 |
+
$('#service_' + service_id).find('input[name=title]').focus();
|
211 |
+
}
|
212 |
+
|
213 |
+
function initColorPicker($jquery_collection) {
|
214 |
+
$jquery_collection.each(function(){
|
215 |
+
$(this).data('last-color', $(this).val());
|
216 |
+
});
|
217 |
+
$jquery_collection.wpColorPicker({
|
218 |
+
width: 200
|
219 |
+
});
|
220 |
+
}
|
221 |
+
|
222 |
+
$('#ab-services-list').on('change', '[name=capacity]', function(){
|
223 |
+
if ($(this).val() > 1) {
|
224 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
225 |
+
$(this).val('1').prop('readonly',true);
|
226 |
+
}
|
227 |
+
}).on('change', '[name=padding_left],[name=padding_right]', function(){
|
228 |
+
if ($(this).val() > 0) {
|
229 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
230 |
+
$(this).val('0').prop('readonly', true);
|
231 |
+
$(this).find('option:gt(0)').prop('disabled', true);
|
232 |
+
}
|
233 |
+
});
|
234 |
+
|
235 |
+
function submitServiceFrom($form, update_staff) {
|
236 |
+
$form.find('input[name=update_staff]').val(update_staff ? 1 : 0);
|
237 |
+
var ladda = rangeTools.ladda($form.find('button.ajax-service-send[type=submit]').get(0)),
|
238 |
+
data = $form.serializeArray();
|
239 |
+
if ($form.find('input[name=type]:checked').val() == 'compound') {
|
240 |
+
$form.find('li[data-sub-service-id]').each(function () {
|
241 |
+
data.push({name: 'sub_services[]', value: $(this).data('sub-service-id')});
|
242 |
+
});
|
243 |
+
} else {
|
244 |
+
data.push({name: 'type', value: 'simple'});
|
245 |
+
data.push({name: 'sub_services[]', value: false});
|
246 |
+
}
|
247 |
+
$.post(ajaxurl, data, function (response) {
|
248 |
+
if (response.success) {
|
249 |
+
var $panel = $form.parents('.bookly-js-collapse'),
|
250 |
+
$price = $form.find('[name=price]'),
|
251 |
+
$capacity = $form.find('[name=capacity]');
|
252 |
+
$panel.find('.bookly-js-service-color').css('background-color', response.data.color);
|
253 |
+
$panel.find('.bookly-js-service-title').html(response.data.title);
|
254 |
+
$panel.find('.bookly-js-service-duration').html(response.data.nice_duration);
|
255 |
+
$panel.find('.bookly-js-service-price').html(response.data.price);
|
256 |
+
$price.data('last_value', $price.val());
|
257 |
+
$capacity.data('last_value', $capacity.val());
|
258 |
+
booklyAlert({success : [BooklyL10n.saved]});
|
259 |
+
$.each(response.data.new_extras, function (front_id, real_id) {
|
260 |
+
var $li = $('li.extra.new[data-extra-id="' + front_id + '"]', $form);
|
261 |
+
$('[name^="extras"]', $li).each(function () {
|
262 |
+
var name = $(this).attr('name');
|
263 |
+
name = name.replace('[' + front_id + ']', '[' + real_id + ']');
|
264 |
+
$(this).attr('name', name);
|
265 |
+
});
|
266 |
+
$li.data('extra-id', real_id).removeClass('new');
|
267 |
+
$li.append('<input type="hidden" value="' + real_id + '" name="extras[' + real_id + '][id]">');
|
268 |
+
});
|
269 |
+
} else {
|
270 |
+
booklyAlert({error: [response.data.message]});
|
271 |
+
}
|
272 |
+
}, 'json').always(function() {
|
273 |
+
ladda.stop();
|
274 |
+
});
|
275 |
+
}
|
276 |
+
|
277 |
+
function updateStaffButton($panel) {
|
278 |
+
var staff_checked = $panel.find('.bookly-js-check-entity:checked').length;
|
279 |
+
if (staff_checked == 0) {
|
280 |
+
$panel.find('.bookly-entity-counter').text(BooklyL10n.selector.nothing_selected);
|
281 |
+
} else if (staff_checked == 1) {
|
282 |
+
$panel.find('.bookly-entity-counter').text($panel.find('.bookly-js-check-entity:checked').data('staff_name'));
|
283 |
+
} else {
|
284 |
+
$panel.find('.bookly-entity-counter').text(staff_checked + '/' + $panel.find('.bookly-js-check-entity').length);
|
285 |
+
}
|
286 |
+
}
|
287 |
+
|
288 |
+
var $category = $('#bookly-category-item-list');
|
289 |
+
$category.sortable({
|
290 |
+
axis : 'y',
|
291 |
+
handle : '.bookly-js-handle',
|
292 |
+
update : function( event, ui ) {
|
293 |
+
var data = [];
|
294 |
+
$category.children('li').each(function() {
|
295 |
+
var $this = $(this);
|
296 |
+
var position = $this.data('category-id');
|
297 |
+
data.push(position);
|
298 |
+
});
|
299 |
+
$.ajax({
|
300 |
+
type : 'POST',
|
301 |
+
url : ajaxurl,
|
302 |
+
data : { action: 'bookly_update_category_position', position: data }
|
303 |
+
});
|
304 |
+
}
|
305 |
+
});
|
306 |
+
|
307 |
+
function makeServicesSortable() {
|
308 |
+
if ($('.bookly-js-all-services').hasClass('active')) {
|
309 |
+
var $services = $('#services_list'),
|
310 |
+
fixHelper = function(e, ui) {
|
311 |
+
ui.children().each(function() {
|
312 |
+
$(this).width($(this).width());
|
313 |
+
});
|
314 |
+
return ui;
|
315 |
+
};
|
316 |
+
$services.sortable({
|
317 |
+
helper : fixHelper,
|
318 |
+
axis : 'y',
|
319 |
+
handle : '.bookly-js-handle',
|
320 |
+
update : function( event, ui ) {
|
321 |
+
var data = [];
|
322 |
+
$services.children('div').each(function() {
|
323 |
+
data.push($(this).data('service-id'));
|
324 |
+
});
|
325 |
+
$.ajax({
|
326 |
+
type : 'POST',
|
327 |
+
url : ajaxurl,
|
328 |
+
data : { action: 'bookly_update_services_position', position: data }
|
329 |
+
});
|
330 |
+
}
|
331 |
+
});
|
332 |
+
} else {
|
333 |
+
$('#services_list .bookly-js-handle').hide();
|
334 |
+
}
|
335 |
+
}
|
336 |
+
|
337 |
+
function onCollapseInitChildren() {
|
338 |
+
$('.panel-collapse').on('show.bs.collapse.bookly', function () {
|
339 |
+
var $panel = $(this);
|
340 |
+
var $sub_services = $('.ab--service-list', $panel);
|
341 |
+
initColorPicker($panel.find('.bookly-js-color-picker'));
|
342 |
+
$('input[name=type]', $panel).on( 'click', function(){
|
343 |
+
if ($(this).val() == 'simple') {
|
344 |
+
$('.ab--for-simple', $panel).show();
|
345 |
+
$('.ab--for-compound', $panel).hide();
|
346 |
+
} else {
|
347 |
+
$('.ab--for-simple', $panel).hide();
|
348 |
+
$('.ab--for-compound', $panel).show();
|
349 |
+
}
|
350 |
+
});
|
351 |
+
$('input[name=type]:checked', $panel).trigger('click');
|
352 |
+
|
353 |
+
$('[data-toggle="popover"]').popover({
|
354 |
+
html: true,
|
355 |
+
placement: 'top',
|
356 |
+
trigger: 'hover',
|
357 |
+
template: '<div class="popover bookly-font-xs" style="width: 220px" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
|
358 |
+
});
|
359 |
+
|
360 |
+
var initSubServicesLi = function ($li) {
|
361 |
+
$("option[value=" + $li.data('sub-service-id') + "]", $sub_services).prop('disabled', true);
|
362 |
+
$('.ab--sub-service-remove', $li).click(function () {
|
363 |
+
$('li.list-group-item[data-sub-service-id="' + $li.data('sub-service-id') + '"]', $panel).remove();
|
364 |
+
$("option[value=" + $li.data('sub-service-id') + "]", $sub_services).prop('disabled', false);
|
365 |
+
});
|
366 |
+
};
|
367 |
+
|
368 |
+
$('.ab--sub-services li.list-group-item[data-sub-service-id]', $panel).each(function () {
|
369 |
+
initSubServicesLi($(this));
|
370 |
+
});
|
371 |
+
|
372 |
+
$sub_services.on('change', function () {
|
373 |
+
if ($(this).val()) {
|
374 |
+
var $li = $('.ab--templates.services .template_' + $sub_services.val() + ' li').clone();
|
375 |
+
$li.insertBefore($(this).parents('li'));
|
376 |
+
initSubServicesLi($li);
|
377 |
+
$(this).val(0);
|
378 |
+
}
|
379 |
+
});
|
380 |
+
|
381 |
+
$('.ab--sub-services', $panel).sortable({axis: 'y', items: "[data-sub-service-id]"});
|
382 |
+
|
383 |
+
updateStaffButton($(this).parents('.bookly-js-collapse'));
|
384 |
+
|
385 |
+
$panel.find('.ajax-service-send').on('click', function (e) {
|
386 |
+
e.preventDefault();
|
387 |
+
var $form = $(this).parents('form'),
|
388 |
+
show_modal = false;
|
389 |
+
if(update_staff_choice === null) {
|
390 |
+
$('.ab-question', $form).each(function () {
|
391 |
+
if ($(this).data('last_value') != $(this).val()) {
|
392 |
+
show_modal = true;
|
393 |
+
}
|
394 |
+
});
|
395 |
+
}
|
396 |
+
if (show_modal) {
|
397 |
+
$modal.data('input', $form).modal('show');
|
398 |
+
} else {
|
399 |
+
submitServiceFrom($form, update_staff_choice);
|
400 |
+
}
|
401 |
+
});
|
402 |
+
|
403 |
+
$panel.find('.js-reset').on('click', function () {
|
404 |
+
$(this).parents('form').trigger('reset');
|
405 |
+
var $color = $(this).parents('form').find('.wp-color-picker'),
|
406 |
+
$panel = $(this).parents('.bookly-js-collapse');
|
407 |
+
$color.val($color.data('last-color')).trigger('change');
|
408 |
+
$panel.find('.parent-range-start').trigger('change');
|
409 |
+
updateStaffButton($panel);
|
410 |
+
});
|
411 |
+
$panel.find('.ab-question').each(function () {
|
412 |
+
$(this).data('last_value', $(this).val());
|
413 |
+
});
|
414 |
+
$panel.unbind('show.bs.collapse.bookly');
|
415 |
+
$(document.body).trigger( 'service_list.service_expand', [ $panel, $panel.closest('.panel').data('service-id') ] );
|
416 |
+
});
|
417 |
+
}
|
418 |
+
makeServicesSortable();
|
419 |
+
onCollapseInitChildren();
|
420 |
+
|
421 |
+
/*<Extras>*/
|
422 |
+
$('.extras-container').sortable({
|
423 |
+
axis : 'y',
|
424 |
+
handle : '.bookly-js-handle',
|
425 |
+
update : function( event, ui ) {
|
426 |
+
var data = [];
|
427 |
+
$(this).find('.extra').each(function() {
|
428 |
+
data.push($(this).data('extra-id'));
|
429 |
+
});
|
430 |
+
$.ajax({
|
431 |
+
type : 'POST',
|
432 |
+
url : ajaxurl,
|
433 |
+
data : { action: 'bookly_update_extra_position', position: data }
|
434 |
+
});
|
435 |
+
}
|
436 |
+
});
|
437 |
+
|
438 |
+
$(document).on('click', '.bookly-js-collapse .extra-new', function (e) {
|
439 |
+
e.preventDefault();
|
440 |
+
e.stopPropagation();
|
441 |
+
var children = $('.extras-container li');
|
442 |
+
|
443 |
+
var id = 1;
|
444 |
+
children.each(function (i, el) {
|
445 |
+
var elId = parseInt($(el).data('extra-id'));
|
446 |
+
id = (elId >= id) ? elId + 1 : id;
|
447 |
+
});
|
448 |
+
var template = $('.ab--templates.extras').html();
|
449 |
+
var $container = $(this).parents('.bookly-js-collapse').find('.extras-container');
|
450 |
+
id++;
|
451 |
+
$container.append(
|
452 |
+
template.replace(/%id%/g, id)
|
453 |
+
);
|
454 |
+
$('#title_' + id).focus();
|
455 |
+
});
|
456 |
+
|
457 |
+
$(document).on('click', '.bookly-js-collapse .extra-attachment', function (e) {
|
458 |
+
e.preventDefault();
|
459 |
+
e.stopPropagation();
|
460 |
+
var extra = $(this).parents('.extra');
|
461 |
+
var frame = wp.media({
|
462 |
+
library: {type: 'image'},
|
463 |
+
multiple: false
|
464 |
+
});
|
465 |
+
frame.on('select', function () {
|
466 |
+
var selection = frame.state().get('selection').toJSON(),
|
467 |
+
img_src
|
468 |
+
;
|
469 |
+
if (selection.length) {
|
470 |
+
if (selection[0].sizes['thumbnail'] !== undefined) {
|
471 |
+
img_src = selection[0].sizes['thumbnail'].url;
|
472 |
+
} else {
|
473 |
+
img_src = selection[0].url;
|
474 |
+
}
|
475 |
+
extra.find("[name='extras[" + extra.data('extra-id') + "][attachment_id]']").val(selection[0].id);
|
476 |
+
extra.find('.extra-attachment-image').css({'background-image': 'url(' + img_src + ')', 'background-size': 'cover'});
|
477 |
+
extra.find('.bookly-js-remove-attachment').show();
|
478 |
+
$(this).hide();
|
479 |
+
}
|
480 |
+
});
|
481 |
+
|
482 |
+
frame.open();
|
483 |
+
});
|
484 |
+
|
485 |
+
$(document).on('click', '.bookly-js-collapse .bookly-js-remove-attachment', function (e) {
|
486 |
+
e.preventDefault();
|
487 |
+
e.stopPropagation();
|
488 |
+
$(this).hide();
|
489 |
+
var extra = $(this).parents('.extra');
|
490 |
+
extra.find("[name='extras[" + extra.data('extra-id') + "][attachment_id]']").attr('value', '');
|
491 |
+
extra.find('.extra-attachment-image').attr('style', '');
|
492 |
+
extra.find('.extra-attachment').show();
|
493 |
+
}).on('change', '.popover-range-start, .popover-range-end', function () {
|
494 |
+
var $popover_content = $(this).closest('.popover-content');
|
495 |
+
rangeTools.hideInaccessibleBreaks($popover_content.find('.popover-range-start'), $popover_content.find('.popover-range-end'));
|
496 |
+
});
|
497 |
+
|
498 |
+
$(document).on('click', '.bookly-js-collapse .extra-delete', function (e) {
|
499 |
+
e.preventDefault();
|
500 |
+
e.stopPropagation();
|
501 |
+
if (confirm(BooklyL10n.are_you_sure)) {
|
502 |
+
var extra = $(this).parents('.extra');
|
503 |
+
if (!extra.hasClass('new')) {
|
504 |
+
$.post(ajaxurl, {action: 'bookly_service_extras_delete_service_extra', id: extra.data('extra-id')}, function () {
|
505 |
+
});
|
506 |
+
}
|
507 |
+
extra.remove();
|
508 |
+
}
|
509 |
+
});
|
510 |
+
/*</Extras>*/
|
511 |
+
});
|
backend/modules/services/templates/_list.php
CHANGED
@@ -1,311 +1,322 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$time_interval = get_option( '
|
3 |
-
?>
|
4 |
-
<?php if ( ! empty( $service_collection ) ) : ?>
|
5 |
-
<div class="panel-group" id="services_list" role="tablist" aria-multiselectable="true">
|
6 |
-
<?php foreach ( $service_collection as $service ) : ?>
|
7 |
-
<?php $service_id = $service['id'];
|
8 |
-
$assigned_staff_ids = $service['staff_ids'] ? explode( ',', $service['staff_ids'] ) : array();
|
9 |
-
$all_staff_selected = count( $assigned_staff_ids ) == count( $staff_collection );
|
10 |
-
?>
|
11 |
-
<div class="panel panel-default bookly-js-collapse" data-service-id="<?php echo $service_id ?>">
|
12 |
-
<div class="panel-heading" role="tab" id="s_<?php echo $service_id ?>">
|
13 |
-
<div class="row">
|
14 |
-
<div class="col-sm-8 col-xs-10">
|
15 |
-
<div class="bookly-flexbox">
|
16 |
-
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 1%">
|
17 |
-
<i class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"
|
18 |
-
title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>"></i>
|
19 |
-
</div>
|
20 |
-
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 1%">
|
21 |
-
<span class="bookly-service-color bookly-margin-right-sm bookly-js-service-color"
|
22 |
-
style="background-color: <?php echo esc_attr( $service['color'] ) ?>"> </span>
|
23 |
-
</div>
|
24 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
25 |
-
<a role="button" class="panel-title collapsed bookly-js-service-title" data-toggle="collapse"
|
26 |
-
data-parent="#services_list" href="#service_<?php echo $service_id ?>"
|
27 |
-
aria-expanded="false" aria-controls="service_<?php echo $service_id ?>">
|
28 |
-
<?php echo esc_html( $service['title'] ) ?>
|
29 |
-
</a>
|
30 |
-
</div>
|
31 |
-
</div>
|
32 |
-
</div>
|
33 |
-
<div class="col-sm-4 col-xs-2">
|
34 |
-
<div class="bookly-flexbox">
|
35 |
-
<div class="bookly-flex-cell bookly-vertical-middle hidden-xs" style="width: 60%">
|
36 |
-
<span class="bookly-js-service-duration">
|
37 |
-
<?php echo( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_SIMPLE ? \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['duration'] ) : sprintf( _n( '%d service', '%d services', count( json_decode( $service['sub_services'], true ) ), 'bookly' ), count( json_decode( $service['sub_services'], true ) ) ) ) ?>
|
38 |
-
</span>
|
39 |
-
</div>
|
40 |
-
<div class="bookly-flex-cell bookly-vertical-middle hidden-xs" style="width: 30%">
|
41 |
-
<span class="bookly-js-service-price">
|
42 |
-
<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $service['price'] ) ?>
|
43 |
-
</span>
|
44 |
-
</div>
|
45 |
-
<div class="bookly-flex-cell bookly-vertical-middle text-right" style="width: 10%">
|
46 |
-
<div class="checkbox bookly-margin-remove">
|
47 |
-
<label><input type="checkbox" class="service-checker" value="<?php echo $service_id ?>"/></label>
|
48 |
-
</div>
|
49 |
-
</div>
|
50 |
-
</div>
|
51 |
-
</div>
|
52 |
-
</div>
|
53 |
-
</div>
|
54 |
-
|
55 |
-
<div id="service_<?php echo $service_id ?>" class="panel-collapse collapse" role="tabpanel" style="height: 0">
|
56 |
-
<div class="panel-body">
|
57 |
-
<form method="post">
|
58 |
-
<?php do_action( 'bookly_render_service_form_contents', $service ) ?>
|
59 |
-
<div class="row">
|
60 |
-
<div class="col-md-9 col-sm-6">
|
61 |
-
<div class="form-group">
|
62 |
-
<label for="title_<?php echo $service_id ?>"><?php _e( 'Title', 'bookly' ) ?></label>
|
63 |
-
<input name="title" value="<?php echo esc_attr( $service['title'] ) ?>" id="title_<?php echo $service_id ?>" class="form-control" type="text">
|
64 |
-
</div>
|
65 |
-
</div>
|
66 |
-
<div class="col-md-3 col-sm-6">
|
67 |
-
<div class="form-group">
|
68 |
-
<label><?php _e( 'Color', 'bookly' ) ?></label>
|
69 |
-
<div class="bookly-color-picker-wrapper">
|
70 |
-
<input name="color" value="<?php echo esc_attr( $service['color'] ) ?>" class="bookly-js-color-picker" data-last-color="<?php echo esc_attr( $service['color'] ) ?>" type="hidden">
|
71 |
-
</div>
|
72 |
-
</div>
|
73 |
-
</div>
|
74 |
-
</div>
|
75 |
-
<div class="row">
|
76 |
-
<div class="col-sm-4">
|
77 |
-
<div class="form-group">
|
78 |
-
<label for="visibility_<?php echo $service_id ?>"><?php _e( 'Visibility', 'bookly' ) ?></label>
|
79 |
-
<p class="help-block"><?php _e( 'To make service invisible to your customers set the visibility to "Private".', 'bookly' ) ?></p>
|
80 |
-
<select name="visibility" class="form-control" id="visibility_<?php echo $service_id ?>">
|
81 |
-
<option value="public" <?php selected( $service['visibility'], 'public' ) ?>><?php _e( 'Public', 'bookly' ) ?></option>
|
82 |
-
<option value="private" <?php selected( $service['visibility'], 'private' ) ?>><?php _e( 'Private', 'bookly' ) ?></option>
|
83 |
-
</select>
|
84 |
-
</div>
|
85 |
-
</div>
|
86 |
-
<div class="col-sm-4">
|
87 |
-
<div class="form-group">
|
88 |
-
<label for="price_<?php echo $service_id ?>"><?php _e( 'Price', 'bookly' ) ?></label>
|
89 |
-
<input id="price_<?php echo $service_id ?>" class="form-control ab-question" type="number" min="0
|
90 |
-
</div>
|
91 |
-
</div>
|
92 |
-
<div class="col-sm-4 ab--for-simple">
|
93 |
-
<div class="form-group">
|
94 |
-
<label for="capacity_<?php echo $service_id ?>"><?php _e( 'Capacity', 'bookly' ) ?></label>
|
95 |
-
<p class="help-block"><?php _e( 'The maximum number of customers allowed to book the service for the certain time period.', 'bookly' ) ?></p>
|
96 |
-
<input id="capacity_<?php echo $service_id ?>" class="form-control ab-question" type="number" min="1" step="1" name="capacity" value="<?php echo esc_attr( $service['capacity'] ) ?>">
|
97 |
-
</div>
|
98 |
-
</div>
|
99 |
-
</div>
|
100 |
-
|
101 |
-
<div class="ab--for-simple">
|
102 |
-
<div class="row">
|
103 |
-
<div class="col-sm-4">
|
104 |
-
<div class="form-group">
|
105 |
-
<label for="duration_<?php echo $service_id ?>">
|
106 |
-
<?php _e( 'Duration', 'bookly' ) ?>
|
107 |
-
</label>
|
108 |
-
<select id="duration_<?php echo $service_id ?>" class="form-control" name="duration">
|
109 |
-
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $service['duration'] / 60 > $j - $time_interval && $service['duration'] / 60 < $j ) : ?><option value="<?php echo esc_attr( $service['duration'] ) ?>" selected><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['duration'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['duration'], $j * 60 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
110 |
-
<option value="86400" <?php selected( $service['duration'], DAY_IN_SECONDS ) ?>><?php _e( 'All day', 'bookly' ) ?></option>
|
111 |
-
</select>
|
112 |
-
</div>
|
113 |
-
</div>
|
114 |
-
<div class="col-sm-8">
|
115 |
-
<div class="form-group">
|
116 |
-
<label for="padding_left_<?php echo $service_id ?>">
|
117 |
-
<?php _e( 'Padding time (before and after)', 'bookly' ) ?>
|
118 |
-
</label>
|
119 |
-
<p class="help-block"><?php _e( 'Set padding time before and/or after an appointment. For example, if you require 15 minutes to prepare for the next appointment then you should set "padding before" to 15 min. If there is an appointment from 8:00 to 9:00 then the next available time slot will be 9:15 rather than 9:00.', 'bookly' ) ?></p>
|
120 |
-
<div class="row">
|
121 |
-
<div class="col-xs-6">
|
122 |
-
<select id="padding_left_<?php echo $service_id ?>" class="form-control" name="padding_left">
|
123 |
-
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
124 |
-
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $service['padding_left'] > 0 && $service['padding_left'] / 60 > $j - $time_interval && $service['padding_left'] / 60 < $j ) : ?><option value="<?php echo esc_attr( $service['padding_left'] ) ?>" selected><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['padding_left'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['padding_left'], $j * 60 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
125 |
-
</select>
|
126 |
-
</div>
|
127 |
-
<div class="col-xs-6">
|
128 |
-
<select id="padding_right_<?php echo $service_id ?>" class="form-control" name="padding_right">
|
129 |
-
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
130 |
-
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $service['padding_right'] > 0 && $service['padding_right'] / 60 > $j - $time_interval && $service['padding_right'] / 60 < $j ) : ?><option value="<?php echo esc_attr( $service['padding_right'] ) ?>" selected><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['padding_right'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['padding_right'], $j * 60 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
131 |
-
</select>
|
132 |
-
</div>
|
133 |
-
</div>
|
134 |
-
</div>
|
135 |
-
</div>
|
136 |
-
</div>
|
137 |
-
</div>
|
138 |
-
|
139 |
-
<div class="row">
|
140 |
-
<div class="col-sm-6">
|
141 |
-
<div class="form-group">
|
142 |
-
<label for="category_<?php echo $service_id ?>"><?php _e( 'Category', 'bookly' ) ?></label>
|
143 |
-
<select id="category_<?php echo $service_id ?>" class="form-control" name="category_id"><option value="0"
|
144 |
-
<?php foreach ( $category_collection as $category ) : ?>
|
145 |
-
<option value="<?php echo $category['id'] ?>" <?php selected( $category['id'], $service['category_id'] ) ?>><?php echo esc_html( $category['name'] ) ?></option>
|
146 |
-
<?php endforeach ?>
|
147 |
-
</select>
|
148 |
-
</div>
|
149 |
-
</div>
|
150 |
-
<div class="col-sm-6 ab--for-simple">
|
151 |
-
<div class="form-group">
|
152 |
-
<label><?php _e( 'Providers', 'bookly' ) ?></label><br>
|
153 |
-
<div class="btn-group">
|
154 |
-
<button class="btn btn-default btn-block dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
155 |
-
<div class="bookly-flex-cell">
|
156 |
-
<i class="dashicons dashicons-admin-users bookly-margin-right-md"></i>
|
157 |
-
</div>
|
158 |
-
<div class="bookly-flex-cell text-left" style="width: 100%">
|
159 |
-
<span class=bookly-entity-counter><?php echo $service['total_staff'] ?></span>
|
160 |
-
</div>
|
161 |
-
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
162 |
-
</button>
|
163 |
-
<ul class="dropdown-menu bookly-entity-selector">
|
164 |
-
<li>
|
165 |
-
<a class="checkbox" href="javascript:void(0)">
|
166 |
-
<label>
|
167 |
-
<input type="checkbox" id="service_<?php echo $service_id ?>_all_bookly-js-check-entity" class="bookly-check-all-entities" <?php checked( $all_staff_selected ) ?>">
|
168 |
-
<?php _e( 'All staff', 'bookly' ) ?>
|
169 |
-
</label>
|
170 |
-
</a>
|
171 |
-
</li>
|
172 |
-
<?php foreach ( $staff_collection as $i => $staff ) : ?>
|
173 |
-
<li>
|
174 |
-
<a class="checkbox" href="javascript:void(0)">
|
175 |
-
<label>
|
176 |
-
<input type="checkbox" name="staff_ids[]" class="bookly-js-check-entity" value="<?php echo $staff['id'] ?>" <?php checked( in_array( $staff['id'], $assigned_staff_ids ) ) ?> data-staff_name="<?php echo esc_attr( $staff['full_name'] ) ?>">
|
177 |
-
<?php echo esc_html( $staff['full_name'] ) ?>
|
178 |
-
</label>
|
179 |
-
</a>
|
180 |
-
</li>
|
181 |
-
<?php endforeach ?>
|
182 |
-
</ul>
|
183 |
-
</div>
|
184 |
-
</div>
|
185 |
-
</div>
|
186 |
-
</div>
|
187 |
-
|
188 |
-
<div class="form-group">
|
189 |
-
<label for="info_<?php echo $service_id ?>">
|
190 |
-
<?php _e( 'Info', 'bookly' ) ?>
|
191 |
-
</label>
|
192 |
-
<p class="help-block">
|
193 |
-
<?php printf( __( 'This text can be inserted into notifications with %s code.', 'bookly' ), '{service_info}' ) ?>
|
194 |
-
</p>
|
195 |
-
<textarea class="form-control" id="info_<?php echo $service_id ?>" name="info" rows="3" type="text"><?php echo esc_textarea( $service['info'] ) ?></textarea>
|
196 |
-
</div>
|
197 |
-
|
198 |
-
<?php do_action( 'bookly_compound_render_sub_services', $service, $service_collection, $service['sub_services'] ) ?>
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
</label>
|
260 |
-
<input name="extras[<?php echo $extra->get( 'id' ) ?>][price]" class="form-control" type="number" step="0.01" id="price_<?php echo $extra->get( 'id' ) ?>" min="0.00" value="<?php echo $extra->get( 'price' ) ?>">
|
261 |
-
</div>
|
262 |
-
</div>
|
263 |
-
|
264 |
-
<div class="col-sm-4">
|
265 |
-
<div class="form-group">
|
266 |
-
<label for="duration_<?php echo $extra->get( 'id' ) ?>">
|
267 |
-
<?php _e( 'Duration', 'bookly' ) ?>
|
268 |
-
</label>
|
269 |
-
<select name="extras[<?php echo $extra->get( 'id' ) ?>][duration]" id="duration_<?php echo $extra->get( 'id' ) ?>" class="form-control">
|
270 |
-
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
271 |
-
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $extra->get( 'duration' ) > 0 && $extra->get( 'duration' ) / 60 > $j - $time_interval && $extra->get( 'duration' ) / 60 < $j ) : ?><option value="<?php echo esc_attr( $extra->get( 'duration' ) ) ?>" selected><?php echo BooklyLite\Lib\Utils\DateTime::secondsToInterval( $extra->get( 'duration' ) ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $extra->get( 'duration' ), $j * 60 ) ?>><?php echo BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
272 |
-
</select>
|
273 |
-
</div>
|
274 |
-
</div>
|
275 |
-
|
276 |
-
<div class="col-sm-4">
|
277 |
-
<div class="form-group">
|
278 |
-
<label for="max_quantity_<?php echo $extra->get( 'id' ) ?>">
|
279 |
-
<?php _e( 'Max quantity', 'bookly' ) ?>
|
280 |
-
</label>
|
281 |
-
<input name="extras[<?php echo $extra->get( 'id' ) ?>][max_quantity]" class="form-control" type="number" step="1" id="max_quantity_<?php echo $extra->get( 'id' ) ?>" min="1" value="<?php echo $extra->get( 'max_quantity' ) ?>">
|
282 |
-
</div>
|
283 |
-
</div>
|
284 |
-
</div>
|
285 |
-
|
286 |
-
<div class="form-group text-right">
|
287 |
-
<?php \BooklyLite\Lib\Utils\Common::deleteButton( null, 'extra-delete' ) ?>
|
288 |
-
</div>
|
289 |
-
</div>
|
290 |
-
</div>
|
291 |
-
</li>
|
292 |
-
<?php endforeach ?>
|
293 |
-
</ul>
|
294 |
-
</div>
|
295 |
-
</div>
|
296 |
-
<?php endif ?>
|
297 |
-
|
298 |
-
<div class="panel-footer">
|
299 |
-
<input type="hidden" name="action" value="ab_update_service">
|
300 |
-
<input type="hidden" name="id" value="<?php echo esc_html( $service_id ) ?>">
|
301 |
-
<input type="hidden" name="update_staff" value="0">
|
302 |
-
<?php \BooklyLite\Lib\Utils\Common::submitButton( null, 'ajax-service-send' ) ?>
|
303 |
-
<?php \BooklyLite\Lib\Utils\Common::resetButton( null, 'js-reset' ) ?>
|
304 |
-
</div>
|
305 |
-
</form>
|
306 |
-
</div>
|
307 |
-
</div>
|
308 |
-
</div>
|
309 |
-
<?php endforeach ?>
|
310 |
-
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
$time_interval = get_option( 'bookly_gen_time_slot_length' );
|
3 |
+
?>
|
4 |
+
<?php if ( ! empty( $service_collection ) ) : ?>
|
5 |
+
<div class="panel-group" id="services_list" role="tablist" aria-multiselectable="true">
|
6 |
+
<?php foreach ( $service_collection as $service ) : ?>
|
7 |
+
<?php $service_id = $service['id'];
|
8 |
+
$assigned_staff_ids = $service['staff_ids'] ? explode( ',', $service['staff_ids'] ) : array();
|
9 |
+
$all_staff_selected = count( $assigned_staff_ids ) == count( $staff_collection );
|
10 |
+
?>
|
11 |
+
<div class="panel panel-default bookly-js-collapse" data-service-id="<?php echo $service_id ?>">
|
12 |
+
<div class="panel-heading" role="tab" id="s_<?php echo $service_id ?>">
|
13 |
+
<div class="row">
|
14 |
+
<div class="col-sm-8 col-xs-10">
|
15 |
+
<div class="bookly-flexbox">
|
16 |
+
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 1%">
|
17 |
+
<i class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"
|
18 |
+
title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>"></i>
|
19 |
+
</div>
|
20 |
+
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 1%">
|
21 |
+
<span class="bookly-service-color bookly-margin-right-sm bookly-js-service-color"
|
22 |
+
style="background-color: <?php echo esc_attr( $service['color'] ) ?>"> </span>
|
23 |
+
</div>
|
24 |
+
<div class="bookly-flex-cell bookly-vertical-middle">
|
25 |
+
<a role="button" class="panel-title collapsed bookly-js-service-title" data-toggle="collapse"
|
26 |
+
data-parent="#services_list" href="#service_<?php echo $service_id ?>"
|
27 |
+
aria-expanded="false" aria-controls="service_<?php echo $service_id ?>">
|
28 |
+
<?php echo esc_html( $service['title'] ) ?>
|
29 |
+
</a>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="col-sm-4 col-xs-2">
|
34 |
+
<div class="bookly-flexbox">
|
35 |
+
<div class="bookly-flex-cell bookly-vertical-middle hidden-xs" style="width: 60%">
|
36 |
+
<span class="bookly-js-service-duration">
|
37 |
+
<?php echo( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_SIMPLE ? \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['duration'] ) : sprintf( _n( '%d service', '%d services', count( json_decode( $service['sub_services'], true ) ), 'bookly' ), count( json_decode( $service['sub_services'], true ) ) ) ) ?>
|
38 |
+
</span>
|
39 |
+
</div>
|
40 |
+
<div class="bookly-flex-cell bookly-vertical-middle hidden-xs" style="width: 30%">
|
41 |
+
<span class="bookly-js-service-price">
|
42 |
+
<?php echo \BooklyLite\Lib\Utils\Common::formatPrice( $service['price'] ) ?>
|
43 |
+
</span>
|
44 |
+
</div>
|
45 |
+
<div class="bookly-flex-cell bookly-vertical-middle text-right" style="width: 10%">
|
46 |
+
<div class="checkbox bookly-margin-remove">
|
47 |
+
<label><input type="checkbox" class="service-checker" value="<?php echo $service_id ?>"/></label>
|
48 |
+
</div>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
</div>
|
54 |
+
|
55 |
+
<div id="service_<?php echo $service_id ?>" class="panel-collapse collapse" role="tabpanel" style="height: 0">
|
56 |
+
<div class="panel-body">
|
57 |
+
<form method="post">
|
58 |
+
<?php do_action( 'bookly_render_service_form_contents', $service ) ?>
|
59 |
+
<div class="row">
|
60 |
+
<div class="col-md-9 col-sm-6">
|
61 |
+
<div class="form-group">
|
62 |
+
<label for="title_<?php echo $service_id ?>"><?php _e( 'Title', 'bookly' ) ?></label>
|
63 |
+
<input name="title" value="<?php echo esc_attr( $service['title'] ) ?>" id="title_<?php echo $service_id ?>" class="form-control" type="text">
|
64 |
+
</div>
|
65 |
+
</div>
|
66 |
+
<div class="col-md-3 col-sm-6">
|
67 |
+
<div class="form-group">
|
68 |
+
<label><?php _e( 'Color', 'bookly' ) ?></label>
|
69 |
+
<div class="bookly-color-picker-wrapper">
|
70 |
+
<input name="color" value="<?php echo esc_attr( $service['color'] ) ?>" class="bookly-js-color-picker" data-last-color="<?php echo esc_attr( $service['color'] ) ?>" type="hidden">
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
</div>
|
75 |
+
<div class="row">
|
76 |
+
<div class="col-sm-4">
|
77 |
+
<div class="form-group">
|
78 |
+
<label for="visibility_<?php echo $service_id ?>"><?php _e( 'Visibility', 'bookly' ) ?></label>
|
79 |
+
<p class="help-block"><?php _e( 'To make service invisible to your customers set the visibility to "Private".', 'bookly' ) ?></p>
|
80 |
+
<select name="visibility" class="form-control" id="visibility_<?php echo $service_id ?>">
|
81 |
+
<option value="public" <?php selected( $service['visibility'], 'public' ) ?>><?php _e( 'Public', 'bookly' ) ?></option>
|
82 |
+
<option value="private" <?php selected( $service['visibility'], 'private' ) ?>><?php _e( 'Private', 'bookly' ) ?></option>
|
83 |
+
</select>
|
84 |
+
</div>
|
85 |
+
</div>
|
86 |
+
<div class="col-sm-4">
|
87 |
+
<div class="form-group">
|
88 |
+
<label for="price_<?php echo $service_id ?>"><?php _e( 'Price', 'bookly' ) ?></label>
|
89 |
+
<input id="price_<?php echo $service_id ?>" class="form-control ab-question" type="number" min="0" step="1" name="price" value="<?php echo esc_attr( $service['price'] ) ?>">
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
<div class="col-sm-4 ab--for-simple">
|
93 |
+
<div class="form-group">
|
94 |
+
<label for="capacity_<?php echo $service_id ?>"><?php _e( 'Capacity', 'bookly' ) ?></label>
|
95 |
+
<p class="help-block"><?php _e( 'The maximum number of customers allowed to book the service for the certain time period.', 'bookly' ) ?></p>
|
96 |
+
<input id="capacity_<?php echo $service_id ?>" class="form-control ab-question" type="number" min="1" step="1" name="capacity" value="<?php echo esc_attr( $service['capacity'] ) ?>">
|
97 |
+
</div>
|
98 |
+
</div>
|
99 |
+
</div>
|
100 |
+
|
101 |
+
<div class="ab--for-simple">
|
102 |
+
<div class="row">
|
103 |
+
<div class="col-sm-4">
|
104 |
+
<div class="form-group">
|
105 |
+
<label for="duration_<?php echo $service_id ?>">
|
106 |
+
<?php _e( 'Duration', 'bookly' ) ?>
|
107 |
+
</label>
|
108 |
+
<select id="duration_<?php echo $service_id ?>" class="form-control" name="duration">
|
109 |
+
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $service['duration'] / 60 > $j - $time_interval && $service['duration'] / 60 < $j ) : ?><option value="<?php echo esc_attr( $service['duration'] ) ?>" selected><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['duration'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['duration'], $j * 60 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
110 |
+
<option value="86400" <?php selected( $service['duration'], DAY_IN_SECONDS ) ?>><?php _e( 'All day', 'bookly' ) ?></option>
|
111 |
+
</select>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
<div class="col-sm-8">
|
115 |
+
<div class="form-group">
|
116 |
+
<label for="padding_left_<?php echo $service_id ?>">
|
117 |
+
<?php _e( 'Padding time (before and after)', 'bookly' ) ?>
|
118 |
+
</label>
|
119 |
+
<p class="help-block"><?php _e( 'Set padding time before and/or after an appointment. For example, if you require 15 minutes to prepare for the next appointment then you should set "padding before" to 15 min. If there is an appointment from 8:00 to 9:00 then the next available time slot will be 9:15 rather than 9:00.', 'bookly' ) ?></p>
|
120 |
+
<div class="row">
|
121 |
+
<div class="col-xs-6">
|
122 |
+
<select id="padding_left_<?php echo $service_id ?>" class="form-control" name="padding_left">
|
123 |
+
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
124 |
+
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $service['padding_left'] > 0 && $service['padding_left'] / 60 > $j - $time_interval && $service['padding_left'] / 60 < $j ) : ?><option value="<?php echo esc_attr( $service['padding_left'] ) ?>" selected><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['padding_left'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['padding_left'], $j * 60 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
125 |
+
</select>
|
126 |
+
</div>
|
127 |
+
<div class="col-xs-6">
|
128 |
+
<select id="padding_right_<?php echo $service_id ?>" class="form-control" name="padding_right">
|
129 |
+
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
130 |
+
<?php for ( $j = $time_interval; $j <= 720; $j += $time_interval ) : ?><?php if ( $service['padding_right'] > 0 && $service['padding_right'] / 60 > $j - $time_interval && $service['padding_right'] / 60 < $j ) : ?><option value="<?php echo esc_attr( $service['padding_right'] ) ?>" selected><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $service['padding_right'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['padding_right'], $j * 60 ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
131 |
+
</select>
|
132 |
+
</div>
|
133 |
+
</div>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
</div>
|
137 |
+
</div>
|
138 |
+
|
139 |
+
<div class="row">
|
140 |
+
<div class="col-sm-6">
|
141 |
+
<div class="form-group">
|
142 |
+
<label for="category_<?php echo $service_id ?>"><?php _e( 'Category', 'bookly' ) ?></label>
|
143 |
+
<select id="category_<?php echo $service_id ?>" class="form-control" name="category_id"><option value="0"><?php _e( 'Uncategorized', 'bookly' ) ?></option>
|
144 |
+
<?php foreach ( $category_collection as $category ) : ?>
|
145 |
+
<option value="<?php echo $category['id'] ?>" <?php selected( $category['id'], $service['category_id'] ) ?>><?php echo esc_html( $category['name'] ) ?></option>
|
146 |
+
<?php endforeach ?>
|
147 |
+
</select>
|
148 |
+
</div>
|
149 |
+
</div>
|
150 |
+
<div class="col-sm-6 ab--for-simple">
|
151 |
+
<div class="form-group">
|
152 |
+
<label><?php _e( 'Providers', 'bookly' ) ?></label><br>
|
153 |
+
<div class="btn-group">
|
154 |
+
<button class="btn btn-default btn-block dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
155 |
+
<div class="bookly-flex-cell">
|
156 |
+
<i class="dashicons dashicons-admin-users bookly-margin-right-md"></i>
|
157 |
+
</div>
|
158 |
+
<div class="bookly-flex-cell text-left" style="width: 100%">
|
159 |
+
<span class=bookly-entity-counter><?php echo $service['total_staff'] ?></span>
|
160 |
+
</div>
|
161 |
+
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
162 |
+
</button>
|
163 |
+
<ul class="dropdown-menu bookly-entity-selector">
|
164 |
+
<li>
|
165 |
+
<a class="checkbox" href="javascript:void(0)">
|
166 |
+
<label>
|
167 |
+
<input type="checkbox" id="service_<?php echo $service_id ?>_all_bookly-js-check-entity" class="bookly-check-all-entities" <?php checked( $all_staff_selected ) ?>">
|
168 |
+
<?php _e( 'All staff', 'bookly' ) ?>
|
169 |
+
</label>
|
170 |
+
</a>
|
171 |
+
</li>
|
172 |
+
<?php foreach ( $staff_collection as $i => $staff ) : ?>
|
173 |
+
<li>
|
174 |
+
<a class="checkbox" href="javascript:void(0)">
|
175 |
+
<label>
|
176 |
+
<input type="checkbox" name="staff_ids[]" class="bookly-js-check-entity" value="<?php echo $staff['id'] ?>" <?php checked( in_array( $staff['id'], $assigned_staff_ids ) ) ?> data-staff_name="<?php echo esc_attr( $staff['full_name'] ) ?>">
|
177 |
+
<?php echo esc_html( $staff['full_name'] ) ?>
|
178 |
+
</label>
|
179 |
+
</a>
|
180 |
+
</li>
|
181 |
+
<?php endforeach ?>
|
182 |
+
</ul>
|
183 |
+
</div>
|
184 |
+
</div>
|
185 |
+
</div>
|
186 |
+
</div>
|
187 |
+
|
188 |
+
<div class="form-group">
|
189 |
+
<label for="info_<?php echo $service_id ?>">
|
190 |
+
<?php _e( 'Info', 'bookly' ) ?>
|
191 |
+
</label>
|
192 |
+
<p class="help-block">
|
193 |
+
<?php printf( __( 'This text can be inserted into notifications with %s code.', 'bookly' ), '{service_info}' ) ?>
|
194 |
+
</p>
|
195 |
+
<textarea class="form-control" id="info_<?php echo $service_id ?>" name="info" rows="3" type="text"><?php echo esc_textarea( $service['info'] ) ?></textarea>
|
196 |
+
</div>
|
197 |
+
|
198 |
+
<?php do_action( 'bookly_compound_render_sub_services', $service, $service_collection, $service['sub_services'] ) ?>
|
199 |
+
|
200 |
+
<?php if ( has_action( 'bookly_service_schedule_render_service_settings' ) ) : ?>
|
201 |
+
<div class="ab--for-simple bookly-margin-bottom-xs">
|
202 |
+
<a class="h4" href="#bookly_service_schedule_container_<?php echo $service_id ?>" data-toggle="collapse" role="button">
|
203 |
+
<?php _e( 'Schedule', 'bookly' ) ?>
|
204 |
+
</a>
|
205 |
+
<div id="bookly_service_schedule_container_<?php echo $service_id ?>" class="bookly-margin-top-lg collapse in">
|
206 |
+
<?php do_action( 'bookly_service_schedule_render_service_settings', $service ) ?>
|
207 |
+
</div>
|
208 |
+
</div>
|
209 |
+
<?php endif ?>
|
210 |
+
|
211 |
+
<?php if ( has_filter( 'bookly_service_extras_find_by_service_id' ) ) : ?>
|
212 |
+
<div class="ab--for-simple bookly-margin-bottom-xs">
|
213 |
+
<a class="h4" href="#bookly_service_extras_container_<?php echo $service_id ?>" data-toggle="collapse" role="button">
|
214 |
+
<?php echo get_option( 'bookly_l10n_step_extras' ) ?>
|
215 |
+
</a>
|
216 |
+
<div id="bookly_service_extras_container_<?php echo $service_id ?>" class="bookly-margin-top-lg collapse in">
|
217 |
+
<ul class="list-group extras-container" data-service="<?php echo $service_id ?>">
|
218 |
+
<div class="form-group text-right">
|
219 |
+
<button type="button" class="btn btn-success extra-new" data-spinner-size="40" data-style="zoom-in">
|
220 |
+
<span class="ladda-label"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'New Item', 'bookly' ) ?></span>
|
221 |
+
</button>
|
222 |
+
</div>
|
223 |
+
<?php foreach ( apply_filters( 'bookly_service_extras_find_by_service_id', array(), $service_id ) as $extra ) : ?>
|
224 |
+
<li class="list-group-item extra" data-extra-id="<?php echo $extra->get( 'id' ) ?>">
|
225 |
+
<div class="row">
|
226 |
+
<div class="col-lg-3">
|
227 |
+
<div class="bookly-flexbox">
|
228 |
+
<div class="bookly-flex-cell bookly-vertical-top">
|
229 |
+
<i class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move" title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>"></i>
|
230 |
+
</div>
|
231 |
+
<div class="bookly-flex-cell" style="width: 100%">
|
232 |
+
<div class="form-group">
|
233 |
+
<input name="extras[<?php echo $extra->get( 'id' ) ?>][id]"
|
234 |
+
value="<?php echo $extra->get( 'id' ) ?>" type="hidden">
|
235 |
+
<input name="extras[<?php echo $extra->get( 'id' ) ?>][attachment_id]"
|
236 |
+
value="<?php echo $extra->get( 'attachment_id' ) ?>" type="hidden">
|
237 |
+
|
238 |
+
<?php $img = wp_get_attachment_image_src( $extra->get( 'attachment_id' ), 'thumbnail' ) ?>
|
239 |
+
|
240 |
+
<div class="extra-attachment-image bookly-thumb bookly-thumb-lg bookly-margin-right-lg"
|
241 |
+
<?php echo $img ? 'style="background-image: url(' . $img[0] . '); background-size: cover;"' : '' ?>
|
242 |
+
>
|
243 |
+
<a class="bookly-js-remove-attachment dashicons dashicons-trash text-danger bookly-thumb-delete" href="javascript:void(0)" title="<?php _e( 'Delete', 'bookly' ) ?>"
|
244 |
+
<?php if ( !$img ) : ?>style="display: none;"<?php endif ?>>
|
245 |
+
</a>
|
246 |
+
<div class="bookly-thumb-edit extra-attachment" <?php if ( $img ) : ?>style="display: none;"<?php endif ?> >
|
247 |
+
<div class="bookly-pretty">
|
248 |
+
<label class="bookly-pretty-indicator bookly-thumb-edit-btn"><?php _e( 'Image', 'bookly' ) ?></label>
|
249 |
+
</div>
|
250 |
+
</div>
|
251 |
+
</div>
|
252 |
+
</div>
|
253 |
+
</div>
|
254 |
+
</div>
|
255 |
+
</div>
|
256 |
+
|
257 |
+
<div class="col-lg-9">
|
258 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|