Version Description
- Fixed issue with Custom Fields after previous update
Download this release
Release Info
Developer | Ladela |
Plugin | WordPress Online Booking and Scheduling Plugin – Bookly |
Version | 14.5 |
Comparing to | |
See all releases |
Code changes from version 13.2 to 14.5
- autoload.php +1 -1
- backend/Backend.php +19 -14
- backend/modules/appearance/Components.php +21 -0
- backend/modules/appearance/Controller.php +110 -86
- backend/modules/appearance/lib/Helper.php +51 -40
- backend/{resources → modules/appearance/resources}/css/bootstrap-editable.css +2 -2
- backend/modules/appearance/resources/js/appearance.js +340 -465
- backend/modules/appearance/resources/js/bootstrap-editable.bookly.js +112 -0
- backend/{resources → modules/appearance/resources}/js/bootstrap-editable.min.js +1 -1
- backend/modules/appearance/templates/_1_service.php +88 -78
- backend/modules/appearance/templates/_3_time.php +70 -64
- backend/modules/appearance/templates/_5_cart.php +59 -50
- backend/modules/appearance/templates/_6_details.php +46 -16
- backend/modules/appearance/templates/_7_payment.php +28 -37
- backend/modules/appearance/templates/_8_complete.php +12 -3
- backend/modules/appearance/templates/_card_payment.php +13 -11
- backend/modules/appearance/templates/_codes.php +17 -22
- backend/modules/appearance/templates/_custom_css.php +40 -0
- backend/modules/appearance/templates/_progress_tracker.php +12 -11
- backend/modules/appearance/templates/index.php +119 -21
- backend/modules/appointments/Controller.php +50 -53
- backend/modules/appointments/resources/js/appointments.js +36 -11
- backend/modules/appointments/templates/_export_dialog.php +8 -2
- backend/modules/appointments/templates/_print_dialog.php +0 -33
- backend/modules/appointments/templates/index.php +22 -17
- backend/modules/calendar/Components.php +15 -18
- backend/modules/calendar/Controller.php +399 -215
- backend/modules/calendar/resources/js/calendar-common.js +279 -0
- backend/modules/calendar/resources/js/calendar.js +52 -240
- backend/modules/calendar/resources/js/ng-appointment_dialog.js +364 -184
- backend/modules/calendar/templates/_appointment_dialog.php +137 -59
- backend/modules/calendar/templates/_customer_details_dialog.php +19 -70
- backend/modules/calendar/templates/calendar.php +9 -8
- backend/modules/coupons/Controller.php +0 -66
- backend/modules/coupons/forms/Coupon.php +0 -19
- backend/modules/coupons/resources/js/coupons.js +0 -63
- backend/modules/coupons/templates/_modal.php +0 -66
- backend/modules/coupons/templates/index.php +0 -44
- backend/modules/custom_fields/Controller.php +0 -90
- backend/modules/custom_fields/resources/js/custom_fields.js +0 -233
- backend/modules/custom_fields/templates/_services.php +0 -32
- backend/modules/custom_fields/templates/index.php +0 -303
- backend/modules/customers/Components.php +16 -1
- backend/modules/customers/Controller.php +51 -37
- backend/modules/customers/forms/Customer.php +5 -2
- backend/modules/customers/resources/js/customers.js +25 -19
- backend/modules/customers/resources/js/ng-customer_dialog.js +59 -54
- backend/modules/customers/templates/_customer_dialog.php +34 -8
- backend/modules/customers/templates/_import.php +10 -2
- backend/modules/customers/templates/index.php +5 -4
- backend/modules/debug/Controller.php +10 -29
- backend/modules/debug/templates/index.php +2 -0
- backend/modules/message/Controller.php +100 -0
- backend/modules/message/resources/js/message.js +71 -0
- backend/modules/message/templates/index.php +24 -0
- backend/modules/notifications/Components.php +357 -0
- backend/modules/notifications/Controller.php +50 -27
- backend/modules/notifications/forms/Notifications.php +145 -62
- backend/modules/notifications/resources/js/ng-app.js +27 -2
- backend/modules/notifications/resources/js/notification.js +7 -1
- backend/modules/notifications/templates/_codes.php +0 -34
- backend/modules/notifications/templates/_codes_cart.php +0 -16
- backend/modules/notifications/templates/_codes_client_new_wp_user.php +0 -15
- backend/modules/notifications/templates/_codes_staff_agenda.php +0 -7
- backend/modules/{customers/templates/_export.php → notifications/templates/_custom_notification.php} +1 -1
- backend/modules/notifications/templates/_test_email_notifications_modal.php +3 -2
- backend/modules/notifications/templates/index.php +106 -53
- backend/modules/payments/Controller.php +25 -34
- backend/modules/payments/resources/js/ng-payment_details_dialog.js +2 -2
- backend/modules/payments/resources/js/payments.js +19 -10
- backend/modules/payments/templates/details.php +22 -17
- backend/modules/payments/templates/index.php +3 -6
- backend/modules/services/Controller.php +139 -100
- backend/modules/services/forms/Category.php +2 -0
- backend/modules/services/forms/Service.php +50 -15
- backend/modules/services/resources/js/service.js +228 -226
- backend/modules/services/templates/_list.php +138 -144
- backend/modules/services/templates/index.php +8 -11
- backend/modules/settings/Components.php +30 -0
- backend/modules/settings/Controller.php +152 -124
- backend/modules/settings/forms/BusinessHours.php +4 -4
- backend/modules/settings/forms/Payments.php +11 -1
- backend/modules/settings/resources/js/collect-stats-notice.js +13 -0
- backend/modules/settings/resources/js/settings.js +71 -61
- backend/modules/settings/templates/_calendarForm.php +21 -0
- backend/modules/settings/templates/_calendar_codes.php +35 -0
- backend/modules/settings/templates/_cartForm.php +5 -3
- backend/modules/settings/templates/_collect_stats_notice.php +24 -0
- backend/modules/settings/templates/_companyForm.php +1 -0
- backend/modules/settings/templates/_customers.php +14 -9
- backend/modules/settings/templates/_generalForm.php +22 -28
- backend/modules/settings/templates/_googleCalendarForm.php +3 -2
- backend/modules/settings/templates/_holidaysForm.php +1 -23
- backend/modules/settings/templates/_hoursForm.php +1 -0
- backend/modules/settings/templates/_paymentsForm.php +33 -128
- backend/modules/settings/templates/_urlForm.php +35 -0
- backend/modules/settings/templates/_woocommerce.php +2 -1
- backend/modules/settings/templates/_woocommerce_codes.php +1 -1
- backend/modules/settings/templates/index.php +16 -5
- backend/modules/sms/Components.php +348 -0
- backend/modules/sms/Controller.php +45 -21
- backend/modules/sms/resources/js/sms.js +107 -21
- backend/modules/sms/templates/_codes.php +0 -29
- backend/modules/sms/templates/_codes_cart.php +0 -15
- backend/modules/sms/templates/_codes_client_new_wp_user.php +0 -14
- backend/modules/sms/templates/_codes_staff_agenda.php +0 -7
- backend/modules/sms/templates/_custom_notification.php +263 -0
- backend/modules/sms/templates/_notifications.php +68 -42
- backend/modules/sms/templates/index.php +23 -64
- backend/modules/staff/Controller.php +100 -100
- backend/modules/staff/forms/StaffSchedule.php +10 -8
- backend/modules/staff/forms/StaffServices.php +26 -16
- backend/modules/staff/forms/widgets/TimeChoice.php +7 -8
- backend/modules/staff/resources/js/staff-days-off.js +52 -0
- backend/modules/staff/resources/js/staff-details.js +142 -0
- backend/modules/staff/resources/js/staff-schedule.js +322 -0
- backend/modules/staff/resources/js/staff-services.js +139 -0
- backend/modules/staff/resources/js/staff.js +99 -505
- backend/modules/staff/templates/_breaks.php +1 -0
- backend/modules/staff/templates/_details.php +110 -0
- backend/modules/staff/templates/_list_item.php +3 -3
- backend/modules/staff/templates/_new.php +5 -5
- backend/modules/staff/templates/edit.php +10 -114
- backend/modules/staff/templates/holidays.php +1 -25
- backend/modules/staff/templates/index.php +0 -1
- backend/modules/staff/templates/schedule.php +70 -67
- backend/modules/staff/templates/services.php +110 -78
- backend/modules/support/Components.php +20 -5
autoload.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
|
3 |
/**
|
4 |
-
*
|
5 |
* @param $class
|
6 |
*/
|
7 |
function bookly_lite_loader( $class )
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
|
3 |
/**
|
4 |
+
* Bookly Lite autoload.
|
5 |
* @param $class
|
6 |
*/
|
7 |
function bookly_lite_loader( $class )
|
backend/Backend.php
CHANGED
@@ -1,7 +1,6 @@
|
|
1 |
<?php
|
2 |
namespace BooklyLite\Backend;
|
3 |
|
4 |
-
use BooklyLite\Backend\Modules;
|
5 |
use BooklyLite\Frontend;
|
6 |
use BooklyLite\Lib;
|
7 |
|
@@ -11,15 +10,16 @@ use BooklyLite\Lib;
|
|
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();
|
@@ -28,6 +28,7 @@ class Backend
|
|
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();
|
@@ -38,6 +39,9 @@ class Backend
|
|
38 |
add_action( 'admin_init', array( $this, 'addTinyMCEPlugin' ) );
|
39 |
}
|
40 |
|
|
|
|
|
|
|
41 |
public function init()
|
42 |
{
|
43 |
if ( ! session_id() ) {
|
@@ -50,14 +54,17 @@ class Backend
|
|
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.
|
@@ -71,14 +78,14 @@ class Backend
|
|
71 |
$payments = __( 'Payments', 'bookly' );
|
72 |
$appearance = __( 'Appearance', 'bookly' );
|
73 |
$settings = __( 'Settings', 'bookly' );
|
74 |
-
$
|
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 |
-
|
|
|
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' ) );
|
@@ -100,20 +107,18 @@ class Backend
|
|
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 |
-
|
104 |
-
|
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 |
}
|
1 |
<?php
|
2 |
namespace BooklyLite\Backend;
|
3 |
|
|
|
4 |
use BooklyLite\Frontend;
|
5 |
use BooklyLite\Lib;
|
6 |
|
10 |
*/
|
11 |
class Backend
|
12 |
{
|
13 |
+
/**
|
14 |
+
* Constructor.
|
15 |
+
*/
|
16 |
public function __construct()
|
17 |
{
|
18 |
// Backend controllers.
|
19 |
$this->apearanceController = Modules\Appearance\Controller::getInstance();
|
20 |
$this->appointmentsController = Modules\Appointments\Controller::getInstance();
|
21 |
$this->calendarController = Modules\Calendar\Controller::getInstance();
|
|
|
22 |
$this->customerController = Modules\Customers\Controller::getInstance();
|
|
|
23 |
$this->debugController = Modules\Debug\Controller::getInstance();
|
24 |
$this->notificationsController = Modules\Notifications\Controller::getInstance();
|
25 |
$this->paymentController = Modules\Payments\Controller::getInstance();
|
28 |
$this->supportController = Modules\Support\Controller::getInstance();
|
29 |
$this->smsController = Modules\Sms\Controller::getInstance();
|
30 |
$this->staffController = Modules\Staff\Controller::getInstance();
|
31 |
+
$this->messageController = Modules\Message\Controller::getInstance();
|
32 |
|
33 |
// Frontend controllers that work via admin-ajax.php.
|
34 |
$this->bookingController = Frontend\Modules\Booking\Controller::getInstance();
|
39 |
add_action( 'admin_init', array( $this, 'addTinyMCEPlugin' ) );
|
40 |
}
|
41 |
|
42 |
+
/**
|
43 |
+
* Init.
|
44 |
+
*/
|
45 |
public function init()
|
46 |
{
|
47 |
if ( ! session_id() ) {
|
54 |
new Modules\TinyMce\Plugin();
|
55 |
}
|
56 |
|
57 |
+
/**
|
58 |
+
* Admin menu.
|
59 |
+
*/
|
60 |
public function addAdminMenu()
|
61 |
{
|
62 |
/** @var \WP_User $current_user */
|
63 |
+
global $current_user, $submenu;
|
64 |
|
65 |
if ( $current_user->has_cap( 'administrator' ) || Lib\Entities\Staff::query()->where( 'wp_user_id', $current_user->ID )->count() ) {
|
66 |
$dynamic_position = '80.0000001' . mt_rand( 1, 1000 ); // position always is under `Settings`
|
67 |
+
add_menu_page( 'Bookly Lite', 'Bookly Lite', 'read', 'bookly-menu', '',
|
68 |
plugins_url( 'resources/images/menu.png', __FILE__ ), $dynamic_position );
|
69 |
|
70 |
// Translated submenu pages.
|
78 |
$payments = __( 'Payments', 'bookly' );
|
79 |
$appearance = __( 'Appearance', 'bookly' );
|
80 |
$settings = __( 'Settings', 'bookly' );
|
81 |
+
$messages = __( 'Messages', 'bookly' );
|
|
|
82 |
|
83 |
add_submenu_page( 'bookly-menu', $calendar, $calendar, 'read',
|
84 |
Modules\Calendar\Controller::page_slug, array( $this->calendarController, 'index' ) );
|
85 |
add_submenu_page( 'bookly-menu', $appointments, $appointments, 'manage_options',
|
86 |
Modules\Appointments\Controller::page_slug, array( $this->appointmentsController, 'index' ) );
|
87 |
+
Lib\Proxy\Locations::addBooklyMenuItem();
|
88 |
+
Lib\Proxy\Packages::addBooklyMenuItem();
|
89 |
if ( $current_user->has_cap( 'administrator' ) ) {
|
90 |
add_submenu_page( 'bookly-menu', $staff_members, $staff_members, 'manage_options',
|
91 |
Modules\Staff\Controller::page_slug, array( $this->staffController, 'index' ) );
|
107 |
Modules\Payments\Controller::page_slug, array( $this->paymentController, 'index' ) );
|
108 |
add_submenu_page( 'bookly-menu', $appearance, $appearance, 'manage_options',
|
109 |
Modules\Appearance\Controller::page_slug, array( $this->apearanceController, 'index' ) );
|
110 |
+
Lib\Proxy\Coupons::addBooklyMenuItem();
|
111 |
+
Lib\Proxy\CustomFields::addBooklyMenuItem();
|
|
|
|
|
112 |
add_submenu_page( 'bookly-menu', $settings, $settings, 'manage_options',
|
113 |
Modules\Settings\Controller::page_slug, array( $this->settingsController, 'index' ) );
|
114 |
+
add_submenu_page( 'bookly-menu', $messages, $messages, 'manage_options',
|
115 |
+
Modules\Message\Controller::page_slug, array( $this->messageController, 'index' ) );
|
116 |
|
117 |
if ( isset ( $_GET['page'] ) && $_GET['page'] == 'bookly-debug' ) {
|
118 |
add_submenu_page( 'bookly-menu', 'Debug', 'Debug', 'manage_options',
|
119 |
Modules\Debug\Controller::page_slug, array( $this->debugController, 'index' ) );
|
120 |
}
|
121 |
|
|
|
|
|
122 |
unset ( $submenu['bookly-menu'][0] );
|
123 |
}
|
124 |
}
|
backend/modules/appearance/Components.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Appearance;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Components
|
8 |
+
* @package BooklyLite\Backend\Modules\Appearance
|
9 |
+
*/
|
10 |
+
class Components extends Lib\Base\Components
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @param array $variables
|
14 |
+
* @param bool $echo
|
15 |
+
* @return string|void
|
16 |
+
*/
|
17 |
+
public function renderCodes( $variables = array(), $echo = true )
|
18 |
+
{
|
19 |
+
return $this->render( '_codes', $variables, $echo );
|
20 |
+
}
|
21 |
+
}
|
backend/modules/appearance/Controller.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
namespace BooklyLite\Backend\Modules\Appearance;
|
3 |
|
4 |
use BooklyLite\Lib;
|
|
|
5 |
|
6 |
/**
|
7 |
* Class Controller
|
@@ -31,17 +32,14 @@ class Controller extends Lib\Base\Controller
|
|
31 |
'css/bookly-main.css',
|
32 |
)
|
33 |
),
|
34 |
-
'backend' => array(
|
35 |
-
|
36 |
-
|
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(
|
@@ -56,10 +54,15 @@ class Controller extends Lib\Base\Controller
|
|
56 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
57 |
),
|
58 |
'wp' => array( 'wp-color-picker' ),
|
59 |
-
'module' => array(
|
|
|
|
|
|
|
|
|
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 ),
|
@@ -76,7 +79,7 @@ class Controller extends Lib\Base\Controller
|
|
76 |
) );
|
77 |
|
78 |
// Initialize steps (tabs).
|
79 |
-
$
|
80 |
1 => get_option( 'bookly_l10n_step_service' ),
|
81 |
get_option( 'bookly_l10n_step_extras' ),
|
82 |
get_option( 'bookly_l10n_step_time' ),
|
@@ -87,8 +90,13 @@ class Controller extends Lib\Base\Controller
|
|
87 |
get_option( 'bookly_l10n_step_done' )
|
88 |
);
|
89 |
|
|
|
|
|
|
|
|
|
|
|
90 |
// Render general layout.
|
91 |
-
$this->render( 'index' );
|
92 |
}
|
93 |
|
94 |
/**
|
@@ -96,76 +104,94 @@ class Controller extends Lib\Base\Controller
|
|
96 |
*/
|
97 |
public function executeUpdateAppearanceOptions()
|
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 |
|
@@ -181,14 +207,12 @@ class Controller extends Lib\Base\Controller
|
|
181 |
}
|
182 |
|
183 |
/**
|
184 |
-
*
|
185 |
-
* so current 'execute*' methods look nicer.
|
186 |
-
*
|
187 |
-
* @param string $prefix
|
188 |
*/
|
189 |
-
|
190 |
{
|
191 |
-
|
192 |
-
}
|
193 |
|
|
|
|
|
194 |
}
|
2 |
namespace BooklyLite\Backend\Modules\Appearance;
|
3 |
|
4 |
use BooklyLite\Lib;
|
5 |
+
use BooklyLite\Backend\Modules\Appearance\Lib\Helper;
|
6 |
|
7 |
/**
|
8 |
* Class Controller
|
32 |
'css/bookly-main.css',
|
33 |
)
|
34 |
),
|
35 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
36 |
+
'wp' => array( 'wp-color-picker', ),
|
37 |
+
'module' => array( 'css/bootstrap-editable.css', )
|
|
|
|
|
38 |
) );
|
39 |
|
40 |
$this->enqueueScripts( array(
|
41 |
'backend' => array(
|
42 |
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
|
|
43 |
'js/alert.js' => array( 'jquery' ),
|
44 |
),
|
45 |
'frontend' => array_merge(
|
54 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
55 |
),
|
56 |
'wp' => array( 'wp-color-picker' ),
|
57 |
+
'module' => array(
|
58 |
+
'js/bootstrap-editable.min.js' => array( 'bookly-bootstrap.min.js' ),
|
59 |
+
'js/bootstrap-editable.bookly.js' => array( 'bookly-bootstrap-editable.min.js' ),
|
60 |
+
'js/appearance.js' => array( 'bookly-bootstrap-editable.bookly.js' )
|
61 |
+
)
|
62 |
) );
|
63 |
|
64 |
wp_localize_script( 'bookly-picker.date.js', 'BooklyL10n', array(
|
65 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
66 |
'today' => __( 'Today', 'bookly' ),
|
67 |
'months' => array_values( $wp_locale->month ),
|
68 |
'days' => array_values( $wp_locale->weekday_abbrev ),
|
79 |
) );
|
80 |
|
81 |
// Initialize steps (tabs).
|
82 |
+
$steps = array(
|
83 |
1 => get_option( 'bookly_l10n_step_service' ),
|
84 |
get_option( 'bookly_l10n_step_extras' ),
|
85 |
get_option( 'bookly_l10n_step_time' ),
|
90 |
get_option( 'bookly_l10n_step_done' )
|
91 |
);
|
92 |
|
93 |
+
$custom_css = get_option( 'bookly_app_custom_styles' );
|
94 |
+
|
95 |
+
// Shortcut to helper class.
|
96 |
+
$editable = new Helper();
|
97 |
+
|
98 |
// Render general layout.
|
99 |
+
$this->render( 'index', compact( 'steps', 'custom_css', 'editable' ) );
|
100 |
}
|
101 |
|
102 |
/**
|
104 |
*/
|
105 |
public function executeUpdateAppearanceOptions()
|
106 |
{
|
107 |
+
$options = $this->getParameter( 'options', array() );
|
108 |
+
|
109 |
+
// Make sure that we save only allowed options.
|
110 |
+
$options_to_save = array_intersect_key( $options, array_flip( array(
|
111 |
+
// Info text.
|
112 |
+
'bookly_l10n_info_cart_step',
|
113 |
+
'bookly_l10n_info_complete_step',
|
114 |
+
'bookly_l10n_info_complete_step_limit_error',
|
115 |
+
'bookly_l10n_info_complete_step_processing',
|
116 |
+
'bookly_l10n_info_details_step',
|
117 |
+
'bookly_l10n_info_details_step_guest',
|
118 |
+
'bookly_l10n_info_payment_step_single_app',
|
119 |
+
'bookly_l10n_info_payment_step_several_apps',
|
120 |
+
'bookly_l10n_info_service_step',
|
121 |
+
'bookly_l10n_info_time_step',
|
122 |
+
// Step, label and option texts.
|
123 |
+
'bookly_l10n_button_apply',
|
124 |
+
'bookly_l10n_button_back',
|
125 |
+
'bookly_l10n_button_book_more',
|
126 |
+
'bookly_l10n_label_category',
|
127 |
+
'bookly_l10n_label_ccard_code',
|
128 |
+
'bookly_l10n_label_ccard_expire',
|
129 |
+
'bookly_l10n_label_ccard_number',
|
130 |
+
'bookly_l10n_label_email',
|
131 |
+
'bookly_l10n_label_employee',
|
132 |
+
'bookly_l10n_label_finish_by',
|
133 |
+
'bookly_l10n_label_name',
|
134 |
+
'bookly_l10n_label_first_name',
|
135 |
+
'bookly_l10n_label_last_name',
|
136 |
+
'bookly_l10n_label_notes',
|
137 |
+
'bookly_l10n_label_number_of_persons',
|
138 |
+
'bookly_l10n_label_pay_ccard',
|
139 |
+
'bookly_l10n_label_pay_locally',
|
140 |
+
'bookly_l10n_label_pay_paypal',
|
141 |
+
'bookly_l10n_label_phone',
|
142 |
+
'bookly_l10n_label_select_date',
|
143 |
+
'bookly_l10n_label_service',
|
144 |
+
'bookly_l10n_label_start_from',
|
145 |
+
'bookly_l10n_option_category',
|
146 |
+
'bookly_l10n_option_employee',
|
147 |
+
'bookly_l10n_option_service',
|
148 |
+
'bookly_l10n_step_service',
|
149 |
+
'bookly_l10n_step_service_mobile_button_next',
|
150 |
+
'bookly_l10n_step_service_button_next',
|
151 |
+
'bookly_l10n_step_time',
|
152 |
+
'bookly_l10n_step_time_slot_not_available',
|
153 |
+
'bookly_l10n_step_cart',
|
154 |
+
'bookly_l10n_step_cart_slot_not_available',
|
155 |
+
'bookly_l10n_step_cart_button_next',
|
156 |
+
'bookly_l10n_step_details',
|
157 |
+
'bookly_l10n_step_details_button_next',
|
158 |
+
'bookly_l10n_step_details_button_login',
|
159 |
+
'bookly_l10n_step_payment',
|
160 |
+
'bookly_l10n_step_payment_button_next',
|
161 |
+
'bookly_l10n_step_done',
|
162 |
+
// Validator errors.
|
163 |
+
'bookly_l10n_required_email',
|
164 |
+
'bookly_l10n_required_employee',
|
165 |
+
'bookly_l10n_required_name',
|
166 |
+
'bookly_l10n_required_first_name',
|
167 |
+
'bookly_l10n_required_last_name',
|
168 |
+
'bookly_l10n_required_phone',
|
169 |
+
'bookly_l10n_required_service',
|
170 |
+
// Color.
|
171 |
+
'bookly_app_color',
|
172 |
+
// Checkboxes.
|
173 |
+
'bookly_app_required_employee',
|
174 |
+
'bookly_app_service_name_with_duration',
|
175 |
+
'bookly_app_show_blocked_timeslots',
|
176 |
+
'bookly_app_show_calendar',
|
177 |
+
'bookly_app_show_day_one_column',
|
178 |
+
'bookly_app_show_login_button',
|
179 |
+
'bookly_app_show_notes',
|
180 |
+
'bookly_app_show_progress_tracker',
|
181 |
+
'bookly_app_staff_name_with_price',
|
182 |
+
'bookly_cst_required_phone',
|
183 |
+
'bookly_cst_first_last_name',
|
184 |
+
) ) );
|
185 |
+
|
186 |
+
// Allow add-ons to add their options.
|
187 |
+
$options_to_save = Lib\Proxy\Shared::prepareAppearanceOptions( $options_to_save, $options );
|
188 |
+
|
189 |
+
// Save options.
|
190 |
+
foreach ( $options_to_save as $option_name => $option_value ) {
|
191 |
+
update_option( $option_name, $option_value );
|
192 |
+
// Register string for translate in WPML.
|
193 |
+
if ( strpos( $option_name, 'bookly_l10n_' ) === 0 ) {
|
194 |
+
do_action( 'wpml_register_single_string', 'bookly', $option_name, $option_value );
|
195 |
}
|
196 |
}
|
197 |
|
207 |
}
|
208 |
|
209 |
/**
|
210 |
+
* Process ajax request to save custom css
|
|
|
|
|
|
|
211 |
*/
|
212 |
+
public function executeSaveCustomCss()
|
213 |
{
|
214 |
+
update_option( 'bookly_app_custom_styles', $this->getParameter( 'custom_css' ) );
|
|
|
215 |
|
216 |
+
wp_send_json_success( array( 'message' => __( 'Your custom CSS was saved. Please refresh the page to see your changes.', 'bookly') ) );
|
217 |
+
}
|
218 |
}
|
backend/modules/appearance/lib/Helper.php
CHANGED
@@ -4,55 +4,66 @@ namespace BooklyLite\Backend\Modules\Appearance\Lib;
|
|
4 |
class Helper
|
5 |
{
|
6 |
/**
|
7 |
-
* Render
|
8 |
*
|
9 |
-
* @param array $
|
10 |
-
* @param null $mirror_class the updated value will be displayed also for the objects with css class
|
11 |
*/
|
12 |
-
public static function
|
13 |
{
|
14 |
-
$
|
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
|
34 |
*
|
35 |
-
* @param array $
|
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 $
|
39 |
{
|
40 |
-
$
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
}
|
57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
}
|
4 |
class Helper
|
5 |
{
|
6 |
/**
|
7 |
+
* Render editable string (single line).
|
8 |
*
|
9 |
+
* @param array $options
|
|
|
10 |
*/
|
11 |
+
public static function renderString(array $options )
|
12 |
{
|
13 |
+
self::_renderEditable( $options, 'span' );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
}
|
15 |
|
16 |
/**
|
17 |
+
* Render editable label.
|
18 |
*
|
19 |
+
* @param array $options
|
|
|
20 |
*/
|
21 |
+
public static function renderLabel( array $options )
|
22 |
{
|
23 |
+
self::_renderEditable( $options, 'label' );
|
24 |
+
}
|
25 |
+
|
26 |
+
/**
|
27 |
+
* Render editable text (multi-line).
|
28 |
+
*
|
29 |
+
* @param string $option_name
|
30 |
+
* @param string $codes
|
31 |
+
* @param string $placement
|
32 |
+
* @param string $title
|
33 |
+
*/
|
34 |
+
public static function renderText( $option_name, $codes = '', $placement = 'bottom', $title = '' )
|
35 |
+
{
|
36 |
+
$option_value = get_option( $option_name );
|
37 |
+
|
38 |
+
printf( '<span class="bookly-js-editable bookly-js-option %s editable-pre-wrapped" data-type="bookly" data-fieldType="textarea" data-values="%s" data-codes="%s" data-title="%s" data-placement="%s">%s</span>',
|
39 |
+
$option_name,
|
40 |
+
esc_attr( json_encode( array( $option_name => $option_value ) ) ),
|
41 |
+
esc_attr( $codes ),
|
42 |
+
esc_attr( $title ),
|
43 |
+
$placement,
|
44 |
+
esc_html( $option_value )
|
45 |
+
);
|
46 |
}
|
47 |
|
48 |
+
/**
|
49 |
+
* Render editable element.
|
50 |
+
*
|
51 |
+
* @param array $options
|
52 |
+
* @param string $tag
|
53 |
+
*/
|
54 |
+
private static function _renderEditable( array $options, $tag )
|
55 |
+
{
|
56 |
+
$data = array();
|
57 |
+
foreach ( $options as $option_name ) {
|
58 |
+
$data[ $option_name ] = get_option( $option_name );
|
59 |
+
}
|
60 |
+
|
61 |
+
printf( '<%s class="bookly-js-editable bookly-js-option %s" data-type="bookly" data-values="%s">%s</%s>',
|
62 |
+
$tag,
|
63 |
+
$options[0],
|
64 |
+
esc_attr( json_encode( $data ) ),
|
65 |
+
esc_html( $data[ $options[0] ] ),
|
66 |
+
$tag
|
67 |
+
);
|
68 |
+
}
|
69 |
}
|
backend/{resources → modules/appearance/resources}/css/bootstrap-editable.css
RENAMED
@@ -56,7 +56,7 @@
|
|
56 |
}
|
57 |
|
58 |
.editableform-loading {
|
59 |
-
background: url('
|
60 |
height: 25px;
|
61 |
width: auto;
|
62 |
min-width: 25px;
|
@@ -124,7 +124,7 @@
|
|
124 |
|
125 |
/* IOS-style clear button for text inputs */
|
126 |
.editable-clear-x {
|
127 |
-
background: url('
|
128 |
display: block;
|
129 |
width: 13px;
|
130 |
height: 13px;
|
56 |
}
|
57 |
|
58 |
.editableform-loading {
|
59 |
+
background: url('../../../../resources/images/loading.gif') center center no-repeat;
|
60 |
height: 25px;
|
61 |
width: auto;
|
62 |
min-width: 25px;
|
124 |
|
125 |
/* IOS-style clear button for text inputs */
|
126 |
.editable-clear-x {
|
127 |
+
background: url('../../../../resources/images/clear.png') center center no-repeat;
|
128 |
display: block;
|
129 |
width: 13px;
|
130 |
height: 13px;
|
backend/modules/appearance/resources/js/appearance.js
CHANGED
@@ -1,180 +1,84 @@
|
|
1 |
jQuery(function($) {
|
2 |
-
var
|
3 |
-
$
|
4 |
-
$
|
5 |
-
|
6 |
-
$
|
7 |
-
|
8 |
-
$
|
9 |
-
$
|
10 |
-
$
|
11 |
-
|
12 |
-
|
13 |
-
$
|
14 |
-
|
15 |
-
$
|
16 |
-
$
|
17 |
-
$
|
18 |
-
$
|
19 |
-
$
|
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 |
-
$
|
68 |
-
$
|
69 |
-
$
|
70 |
-
$
|
71 |
-
$
|
72 |
-
$
|
73 |
-
$
|
74 |
-
// Step
|
75 |
-
$
|
76 |
-
$
|
77 |
-
$
|
78 |
-
$
|
79 |
-
|
80 |
-
$
|
81 |
-
$
|
82 |
-
$
|
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 |
-
|
106 |
-
$(
|
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
|
147 |
-
|
148 |
-
$('.
|
149 |
-
$('.
|
150 |
-
$('.bookly-
|
151 |
-
$('.bookly-
|
152 |
-
$('.bookly-
|
|
|
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(){
|
|
|
|
|
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',
|
162 |
-
$('.
|
163 |
-
'background':
|
164 |
-
'border-color':
|
165 |
});
|
166 |
-
$('.
|
167 |
function() { // mouse-on
|
168 |
$(this).css({
|
169 |
-
'color':
|
170 |
-
'border': '2px solid ' +
|
171 |
});
|
172 |
-
$(this).find('.
|
173 |
-
'border-color':
|
174 |
-
'color':
|
175 |
});
|
176 |
-
$(this).find('.
|
177 |
-
'background':
|
178 |
});
|
179 |
},
|
180 |
function() { // mouse-out
|
@@ -182,28 +86,61 @@ jQuery(function($) {
|
|
182 |
'color': '#333333',
|
183 |
'border': '1px solid #cccccc'
|
184 |
});
|
185 |
-
$(this).find('.
|
186 |
'border-color': '#333333',
|
187 |
'color': '#cccccc'
|
188 |
});
|
189 |
-
$(this).find('.
|
190 |
'background': '#cccccc'
|
191 |
});
|
192 |
}
|
193 |
);
|
194 |
-
$('.
|
195 |
-
$('.
|
196 |
-
$('.
|
197 |
-
$('.bookly-triangle').css('border-bottom-color',
|
198 |
-
$('
|
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 |
-
|
206 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
207 |
formatSubmit : 'yyyy-mm-dd',
|
208 |
format : BooklyL10n.date_format,
|
209 |
min : true,
|
@@ -218,7 +155,38 @@ jQuery(function($) {
|
|
218 |
firstDay : BooklyL10n.start_of_week == 1
|
219 |
});
|
220 |
|
221 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
222 |
formatSubmit : 'yyyy-mm-dd',
|
223 |
format : BooklyL10n.date_format,
|
224 |
min : true,
|
@@ -239,224 +207,50 @@ jQuery(function($) {
|
|
239 |
this.open(false);
|
240 |
}
|
241 |
});
|
242 |
-
$
|
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 |
-
//
|
409 |
-
$
|
410 |
if (this.checked) {
|
411 |
-
$
|
412 |
-
|
413 |
-
|
414 |
-
day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').hide();
|
415 |
} else {
|
416 |
-
$
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
421 |
}
|
422 |
-
});
|
423 |
|
424 |
-
//
|
425 |
-
$
|
426 |
if (this.checked) {
|
427 |
-
$('.
|
428 |
} else {
|
429 |
-
$('.
|
430 |
}
|
431 |
});
|
432 |
|
433 |
-
//
|
434 |
-
$
|
435 |
if (this.checked) {
|
436 |
-
day_one_column.show();
|
437 |
-
|
438 |
} else {
|
439 |
-
day_one_column.hide();
|
440 |
-
|
441 |
}
|
442 |
});
|
443 |
|
444 |
-
|
445 |
-
|
446 |
-
|
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 |
-
//
|
459 |
-
$
|
460 |
formatSubmit : 'yyyy-mm-dd',
|
461 |
format : BooklyL10n.date_format,
|
462 |
min : true,
|
@@ -470,17 +264,17 @@ jQuery(function($) {
|
|
470 |
onRender : applyColor,
|
471 |
firstDay : BooklyL10n.start_of_week == 1
|
472 |
});
|
473 |
-
$
|
474 |
-
$
|
475 |
-
$('.bookly-variant-' + this.value).show()
|
476 |
}).trigger('change');
|
477 |
|
478 |
-
$
|
479 |
-
$
|
480 |
-
$
|
481 |
}).trigger('change');
|
482 |
|
483 |
-
$
|
484 |
var $this = $(this);
|
485 |
if ($this.is(':checked')) {
|
486 |
$this.parent().not("[class*='active']").addClass('active');
|
@@ -489,110 +283,191 @@ jQuery(function($) {
|
|
489 |
}
|
490 |
});
|
491 |
|
492 |
-
// Inherit from Abstract input.
|
493 |
-
$.fn.editableutils.inherit(multiple, $.fn.editabletypes.abstractinput);
|
494 |
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
render : function() {
|
499 |
-
this.container = jQuery('div.bookly-js-container', this.tpl);
|
500 |
-
},
|
501 |
-
|
502 |
-
value2html: function (value, element) { },
|
503 |
|
504 |
-
|
505 |
-
|
506 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
507 |
|
508 |
-
|
509 |
-
|
510 |
-
|
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 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
$target.text(this.value);
|
538 |
-
}
|
539 |
-
});
|
540 |
-
this.$elem.data('options', options);
|
541 |
-
return {elem: this.$elem};
|
542 |
}
|
543 |
});
|
544 |
-
|
545 |
-
|
546 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
547 |
});
|
548 |
|
549 |
-
|
550 |
-
$('
|
551 |
-
|
552 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
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 |
-
|
595 |
-
|
|
|
|
|
|
|
|
|
596 |
});
|
597 |
-
|
598 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
jQuery(function($) {
|
2 |
+
var
|
3 |
+
$color_picker = $('.bookly-js-color-picker'),
|
4 |
+
$editableElements = $('.bookly-js-editable'),
|
5 |
+
$show_progress_tracker = $('#bookly-show-progress-tracker'),
|
6 |
+
$step_settings = $('#bookly-step-settings'),
|
7 |
+
// Service step.
|
8 |
+
$staff_name_with_price = $('#bookly-staff-name-with-price'),
|
9 |
+
$service_name_with_duration = $('#bookly-service-name-with-duration'),
|
10 |
+
$required_employee = $('#bookly-required-employee'),
|
11 |
+
$required_location = $('#bookly-required-location'),
|
12 |
+
// Time step.
|
13 |
+
$time_step_calendar = $('.bookly-js-selected-date'),
|
14 |
+
$time_step_calendar_wrap = $('.bookly-js-slot-calendar'),
|
15 |
+
$show_blocked_timeslots = $('#bookly-show-blocked-timeslots'),
|
16 |
+
$show_day_one_column = $('#bookly-show-day-one-column'),
|
17 |
+
$show_calendar = $('#bookly-show-calendar'),
|
18 |
+
$day_one_column = $('#bookly-day-one-column'),
|
19 |
+
$day_multi_columns = $('#bookly-day-multi-columns'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
// Step repeat.
|
21 |
+
$repeat_step_calendar = $('.bookly-js-repeat-until'),
|
22 |
+
$repeat_variants = $('[class^="bookly-js-variant"]'),
|
23 |
+
$repeat_variant = $('.bookly-js-repeat-variant'),
|
24 |
+
$repeat_variant_monthly = $('.bookly-js-repeat-variant-monthly'),
|
25 |
+
$repeat_weekly_week_day = $('.bookly-js-week-day'),
|
26 |
+
$repeat_monthly_specific_day = $('.bookly-js-monthly-specific-day'),
|
27 |
+
$repeat_monthly_week_day = $('.bookly-js-monthly-week-day'),
|
28 |
+
// Step details.
|
29 |
+
$required_phone = $('#bookly-cst-required-phone'),
|
30 |
+
$show_login_button = $('#bookly-show-login-button'),
|
31 |
+
$first_last_name = $('#bookly-cst-first-last-name'),
|
32 |
+
$show_notes_field = $('#bookly-show-notes'),
|
33 |
+
// Buttons.
|
34 |
+
$save_button = $('#ajax-send-appearance'),
|
35 |
+
$reset_button = $('button[type=reset]'),
|
36 |
+
$checkboxes = $('#bookly-appearance').find('input[type="checkbox"]')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
;
|
38 |
|
39 |
+
$checkboxes.each(function () {
|
40 |
+
$(this).data('default', $(this).prop('checked'));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
});
|
42 |
+
// Menu fix for WP 3.8.1
|
43 |
+
$('#toplevel_page_ab-system > ul').css('margin-left', '0px');
|
44 |
|
|
|
|
|
|
|
45 |
// Apply color from color picker.
|
46 |
var applyColor = function() {
|
47 |
+
var color = $color_picker.wpColorPicker('color'),
|
48 |
+
color_important = color + '!important;';
|
49 |
+
$('.bookly-progress-tracker').find('.active').css('color', color).find('.step').css('background', color);
|
50 |
+
$('.bookly-js-mobile-step-1 label').css('color', color);
|
51 |
+
$('.bookly-label-error').css('color', color);
|
52 |
+
$('.bookly-js-actions > a').css('background-color', color);
|
53 |
+
$('.bookly-js-mobile-next-step').css('background', color);
|
54 |
+
$('.bookly-js-week-days label').css('background-color', color);
|
55 |
$('.picker__frame').attr('style', 'background: ' + color_important);
|
56 |
$('.picker__header').attr('style', 'border-bottom: ' + '1px solid ' + color_important);
|
57 |
+
$('.picker__day').off().mouseenter(function() {
|
58 |
$(this).attr('style', 'color: ' + color_important);
|
59 |
+
}).mouseleave(function(){
|
60 |
+
$(this).attr('style', $(this).hasClass('picker__day--selected') ? 'color: ' + color_important : '')
|
61 |
+
});
|
62 |
$('.picker__day--selected').attr('style', 'color: ' + color_important);
|
63 |
$('.picker__button--clear').attr('style', 'color: ' + color_important);
|
64 |
$('.picker__button--today').attr('style', 'color: ' + color_important);
|
65 |
+
$('.bookly-extra-step .bookly-extras-thumb.bookly-extras-selected').css('border-color', color);
|
66 |
+
$('.bookly-columnizer .bookly-day, .bookly-schedule-date,.bookly-pagination li.active').css({
|
67 |
+
'background': color,
|
68 |
+
'border-color': color
|
69 |
});
|
70 |
+
$('.bookly-columnizer .bookly-hour').off().hover(
|
71 |
function() { // mouse-on
|
72 |
$(this).css({
|
73 |
+
'color': color,
|
74 |
+
'border': '2px solid ' + color
|
75 |
});
|
76 |
+
$(this).find('.bookly-hour-icon').css({
|
77 |
+
'border-color': color,
|
78 |
+
'color': color
|
79 |
});
|
80 |
+
$(this).find('.bookly-hour-icon > span').css({
|
81 |
+
'background': color
|
82 |
});
|
83 |
},
|
84 |
function() { // mouse-out
|
86 |
'color': '#333333',
|
87 |
'border': '1px solid #cccccc'
|
88 |
});
|
89 |
+
$(this).find('.bookly-hour-icon').css({
|
90 |
'border-color': '#333333',
|
91 |
'color': '#cccccc'
|
92 |
});
|
93 |
+
$(this).find('.bookly-hour-icon > span').css({
|
94 |
'background': '#cccccc'
|
95 |
});
|
96 |
}
|
97 |
);
|
98 |
+
$('.bookly-details-step label').css('color', color);
|
99 |
+
$('.bookly-card-form label').css('color', color);
|
100 |
+
$('.bookly-nav-tabs .ladda-button, .bookly-nav-steps .ladda-button, .bookly-btn, .bookly-round, .bookly-square').css('background-color', color);
|
101 |
+
$('.bookly-triangle').css('border-bottom-color', color);
|
102 |
+
$('#bookly-pickadate-style').html('.picker__nav--next:before { border-left: 6px solid ' + color_important + ' } .picker__nav--prev:before { border-right: 6px solid ' + color_important + ' }');
|
|
|
|
|
103 |
};
|
104 |
+
|
105 |
+
// Init color picker.
|
106 |
$color_picker.wpColorPicker({
|
107 |
change : applyColor
|
108 |
});
|
109 |
+
|
110 |
+
// Init editable elements.
|
111 |
+
$editableElements.editable();
|
112 |
+
|
113 |
+
// Show progress tracker.
|
114 |
+
$show_progress_tracker.on('change', function() {
|
115 |
+
$('.bookly-progress-tracker').toggle(this.checked);
|
116 |
+
}).trigger('change');
|
117 |
+
|
118 |
+
// Show step specific settings.
|
119 |
+
$('li.bookly-nav-item').on('shown.bs.tab', function (e) {
|
120 |
+
$step_settings.children().hide();
|
121 |
+
switch (e.target.getAttribute('data-target')) {
|
122 |
+
case '#bookly-step-1': $step_settings.find('.bookly-js-service-settings').show(); break;
|
123 |
+
case '#bookly-step-3': $step_settings.find('.bookly-js-time-settings').show(); break;
|
124 |
+
case '#bookly-step-6': $step_settings.find('.bookly-js-details-settings').show(); break;
|
125 |
+
case '#bookly-step-7': $step_settings.find('.bookly-js-payment-settings').show(); break;
|
126 |
+
case '#bookly-step-8': $step_settings.find('.bookly-js-done-settings').show(); break;
|
127 |
+
}
|
128 |
+
});
|
129 |
+
|
130 |
+
// Dismiss help notice.
|
131 |
+
$('#bookly-js-hint-alert').on('closed.bs.alert', function () {
|
132 |
+
$.ajax({
|
133 |
+
url: ajaxurl,
|
134 |
+
data: { action: 'bookly_dismiss_appearance_notice', csrf_token : BooklyL10n.csrf_token }
|
135 |
+
});
|
136 |
+
});
|
137 |
+
|
138 |
+
/**
|
139 |
+
* Step Service
|
140 |
+
*/
|
141 |
+
|
142 |
+
// Init calendar.
|
143 |
+
$('.bookly-js-date-from').pickadate({
|
144 |
formatSubmit : 'yyyy-mm-dd',
|
145 |
format : BooklyL10n.date_format,
|
146 |
min : true,
|
155 |
firstDay : BooklyL10n.start_of_week == 1
|
156 |
});
|
157 |
|
158 |
+
// Show price next to staff member name.
|
159 |
+
$staff_name_with_price.on('change', function () {
|
160 |
+
var staff = $('.bookly-js-select-employee').val();
|
161 |
+
if (staff) {
|
162 |
+
$('.bookly-js-select-employee').val(staff * -1);
|
163 |
+
}
|
164 |
+
$('.employee-name-price').toggle($staff_name_with_price.prop("checked"));
|
165 |
+
$('.employee-name').toggle(!$staff_name_with_price.prop("checked"));
|
166 |
+
}).trigger('change');
|
167 |
+
|
168 |
+
// Show duration next to service name.
|
169 |
+
$service_name_with_duration.on('change', function () {
|
170 |
+
var service = $('.bookly-js-select-service').val();
|
171 |
+
if (service) {
|
172 |
+
$('.bookly-js-select-service').val(service * -1);
|
173 |
+
}
|
174 |
+
$('.service-name-duration').toggle($service_name_with_duration.prop("checked"));
|
175 |
+
$('.service-name').toggle(!$service_name_with_duration.prop("checked"));
|
176 |
+
}).trigger('change');
|
177 |
+
|
178 |
+
// Clickable week-days.
|
179 |
+
$repeat_weekly_week_day.on('change', function () {
|
180 |
+
$(this).parent().toggleClass('active', this.checked);
|
181 |
+
});
|
182 |
+
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Step Time
|
186 |
+
*/
|
187 |
+
|
188 |
+
// Init calendar.
|
189 |
+
$time_step_calendar.pickadate({
|
190 |
formatSubmit : 'yyyy-mm-dd',
|
191 |
format : BooklyL10n.date_format,
|
192 |
min : true,
|
207 |
this.open(false);
|
208 |
}
|
209 |
});
|
210 |
+
$time_step_calendar_wrap.find('.picker__holder').css({ top : '0px', left : '0px' });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
211 |
|
212 |
+
// Show calendar.
|
213 |
+
$show_calendar.on('change', function() {
|
214 |
if (this.checked) {
|
215 |
+
$time_step_calendar_wrap.show();
|
216 |
+
$day_multi_columns.find('.col3,.col4,.col5,.col6,.col7').hide();
|
217 |
+
$day_multi_columns.find('.col2 button:gt(0)').attr('style', 'display: none !important');
|
218 |
+
$day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').hide();
|
219 |
} else {
|
220 |
+
$time_step_calendar_wrap.hide();
|
221 |
+
$day_multi_columns.find('.col2 button:gt(0)').attr('style', 'display: block !important');
|
222 |
+
$day_multi_columns.find('.col2 button.bookly-js-first-child').attr('style', 'background: ' + $color_picker.wpColorPicker('color') + '!important;display: block !important');
|
223 |
+
$day_multi_columns.find('.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
224 |
+
$day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
225 |
}
|
226 |
+
}).trigger('change');
|
227 |
|
228 |
+
// Show blocked time slots.
|
229 |
+
$show_blocked_timeslots.on('change', function(){
|
230 |
if (this.checked) {
|
231 |
+
$('.bookly-hour.no-booked').removeClass('no-booked').addClass('booked');
|
232 |
} else {
|
233 |
+
$('.bookly-hour.booked').removeClass('booked').addClass('no-booked');
|
234 |
}
|
235 |
});
|
236 |
|
237 |
+
// Show day as one column.
|
238 |
+
$show_day_one_column.change(function() {
|
239 |
if (this.checked) {
|
240 |
+
$day_one_column.show();
|
241 |
+
$day_multi_columns.hide();
|
242 |
} else {
|
243 |
+
$day_one_column.hide();
|
244 |
+
$day_multi_columns.show();
|
245 |
}
|
246 |
});
|
247 |
|
248 |
+
/**
|
249 |
+
* Step repeat.
|
250 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
|
252 |
+
// Init calendar.
|
253 |
+
$repeat_step_calendar.pickadate({
|
254 |
formatSubmit : 'yyyy-mm-dd',
|
255 |
format : BooklyL10n.date_format,
|
256 |
min : true,
|
264 |
onRender : applyColor,
|
265 |
firstDay : BooklyL10n.start_of_week == 1
|
266 |
});
|
267 |
+
$repeat_variant.on('change', function () {
|
268 |
+
$repeat_variants.hide();
|
269 |
+
$('.bookly-js-variant-' + this.value).show()
|
270 |
}).trigger('change');
|
271 |
|
272 |
+
$repeat_variant_monthly.on('change', function () {
|
273 |
+
$repeat_monthly_week_day.toggle(this.value != 'specific');
|
274 |
+
$repeat_monthly_specific_day.toggle(this.value == 'specific');
|
275 |
}).trigger('change');
|
276 |
|
277 |
+
$repeat_weekly_week_day.on('change', function () {
|
278 |
var $this = $(this);
|
279 |
if ($this.is(':checked')) {
|
280 |
$this.parent().not("[class*='active']").addClass('active');
|
283 |
}
|
284 |
});
|
285 |
|
|
|
|
|
286 |
|
287 |
+
/**
|
288 |
+
* Step Details
|
289 |
+
*/
|
|
|
|
|
|
|
|
|
|
|
290 |
|
291 |
+
// Init phone field.
|
292 |
+
if (BooklyL10n.intlTelInput.enabled) {
|
293 |
+
$('.bookly-user-phone').intlTelInput({
|
294 |
+
preferredCountries: [BooklyL10n.intlTelInput.country],
|
295 |
+
initialCountry: BooklyL10n.intlTelInput.country,
|
296 |
+
geoIpLookup: function (callback) {
|
297 |
+
$.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
298 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
299 |
+
callback(countryCode);
|
300 |
+
});
|
301 |
+
},
|
302 |
+
utilsScript: BooklyL10n.intlTelInput.utils
|
303 |
+
});
|
304 |
+
}
|
305 |
|
306 |
+
// Show login form.
|
307 |
+
$show_login_button.change(function () {
|
308 |
+
$('#bookly-js-show-login-form').toggle(this.checked);
|
309 |
+
}).trigger('change');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
310 |
|
311 |
+
// Show first and last name.
|
312 |
+
$first_last_name.on('change', function () {
|
313 |
+
$first_last_name.popover('toggle');
|
314 |
+
if (this.checked) {
|
315 |
+
$('.bookly-details-full-name').css('display', 'none');
|
316 |
+
$('.bookly-details-first-last-name').css('display', 'table');
|
317 |
+
} else {
|
318 |
+
$('.bookly-details-full-name').css('display', 'block');
|
319 |
+
$('.bookly-details-first-last-name').css('display', 'none');
|
|
|
|
|
|
|
|
|
|
|
320 |
}
|
321 |
});
|
322 |
+
|
323 |
+
// Show notes field.
|
324 |
+
$show_notes_field.change(function () {
|
325 |
+
$('#bookly-js-notes').toggle(this.checked);
|
326 |
+
}).trigger('change');
|
327 |
+
|
328 |
+
/**
|
329 |
+
* Step Payment.
|
330 |
+
*/
|
331 |
+
|
332 |
+
// Switch payment step view (single/several services).
|
333 |
+
$('#bookly-payment-step-view').on('change', function () {
|
334 |
+
$('.bookly-js-payment-single-app').toggle(this.value == 'single-app');
|
335 |
+
$('.bookly-js-payment-several-apps').toggle(this.value == 'several-apps');
|
336 |
});
|
337 |
|
338 |
+
// Show credit card form.
|
339 |
+
$('.bookly-payment-nav :radio').on('change', function () {
|
340 |
+
$('form.bookly-card-form').toggle(this.id == 'bookly-card-payment');
|
341 |
+
});
|
342 |
+
|
343 |
+
/**
|
344 |
+
* Step Done.
|
345 |
+
*/
|
346 |
+
|
347 |
+
// Switch done step view (success/error).
|
348 |
+
$('#bookly-done-step-view').on('change', function () {
|
349 |
+
$('.bookly-js-done-success').toggle(this.value == 'booking-success');
|
350 |
+
$('.bookly-js-done-limit-error').toggle(this.value == 'booking-limit-error');
|
351 |
+
$('.bookly-js-done-processing').toggle(this.value == 'booking-processing');
|
352 |
});
|
353 |
|
|
|
|
|
354 |
|
355 |
+
/**
|
356 |
+
* Misc.
|
357 |
+
*/
|
358 |
+
|
359 |
+
// Custom CSS.
|
360 |
+
$('#bookly-custom-css-save').on('click', function (e) {
|
361 |
+
var $custom_css = $('#bookly-custom-css'),
|
362 |
+
$modal = $('#bookly-custom-css-dialog');
|
363 |
+
|
364 |
+
saved_css = $custom_css.val();
|
365 |
+
|
366 |
+
var ladda = Ladda.create(this);
|
367 |
+
ladda.start();
|
368 |
|
369 |
+
$.ajax({
|
370 |
+
url : ajaxurl,
|
371 |
+
type : 'POST',
|
372 |
+
data : {
|
373 |
+
action : 'bookly_save_custom_css',
|
374 |
+
csrf_token : BooklyL10n.csrf_token,
|
375 |
+
custom_css : $custom_css.val()
|
376 |
+
},
|
377 |
+
dataType : 'json',
|
378 |
+
success : function (response) {
|
379 |
+
if (response.success) {
|
380 |
+
$modal.modal('hide');
|
381 |
+
booklyAlert({success : [response.data.message]});
|
382 |
+
}
|
383 |
+
},
|
384 |
+
complete : function () {
|
385 |
+
ladda.stop();
|
386 |
+
}
|
387 |
+
});
|
388 |
});
|
389 |
+
|
390 |
+
$('#bookly-custom-css-cancel').on('click', function (e) {
|
391 |
+
var $custom_css = $('#bookly-custom-css'),
|
392 |
+
$modal = $('#bookly-custom-css-dialog');
|
393 |
+
|
394 |
+
$modal.modal('hide');
|
395 |
+
|
396 |
+
$custom_css.val(saved_css);
|
397 |
});
|
398 |
|
399 |
+
$('#bookly-custom-css').keydown(function(e) {
|
400 |
+
if(e.keyCode === 9) { //tab button
|
401 |
+
var start = this.selectionStart;
|
402 |
+
var end = this.selectionEnd;
|
403 |
+
|
404 |
+
var $this = $(this);
|
405 |
+
var value = $this.val();
|
406 |
+
|
407 |
+
$this.val(value.substring(0, start)
|
408 |
+
+ "\t"
|
409 |
+
+ value.substring(end));
|
410 |
+
|
411 |
+
this.selectionStart = this.selectionEnd = start + 1;
|
412 |
+
|
413 |
+
e.preventDefault();
|
414 |
}
|
415 |
});
|
416 |
|
417 |
+
// Save options.
|
418 |
+
$save_button.on('click', function(e) {
|
419 |
+
e.preventDefault();
|
420 |
+
// Prepare data.
|
421 |
+
var data = {
|
422 |
+
action: 'bookly_update_appearance_options',
|
423 |
+
csrf_token: BooklyL10n.csrf_token,
|
424 |
+
options: {
|
425 |
+
// Color.
|
426 |
+
'bookly_app_color' : $color_picker.wpColorPicker('color'),
|
427 |
+
// Checkboxes.
|
428 |
+
'bookly_app_service_name_with_duration' : Number($service_name_with_duration.prop('checked')),
|
429 |
+
'bookly_app_show_blocked_timeslots' : Number($show_blocked_timeslots.prop('checked')),
|
430 |
+
'bookly_app_show_calendar' : Number($show_calendar.prop('checked')),
|
431 |
+
'bookly_app_show_day_one_column' : Number($show_day_one_column.prop('checked')),
|
432 |
+
'bookly_app_show_login_button' : Number($show_login_button.prop('checked')),
|
433 |
+
'bookly_app_show_notes' : Number($show_notes_field.prop('checked')),
|
434 |
+
'bookly_app_show_progress_tracker' : Number($show_progress_tracker.prop('checked')),
|
435 |
+
'bookly_app_staff_name_with_price' : Number($staff_name_with_price.prop('checked')),
|
436 |
+
'bookly_app_required_employee' : Number($required_employee.prop('checked')),
|
437 |
+
'bookly_app_required_location' : Number($required_location.prop('checked')),
|
438 |
+
'bookly_cst_required_phone' : Number($required_phone.prop('checked')),
|
439 |
+
'bookly_cst_first_last_name' : Number($first_last_name.prop('checked'))
|
440 |
+
}
|
441 |
+
};
|
442 |
+
// Add data from editable elements.
|
443 |
+
$editableElements.each(function () {
|
444 |
+
$.extend(data.options, $(this).editable('getValue', true));
|
445 |
+
});
|
446 |
+
|
447 |
+
// Update data and show spinner while updating.
|
448 |
+
var ladda = Ladda.create(this);
|
449 |
+
ladda.start();
|
450 |
+
$.post(ajaxurl, data, function (response) {
|
451 |
+
ladda.stop();
|
452 |
+
booklyAlert({success : [BooklyL10n.saved]});
|
453 |
+
});
|
454 |
});
|
455 |
|
456 |
+
// Reset options to defaults.
|
457 |
+
$reset_button.on('click', function() {
|
458 |
+
// Reset color.
|
459 |
+
$color_picker.wpColorPicker('color', $color_picker.data('selected'));
|
460 |
+
|
461 |
+
// Reset editable texts.
|
462 |
+
$editableElements.each(function () {
|
463 |
+
$(this).editable('setValue', $.extend({}, $(this).data('values')));
|
464 |
});
|
465 |
+
|
466 |
+
$checkboxes.each(function () {
|
467 |
+
if ($(this).prop('checked') != $(this).data('default')) {
|
468 |
+
$(this).prop('checked', $(this).data('default')).trigger('change');
|
469 |
+
}
|
470 |
+
});
|
471 |
+
$first_last_name.popover('hide');
|
472 |
+
});
|
473 |
+
});
|
backend/modules/appearance/resources/js/bootstrap-editable.bookly.js
ADDED
@@ -0,0 +1,112 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function($) {
|
2 |
+
var Bookly = function (options) {
|
3 |
+
this.init('bookly', options, Bookly.defaults);
|
4 |
+
};
|
5 |
+
|
6 |
+
// Inherit from Abstract input.
|
7 |
+
$.fn.editableutils.inherit(Bookly, $.fn.editabletypes.abstractinput);
|
8 |
+
|
9 |
+
$.extend(Bookly.prototype, {
|
10 |
+
html2value: function(html) {
|
11 |
+
return $.extend({}, $(this.options.scope).data('values'));
|
12 |
+
},
|
13 |
+
value2html: function (values, element) {
|
14 |
+
$.each(values, function (option_name, option_value) {
|
15 |
+
// Find all elements which display option value.
|
16 |
+
$('.bookly-js-option.' + option_name).each(function () {
|
17 |
+
var $this = $(this);
|
18 |
+
if (!$this.hasClass('editable') || $this.is(element)) {
|
19 |
+
// Update text.
|
20 |
+
$this.text(option_value);
|
21 |
+
}
|
22 |
+
});
|
23 |
+
});
|
24 |
+
},
|
25 |
+
activate: function () {
|
26 |
+
this.$tpl.find(':input:first').focus();
|
27 |
+
},
|
28 |
+
value2input: function (values) {
|
29 |
+
var _this = this;
|
30 |
+
this.$tpl.empty();
|
31 |
+
$.each(values, function (option_name, option_value) {
|
32 |
+
var $row = $('<div/>')
|
33 |
+
.css({position: 'relative', 'margin-top': '6px'})
|
34 |
+
.appendTo(_this.$tpl);
|
35 |
+
if (_this.options.fieldType == 'input') {
|
36 |
+
// Create input with "x" button.
|
37 |
+
var $clear = $('<span class="editable-clear-x"></span>');
|
38 |
+
var $input = $('<input/>', {
|
39 |
+
type : 'text',
|
40 |
+
class: 'form-control',
|
41 |
+
name : option_name,
|
42 |
+
value: option_value
|
43 |
+
});
|
44 |
+
$input.keyup(function(e) {
|
45 |
+
// arrows, enter, tab, etc
|
46 |
+
if (~$.inArray(e.keyCode, [40,38,9,13,27])) {
|
47 |
+
return;
|
48 |
+
}
|
49 |
+
clearTimeout(this.t);
|
50 |
+
this.t = setTimeout(function() {
|
51 |
+
var len = $input.val().length,
|
52 |
+
visible = $clear.is(':visible');
|
53 |
+
if (len && !visible) {
|
54 |
+
$clear.show();
|
55 |
+
}
|
56 |
+
if (!len && visible) {
|
57 |
+
$clear.hide();
|
58 |
+
}
|
59 |
+
}, 100);
|
60 |
+
});
|
61 |
+
$clear.click(function () {
|
62 |
+
$clear.hide();
|
63 |
+
$input.val('').focus();
|
64 |
+
});
|
65 |
+
$row.append($input).append($clear);
|
66 |
+
} else {
|
67 |
+
// Create textarea.
|
68 |
+
$('<textarea/>', {
|
69 |
+
class: 'form-control',
|
70 |
+
name : option_name,
|
71 |
+
rows : 7
|
72 |
+
}).val(option_value).appendTo($row);
|
73 |
+
}
|
74 |
+
});
|
75 |
+
// Set codes.
|
76 |
+
this.$tpl.closest('form').find('.bookly-js-codes').html($(this.options.scope).data('codes'));
|
77 |
+
},
|
78 |
+
input2value: function () {
|
79 |
+
var _this = this;
|
80 |
+
var values = {};
|
81 |
+
this.$tpl.find(':input').each(function () {
|
82 |
+
values[this.name] = this.value;
|
83 |
+
// Find all elements which display option value.
|
84 |
+
var option_name = this.name;
|
85 |
+
var option_value = this.value;
|
86 |
+
$('.bookly-js-option.' + option_name).each(function () {
|
87 |
+
var $this = $(this);
|
88 |
+
if ($this.hasClass('editable') && !$this.is(_this.$tpl)) {
|
89 |
+
// Update editable value.
|
90 |
+
var val = $this.editable('getValue', true);
|
91 |
+
val[option_name] = option_value;
|
92 |
+
$this.editable('setValue', val);
|
93 |
+
}
|
94 |
+
});
|
95 |
+
});
|
96 |
+
|
97 |
+
return values;
|
98 |
+
}
|
99 |
+
});
|
100 |
+
|
101 |
+
Bookly.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
102 |
+
tpl: '<div/>',
|
103 |
+
fieldType: 'input'
|
104 |
+
});
|
105 |
+
|
106 |
+
$.fn.editabletypes.bookly = Bookly;
|
107 |
+
|
108 |
+
// Set template for popovers and editable form.
|
109 |
+
$.fn.popover.Constructor.DEFAULTS.template = '<div class="popover"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>';
|
110 |
+
$.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="bookly-js-codes"></div><div class="editable-error-block"></div></div></form>';
|
111 |
+
$.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>';
|
112 |
+
});
|
backend/{resources → modules/appearance/resources}/js/bootstrap-editable.min.js
RENAMED
@@ -1,4 +1,4 @@
|
|
1 |
-
/*! X-editable - v1.5.1
|
2 |
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
3 |
* http://github.com/vitalets/x-editable
|
4 |
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
|
1 |
+
/*! X-editable - v1.5.1
|
2 |
* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery
|
3 |
* http://github.com/vitalets/x-editable
|
4 |
* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */
|
backend/modules/appearance/templates/_1_service.php
CHANGED
@@ -1,28 +1,34 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
11 |
-
|
12 |
-
|
13 |
</div>
|
14 |
-
<div class="
|
15 |
<div class="bookly-js-chain-item bookly-table bookly-box">
|
16 |
-
<?php if ( \BooklyLite\Lib\Config::
|
17 |
-
<div class="
|
18 |
-
<?php
|
19 |
</div>
|
20 |
<?php endif ?>
|
21 |
-
<div class="
|
22 |
-
<?php
|
23 |
<div>
|
24 |
-
<select class="
|
25 |
-
<option value=""
|
26 |
<option value="1">Cosmetic Dentistry</option>
|
27 |
<option value="2">Invisalign</option>
|
28 |
<option value="3">Orthodontics</option>
|
@@ -30,126 +36,133 @@
|
|
30 |
</select>
|
31 |
</div>
|
32 |
</div>
|
33 |
-
<div class="
|
34 |
-
<?php
|
35 |
'bookly_l10n_label_service',
|
36 |
'bookly_l10n_option_service',
|
37 |
'bookly_l10n_required_service',
|
38 |
) ) ?>
|
39 |
<div>
|
40 |
-
<select class="
|
41 |
-
<option
|
42 |
-
<option>Crown and Bridge</option>
|
43 |
-
<option>
|
44 |
-
<option>
|
45 |
-
<option>
|
46 |
-
<option>
|
47 |
-
<option
|
48 |
-
<option>
|
49 |
-
<option>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
</select>
|
51 |
</div>
|
52 |
</div>
|
53 |
-
<div class="
|
54 |
-
<?php
|
55 |
'bookly_l10n_label_employee',
|
56 |
'bookly_l10n_option_employee',
|
57 |
'bookly_l10n_required_employee',
|
58 |
) ) ?>
|
59 |
<div>
|
60 |
-
<select class="
|
61 |
-
<option value="0"
|
62 |
-
<option value="1" class="employee-name-price">Nick Knight (<?php echo
|
63 |
<option value="-1" class="employee-name">Nick Knight</option>
|
64 |
-
<option value="2" class="employee-name-price">Jane Howard (<?php echo
|
65 |
<option value="-2" class="employee-name">Jane Howard</option>
|
66 |
-
<option value="3" class="employee-name-price">Ashley Stamp (<?php echo
|
67 |
<option value="-3" class="employee-name">Ashley Stamp</option>
|
68 |
-
<option value="4" class="employee-name-price">Bradley Tannen (<?php echo
|
69 |
<option value="-4" class="employee-name">Bradley Tannen</option>
|
70 |
-
<option value="5" class="employee-name-price">Wayne Turner (<?php echo
|
71 |
<option value="-5" class="employee-name">Wayne Turner</option>
|
72 |
-
<option value="6" class="employee-name-price">Emily Taylor (<?php echo
|
73 |
<option value="-6" class="employee-name">Emily Taylor</option>
|
74 |
-
<option value="7" class="employee-name-price">Hugh Canberg (<?php echo
|
75 |
<option value="-7" class="employee-name">Hugh Canberg</option>
|
76 |
-
<option value="8" class="employee-name-price">Jim Gonzalez (<?php echo
|
77 |
<option value="-8" class="employee-name">Jim Gonzalez</option>
|
78 |
-
<option value="9" class="employee-name-price">Nancy Stinson (<?php echo
|
79 |
<option value="-9" class="employee-name">Nancy Stinson</option>
|
80 |
-
<option value="10" class="employee-name-price">Marry Murphy (<?php echo
|
81 |
<option value="-10" class="employee-name">Marry Murphy</option>
|
82 |
</select>
|
83 |
</div>
|
84 |
</div>
|
85 |
-
<div class="
|
86 |
-
<?php
|
87 |
<div>
|
88 |
-
<select class="
|
89 |
<option>1</option>
|
90 |
<option>2</option>
|
91 |
<option>3</option>
|
92 |
</select>
|
93 |
</div>
|
94 |
</div>
|
95 |
-
<?php if ( \BooklyLite\Lib\Config::
|
96 |
-
<div class="
|
97 |
-
<?php
|
98 |
</div>
|
99 |
<?php endif ?>
|
100 |
-
<?php if ( \BooklyLite\Lib\Config::
|
101 |
-
<div class="
|
102 |
<label></label>
|
103 |
<div>
|
104 |
-
<button class="bookly-round"
|
105 |
</div>
|
106 |
</div>
|
107 |
<?php endif ?>
|
108 |
</div>
|
109 |
-
|
110 |
-
|
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="
|
115 |
<div class="bookly-box">
|
116 |
-
<div class="
|
117 |
-
<div class="
|
118 |
-
<div class="
|
119 |
-
<?php
|
120 |
<div>
|
121 |
-
<input class="
|
122 |
</div>
|
123 |
</div>
|
124 |
</div>
|
125 |
-
<div class="bookly-week-days bookly-table
|
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="
|
137 |
-
<div class="
|
138 |
-
<?php
|
139 |
<div>
|
140 |
-
<select class="
|
141 |
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
142 |
-
<option><?php echo
|
143 |
<?php endfor ?>
|
144 |
</select>
|
145 |
</div>
|
146 |
</div>
|
147 |
-
<div class="
|
148 |
-
<?php
|
149 |
<div>
|
150 |
-
<select class="
|
151 |
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
152 |
-
<option<?php selected( $i == 64800 ) ?>><?php echo
|
153 |
<?php endfor ?>
|
154 |
</select>
|
155 |
</div>
|
@@ -157,23 +170,20 @@
|
|
157 |
</div>
|
158 |
</div>
|
159 |
<div class="bookly-box bookly-nav-steps">
|
160 |
-
<div class="
|
161 |
-
<?php
|
162 |
</div>
|
163 |
-
<div class="bookly-next-step
|
164 |
-
<?php
|
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
|
174 |
<?php endforeach ?>
|
175 |
</div>
|
176 |
-
<style id="
|
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>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Price;
|
3 |
+
use BooklyLite\Lib\Utils\DateTime;
|
4 |
+
|
5 |
+
/**
|
6 |
+
* @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable
|
7 |
+
* @var WP_Locale $wp_locale
|
8 |
+
*/
|
9 |
+
global $wp_locale;
|
10 |
?>
|
11 |
<div class="bookly-form">
|
12 |
<?php include '_progress_tracker.php' ?>
|
13 |
|
14 |
<div class="bookly-service-step">
|
15 |
<div class="bookly-box">
|
16 |
+
<span class="bookly-bold bookly-desc">
|
17 |
+
<?php $editable::renderText( 'bookly_l10n_info_service_step' ) ?>
|
18 |
+
</span>
|
19 |
</div>
|
20 |
+
<div class="bookly-mobile-step-1 bookly-js-mobile-step-1 bookly-box">
|
21 |
<div class="bookly-js-chain-item bookly-table bookly-box">
|
22 |
+
<?php if ( \BooklyLite\Lib\Config::locationsEnabled() ) : ?>
|
23 |
+
<div class="bookly-form-group">
|
24 |
+
<?php \BooklyLite\Lib\Proxy\Locations::renderAppearance() ?>
|
25 |
</div>
|
26 |
<?php endif ?>
|
27 |
+
<div class="bookly-form-group">
|
28 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_category', 'bookly_l10n_option_category', ) ) ?>
|
29 |
<div>
|
30 |
+
<select class="bookly-select-mobile bookly-js-select-category">
|
31 |
+
<option value="" class="bookly-js-option bookly_l10n_option_category"><?php echo esc_html( get_option( 'bookly_l10n_option_category' ) ) ?></option>
|
32 |
<option value="1">Cosmetic Dentistry</option>
|
33 |
<option value="2">Invisalign</option>
|
34 |
<option value="3">Orthodontics</option>
|
36 |
</select>
|
37 |
</div>
|
38 |
</div>
|
39 |
+
<div class="bookly-form-group">
|
40 |
+
<?php $editable::renderLabel( array(
|
41 |
'bookly_l10n_label_service',
|
42 |
'bookly_l10n_option_service',
|
43 |
'bookly_l10n_required_service',
|
44 |
) ) ?>
|
45 |
<div>
|
46 |
+
<select class="bookly-select-mobile bookly-js-select-service">
|
47 |
+
<option value="0" class="bookly-js-option bookly_l10n_option_service"><?php echo esc_html( get_option( 'bookly_l10n_option_service' ) ) ?></option>
|
48 |
+
<option value="1" class="service-name-duration">Crown and Bridge (<?php echo DateTime::secondsToInterval( 3600 ) ?>)</option>
|
49 |
+
<option value="-1" class="service-name">Crown and Bridge</option>
|
50 |
+
<option value="2" class="service-name-duration">Teeth Whitening (<?php echo DateTime::secondsToInterval( 3600 * 2 ) ?>)</option>
|
51 |
+
<option value="-2" class="service-name">Teeth Whitening</option>
|
52 |
+
<option value="3" class="service-name-duration">Veneers (<?php echo DateTime::secondsToInterval( 3600 * 12 ) ?>)</option>
|
53 |
+
<option value="-3" class="service-name">Veneers</option>
|
54 |
+
<option value="4" class="service-name-duration">Invisalign (invisable braces) (<?php echo DateTime::secondsToInterval( 3600 * 24 ) ?>)</option>
|
55 |
+
<option value="-4" class="service-name">Invisalign (invisable braces)</option>
|
56 |
+
<option value="5" class="service-name-duration">Orthodontics (braces) (<?php echo DateTime::secondsToInterval( 3600 * 8 ) ?>)</option>
|
57 |
+
<option value="-5" class="service-name">Orthodontics (braces)</option>
|
58 |
+
<option value="6" class="service-name-duration">Wisdom tooth Removal (<?php echo DateTime::secondsToInterval( 3600 * 6 ) ?>)</option>
|
59 |
+
<option value="-6" class="service-name">Wisdom tooth Removal</option>
|
60 |
+
<option value="7" class="service-name-duration">Root Canal Treatment (<?php echo DateTime::secondsToInterval( 3600 * 16 ) ?>)</option>
|
61 |
+
<option value="-7" class="service-name">Root Canal Treatment</option>
|
62 |
+
<option value="8" class="service-name-duration">Dentures (<?php echo DateTime::secondsToInterval( 3600 * 48 ) ?>)</option>
|
63 |
+
<option value="-8" class="service-name">Dentures</option>
|
64 |
</select>
|
65 |
</div>
|
66 |
</div>
|
67 |
+
<div class="bookly-form-group">
|
68 |
+
<?php $editable::renderLabel( array(
|
69 |
'bookly_l10n_label_employee',
|
70 |
'bookly_l10n_option_employee',
|
71 |
'bookly_l10n_required_employee',
|
72 |
) ) ?>
|
73 |
<div>
|
74 |
+
<select class="bookly-select-mobile bookly-js-select-employee">
|
75 |
+
<option value="0" class="bookly-js-option bookly_l10n_option_employee"><?php echo esc_html( get_option( 'bookly_l10n_option_employee' ) ) ?></option>
|
76 |
+
<option value="1" class="employee-name-price">Nick Knight (<?php echo Price::format( 350 ) ?>)</option>
|
77 |
<option value="-1" class="employee-name">Nick Knight</option>
|
78 |
+
<option value="2" class="employee-name-price">Jane Howard (<?php echo Price::format( 375 ) ?>)</option>
|
79 |
<option value="-2" class="employee-name">Jane Howard</option>
|
80 |
+
<option value="3" class="employee-name-price">Ashley Stamp (<?php echo Price::format( 300 ) ?>)</option>
|
81 |
<option value="-3" class="employee-name">Ashley Stamp</option>
|
82 |
+
<option value="4" class="employee-name-price">Bradley Tannen (<?php echo Price::format( 400 ) ?>)</option>
|
83 |
<option value="-4" class="employee-name">Bradley Tannen</option>
|
84 |
+
<option value="5" class="employee-name-price">Wayne Turner (<?php echo Price::format( 350 ) ?>)</option>
|
85 |
<option value="-5" class="employee-name">Wayne Turner</option>
|
86 |
+
<option value="6" class="employee-name-price">Emily Taylor (<?php echo Price::format( 350 ) ?>)</option>
|
87 |
<option value="-6" class="employee-name">Emily Taylor</option>
|
88 |
+
<option value="7" class="employee-name-price">Hugh Canberg (<?php echo Price::format( 380 ) ?>)</option>
|
89 |
<option value="-7" class="employee-name">Hugh Canberg</option>
|
90 |
+
<option value="8" class="employee-name-price">Jim Gonzalez (<?php echo Price::format( 390 ) ?>)</option>
|
91 |
<option value="-8" class="employee-name">Jim Gonzalez</option>
|
92 |
+
<option value="9" class="employee-name-price">Nancy Stinson (<?php echo Price::format( 360 ) ?>)</option>
|
93 |
<option value="-9" class="employee-name">Nancy Stinson</option>
|
94 |
+
<option value="10" class="employee-name-price">Marry Murphy (<?php echo Price::format( 350 ) ?>)</option>
|
95 |
<option value="-10" class="employee-name">Marry Murphy</option>
|
96 |
</select>
|
97 |
</div>
|
98 |
</div>
|
99 |
+
<div class="bookly-form-group" style="display: none">
|
100 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_number_of_persons', ) ) ?>
|
101 |
<div>
|
102 |
+
<select class="bookly-select-mobile bookly-js-select-number-of-persons">
|
103 |
<option>1</option>
|
104 |
<option>2</option>
|
105 |
<option>3</option>
|
106 |
</select>
|
107 |
</div>
|
108 |
</div>
|
109 |
+
<?php if ( \BooklyLite\Lib\Config::multiplyAppointmentsEnabled() ) : ?>
|
110 |
+
<div class="bookly-form-group">
|
111 |
+
<?php \BooklyLite\Lib\Proxy\MultiplyAppointments::renderAppearance() ?>
|
112 |
</div>
|
113 |
<?php endif ?>
|
114 |
+
<?php if ( \BooklyLite\Lib\Config::chainAppointmentsEnabled() ) : ?>
|
115 |
+
<div class="bookly-form-group">
|
116 |
<label></label>
|
117 |
<div>
|
118 |
+
<button class="bookly-round"><i class="bookly-icon-sm bookly-icon-plus"></i></button>
|
119 |
</div>
|
120 |
</div>
|
121 |
<?php endif ?>
|
122 |
</div>
|
123 |
+
<div class="bookly-right bookly-mobile-next-step bookly-js-mobile-next-step bookly-btn bookly-none">
|
124 |
+
<?php $editable::renderString( array( 'bookly_l10n_step_service_mobile_button_next' ) ) ?>
|
|
|
125 |
</div>
|
126 |
</div>
|
127 |
+
<div class="bookly-mobile-step-2 bookly-js-mobile-step-2">
|
128 |
<div class="bookly-box">
|
129 |
+
<div class="bookly-left">
|
130 |
+
<div class="bookly-available-date bookly-js-available-date bookly-left">
|
131 |
+
<div class="bookly-form-group">
|
132 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_select_date', ) ) ?>
|
133 |
<div>
|
134 |
+
<input class="bookly-date-from bookly-js-date-from" style="background-color: #fff;" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
135 |
</div>
|
136 |
</div>
|
137 |
</div>
|
138 |
+
<div class="bookly-week-days bookly-js-week-days bookly-table bookly-left">
|
139 |
<?php foreach ( $wp_locale->weekday_abbrev as $weekday_abbrev ) : ?>
|
140 |
<div>
|
141 |
<div class="bookly-font-bold"><?php echo $weekday_abbrev ?></div>
|
142 |
<label class="active">
|
143 |
+
<input class="bookly-js-week-day" value="1" checked="checked" type="checkbox">
|
144 |
</label>
|
145 |
</div>
|
146 |
<?php endforeach ?>
|
147 |
</div>
|
148 |
</div>
|
149 |
+
<div class="bookly-time-range bookly-js-time-range bookly-left">
|
150 |
+
<div class="bookly-form-group bookly-time-from bookly-left">
|
151 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_start_from', ) ) ?>
|
152 |
<div>
|
153 |
+
<select class="bookly-js-select-time-from">
|
154 |
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
155 |
+
<option><?php echo DateTime::formatTime( $i ) ?></option>
|
156 |
<?php endfor ?>
|
157 |
</select>
|
158 |
</div>
|
159 |
</div>
|
160 |
+
<div class="bookly-form-group bookly-time-to bookly-left">
|
161 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_finish_by', ) ) ?>
|
162 |
<div>
|
163 |
+
<select class="bookly-js-select-time-to">
|
164 |
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
165 |
+
<option<?php selected( $i == 64800 ) ?>><?php echo DateTime::formatTime( $i ) ?></option>
|
166 |
<?php endfor ?>
|
167 |
</select>
|
168 |
</div>
|
170 |
</div>
|
171 |
</div>
|
172 |
<div class="bookly-box bookly-nav-steps">
|
173 |
+
<div class="bookly-right bookly-mobile-prev-step bookly-js-mobile-prev-step bookly-btn bookly-none">
|
174 |
+
<?php $editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
175 |
</div>
|
176 |
+
<div class="bookly-next-step bookly-js-next-step bookly-btn">
|
177 |
+
<?php $editable::renderString( array( 'bookly_l10n_step_service_button_next' ) ) ?>
|
178 |
</div>
|
179 |
+
<button class="bookly-go-to-cart bookly-js-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>
|
180 |
</div>
|
181 |
</div>
|
182 |
</div>
|
183 |
</div>
|
184 |
<div style="display: none">
|
185 |
<?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 ) : ?>
|
186 |
+
<div class="bookly-js-option <?php echo $validator ?>"><?php echo get_option( $validator ) ?></div>
|
187 |
<?php endforeach ?>
|
188 |
</div>
|
189 |
+
<style id="bookly-pickadate-style"></style>
|
|
|
|
|
|
backend/modules/appearance/templates/_3_time.php
CHANGED
@@ -1,146 +1,152 @@
|
|
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 |
-
|
|
|
|
|
|
|
7 |
</div>
|
8 |
<!-- timeslots -->
|
9 |
-
<div class="
|
10 |
-
<div class="
|
11 |
-
<div class="
|
12 |
-
<div class="
|
13 |
-
<div class="
|
14 |
-
<span class="
|
15 |
-
<input style="display: none" class="
|
16 |
</span>
|
17 |
</div>
|
18 |
-
<div class="
|
19 |
-
<button class="
|
20 |
<?php for ( $i = 28800; $i <= 57600; $i += 3600 ) : ?>
|
21 |
-
<button class="
|
22 |
<span class="ladda-label">
|
23 |
-
<i class="
|
24 |
<?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
25 |
</span>
|
26 |
</button>
|
27 |
<?php endfor ?>
|
28 |
</div>
|
29 |
-
<div class="
|
30 |
-
<button class="
|
31 |
<span class="ladda-label">
|
32 |
-
<i class="
|
33 |
</span>
|
34 |
</button>
|
35 |
-
<button class="
|
36 |
<?php for ( $i = 28800; $i <= 54000; $i += 3600 ) : ?>
|
37 |
-
<button class="
|
38 |
<span class="ladda-label">
|
39 |
-
<i class="
|
40 |
</span>
|
41 |
</button>
|
42 |
<?php endfor ?>
|
43 |
</div>
|
44 |
-
<div class="
|
45 |
<?php for ( $i = 57600; $i <= 61200; $i += 3600 ) : ?>
|
46 |
-
<button class="
|
47 |
<span class="ladda-label">
|
48 |
-
<i class="
|
49 |
</span>
|
50 |
</button>
|
51 |
<?php endfor ?>
|
52 |
-
<button class="
|
53 |
<?php for ( $i = 28800; $i <= 50400; $i += 3600 ) : ?>
|
54 |
-
<button class="
|
55 |
<span class="ladda-label">
|
56 |
-
<i class="
|
57 |
</span>
|
58 |
</button>
|
59 |
<?php endfor ?>
|
60 |
</div>
|
61 |
-
<div class="
|
62 |
<?php for ( $i = 54000; $i <= 61200; $i += 3600 ) : ?>
|
63 |
-
<button class="
|
64 |
<span class="ladda-label">
|
65 |
-
<i class="
|
66 |
</span>
|
67 |
</button>
|
68 |
<?php endfor ?>
|
69 |
-
<button class="
|
70 |
<?php for ( $i = 28800; $i <= 46800; $i += 3600 ) : ?>
|
71 |
-
<button class="
|
72 |
<span class="ladda-label">
|
73 |
-
<i class="
|
74 |
</span>
|
75 |
</button>
|
76 |
<?php endfor ?>
|
77 |
</div>
|
78 |
-
<div class="
|
79 |
<?php for ( $i = 50400; $i <= 61200; $i += 3600 ) : ?>
|
80 |
-
<button class="
|
81 |
<span class="ladda-label">
|
82 |
-
<i class="
|
83 |
</span>
|
84 |
</button>
|
85 |
<?php endfor ?>
|
86 |
-
<button class="
|
87 |
<?php for ( $i = 28800; $i <= 43200; $i += 3600 ) : ?>
|
88 |
-
<button class="
|
89 |
<span class="ladda-label">
|
90 |
-
<i class="
|
91 |
</span>
|
92 |
</button>
|
93 |
<?php endfor ?>
|
94 |
</div>
|
95 |
-
<div class="
|
96 |
<?php for ( $i = 46800; $i <= 61200; $i += 3600 ) : ?>
|
97 |
-
<button class="
|
98 |
<span class="ladda-label">
|
99 |
-
<i class="
|
100 |
</span>
|
101 |
</button>
|
102 |
<?php endfor ?>
|
103 |
-
<button class="
|
104 |
<?php for ( $i = 28800; $i <= 39600; $i += 3600 ) : ?>
|
105 |
-
<button class="
|
106 |
<span class="ladda-label">
|
107 |
-
<i class="
|
108 |
</span>
|
109 |
</button>
|
110 |
<?php endfor ?>
|
111 |
</div>
|
112 |
-
<div class="
|
113 |
<?php for ( $i = 43200; $i <= 61200; $i += 3600 ) : ?>
|
114 |
-
<button class="
|
115 |
<span class="ladda-label">
|
116 |
-
<i class="
|
117 |
</span>
|
118 |
</button>
|
119 |
<?php endfor ?>
|
120 |
-
<button class="
|
121 |
<?php for ( $i = 28800; $i <= 36000; $i += 3600 ) : ?>
|
122 |
-
<button class="
|
123 |
<span class="ladda-label">
|
124 |
-
<i class="
|
125 |
</span>
|
126 |
</button>
|
127 |
<?php endfor ?>
|
128 |
</div>
|
129 |
</div>
|
130 |
|
131 |
-
<div
|
132 |
-
<div class="
|
133 |
-
<span class="
|
134 |
-
<input style="display: none" class="
|
135 |
</span>
|
136 |
</div>
|
137 |
<?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
|
138 |
-
<div class="
|
139 |
-
<button class="
|
140 |
<?php for ( $j = 28800; $j <= 61200; $j += 3600 ) : ?>
|
141 |
-
<button class="
|
142 |
<span class="ladda-label">
|
143 |
-
<i class="
|
144 |
</span>
|
145 |
</button>
|
146 |
<?php endfor ?>
|
@@ -151,15 +157,15 @@
|
|
151 |
</div>
|
152 |
</div>
|
153 |
<div class="bookly-box bookly-nav-steps">
|
154 |
-
<button class="
|
155 |
-
<span class="
|
156 |
</button>
|
157 |
-
<button class="
|
158 |
-
<span class="
|
159 |
</button>
|
160 |
-
<div class="bookly-back-step
|
161 |
-
<?php
|
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>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Backend\Modules\Appearance\Components;
|
3 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
4 |
+
?>
|
5 |
<div class="bookly-form">
|
6 |
<?php include '_progress_tracker.php' ?>
|
7 |
|
8 |
<div class="bookly-box">
|
9 |
+
<?php $editable::renderText( 'bookly_l10n_info_time_step', Components::getInstance()->renderCodes( array( 'step' => 3 ), false ) ) ?>
|
10 |
+
<div class="bookly-holder bookly-label-error bookly-bold">
|
11 |
+
<?php $editable::renderText( 'bookly_l10n_step_time_slot_not_available', null, 'bottom', __( 'Visible when the chosen time slot has been already booked', 'bookly' ) ) ?>
|
12 |
+
</div>
|
13 |
</div>
|
14 |
<!-- timeslots -->
|
15 |
+
<div class="bookly-time-step">
|
16 |
+
<div class="bookly-columnizer-wrap">
|
17 |
+
<div class="bookly-columnizer">
|
18 |
+
<div id="bookly-day-multi-columns" class="bookly-time-screen" style="display: <?php echo get_option( 'bookly_app_show_day_one_column' ) == 1 ? ' none' : 'block' ?>">
|
19 |
+
<div class="bookly-input-wrap bookly-slot-calendar bookly-js-slot-calendar">
|
20 |
+
<span class="bookly-date-wrap">
|
21 |
+
<input style="display: none" class="bookly-js-selected-date bookly-form-element" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
22 |
</span>
|
23 |
</div>
|
24 |
+
<div class="bookly-column col1">
|
25 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', current_time( 'timestamp' ) ) ?></button>
|
26 |
<?php for ( $i = 28800; $i <= 57600; $i += 3600 ) : ?>
|
27 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
28 |
<span class="ladda-label">
|
29 |
+
<i class="bookly-hour-icon"><span></span></i>
|
30 |
<?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
31 |
</span>
|
32 |
</button>
|
33 |
<?php endfor ?>
|
34 |
</div>
|
35 |
+
<div class="bookly-column col2">
|
36 |
+
<button class="bookly-hour ladda-button bookly-last-child">
|
37 |
<span class="ladda-label">
|
38 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( 61200 ) ?>
|
39 |
</span>
|
40 |
</button>
|
41 |
+
<button class="bookly-day bookly-js-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>
|
42 |
<?php for ( $i = 28800; $i <= 54000; $i += 3600 ) : ?>
|
43 |
+
<button class="bookly-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' ?>">
|
44 |
<span class="ladda-label">
|
45 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
46 |
</span>
|
47 |
</button>
|
48 |
<?php endfor ?>
|
49 |
</div>
|
50 |
+
<div class="bookly-column col3" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
51 |
<?php for ( $i = 57600; $i <= 61200; $i += 3600 ) : ?>
|
52 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
53 |
<span class="ladda-label">
|
54 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
55 |
</span>
|
56 |
</button>
|
57 |
<?php endfor ?>
|
58 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+2 days', current_time('timestamp') ) ) ?></button>
|
59 |
<?php for ( $i = 28800; $i <= 50400; $i += 3600 ) : ?>
|
60 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
61 |
<span class="ladda-label">
|
62 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
63 |
</span>
|
64 |
</button>
|
65 |
<?php endfor ?>
|
66 |
</div>
|
67 |
+
<div class="bookly-column col4" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
68 |
<?php for ( $i = 54000; $i <= 61200; $i += 3600 ) : ?>
|
69 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
70 |
<span class="ladda-label">
|
71 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
72 |
</span>
|
73 |
</button>
|
74 |
<?php endfor ?>
|
75 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+3 days', current_time( 'timestamp' ) ) ) ?></button>
|
76 |
<?php for ( $i = 28800; $i <= 46800; $i += 3600 ) : ?>
|
77 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
78 |
<span class="ladda-label">
|
79 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
80 |
</span>
|
81 |
</button>
|
82 |
<?php endfor ?>
|
83 |
</div>
|
84 |
+
<div class="bookly-column col5" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
85 |
<?php for ( $i = 50400; $i <= 61200; $i += 3600 ) : ?>
|
86 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
87 |
<span class="ladda-label">
|
88 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
89 |
</span>
|
90 |
</button>
|
91 |
<?php endfor ?>
|
92 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+4 days', current_time( 'timestamp' ) ) ) ?></button>
|
93 |
<?php for ( $i = 28800; $i <= 43200; $i += 3600 ) : ?>
|
94 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
95 |
<span class="ladda-label">
|
96 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
97 |
</span>
|
98 |
</button>
|
99 |
<?php endfor ?>
|
100 |
</div>
|
101 |
+
<div class="bookly-column col6" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
102 |
<?php for ( $i = 46800; $i <= 61200; $i += 3600 ) : ?>
|
103 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
104 |
<span class="ladda-label">
|
105 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
106 |
</span>
|
107 |
</button>
|
108 |
<?php endfor ?>
|
109 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+5 days', current_time( 'timestamp' ) ) ) ?></button>
|
110 |
<?php for ( $i = 28800; $i <= 39600; $i += 3600 ) : ?>
|
111 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
112 |
<span class="ladda-label">
|
113 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
114 |
</span>
|
115 |
</button>
|
116 |
<?php endfor ?>
|
117 |
</div>
|
118 |
+
<div class="bookly-column col7" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
119 |
<?php for ( $i = 43200; $i <= 61200; $i += 3600 ) : ?>
|
120 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
121 |
<span class="ladda-label">
|
122 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
123 |
</span>
|
124 |
</button>
|
125 |
<?php endfor ?>
|
126 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+6 days', current_time( 'timestamp' ) ) ) ?></button>
|
127 |
<?php for ( $i = 28800; $i <= 36000; $i += 3600 ) : ?>
|
128 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
129 |
<span class="ladda-label">
|
130 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $i ) ?>
|
131 |
</span>
|
132 |
</button>
|
133 |
<?php endfor ?>
|
134 |
</div>
|
135 |
</div>
|
136 |
|
137 |
+
<div id="bookly-day-one-column" class="bookly-time-screen" style="display: <?php echo get_option( 'bookly_app_show_day_one_column' ) == 1 ? ' block' : 'none' ?>">
|
138 |
+
<div class="bookly-input-wrap bookly-slot-calendar bookly-js-slot-calendar">
|
139 |
+
<span class="bookly-date-wrap">
|
140 |
+
<input style="display: none" class="bookly-js-selected-date bookly-form-element" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
141 |
</span>
|
142 |
</div>
|
143 |
<?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
|
144 |
+
<div class="bookly-column col<?php echo $i ?>">
|
145 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+' . ( $i - 1 ) . ' days', current_time( 'timestamp' ) ) ) ?></button>
|
146 |
<?php for ( $j = 28800; $j <= 61200; $j += 3600 ) : ?>
|
147 |
+
<button class="bookly-hour ladda-button<?php if ( mt_rand( 0, 1 ) ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked' ?>">
|
148 |
<span class="ladda-label">
|
149 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo \BooklyLite\Lib\Utils\DateTime::formatTime( $j ) ?>
|
150 |
</span>
|
151 |
</button>
|
152 |
<?php endfor ?>
|
157 |
</div>
|
158 |
</div>
|
159 |
<div class="bookly-box bookly-nav-steps">
|
160 |
+
<button class="bookly-time-next bookly-btn bookly-right ladda-button">
|
161 |
+
<span class="bookly-label">></span>
|
162 |
</button>
|
163 |
+
<button class="bookly-time-prev bookly-btn bookly-right ladda-button">
|
164 |
+
<span class="bookly-label"><</span>
|
165 |
</button>
|
166 |
+
<div class="bookly-back-step bookly-js-back-step bookly-btn">
|
167 |
+
<?php $editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
168 |
</div>
|
169 |
+
<button class="bookly-go-to-cart bookly-js-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>
|
170 |
</div>
|
171 |
</div>
|
backend/modules/appearance/templates/_5_cart.php
CHANGED
@@ -1,103 +1,112 @@
|
|
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 |
-
|
|
|
|
|
|
|
7 |
</div>
|
8 |
|
9 |
<div class="bookly-box">
|
10 |
-
<div class="
|
11 |
-
<?php
|
12 |
</div>
|
13 |
</div>
|
14 |
|
15 |
-
<div class="
|
16 |
-
<div class="
|
17 |
<table>
|
18 |
-
<thead class="
|
19 |
<tr>
|
20 |
-
<th
|
21 |
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
22 |
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
23 |
-
<th
|
24 |
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
25 |
<th></th>
|
26 |
</tr>
|
27 |
</thead>
|
28 |
-
<tbody class="
|
29 |
-
<tr>
|
30 |
<td>Crown and Bridge</td>
|
31 |
-
<td><?php echo
|
32 |
-
<td><?php echo
|
33 |
<td>Nick Knight</td>
|
34 |
-
<td><?php echo
|
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
|
43 |
-
<td><?php echo
|
44 |
<td>Wayne Turner</td>
|
45 |
-
<td><?php echo
|
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="
|
53 |
-
<tr>
|
54 |
-
<th
|
55 |
<td>Crown and Bridge</td>
|
56 |
</tr>
|
57 |
-
<tr>
|
58 |
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
59 |
-
<td><?php echo
|
60 |
</tr>
|
61 |
-
<tr>
|
62 |
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
63 |
-
<td><?php echo
|
64 |
</tr>
|
65 |
-
<tr>
|
66 |
-
<th
|
67 |
<td>Nick Knight</td>
|
68 |
</tr>
|
69 |
-
<tr>
|
70 |
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
71 |
-
<td><?php echo
|
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
|
82 |
<td>Teeth Whitening</td>
|
83 |
</tr>
|
84 |
-
<tr>
|
85 |
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
86 |
-
<td><?php echo
|
87 |
</tr>
|
88 |
-
<tr>
|
89 |
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
90 |
-
<td><?php echo
|
91 |
</tr>
|
92 |
-
<tr>
|
93 |
-
<th
|
94 |
<td>Wayne Turner</td>
|
95 |
</tr>
|
96 |
-
<tr>
|
97 |
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
98 |
-
<td><?php echo
|
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>
|
@@ -105,31 +114,31 @@
|
|
105 |
</td>
|
106 |
</tr>
|
107 |
</tbody>
|
108 |
-
<tfoot class="
|
109 |
<tr>
|
110 |
<td colspan="4"><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></td>
|
111 |
-
<td><strong class="bookly-js-total-price"><?php echo
|
112 |
<td></td>
|
113 |
</tr>
|
114 |
</tfoot>
|
115 |
-
<tfoot class="
|
116 |
<tr>
|
117 |
<th><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></th>
|
118 |
-
<td><strong class="bookly-js-total-price"><?php echo
|
119 |
</tr>
|
120 |
</tfoot>
|
121 |
</table>
|
122 |
</div>
|
123 |
</div>
|
124 |
|
125 |
-
<?php
|
126 |
|
127 |
<div class="bookly-box bookly-nav-steps">
|
128 |
-
<div class="bookly-back-step
|
129 |
-
<?php
|
130 |
</div>
|
131 |
-
<div class="bookly-next-step
|
132 |
-
<?php
|
133 |
</div>
|
134 |
</div>
|
135 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Price;
|
3 |
+
use BooklyLite\Lib\Utils\DateTime;
|
4 |
+
use BooklyLite\Backend\Modules\Appearance\Components;
|
5 |
+
|
6 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
7 |
+
?>
|
8 |
<div class="bookly-form">
|
9 |
<?php include '_progress_tracker.php' ?>
|
10 |
|
11 |
<div class="bookly-box">
|
12 |
+
<?php $editable::renderText( 'bookly_l10n_info_cart_step', Components::getInstance()->renderCodes( array( 'step' => 5 ), false ) ) ?>
|
13 |
+
<div class="bookly-holder bookly-label-error bookly-bold">
|
14 |
+
<?php $editable::renderText( 'bookly_l10n_step_cart_slot_not_available', null, 'bottom', __( 'Visible when the chosen time slot has been already booked', 'bookly' ) ) ?>
|
15 |
+
</div>
|
16 |
</div>
|
17 |
|
18 |
<div class="bookly-box">
|
19 |
+
<div class="bookly-btn bookly-add-item bookly-inline-block">
|
20 |
+
<?php $editable::renderString( array( 'bookly_l10n_button_book_more', ) ) ?>
|
21 |
</div>
|
22 |
</div>
|
23 |
|
24 |
+
<div class="bookly-cart-step">
|
25 |
+
<div class="bookly-cart bookly-box">
|
26 |
<table>
|
27 |
+
<thead class="bookly-desktop-version">
|
28 |
<tr>
|
29 |
+
<th class="bookly-js-option bookly_l10n_label_service"><?php echo esc_html( get_option( 'bookly_l10n_label_service' ) ) ?></th>
|
30 |
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
31 |
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
32 |
+
<th class="bookly-js-option bookly_l10n_label_employee"><?php echo esc_html( get_option( 'bookly_l10n_label_employee' ) ) ?></th>
|
33 |
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
34 |
<th></th>
|
35 |
</tr>
|
36 |
</thead>
|
37 |
+
<tbody class="bookly-desktop-version">
|
38 |
+
<tr class="bookly-cart-primary">
|
39 |
<td>Crown and Bridge</td>
|
40 |
+
<td><?php echo DateTime::formatDate( '+2 days' ) ?></td>
|
41 |
+
<td><?php echo DateTime::formatTime( 28800 ) ?></td>
|
42 |
<td>Nick Knight</td>
|
43 |
+
<td><?php echo Price::format( 350 ) ?></td>
|
44 |
<td>
|
45 |
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
46 |
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
47 |
</td>
|
48 |
</tr>
|
49 |
+
<tr class="bookly-cart-primary">
|
50 |
<td>Teeth Whitening</td>
|
51 |
+
<td><?php echo DateTime::formatDate( '+3 days' ) ?></td>
|
52 |
+
<td><?php echo DateTime::formatTime( 57600 ) ?></td>
|
53 |
<td>Wayne Turner</td>
|
54 |
+
<td><?php echo Price::format( 400 ) ?></td>
|
55 |
<td>
|
56 |
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
57 |
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
58 |
</td>
|
59 |
</tr>
|
60 |
</tbody>
|
61 |
+
<tbody class="bookly-mobile-version">
|
62 |
+
<tr class="bookly-cart-primary">
|
63 |
+
<th class="bookly-js-option bookly_l10n_label_service"><?php echo esc_html( get_option( 'bookly_l10n_label_service' ) ) ?></th>
|
64 |
<td>Crown and Bridge</td>
|
65 |
</tr>
|
66 |
+
<tr class="bookly-cart-primary">
|
67 |
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
68 |
+
<td><?php echo DateTime::formatDate( '+2 days' ) ?></td>
|
69 |
</tr>
|
70 |
+
<tr class="bookly-cart-primary">
|
71 |
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
72 |
+
<td><?php echo DateTime::formatTime( 28800 ) ?></td>
|
73 |
</tr>
|
74 |
+
<tr class="bookly-cart-primary">
|
75 |
+
<th class="bookly-js-option bookly_l10n_label_employee"><?php echo esc_html( get_option( 'bookly_l10n_label_employee' ) ) ?></th>
|
76 |
<td>Nick Knight</td>
|
77 |
</tr>
|
78 |
+
<tr class="bookly-cart-primary">
|
79 |
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
80 |
+
<td><?php echo Price::format( 350 ) ?></td>
|
81 |
</tr>
|
82 |
+
<tr class="bookly-cart-primary">
|
83 |
<th></th>
|
84 |
<td>
|
85 |
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
86 |
<button class="bookly-round" title="<?php esc_attr_e( 'Remove', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-drop"></i></button>
|
87 |
</td>
|
88 |
</tr>
|
89 |
+
<tr class="bookly-cart-primary">
|
90 |
+
<th class="bookly-js-option bookly_l10n_label_service"><?php echo esc_html( get_option( 'bookly_l10n_label_service' ) ) ?></th>
|
91 |
<td>Teeth Whitening</td>
|
92 |
</tr>
|
93 |
+
<tr class="bookly-cart-primary">
|
94 |
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
95 |
+
<td><?php echo DateTime::formatDate( '+3 days' ) ?></td>
|
96 |
</tr>
|
97 |
+
<tr class="bookly-cart-primary">
|
98 |
<th><?php _e( 'Time', 'bookly' ) ?></th>
|
99 |
+
<td><?php echo DateTime::formatTime( 57600 ) ?></td>
|
100 |
</tr>
|
101 |
+
<tr class="bookly-cart-primary">
|
102 |
+
<th class="bookly-js-option bookly_l10n_label_employee"><?php echo esc_html( get_option( 'bookly_l10n_label_employee' ) ) ?></th>
|
103 |
<td>Wayne Turner</td>
|
104 |
</tr>
|
105 |
+
<tr class="bookly-cart-primary">
|
106 |
<th><?php _e( 'Price', 'bookly' ) ?></th>
|
107 |
+
<td><?php echo Price::format( 400 ) ?></td>
|
108 |
</tr>
|
109 |
+
<tr class="bookly-cart-primary">
|
110 |
<th></th>
|
111 |
<td>
|
112 |
<button class="bookly-round" title="<?php esc_attr_e( 'Edit', 'bookly' ) ?>"><i class="bookly-icon-sm bookly-icon-edit"></i></button>
|
114 |
</td>
|
115 |
</tr>
|
116 |
</tbody>
|
117 |
+
<tfoot class="bookly-desktop-version">
|
118 |
<tr>
|
119 |
<td colspan="4"><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></td>
|
120 |
+
<td><strong class="bookly-js-total-price"><?php echo Price::format( 750 ) ?></strong></td>
|
121 |
<td></td>
|
122 |
</tr>
|
123 |
</tfoot>
|
124 |
+
<tfoot class="bookly-mobile-version">
|
125 |
<tr>
|
126 |
<th><strong><?php _e( 'Total', 'bookly' ) ?>:</strong></th>
|
127 |
+
<td><strong class="bookly-js-total-price"><?php echo Price::format( 750 ) ?></strong></td>
|
128 |
</tr>
|
129 |
</tfoot>
|
130 |
</table>
|
131 |
</div>
|
132 |
</div>
|
133 |
|
134 |
+
<?php \BooklyLite\Lib\Proxy\RecurringAppointments::renderAppearanceEditableInfoMessage() ?>
|
135 |
|
136 |
<div class="bookly-box bookly-nav-steps">
|
137 |
+
<div class="bookly-back-step bookly-js-back-step bookly-btn">
|
138 |
+
<?php $editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
139 |
</div>
|
140 |
+
<div class="bookly-next-step bookly-js-next-step bookly-btn">
|
141 |
+
<?php $editable::renderString( array( 'bookly_l10n_step_cart_button_next' ) ) ?>
|
142 |
</div>
|
143 |
</div>
|
144 |
</div>
|
backend/modules/appearance/templates/_6_details.php
CHANGED
@@ -1,44 +1,74 @@
|
|
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 |
-
|
7 |
</div>
|
8 |
<div class="bookly-box">
|
9 |
-
|
10 |
</div>
|
11 |
-
<div class="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
<div class="bookly-box bookly-table">
|
13 |
-
<div class="
|
14 |
-
<?php
|
15 |
<div>
|
16 |
<input type="text" value="" maxlength="60" />
|
17 |
</div>
|
18 |
</div>
|
19 |
-
<div class="
|
20 |
-
<?php
|
21 |
<div>
|
22 |
-
<input type="text" class="<?php if ( get_option( 'bookly_cst_phone_default_country' ) != 'disabled' ) : ?>
|
23 |
</div>
|
24 |
</div>
|
25 |
-
<div class="
|
26 |
-
<?php
|
27 |
<div>
|
28 |
<input maxlength="40" type="text" value="" />
|
29 |
</div>
|
30 |
</div>
|
31 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
</div>
|
33 |
|
34 |
-
<?php
|
35 |
|
36 |
<div class="bookly-box bookly-nav-steps">
|
37 |
-
<div class="bookly-back-step
|
38 |
-
<?php
|
39 |
</div>
|
40 |
-
<div class="bookly-next-step
|
41 |
-
<?php
|
42 |
</div>
|
43 |
</div>
|
44 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Backend\Modules\Appearance\Components;
|
3 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
4 |
+
?>
|
5 |
<div class="bookly-form">
|
6 |
<?php include '_progress_tracker.php' ?>
|
7 |
|
8 |
<div class="bookly-box">
|
9 |
+
<?php $editable::renderText( 'bookly_l10n_info_details_step', Components::getInstance()->renderCodes( array( 'step' => 6 ), false ) ) ?>
|
10 |
</div>
|
11 |
<div class="bookly-box">
|
12 |
+
<?php $editable::renderText( 'bookly_l10n_info_details_step_guest', Components::getInstance()->renderCodes( array( 'step' => 6, 'extra_codes' => 1 ), false ), 'bottom', __( 'Visible to non-logged in customers only', 'bookly' ) ) ?>
|
13 |
</div>
|
14 |
+
<div class="bookly-box" id="bookly-js-show-login-form">
|
15 |
+
<div class="bookly-btn bookly-inline-block">
|
16 |
+
<?php $editable::renderString( array( 'bookly_l10n_step_details_button_login' ) ) ?>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
<div class="bookly-details-step">
|
20 |
+
<div class="bookly-box bookly-table bookly-details-first-last-name" style="display: <?php echo get_option( 'bookly_cst_first_last_name' ) == 0 ? ' none' : 'table' ?>">
|
21 |
+
<div class="bookly-form-group">
|
22 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_first_name', 'bookly_l10n_required_first_name', ) ) ?>
|
23 |
+
<div>
|
24 |
+
<input type="text" value="" maxlength="60" />
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
<div class="bookly-form-group">
|
28 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_last_name', 'bookly_l10n_required_last_name', ) ) ?>
|
29 |
+
<div>
|
30 |
+
<input type="text" value="" maxlength="60" />
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
</div>
|
34 |
<div class="bookly-box bookly-table">
|
35 |
+
<div class="bookly-form-group bookly-details-full-name" style="display: <?php echo get_option( 'bookly_cst_first_last_name' ) == 1 ? ' none' : 'block' ?>">
|
36 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_name', 'bookly_l10n_required_name', ) ) ?>
|
37 |
<div>
|
38 |
<input type="text" value="" maxlength="60" />
|
39 |
</div>
|
40 |
</div>
|
41 |
+
<div class="bookly-form-group">
|
42 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_phone', 'bookly_l10n_required_phone', ) ) ?>
|
43 |
<div>
|
44 |
+
<input type="text" class="<?php if ( get_option( 'bookly_cst_phone_default_country' ) != 'disabled' ) : ?>bookly-user-phone<?php endif ?>" value="" />
|
45 |
</div>
|
46 |
</div>
|
47 |
+
<div class="bookly-form-group">
|
48 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_email', 'bookly_l10n_required_email', ) ) ?>
|
49 |
<div>
|
50 |
<input maxlength="40" type="text" value="" />
|
51 |
</div>
|
52 |
</div>
|
53 |
</div>
|
54 |
+
<div class="bookly-box" id="bookly-js-notes">
|
55 |
+
<div class="bookly-form-group">
|
56 |
+
<?php $editable::renderLabel( array( 'bookly_l10n_label_notes' ) ) ?>
|
57 |
+
<div>
|
58 |
+
<textarea rows="3"></textarea>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
</div>
|
62 |
</div>
|
63 |
|
64 |
+
<?php \BooklyLite\Lib\Proxy\RecurringAppointments::renderAppearanceEditableInfoMessage() ?>
|
65 |
|
66 |
<div class="bookly-box bookly-nav-steps">
|
67 |
+
<div class="bookly-back-step bookly-js-back-step bookly-btn">
|
68 |
+
<?php $editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
69 |
</div>
|
70 |
+
<div class="bookly-next-step bookly-js-next-step bookly-btn">
|
71 |
+
<?php $editable::renderString( array( 'bookly_l10n_step_details_button_next' ) ) ?>
|
72 |
</div>
|
73 |
</div>
|
74 |
</div>
|
backend/modules/appearance/templates/_7_payment.php
CHANGED
@@ -1,69 +1,60 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
|
|
2 |
<div class="bookly-form">
|
3 |
<?php include '_progress_tracker.php' ?>
|
4 |
-
|
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-
|
9 |
-
|
10 |
-
|
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 |
-
|
17 |
-
|
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
|
23 |
<label>
|
24 |
<input type="radio" name="payment" checked="checked" />
|
25 |
-
<?php
|
26 |
</label>
|
27 |
</div>
|
28 |
|
29 |
-
<div class="bookly-box
|
30 |
<label>
|
31 |
<input type="radio" name="payment" />
|
32 |
-
<?php
|
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
|
|
|
|
|
|
|
|
|
38 |
<label>
|
39 |
-
<input type="radio" name="payment"
|
40 |
-
<?php
|
41 |
<img src="<?php echo plugins_url( 'frontend/resources/images/cards.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="cards" />
|
42 |
</label>
|
43 |
-
<form class="
|
44 |
<?php include '_card_payment.php' ?>
|
45 |
</form>
|
46 |
</div>
|
47 |
|
48 |
-
|
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
|
60 |
|
61 |
<div class="bookly-box bookly-nav-steps">
|
62 |
-
<div class="bookly-back-step
|
63 |
-
<?php
|
64 |
</div>
|
65 |
-
<div class="bookly-next-step
|
66 |
-
<?php
|
67 |
</div>
|
68 |
</div>
|
69 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Backend\Modules\Appearance\Components;
|
3 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
4 |
+
?>
|
5 |
<div class="bookly-form">
|
6 |
<?php include '_progress_tracker.php' ?>
|
7 |
+
<?php \BooklyLite\Lib\Proxy\Coupons::renderAppearance() ?>
|
|
|
|
|
8 |
|
9 |
+
<div class="bookly-payment-nav">
|
10 |
+
<div class="bookly-box bookly-js-payment-single-app">
|
11 |
+
<?php $editable::renderText( 'bookly_l10n_info_payment_step_single_app', Components::getInstance()->renderCodes( array( 'step' => 7 ), false ), 'right' ) ?>
|
|
|
|
|
|
|
|
|
12 |
</div>
|
13 |
+
<div class="bookly-box bookly-js-payment-several-apps" style="display:none">
|
14 |
+
<?php $editable::renderText( 'bookly_l10n_info_payment_step_several_apps', Components::getInstance()->renderCodes( array( 'step' => 7, 'extra_codes' => 1 ), false ), 'right' ) ?>
|
|
|
|
|
15 |
</div>
|
16 |
|
17 |
+
<div class="bookly-box bookly-list">
|
18 |
<label>
|
19 |
<input type="radio" name="payment" checked="checked" />
|
20 |
+
<?php $editable::renderString( array( 'bookly_l10n_label_pay_locally', ) ) ?>
|
21 |
</label>
|
22 |
</div>
|
23 |
|
24 |
+
<div class="bookly-box bookly-list">
|
25 |
<label>
|
26 |
<input type="radio" name="payment" />
|
27 |
+
<?php $editable::renderString( array( 'bookly_l10n_label_pay_paypal', ) ) ?>
|
28 |
<img src="<?php echo plugins_url( 'frontend/resources/images/paypal.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="paypal" />
|
29 |
</label>
|
30 |
</div>
|
31 |
|
32 |
+
<div class="bookly-box bookly-list"
|
33 |
+
<?php if ( BooklyLite\Lib\Proxy\Shared::appearanceRequiredInterfaceCreditCard( false ) == false ) : ?>
|
34 |
+
style="display: none"
|
35 |
+
<?php endif ?>
|
36 |
+
>
|
37 |
<label>
|
38 |
+
<input type="radio" name="payment" id="bookly-card-payment" />
|
39 |
+
<?php $editable::renderString( array( 'bookly_l10n_label_pay_ccard', ) ) ?>
|
40 |
<img src="<?php echo plugins_url( 'frontend/resources/images/cards.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" alt="cards" />
|
41 |
</label>
|
42 |
+
<form class="bookly-card-form bookly-clear-bottom" style="margin-top:15px;display: none;">
|
43 |
<?php include '_card_payment.php' ?>
|
44 |
</form>
|
45 |
</div>
|
46 |
|
47 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderAppearancePaymentGatewaySelector() ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
</div>
|
49 |
|
50 |
+
<?php \BooklyLite\Lib\Proxy\RecurringAppointments::renderAppearanceEditableInfoMessage() ?>
|
51 |
|
52 |
<div class="bookly-box bookly-nav-steps">
|
53 |
+
<div class="bookly-back-step bookly-js-back-step bookly-btn">
|
54 |
+
<?php $editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
55 |
</div>
|
56 |
+
<div class="bookly-next-step bookly-js-next-step bookly-btn">
|
57 |
+
<?php $editable::renderString( array( 'bookly_l10n_step_payment_button_next' ) ) ?>
|
58 |
</div>
|
59 |
</div>
|
60 |
</div>
|
backend/modules/appearance/templates/_8_complete.php
CHANGED
@@ -1,7 +1,16 @@
|
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
6 |
</div>
|
7 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Backend\Modules\Appearance\Components;
|
3 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
4 |
+
?>
|
5 |
<div class="bookly-form">
|
6 |
<?php include '_progress_tracker.php' ?>
|
7 |
+
<div class="bookly-box bookly-js-done-success">
|
8 |
+
<?php $editable::renderText( 'bookly_l10n_info_complete_step', Components::getInstance()->renderCodes( array( 'step' => 8, 'extra_codes' => 1 ), false ) ) ?>
|
9 |
+
</div>
|
10 |
+
<div class="bookly-box bookly-js-done-limit-error collapse">
|
11 |
+
<?php $editable::renderText( 'bookly_l10n_info_complete_step_limit_error', Components::getInstance()->renderCodes( array( 'step' => 8 ), false ) ) ?>
|
12 |
+
</div>
|
13 |
+
<div class="bookly-box bookly-js-done-processing collapse">
|
14 |
+
<?php $editable::renderText( 'bookly_l10n_info_complete_step_processing', Components::getInstance()->renderCodes( array( 'step' => 8, 'extra_codes' => 1 ), false ) ) ?>
|
15 |
</div>
|
16 |
</div>
|
backend/modules/appearance/templates/_card_payment.php
CHANGED
@@ -1,24 +1,26 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
2 |
<div class="bookly-box bookly-table">
|
3 |
-
<div class="
|
4 |
<label>
|
5 |
-
<?php
|
6 |
</label>
|
7 |
<div>
|
8 |
<input type="text" />
|
9 |
</div>
|
10 |
</div>
|
11 |
-
<div class="
|
12 |
<label>
|
13 |
-
<?php
|
14 |
</label>
|
15 |
<div>
|
16 |
-
<select class="
|
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="
|
22 |
<?php for ( $i = date( 'Y' ); $i <= date( 'Y' ) + 10; ++ $i ) : ?>
|
23 |
<option value="<?php echo $i ?>"><?php echo $i ?></option>
|
24 |
<?php endfor ?>
|
@@ -26,13 +28,13 @@
|
|
26 |
</div>
|
27 |
</div>
|
28 |
</div>
|
29 |
-
<div class="bookly-box
|
30 |
-
<div class="
|
31 |
<label>
|
32 |
-
<?php
|
33 |
</label>
|
34 |
<div>
|
35 |
-
<input class="
|
36 |
</div>
|
37 |
</div>
|
38 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
3 |
+
?>
|
4 |
<div class="bookly-box bookly-table">
|
5 |
+
<div class="bookly-form-group" style="width:200px!important">
|
6 |
<label>
|
7 |
+
<?php $editable::renderString( array( 'bookly_l10n_label_ccard_number', ) ) ?>
|
8 |
</label>
|
9 |
<div>
|
10 |
<input type="text" />
|
11 |
</div>
|
12 |
</div>
|
13 |
+
<div class="bookly-form-group">
|
14 |
<label>
|
15 |
+
<?php $editable::renderString( array( 'bookly_l10n_label_ccard_expire', ) ) ?>
|
16 |
</label>
|
17 |
<div>
|
18 |
+
<select class="bookly-card-exp">
|
19 |
<?php for ( $i = 1; $i <= 12; ++ $i ) : ?>
|
20 |
<option value="<?php echo $i ?>"><?php printf( '%02d', $i ) ?></option>
|
21 |
<?php endfor ?>
|
22 |
</select>
|
23 |
+
<select class="bookly-card-exp">
|
24 |
<?php for ( $i = date( 'Y' ); $i <= date( 'Y' ) + 10; ++ $i ) : ?>
|
25 |
<option value="<?php echo $i ?>"><?php echo $i ?></option>
|
26 |
<?php endfor ?>
|
28 |
</div>
|
29 |
</div>
|
30 |
</div>
|
31 |
+
<div class="bookly-box bookly-clear-bottom">
|
32 |
+
<div class="bookly-form-group">
|
33 |
<label>
|
34 |
+
<?php $editable::renderString( array( 'bookly_l10n_label_ccard_code', ) ) ?>
|
35 |
</label>
|
36 |
<div>
|
37 |
+
<input class="bookly-card-cvc" type="text" />
|
38 |
</div>
|
39 |
</div>
|
40 |
</div>
|
backend/modules/appearance/templates/_codes.php
CHANGED
@@ -1,25 +1,20 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
|
|
2 |
$codes = array(
|
3 |
-
array( 'code' => '
|
4 |
-
array( 'code' => '
|
5 |
-
|
6 |
-
|
7 |
-
),
|
8 |
-
array( 'code' => '
|
9 |
-
array( 'code' => '
|
10 |
-
|
11 |
-
),
|
12 |
-
array( 'code' => '
|
13 |
-
|
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 |
-
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
|
3 |
+
use BooklyLite\Lib;
|
4 |
+
|
5 |
$codes = array(
|
6 |
+
array( 'code' => 'appointments_count', 'description' => __( 'total quantity of appointments in cart', 'bookly' ), 'flags' => array( 'step' => 7, 'extra_codes' => true ) ),
|
7 |
+
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ), 'flags' => array( 'step' => 8, 'extra_codes' => true ) ),
|
8 |
+
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
9 |
+
array( 'code' => 'login_form', 'description' => __( 'login form', 'bookly' ), 'flags' => array( 'step' => 6, 'extra_codes' => true ) ),
|
10 |
+
array( 'code' => 'service_date', 'description' => __( 'date of service', 'bookly' ), 'flags' => array( 'step' => '>3' ) ),
|
11 |
+
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) ),
|
12 |
+
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) ),
|
13 |
+
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) ),
|
14 |
+
array( 'code' => 'service_time', 'description' => __( 'time of service', 'bookly' ), 'flags' => array( 'step' => '>3' ) ),
|
15 |
+
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) ),
|
16 |
+
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
17 |
+
array( 'code' => 'total_price', 'description' => __( 'total price of booking', 'bookly' ) ),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
);
|
19 |
+
|
20 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareAppearanceCodes( $codes ), array( 'step' => $step, 'extra_codes' => isset ( $extra_codes ) ) );
|
backend/modules/appearance/templates/_custom_css.php
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Template to work with custom css.
|
4 |
+
* Template includes button to show custom css form + form to edit it
|
5 |
+
*
|
6 |
+
* @var string $custom_css custom css text
|
7 |
+
*/
|
8 |
+
?>
|
9 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
10 |
+
|
11 |
+
<div class="form-group">
|
12 |
+
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#bookly-custom-css-dialog">
|
13 |
+
<?php _e( 'Edit custom CSS', 'bookly' ); ?>
|
14 |
+
</button>
|
15 |
+
</div>
|
16 |
+
|
17 |
+
<div id="bookly-custom-css-dialog" class="modal fade" tabindex=-1 role="dialog">
|
18 |
+
<div class="modal-dialog">
|
19 |
+
<div class="modal-content">
|
20 |
+
<div class="modal-header">
|
21 |
+
<?php _e( 'Edit custom CSS', 'bookly' ) ?>
|
22 |
+
</div>
|
23 |
+
<div class="modal-body">
|
24 |
+
<div class="form-group">
|
25 |
+
<label for="bookly-custom-css" class="control-label"><?php _e( 'Set up your custom CSS styles', 'bookly' ) ?></label>
|
26 |
+
<textarea id="bookly-custom-css" class="form-control" rows="10"><?php echo $custom_css ?></textarea>
|
27 |
+
</div>
|
28 |
+
</div>
|
29 |
+
<div class="modal-footer">
|
30 |
+
<div id="bookly-custom-css-error"></div>
|
31 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( 'bookly-custom-css-save', 'btn-success btn-lg', __( 'Save', 'bookly' ) ) ?>
|
32 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( 'bookly-custom-css-cancel', 'btn-default btn-lg', __( 'Cancel', 'bookly' ) ) ?>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
|
38 |
+
<script type="text/javascript">
|
39 |
+
var saved_css = <?php echo json_encode( $custom_css ); ?>;
|
40 |
+
</script>
|
backend/modules/appearance/templates/_progress_tracker.php
CHANGED
@@ -1,41 +1,42 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
2 |
$i = 1;
|
3 |
?>
|
4 |
-
<div class="
|
5 |
<div class="active">
|
6 |
-
<?php echo $i ++ ?>. <?php
|
7 |
<div class="step"></div>
|
8 |
</div>
|
9 |
-
<?php if ( \BooklyLite\Lib\Config::
|
10 |
<div <?php if ( $step >= 2 ) : ?>class="active"<?php endif ?>>
|
11 |
-
<?php echo $i ++ ?>. <?php
|
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
|
17 |
<div class="step"></div>
|
18 |
</div>
|
19 |
-
<?php if ( \BooklyLite\Lib\Config::
|
20 |
<div <?php if ( $step >= 4 ) : ?>class="active"<?php endif ?>>
|
21 |
-
<?php echo $i ++ ?>. <?php
|
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
|
27 |
<div class="step"></div>
|
28 |
</div>
|
29 |
<div <?php if ( $step >= 6 ) : ?>class="active"<?php endif ?>>
|
30 |
-
<?php echo $i ++ ?>. <?php
|
31 |
<div class="step"></div>
|
32 |
</div>
|
33 |
<div <?php if ( $step >= 7 ) : ?>class="active"<?php endif ?>>
|
34 |
-
<?php echo $i ++ ?>. <?php
|
35 |
<div class="step"></div>
|
36 |
</div>
|
37 |
<div <?php if ( $step >= 8 ) : ?>class="active"<?php endif ?>>
|
38 |
-
<?php echo $i ++ ?>. <?php
|
39 |
<div class="step"></div>
|
40 |
</div>
|
41 |
</div>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var BooklyLite\Backend\Modules\Appearance\Lib\Helper $editable */
|
3 |
$i = 1;
|
4 |
?>
|
5 |
+
<div class="bookly-progress-tracker bookly-table">
|
6 |
<div class="active">
|
7 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_service' ) ) ?>
|
8 |
<div class="step"></div>
|
9 |
</div>
|
10 |
+
<?php if ( \BooklyLite\Lib\Config::serviceExtrasEnabled() ) : ?>
|
11 |
<div <?php if ( $step >= 2 ) : ?>class="active"<?php endif ?>>
|
12 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_extras' ) ) ?>
|
13 |
<div class="step"></div>
|
14 |
</div>
|
15 |
<?php endif ?>
|
16 |
<div <?php if ( $step >= 3 ) : ?>class="active"<?php endif ?>>
|
17 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_time' ) ) ?>
|
18 |
<div class="step"></div>
|
19 |
</div>
|
20 |
+
<?php if ( \BooklyLite\Lib\Config::recurringAppointmentsEnabled() ) : ?>
|
21 |
<div <?php if ( $step >= 4 ) : ?>class="active"<?php endif ?>>
|
22 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_repeat' ) ) ?>
|
23 |
<div class=step></div>
|
24 |
</div>
|
25 |
<?php endif ?>
|
26 |
<div <?php if ( $step >= 5 ) : ?>class="active"<?php endif ?>>
|
27 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_cart' ) ) ?>
|
28 |
<div class="step"></div>
|
29 |
</div>
|
30 |
<div <?php if ( $step >= 6 ) : ?>class="active"<?php endif ?>>
|
31 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_details' ) ) ?>
|
32 |
<div class="step"></div>
|
33 |
</div>
|
34 |
<div <?php if ( $step >= 7 ) : ?>class="active"<?php endif ?>>
|
35 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_payment' ) ) ?>
|
36 |
<div class="step"></div>
|
37 |
</div>
|
38 |
<div <?php if ( $step >= 8 ) : ?>class="active"<?php endif ?>>
|
39 |
+
<?php echo $i ++ ?>. <?php $editable::renderString( array( 'bookly_l10n_step_done' ) ) ?>
|
40 |
<div class="step"></div>
|
41 |
</div>
|
42 |
</div>
|
backend/modules/appearance/templates/index.php
CHANGED
@@ -1,4 +1,17 @@
|
|
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">
|
@@ -9,7 +22,7 @@
|
|
9 |
</div>
|
10 |
<div class="panel panel-default bookly-main">
|
11 |
<div class="panel-body">
|
12 |
-
<div id="
|
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"
|
@@ -19,7 +32,7 @@
|
|
19 |
<div class="col-sm-9 col-lg-10">
|
20 |
<div class="checkbox">
|
21 |
<label>
|
22 |
-
<input type="checkbox" id=
|
23 |
<?php _e( 'Show form progress tracker', 'bookly' ) ?>
|
24 |
</label>
|
25 |
</div>
|
@@ -29,9 +42,9 @@
|
|
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::
|
33 |
-
&& ( $step != 4 || \BooklyLite\Lib\Config::
|
34 |
-
<li class="bookly-nav-item <?php if ( $step == 1 ) : ?>active<?php endif ?>" data-target="#
|
35 |
<?php echo $i++ ?>. <?php echo esc_html( $step_name ) ?>
|
36 |
</li>
|
37 |
<?php endif ?>
|
@@ -45,31 +58,39 @@
|
|
45 |
</div>
|
46 |
<?php endif ?>
|
47 |
|
48 |
-
<div class="row" id="bookly-
|
49 |
-
<div
|
50 |
-
<?php
|
51 |
-
<div class="col-md-
|
52 |
<div class="checkbox">
|
53 |
<label>
|
54 |
-
<input type="checkbox" id=
|
55 |
<?php _e( 'Make selecting employee required', 'bookly' ) ?>
|
56 |
</label>
|
57 |
</div>
|
58 |
</div>
|
59 |
-
<div class="col-md-
|
60 |
<div class="checkbox">
|
61 |
<label>
|
62 |
-
<input type="checkbox" id=
|
63 |
<?php _e( 'Show service price next to employee name', 'bookly' ) ?>
|
64 |
</label>
|
65 |
</div>
|
66 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
</div>
|
68 |
-
<div
|
69 |
<div class="col-md-4">
|
70 |
<div class="checkbox">
|
71 |
<label>
|
72 |
-
<input type="checkbox" id="
|
73 |
<?php _e( 'Show calendar', 'bookly' ) ?>
|
74 |
</label>
|
75 |
</div>
|
@@ -77,7 +98,7 @@
|
|
77 |
<div class="col-md-4">
|
78 |
<div class="checkbox">
|
79 |
<label>
|
80 |
-
<input type="checkbox" id="
|
81 |
<?php _e( 'Show blocked timeslots', 'bookly' ) ?>
|
82 |
</label>
|
83 |
</div>
|
@@ -85,26 +106,101 @@
|
|
85 |
<div class="col-md-4">
|
86 |
<div class="checkbox">
|
87 |
<label>
|
88 |
-
<input type="checkbox" id="
|
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="
|
101 |
<?php // Render unique data per step
|
102 |
switch ( $step ) :
|
103 |
case 1: include '_1_service.php'; break;
|
104 |
-
case 2:
|
105 |
break;
|
106 |
case 3: include '_3_time.php'; break;
|
107 |
-
case 4:
|
108 |
break;
|
109 |
case 5: include '_5_cart.php'; break;
|
110 |
case 6: include '_6_details.php'; break;
|
@@ -116,7 +212,9 @@
|
|
116 |
</div>
|
117 |
</div>
|
118 |
</div>
|
119 |
-
|
|
|
|
|
120 |
</div>
|
121 |
</div>
|
122 |
<div class="panel-footer">
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/**
|
3 |
+
* Template to show appearance page
|
4 |
+
* @var array $steps list of steps in booking form, could be string (the name of step) or false if step disabled
|
5 |
+
* @var string $custom_css custom css text
|
6 |
+
*/
|
7 |
+
?>
|
8 |
+
|
9 |
+
<?php if ( trim( $custom_css ) ) : ?>
|
10 |
+
<style type="text/css">
|
11 |
+
<?php echo $custom_css ?>
|
12 |
+
</style>
|
13 |
+
<?php endif ?>
|
14 |
+
|
15 |
<div id="bookly-tbs" class="wrap">
|
16 |
<div class="bookly-tbs-body">
|
17 |
<div class="page-header text-right clearfix">
|
22 |
</div>
|
23 |
<div class="panel panel-default bookly-main">
|
24 |
<div class="panel-body">
|
25 |
+
<div id="bookly-appearance">
|
26 |
<div class="row">
|
27 |
<div class="col-sm-3 col-lg-2 bookly-color-picker-wrapper">
|
28 |
<input type="text" name="color" class="bookly-js-color-picker"
|
32 |
<div class="col-sm-9 col-lg-10">
|
33 |
<div class="checkbox">
|
34 |
<label>
|
35 |
+
<input type="checkbox" id=bookly-show-progress-tracker <?php checked( get_option( 'bookly_app_show_progress_tracker' ) ) ?>>
|
36 |
<?php _e( 'Show form progress tracker', 'bookly' ) ?>
|
37 |
</label>
|
38 |
</div>
|
42 |
<ul class="bookly-nav bookly-nav-tabs bookly-margin-top-lg" role="tablist">
|
43 |
<?php $i = 1 ?>
|
44 |
<?php foreach ( $steps as $step => $step_name ) : ?>
|
45 |
+
<?php if ( ( $step != 2 || \BooklyLite\Lib\Config::serviceExtrasEnabled() )
|
46 |
+
&& ( $step != 4 || \BooklyLite\Lib\Config::recurringAppointmentsEnabled() ) ) : ?>
|
47 |
+
<li class="bookly-nav-item <?php if ( $step == 1 ) : ?>active<?php endif ?>" data-target="#bookly-step-<?php echo $step ?>" data-toggle="tab">
|
48 |
<?php echo $i++ ?>. <?php echo esc_html( $step_name ) ?>
|
49 |
</li>
|
50 |
<?php endif ?>
|
58 |
</div>
|
59 |
<?php endif ?>
|
60 |
|
61 |
+
<div class="row" id="bookly-step-settings">
|
62 |
+
<div class="bookly-js-service-settings bookly-margin-top-lg">
|
63 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderAppearanceStepServiceSettings() ?>
|
64 |
+
<div class="col-md-3">
|
65 |
<div class="checkbox">
|
66 |
<label>
|
67 |
+
<input type="checkbox" id=bookly-required-employee <?php checked( get_option( 'bookly_app_required_employee' ) ) ?>>
|
68 |
<?php _e( 'Make selecting employee required', 'bookly' ) ?>
|
69 |
</label>
|
70 |
</div>
|
71 |
</div>
|
72 |
+
<div class="col-md-3">
|
73 |
<div class="checkbox">
|
74 |
<label>
|
75 |
+
<input type="checkbox" id=bookly-staff-name-with-price <?php checked( get_option( 'bookly_app_staff_name_with_price' ) ) ?>>
|
76 |
<?php _e( 'Show service price next to employee name', 'bookly' ) ?>
|
77 |
</label>
|
78 |
</div>
|
79 |
</div>
|
80 |
+
<div class="col-md-3">
|
81 |
+
<div class="checkbox">
|
82 |
+
<label>
|
83 |
+
<input type="checkbox" id=bookly-service-name-with-duration <?php checked( get_option( 'bookly_app_service_name_with_duration' ) ) ?>>
|
84 |
+
<?php _e( 'Show service duration next to service name', 'bookly' ) ?>
|
85 |
+
</label>
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
</div>
|
89 |
+
<div class="bookly-js-time-settings bookly-margin-top-lg" style="display:none">
|
90 |
<div class="col-md-4">
|
91 |
<div class="checkbox">
|
92 |
<label>
|
93 |
+
<input type="checkbox" id="bookly-show-calendar" <?php checked( get_option( 'bookly_app_show_calendar' ) ) ?>>
|
94 |
<?php _e( 'Show calendar', 'bookly' ) ?>
|
95 |
</label>
|
96 |
</div>
|
98 |
<div class="col-md-4">
|
99 |
<div class="checkbox">
|
100 |
<label>
|
101 |
+
<input type="checkbox" id="bookly-show-blocked-timeslots" <?php checked( get_option( 'bookly_app_show_blocked_timeslots' ) ) ?>>
|
102 |
<?php _e( 'Show blocked timeslots', 'bookly' ) ?>
|
103 |
</label>
|
104 |
</div>
|
106 |
<div class="col-md-4">
|
107 |
<div class="checkbox">
|
108 |
<label>
|
109 |
+
<input type="checkbox" id="bookly-show-day-one-column" <?php checked( get_option( 'bookly_app_show_day_one_column' ) ) ?>>
|
110 |
<?php _e( 'Show each day in one column', 'bookly' ) ?>
|
111 |
</label>
|
112 |
</div>
|
113 |
</div>
|
114 |
</div>
|
115 |
+
<div class="bookly-js-details-settings bookly-margin-top-lg" style="display:none">
|
116 |
+
<div class="col-md-3">
|
117 |
+
<div class="checkbox">
|
118 |
+
<label>
|
119 |
+
<input type="checkbox" id="bookly-cst-required-phone" <?php checked( get_option( 'bookly_cst_required_phone' ) ) ?>>
|
120 |
+
<?php _e( 'Make phone field required', 'bookly' ) ?>
|
121 |
+
</label>
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
<div class="col-md-3">
|
125 |
+
<div class="checkbox">
|
126 |
+
<label>
|
127 |
+
<input type="checkbox" id="bookly-show-login-button" <?php checked( get_option( 'bookly_app_show_login_button' ) ) ?>>
|
128 |
+
<?php _e( 'Show Login button', 'bookly' ) ?>
|
129 |
+
</label>
|
130 |
+
</div>
|
131 |
+
</div>
|
132 |
+
<div class="col-md-3">
|
133 |
+
<div class="checkbox">
|
134 |
+
<label>
|
135 |
+
<input type="checkbox" id="bookly-cst-first-last-name" <?php checked( get_option( 'bookly_cst_first_last_name' ) ) ?> data-toggle="popover" data-trigger="focus" data-placement="auto bottom" data-content="<?php _e( 'Do not forget to update your email and SMS codes for customer names', 'bookly' ) ?>">
|
136 |
+
<?php _e( 'Use first and last name instead of full name', 'bookly' ) ?>
|
137 |
+
</label>
|
138 |
+
</div>
|
139 |
+
</div>
|
140 |
+
<div class="col-md-3">
|
141 |
+
<div class="checkbox">
|
142 |
+
<label>
|
143 |
+
<input type="checkbox" id="bookly-show-notes" <?php checked( get_option( 'bookly_app_show_notes' ) ) ?>>
|
144 |
+
<?php _e( 'Show notes field', 'bookly' ) ?>
|
145 |
+
</label>
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
</div>
|
149 |
+
<div class="bookly-js-payment-settings bookly-margin-top-lg" style="display:none">
|
150 |
+
<div class="col-md-12">
|
151 |
+
<div class="alert alert-info bookly-margin-top-lg bookly-margin-bottom-remove bookly-flexbox">
|
152 |
+
<div class="bookly-flex-row">
|
153 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
154 |
+
<div class="bookly-flex-cell">
|
155 |
+
<div>
|
156 |
+
<?php _e( 'The booking form on this step may have different set or states of its elements. It depends on various conditions such as installed/activated add-ons, settings configuration or choices made on previous steps. Select option and click on the underlined text to edit.', 'bookly' ) ?>
|
157 |
+
</div>
|
158 |
+
<div class="bookly-margin-top-lg">
|
159 |
+
<select id="bookly-payment-step-view" class="form-control">
|
160 |
+
<option value="single-app"><?php _e( 'Form view in case of single booking', 'bookly' ) ?></option>
|
161 |
+
<option value="several-apps"><?php _e( 'Form view in case of multiple booking', 'bookly' ) ?></option>
|
162 |
+
</select>
|
163 |
+
</div>
|
164 |
+
</div>
|
165 |
+
</div>
|
166 |
+
</div>
|
167 |
+
</div>
|
168 |
+
</div>
|
169 |
+
<div class="bookly-js-done-settings bookly-margin-top-lg" style="display:none">
|
170 |
+
<div class="col-md-12">
|
171 |
+
<div class="alert alert-info bookly-margin-top-lg bookly-margin-bottom-remove bookly-flexbox">
|
172 |
+
<div class="bookly-flex-row">
|
173 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
174 |
+
<div class="bookly-flex-cell">
|
175 |
+
<div>
|
176 |
+
<?php _e( 'The booking form on this step may have different set or states of its elements. It depends on various conditions such as installed/activated add-ons, settings configuration or choices made on previous steps. Select option and click on the underlined text to edit.', 'bookly' ) ?>
|
177 |
+
</div>
|
178 |
+
<div class="bookly-margin-top-lg">
|
179 |
+
<select id="bookly-done-step-view" class="form-control">
|
180 |
+
<option value="booking-success"><?php _e( 'Form view in case of successful booking', 'bookly' ) ?></option>
|
181 |
+
<option value="booking-limit-error"><?php _e( 'Form view in case the number of bookings exceeds the limit', 'bookly' ) ?></option>
|
182 |
+
<option value="booking-processing"><?php _e( 'Form view in case of payment has been accepted for processing', 'bookly' ) ?></option>
|
183 |
+
</select>
|
184 |
+
</div>
|
185 |
+
</div>
|
186 |
+
</div>
|
187 |
+
</div>
|
188 |
+
</div>
|
189 |
+
</div>
|
190 |
</div>
|
191 |
|
192 |
<div class="panel panel-default bookly-margin-top-lg">
|
193 |
<div class="panel-body">
|
194 |
<div class="tab-content">
|
195 |
<?php foreach ( $steps as $step => $step_name ) : ?>
|
196 |
+
<div id="bookly-step-<?php echo $step ?>" class="tab-pane <?php if ( $step == 1 ) : ?>active<?php endif ?>" data-target="<?php echo $step ?>">
|
197 |
<?php // Render unique data per step
|
198 |
switch ( $step ) :
|
199 |
case 1: include '_1_service.php'; break;
|
200 |
+
case 2: \BooklyLite\Lib\Proxy\ServiceExtras::renderAppearance( $this->render( '_progress_tracker', compact( 'step', 'editable' ), false ) );
|
201 |
break;
|
202 |
case 3: include '_3_time.php'; break;
|
203 |
+
case 4: \BooklyLite\Lib\Proxy\RecurringAppointments::renderAppearance( $this->render( '_progress_tracker', compact( 'step', 'editable' ), false ) );
|
204 |
break;
|
205 |
case 5: include '_5_cart.php'; break;
|
206 |
case 6: include '_6_details.php'; break;
|
212 |
</div>
|
213 |
</div>
|
214 |
</div>
|
215 |
+
<div>
|
216 |
+
<?php $this->render( '_custom_css', array( 'custom_css' => $custom_css) ); ?>
|
217 |
+
</div>
|
218 |
</div>
|
219 |
</div>
|
220 |
<div class="panel-footer">
|
backend/modules/appointments/Controller.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
namespace BooklyLite\Backend\Modules\Appointments;
|
3 |
|
4 |
use BooklyLite\Lib;
|
|
|
5 |
|
6 |
/**
|
7 |
* Class Controller
|
@@ -19,6 +20,7 @@ class Controller extends Lib\Base\Controller
|
|
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 |
),
|
@@ -27,9 +29,10 @@ class Controller extends Lib\Base\Controller
|
|
27 |
$this->enqueueScripts( array(
|
28 |
'backend' => array(
|
29 |
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
30 |
-
'js/datatables.min.js'
|
31 |
'js/moment.min.js',
|
32 |
-
'js/daterangepicker.js'
|
|
|
33 |
),
|
34 |
'frontend' => array(
|
35 |
'js/spin.min.js' => array( 'jquery' ),
|
@@ -38,12 +41,11 @@ class Controller extends Lib\Base\Controller
|
|
38 |
'module' => array( 'js/appointments.js' => array( 'bookly-datatables.min.js' ), ),
|
39 |
) );
|
40 |
|
41 |
-
// Custom fields without captcha field.
|
42 |
-
$custom_fields =
|
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' ),
|
@@ -68,14 +70,16 @@ class Controller extends Lib\Base\Controller
|
|
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 |
-
'
|
|
|
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.
|
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' ) );
|
@@ -89,25 +93,27 @@ class Controller extends Lib\Base\Controller
|
|
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.
|
101 |
-
c.
|
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' )
|
@@ -125,19 +131,19 @@ class Controller extends Lib\Base\Controller
|
|
125 |
$end = date( 'Y-m-d', strtotime( '+1 day', strtotime( $end ) ) );
|
126 |
$query->whereBetween( 'a.start_date', $start, $end );
|
127 |
|
128 |
-
if ( $filter['staff'] !=
|
129 |
$query->where( 'a.staff_id', $filter['staff'] );
|
130 |
}
|
131 |
|
132 |
-
if ( $filter['customer'] !=
|
133 |
$query->where( 'ca.customer_id', $filter['customer'] );
|
134 |
}
|
135 |
|
136 |
-
if ( $filter['service']
|
137 |
-
$query->where( 'a.service_id', $filter['service'] );
|
138 |
}
|
139 |
|
140 |
-
if ( $filter['status'] !=
|
141 |
$query->where( 'ca.status', $filter['status'] );
|
142 |
}
|
143 |
|
@@ -147,9 +153,7 @@ class Controller extends Lib\Base\Controller
|
|
147 |
}
|
148 |
|
149 |
$custom_fields = array();
|
150 |
-
$fields_data =
|
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 |
}
|
@@ -158,18 +162,14 @@ class Controller extends Lib\Base\Controller
|
|
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\
|
171 |
if ( $row['payment'] != $row['payment_total'] ) {
|
172 |
-
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\
|
173 |
}
|
174 |
$payment_title .= sprintf(
|
175 |
' %s <span%s>%s</span>',
|
@@ -181,7 +181,7 @@ class Controller extends Lib\Base\Controller
|
|
181 |
// Custom fields
|
182 |
$customer_appointment = new Lib\Entities\CustomerAppointment();
|
183 |
$customer_appointment->load( $row['ca_id'] );
|
184 |
-
foreach ( $customer_appointment
|
185 |
$custom_fields[ $custom_field['id'] ] = $custom_field['value'];
|
186 |
}
|
187 |
|
@@ -189,20 +189,21 @@ class Controller extends Lib\Base\Controller
|
|
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'
|
195 |
-
'
|
196 |
-
'phone'
|
197 |
-
'email'
|
198 |
),
|
199 |
'service' => array(
|
200 |
'title' => $row['service_title'],
|
201 |
'duration' => $service_duration,
|
202 |
-
'extras' =>
|
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'],
|
@@ -215,7 +216,7 @@ class Controller extends Lib\Base\Controller
|
|
215 |
update_user_meta( get_current_user_id(), 'bookly_filter_appointments_list', $filter );
|
216 |
|
217 |
wp_send_json( array(
|
218 |
-
'draw' => (
|
219 |
'recordsTotal' => $total,
|
220 |
'recordsFiltered' => count( $data ),
|
221 |
'data' => $data,
|
@@ -230,27 +231,23 @@ class Controller extends Lib\Base\Controller
|
|
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 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
-
|
|
|
|
|
|
|
|
|
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 |
}
|
2 |
namespace BooklyLite\Backend\Modules\Appointments;
|
3 |
|
4 |
use BooklyLite\Lib;
|
5 |
+
use BooklyLite\Lib\DataHolders\Booking as DataHolders;
|
6 |
|
7 |
/**
|
8 |
* Class Controller
|
20 |
$this->enqueueStyles( array(
|
21 |
'frontend' => array( 'css/ladda.min.css', ),
|
22 |
'backend' => array(
|
23 |
+
'css/select2.min.css',
|
24 |
'bootstrap/css/bootstrap-theme.min.css',
|
25 |
'css/daterangepicker.css',
|
26 |
),
|
29 |
$this->enqueueScripts( array(
|
30 |
'backend' => array(
|
31 |
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
32 |
+
'js/datatables.min.js' => array( 'jquery' ),
|
33 |
'js/moment.min.js',
|
34 |
+
'js/daterangepicker.js' => array( 'jquery' ),
|
35 |
+
'js/select2.full.min.js' => array( 'jquery' ),
|
36 |
),
|
37 |
'frontend' => array(
|
38 |
'js/spin.min.js' => array( 'jquery' ),
|
41 |
'module' => array( 'js/appointments.js' => array( 'bookly-datatables.min.js' ), ),
|
42 |
) );
|
43 |
|
44 |
+
// Custom fields without captcha & text content field.
|
45 |
+
$custom_fields = (array) Lib\Proxy\CustomFields::getWhichHaveData();
|
|
|
|
|
46 |
|
47 |
wp_localize_script( 'bookly-appointments.js', 'BooklyL10n', array(
|
48 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
49 |
'tomorrow' => __( 'Tomorrow', 'bookly' ),
|
50 |
'today' => __( 'Today', 'bookly' ),
|
51 |
'yesterday' => __( 'Yesterday', 'bookly' ),
|
70 |
'zeroRecords' => __( 'No appointments for selected period.', 'bookly' ),
|
71 |
'processing' => __( 'Processing...', 'bookly' ),
|
72 |
'edit' => __( 'Edit', 'bookly' ),
|
73 |
+
'show_notes' => Lib\Config::showNotes(),
|
74 |
'cf_columns' => array_map( function ( $custom_field ) { return $custom_field->id; }, $custom_fields ),
|
75 |
'filter' => (array) get_user_meta( get_current_user_id(), 'bookly_filter_appointments_list', true ),
|
76 |
+
'no_result_found' => __( 'No result found', 'bookly' ),
|
77 |
+
'limitations' => __( '<b class="h4">This function is not available in the Lite version of Bookly.</b><br><br>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', 'bookly' ) . ' <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
78 |
) );
|
79 |
|
80 |
// Filters data
|
81 |
+
$staff_members = Lib\Entities\Staff::query( 's' )->select( 's.id, s.full_name' )->where( 'id', 1 )->fetchArray();
|
82 |
+
$customers = Lib\Entities\Customer::query( 'c' )->select( 'c.id, c.full_name, c.first_name, c.last_name' )->fetchArray();
|
83 |
$services = Lib\Entities\Service::query( 's' )->select( 's.id, s.title' )->where( 'type', Lib\Entities\Service::TYPE_SIMPLE )->fetchArray();
|
84 |
|
85 |
$this->render( 'index', compact( 'custom_fields', 'staff_members', 'customers', 'services' ) );
|
93 |
$columns = $this->getParameter( 'columns' );
|
94 |
$order = $this->getParameter( 'order' );
|
95 |
$filter = $this->getParameter( 'filter' );
|
96 |
+
$postfix_any = sprintf( ' (%s)', get_option( 'bookly_l10n_option_employee' ) );
|
97 |
|
98 |
$query = Lib\Entities\CustomerAppointment::query( 'ca' )
|
99 |
->select( 'a.id,
|
100 |
ca.payment_id,
|
101 |
ca.status,
|
102 |
ca.id AS ca_id,
|
103 |
+
ca.notes,
|
104 |
ca.extras,
|
105 |
a.start_date,
|
106 |
+
a.staff_any,
|
107 |
+
c.full_name AS customer_full_name,
|
108 |
c.phone AS customer_phone,
|
109 |
c.email AS customer_email,
|
|
|
|
|
110 |
st.full_name AS staff_name,
|
111 |
p.paid AS payment,
|
112 |
p.total AS payment_total,
|
113 |
p.type AS payment_type,
|
114 |
+
p.status AS payment_status,
|
115 |
+
COALESCE(s.title, a.custom_service_name) AS service_title,
|
116 |
+
TIME_TO_SEC(TIMEDIFF(a.end_date, a.start_date)) + a.extras_duration AS service_duration' )
|
117 |
->leftJoin( 'Appointment', 'a', 'a.id = ca.appointment_id' )
|
118 |
->leftJoin( 'Service', 's', 's.id = a.service_id' )
|
119 |
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
131 |
$end = date( 'Y-m-d', strtotime( '+1 day', strtotime( $end ) ) );
|
132 |
$query->whereBetween( 'a.start_date', $start, $end );
|
133 |
|
134 |
+
if ( $filter['staff'] != '' ) {
|
135 |
$query->where( 'a.staff_id', $filter['staff'] );
|
136 |
}
|
137 |
|
138 |
+
if ( $filter['customer'] != '' ) {
|
139 |
$query->where( 'ca.customer_id', $filter['customer'] );
|
140 |
}
|
141 |
|
142 |
+
if ( $filter['service'] != '' ) {
|
143 |
+
$query->where( 'a.service_id', $filter['service'] ?: null );
|
144 |
}
|
145 |
|
146 |
+
if ( $filter['status'] != '' ) {
|
147 |
$query->where( 'ca.status', $filter['status'] );
|
148 |
}
|
149 |
|
153 |
}
|
154 |
|
155 |
$custom_fields = array();
|
156 |
+
$fields_data = (array) Lib\Proxy\CustomFields::getWhichHaveData();
|
|
|
|
|
157 |
foreach ( $fields_data as $field_data ) {
|
158 |
$custom_fields[ $field_data->id ] = '';
|
159 |
}
|
162 |
foreach ( $query->fetchArray() as $row ) {
|
163 |
// Service duration.
|
164 |
$service_duration = Lib\Utils\DateTime::secondsToInterval( $row['service_duration'] );
|
|
|
|
|
|
|
165 |
// Appointment status.
|
166 |
$row['status'] = Lib\Entities\CustomerAppointment::statusToString( $row['status'] );
|
|
|
167 |
// Payment title.
|
168 |
$payment_title = '';
|
169 |
if ( $row['payment'] !== null ) {
|
170 |
+
$payment_title = Lib\Utils\Price::format( $row['payment'] );
|
171 |
if ( $row['payment'] != $row['payment_total'] ) {
|
172 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $row['payment_total'] ) );
|
173 |
}
|
174 |
$payment_title .= sprintf(
|
175 |
' %s <span%s>%s</span>',
|
181 |
// Custom fields
|
182 |
$customer_appointment = new Lib\Entities\CustomerAppointment();
|
183 |
$customer_appointment->load( $row['ca_id'] );
|
184 |
+
foreach ( (array) Lib\Proxy\CustomFields::getForCustomerAppointment( $customer_appointment ) as $custom_field ) {
|
185 |
$custom_fields[ $custom_field['id'] ] = $custom_field['value'];
|
186 |
}
|
187 |
|
189 |
'id' => $row['id'],
|
190 |
'start_date' => Lib\Utils\DateTime::formatDateTime( $row['start_date'] ),
|
191 |
'staff' => array(
|
192 |
+
'name' => $row['staff_name'] . ( $row['staff_any'] ? $postfix_any : '' ),
|
193 |
),
|
194 |
+
'customer' => array(
|
195 |
+
'full_name' => $row['customer_full_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' => (array) Lib\Proxy\ServiceExtras::getInfo( json_decode( $row['extras'], true ), false ),
|
203 |
),
|
204 |
'status' => $row['status'],
|
205 |
'payment' => $payment_title,
|
206 |
+
'notes' => $row['notes'],
|
207 |
'custom_fields' => $custom_fields,
|
208 |
'ca_id' => $row['ca_id'],
|
209 |
'payment_id' => $row['payment_id'],
|
216 |
update_user_meta( get_current_user_id(), 'bookly_filter_appointments_list', $filter );
|
217 |
|
218 |
wp_send_json( array(
|
219 |
+
'draw' => (int) $this->getParameter( 'draw' ),
|
220 |
'recordsTotal' => $total,
|
221 |
'recordsFiltered' => count( $data ),
|
222 |
'data' => $data,
|
231 |
/** @var Lib\Entities\CustomerAppointment $ca */
|
232 |
foreach ( Lib\Entities\CustomerAppointment::query()->whereIn( 'id', $this->getParameter( 'data', array() ) )->find() as $ca ) {
|
233 |
if ( $this->getParameter( 'notify' ) ) {
|
234 |
+
switch ( $ca->getStatus() ) {
|
235 |
+
case Lib\Entities\CustomerAppointment::STATUS_PENDING:
|
236 |
+
case Lib\Entities\CustomerAppointment::STATUS_WAITLISTED:
|
237 |
+
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_REJECTED );
|
238 |
+
break;
|
239 |
+
case Lib\Entities\CustomerAppointment::STATUS_APPROVED:
|
240 |
+
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_CANCELLED );
|
241 |
+
break;
|
242 |
}
|
243 |
+
Lib\NotificationSender::sendSingle(
|
244 |
+
DataHolders\Simple::create( $ca ),
|
245 |
+
null,
|
246 |
+
array( 'cancellation_reason' => $this->getParameter( 'reason' ) )
|
247 |
+
);
|
248 |
}
|
249 |
$ca->deleteCascade();
|
250 |
}
|
251 |
wp_send_json_success();
|
252 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
253 |
}
|
backend/modules/appointments/resources/js/appointments.js
CHANGED
@@ -23,10 +23,17 @@ jQuery(function($) {
|
|
23 |
|
24 |
}
|
25 |
|
|
|
26 |
$.each(BooklyL10n.filter, function (field, value) {
|
27 |
-
if (value !=
|
28 |
$('#bookly-filter-' + field).val(value);
|
29 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
});
|
31 |
|
32 |
/**
|
@@ -36,7 +43,7 @@ jQuery(function($) {
|
|
36 |
{ data: 'id', responsivePriority: 2 },
|
37 |
{ data: 'start_date', responsivePriority: 2 },
|
38 |
{ data: 'staff.name', responsivePriority: 2 },
|
39 |
-
{ data: 'customer.
|
40 |
{
|
41 |
data: 'customer.phone',
|
42 |
responsivePriority: 3,
|
@@ -76,6 +83,13 @@ jQuery(function($) {
|
|
76 |
}
|
77 |
}
|
78 |
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
$.each(BooklyL10n.cf_columns, function (i, cf_id) {
|
80 |
columns.push({
|
81 |
data: 'custom_fields.' + cf_id,
|
@@ -96,7 +110,7 @@ jQuery(function($) {
|
|
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'),
|
@@ -214,10 +228,11 @@ jQuery(function($) {
|
|
214 |
url : ajaxurl,
|
215 |
type : 'POST',
|
216 |
data : {
|
217 |
-
action
|
218 |
-
|
219 |
-
|
220 |
-
|
|
|
221 |
},
|
222 |
dataType : 'json',
|
223 |
success : function(response) {
|
@@ -282,10 +297,20 @@ jQuery(function($) {
|
|
282 |
/**
|
283 |
* On filters change.
|
284 |
*/
|
285 |
-
$('.bookly-js-
|
286 |
-
|
287 |
-
|
288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
$id_filter.on('keyup', function () { dt.ajax.reload(); });
|
290 |
$date_filter.on('apply.daterangepicker', function () { dt.ajax.reload(); });
|
291 |
$staff_filter.on('change', function () { dt.ajax.reload(); });
|
23 |
|
24 |
}
|
25 |
|
26 |
+
$('.bookly-js-select').val(null);
|
27 |
$.each(BooklyL10n.filter, function (field, value) {
|
28 |
+
if (value != '') {
|
29 |
$('#bookly-filter-' + field).val(value);
|
30 |
}
|
31 |
+
// check if select has correct values
|
32 |
+
if ($('#bookly-filter-' + field).prop('type') == 'select-one') {
|
33 |
+
if ($('#bookly-filter-' + field +' option[value="' + value + '"]').length == 0) {
|
34 |
+
$('#bookly-filter-' + field).val(null);
|
35 |
+
}
|
36 |
+
}
|
37 |
});
|
38 |
|
39 |
/**
|
43 |
{ data: 'id', responsivePriority: 2 },
|
44 |
{ data: 'start_date', responsivePriority: 2 },
|
45 |
{ data: 'staff.name', responsivePriority: 2 },
|
46 |
+
{ data: 'customer.full_name', render: $.fn.dataTable.render.text(), responsivePriority: 2 },
|
47 |
{
|
48 |
data: 'customer.phone',
|
49 |
responsivePriority: 3,
|
83 |
}
|
84 |
}
|
85 |
];
|
86 |
+
if (BooklyL10n.show_notes) {
|
87 |
+
columns.push({
|
88 |
+
data: 'notes',
|
89 |
+
render: $.fn.dataTable.render.text(),
|
90 |
+
responsivePriority: 4
|
91 |
+
});
|
92 |
+
}
|
93 |
$.each(BooklyL10n.cf_columns, function (i, cf_id) {
|
94 |
columns.push({
|
95 |
data: 'custom_fields.' + cf_id,
|
110 |
url : ajaxurl,
|
111 |
type: 'POST',
|
112 |
data: function (d) {
|
113 |
+
return $.extend({action: 'bookly_get_appointments', csrf_token : BooklyL10n.csrf_token}, {
|
114 |
filter: {
|
115 |
id : $id_filter.val(),
|
116 |
date : $date_filter.data('date'),
|
228 |
url : ajaxurl,
|
229 |
type : 'POST',
|
230 |
data : {
|
231 |
+
action : 'bookly_delete_customer_appointments',
|
232 |
+
csrf_token : BooklyL10n.csrf_token,
|
233 |
+
data : data,
|
234 |
+
notify : $('#bookly-delete-notify').prop('checked') ? 1 : 0,
|
235 |
+
reason : $('#bookly-delete-reason').val()
|
236 |
},
|
237 |
dataType : 'json',
|
238 |
success : function(response) {
|
297 |
/**
|
298 |
* On filters change.
|
299 |
*/
|
300 |
+
$('.bookly-js-select')
|
301 |
+
.on('select2:unselecting', function(e) {
|
302 |
+
e.preventDefault();
|
303 |
+
$(this).val(null).trigger('change');
|
304 |
+
})
|
305 |
+
.select2({
|
306 |
+
width: '100%',
|
307 |
+
theme: 'bootstrap',
|
308 |
+
allowClear: true,
|
309 |
+
language : {
|
310 |
+
noResults: function() { return BooklyL10n.no_result_found; }
|
311 |
+
}
|
312 |
+
});
|
313 |
+
|
314 |
$id_filter.on('keyup', function () { dt.ajax.reload(); });
|
315 |
$date_filter.on('apply.daterangepicker', function () { dt.ajax.reload(); });
|
316 |
$staff_filter.on('change', function () { dt.ajax.reload(); });
|
backend/modules/appointments/templates/_export_dialog.php
CHANGED
@@ -1,4 +1,7 @@
|
|
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">
|
@@ -25,7 +28,10 @@
|
|
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;
|
|
|
|
|
|
|
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>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Common;
|
3 |
+
use BooklyLite\Lib\Config;
|
4 |
+
?>
|
5 |
<div id="bookly-export-dialog" class="modal fade" tabindex=-1 role="dialog">
|
6 |
<div class="modal-dialog">
|
7 |
<div class="modal-content">
|
28 |
<div class="checkbox"><label><input checked value="7" type="checkbox" /><?php _e( 'Duration', 'bookly' ) ?></label></div>
|
29 |
<div class="checkbox"><label><input checked value="8" type="checkbox" /><?php _e( 'Status', 'bookly' ) ?></label></div>
|
30 |
<div class="checkbox"><label><input checked value="9" type="checkbox" /><?php _e( 'Payment', 'bookly' ) ?></label></div>
|
31 |
+
<?php $i = 10; if ( Config::showNotes() ): $i = 11; ?>
|
32 |
+
<div class="checkbox"><label><input checked value="10" type="checkbox" /><?php echo esc_html( Common::getTranslatedOption( 'bookly_l10n_label_notes' ) ) ?></label></div>
|
33 |
+
<?php endif ?>
|
34 |
+
<?php foreach ( $custom_fields as $custom_field ) : ?>
|
35 |
<div class="checkbox"><label><input checked value="<?php echo $i ++ ?>" type="checkbox"/><?php echo $custom_field->label ?></label></div>
|
36 |
<?php endforeach ?>
|
37 |
</div>
|
backend/modules/appointments/templates/_print_dialog.php
DELETED
@@ -1,33 +0,0 @@
|
|
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,5 +1,7 @@
|
|
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">
|
@@ -23,7 +25,8 @@ use BooklyLite\Lib\Entities\CustomerAppointment;
|
|
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' ) ?>" />
|
@@ -41,10 +44,9 @@ use BooklyLite\Lib\Entities\CustomerAppointment;
|
|
41 |
</div>
|
42 |
<div class="col-md-4 col-lg-2">
|
43 |
<div class="form-group">
|
44 |
-
<select class="form-control bookly-js-
|
45 |
-
<option value="-1"></option>
|
46 |
<?php foreach ( $staff_members as $staff ) : ?>
|
47 |
-
<option value="<?php echo $staff['id'] ?>"><?php
|
48 |
<?php endforeach ?>
|
49 |
</select>
|
50 |
</div>
|
@@ -52,32 +54,33 @@ use BooklyLite\Lib\Entities\CustomerAppointment;
|
|
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-
|
56 |
-
<option value="-1"></option>
|
57 |
<?php foreach ( $customers as $customer ) : ?>
|
58 |
-
<option value="<?php echo $customer['id'] ?>"><?php
|
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-
|
66 |
-
<option value="
|
67 |
<?php foreach ( $services as $service ) : ?>
|
68 |
-
<option value="<?php echo $service['id'] ?>"><?php
|
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-
|
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>
|
@@ -88,14 +91,17 @@ use BooklyLite\Lib\Entities\CustomerAppointment;
|
|
88 |
<tr>
|
89 |
<th><?php _e( 'No.', 'bookly' ) ?></th>
|
90 |
<th><?php _e( 'Appointment Date', 'bookly' ) ?></th>
|
91 |
-
<th><?php echo
|
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
|
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 ?>
|
@@ -106,16 +112,15 @@ use BooklyLite\Lib\Entities\CustomerAppointment;
|
|
106 |
</table>
|
107 |
|
108 |
<div class="text-right bookly-margin-top-lg">
|
109 |
-
<?php
|
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
|
120 |
</div>
|
121 |
</div>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
use BooklyLite\Lib\Entities\CustomerAppointment;
|
3 |
+
use BooklyLite\Lib\Utils\Common;
|
4 |
+
use BooklyLite\Lib\Config;
|
5 |
?>
|
6 |
<div id="bookly-tbs" class="wrap">
|
7 |
<div class="bookly-tbs-body">
|
25 |
<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>
|
26 |
</div>
|
27 |
</div>
|
28 |
+
</div>
|
29 |
+
<div class="row">
|
30 |
<div class="col-md-4 col-lg-1">
|
31 |
<div class="form-group">
|
32 |
<input class="form-control" type="text" id="bookly-filter-id" placeholder="<?php esc_attr_e( 'No.', 'bookly' ) ?>" />
|
44 |
</div>
|
45 |
<div class="col-md-4 col-lg-2">
|
46 |
<div class="form-group">
|
47 |
+
<select class="form-control bookly-js-select" id="bookly-filter-staff" data-placeholder="<?php echo esc_attr( Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ) ?>">
|
|
|
48 |
<?php foreach ( $staff_members as $staff ) : ?>
|
49 |
+
<option value="<?php echo $staff['id'] ?>"><?php echo esc_html( $staff['full_name'] ) ?></option>
|
50 |
<?php endforeach ?>
|
51 |
</select>
|
52 |
</div>
|
54 |
<div class="clearfix visible-md-block"></div>
|
55 |
<div class="col-md-4 col-lg-2">
|
56 |
<div class="form-group">
|
57 |
+
<select class="form-control bookly-js-select" id="bookly-filter-customer" data-placeholder="<?php esc_attr_e( 'Customer', 'bookly' ) ?>">
|
|
|
58 |
<?php foreach ( $customers as $customer ) : ?>
|
59 |
+
<option value="<?php echo $customer['id'] ?>"><?php echo esc_html( $customer['full_name'] ) ?></option>
|
60 |
<?php endforeach ?>
|
61 |
</select>
|
62 |
</div>
|
63 |
</div>
|
64 |
<div class="col-md-4 col-lg-2">
|
65 |
<div class="form-group">
|
66 |
+
<select class="form-control bookly-js-select" id="bookly-filter-service" data-placeholder="<?php echo esc_attr( Common::getTranslatedOption( 'bookly_l10n_label_service' ) ) ?>">
|
67 |
+
<option value="0"><?php esc_html_e( 'Custom', 'bookly' ) ?></option>
|
68 |
<?php foreach ( $services as $service ) : ?>
|
69 |
+
<option value="<?php echo $service['id'] ?>"><?php echo esc_html( $service['title'] ) ?></option>
|
70 |
<?php endforeach ?>
|
71 |
</select>
|
72 |
</div>
|
73 |
</div>
|
74 |
<div class="col-md-4 col-lg-2">
|
75 |
<div class="form-group">
|
76 |
+
<select class="form-control bookly-js-select" id="bookly-filter-status" data-placeholder="<?php esc_attr_e( 'Status', 'bookly' ) ?>">
|
|
|
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 |
+
<?php if ( Config::waitingListActive() ): ?>
|
82 |
+
<option value="<?php echo CustomerAppointment::STATUS_WAITLISTED ?>"><?php echo CustomerAppointment::statusToString( CustomerAppointment::STATUS_WAITLISTED ) ?></option>
|
83 |
+
<?php endif ?>
|
84 |
</select>
|
85 |
</div>
|
86 |
</div>
|
91 |
<tr>
|
92 |
<th><?php _e( 'No.', 'bookly' ) ?></th>
|
93 |
<th><?php _e( 'Appointment Date', 'bookly' ) ?></th>
|
94 |
+
<th><?php echo esc_html( Common::getTranslatedOption( 'bookly_l10n_label_employee' ) ) ?></th>
|
95 |
<th><?php _e( 'Customer Name', 'bookly' ) ?></th>
|
96 |
<th><?php _e( 'Customer Phone', 'bookly' ) ?></th>
|
97 |
<th><?php _e( 'Customer Email', 'bookly' ) ?></th>
|
98 |
+
<th><?php echo esc_html( Common::getTranslatedOption( 'bookly_l10n_label_service' ) ) ?></th>
|
99 |
<th><?php _e( 'Duration', 'bookly' ) ?></th>
|
100 |
<th><?php _e( 'Status', 'bookly' ) ?></th>
|
101 |
<th><?php _e( 'Payment', 'bookly' ) ?></th>
|
102 |
+
<?php if ( Config::showNotes() ): ?>
|
103 |
+
<th><?php echo esc_html( Common::getTranslatedOption( 'bookly_l10n_label_notes' ) ) ?></th>
|
104 |
+
<?php endif ?>
|
105 |
<?php foreach ( $custom_fields as $custom_field ) : ?>
|
106 |
<th><?php echo $custom_field->label ?></th>
|
107 |
<?php endforeach ?>
|
112 |
</table>
|
113 |
|
114 |
<div class="text-right bookly-margin-top-lg">
|
115 |
+
<?php Common::deleteButton( '', '', '#bookly-delete-dialog' ) ?>
|
116 |
</div>
|
117 |
</div>
|
118 |
</div>
|
119 |
|
120 |
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderDeleteDialog(); ?>
|
121 |
<?php include '_export_dialog.php' ?>
|
|
|
122 |
|
123 |
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderAppointmentDialog() ?>
|
124 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderComponentAppointments() ?>
|
125 |
</div>
|
126 |
</div>
|
backend/modules/calendar/Components.php
CHANGED
@@ -18,7 +18,7 @@ class Components extends Lib\Base\Components
|
|
18 |
global $wp_locale;
|
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 |
|
@@ -27,7 +27,7 @@ class Components extends Lib\Base\Components
|
|
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/
|
31 |
'js/help.js' => array( 'jquery' ),
|
32 |
),
|
33 |
'frontend' => array(
|
@@ -40,28 +40,25 @@ class Components extends Lib\Base\Components
|
|
40 |
) );
|
41 |
|
42 |
wp_localize_script( 'bookly-ng-appointment_dialog.js', 'BooklyL10nAppDialog', array(
|
43 |
-
'
|
44 |
-
|
45 |
-
'
|
46 |
-
'
|
47 |
-
'
|
|
|
|
|
|
|
48 |
),
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
52 |
-
'title'
|
53 |
'edit_appointment' => __( 'Edit appointment', 'bookly' ),
|
54 |
'new_appointment' => __( 'New appointment', 'bookly' ),
|
55 |
),
|
56 |
) );
|
57 |
|
58 |
-
|
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 |
/**
|
18 |
global $wp_locale;
|
19 |
|
20 |
$this->enqueueStyles( array(
|
21 |
+
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', 'css/select2.min.css' ),
|
22 |
'frontend' => array( 'css/ladda.min.css', ),
|
23 |
) );
|
24 |
|
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/select2.full.min.js' => array( 'jquery' ),
|
31 |
'js/help.js' => array( 'jquery' ),
|
32 |
),
|
33 |
'frontend' => array(
|
40 |
) );
|
41 |
|
42 |
wp_localize_script( 'bookly-ng-appointment_dialog.js', 'BooklyL10nAppDialog', array(
|
43 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
44 |
+
'dateOptions' => array(
|
45 |
+
'dateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_JQUERY_DATEPICKER ),
|
46 |
+
'monthNamesShort' => array_values( $wp_locale->month_abbrev ),
|
47 |
+
'monthNames' => array_values( $wp_locale->month ),
|
48 |
+
'dayNamesMin' => array_values( $wp_locale->weekday_abbrev ),
|
49 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
50 |
+
'firstDay' => (int) get_option( 'start_of_week' ),
|
51 |
),
|
52 |
+
'cf_per_service' => (int) Lib\Config::customFieldsPerService(),
|
53 |
+
'no_result_found' => __( 'No result found', 'bookly' ),
|
54 |
+
'staff_any' => get_option( 'bookly_l10n_option_employee' ),
|
55 |
+
'title' => array(
|
56 |
'edit_appointment' => __( 'Edit appointment', 'bookly' ),
|
57 |
'new_appointment' => __( 'New appointment', 'bookly' ),
|
58 |
),
|
59 |
) );
|
60 |
|
61 |
+
$this->render( '_appointment_dialog' );
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
}
|
63 |
|
64 |
/**
|
backend/modules/calendar/Controller.php
CHANGED
@@ -2,6 +2,7 @@
|
|
2 |
namespace BooklyLite\Backend\Modules\Calendar;
|
3 |
|
4 |
use BooklyLite\Lib;
|
|
|
5 |
|
6 |
/**
|
7 |
* Class Controller
|
@@ -23,7 +24,7 @@ class Controller extends Lib\Base\Controller
|
|
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(
|
@@ -31,7 +32,8 @@ class Controller extends Lib\Base\Controller
|
|
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'
|
|
|
35 |
),
|
36 |
) );
|
37 |
|
@@ -39,10 +41,11 @@ class Controller extends Lib\Base\Controller
|
|
39 |
$slot = new \DateInterval( 'PT' . $slot_length_minutes . 'M' );
|
40 |
|
41 |
$staff_members = Lib\Utils\Common::isCurrentUserAdmin()
|
42 |
-
? Lib\Entities\Staff::query()->
|
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 ),
|
@@ -62,7 +65,18 @@ class Controller extends Lib\Base\Controller
|
|
62 |
'noStaffSelected' => __( 'No staff selected', 'bookly' ),
|
63 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
64 |
'startOfWeek' => (int) get_option( 'start_of_week' ),
|
65 |
-
'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
) );
|
67 |
|
68 |
$this->render( 'calendar', compact( 'staff_members' ) );
|
@@ -83,25 +97,26 @@ class Controller extends Lib\Base\Controller
|
|
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 |
-
$
|
92 |
->where( 'wp_user_id', get_current_user_id() )
|
93 |
->findOne();
|
94 |
-
$
|
95 |
}
|
96 |
// Load special days.
|
97 |
$special_days = array();
|
98 |
-
foreach (
|
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->
|
105 |
|
106 |
// Schedule.
|
107 |
$items = $staff->getScheduleItems();
|
@@ -110,7 +125,7 @@ class Controller extends Lib\Base\Controller
|
|
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 ]->
|
114 |
if ( $end_time !== null ) {
|
115 |
$end_time = explode( ':', $end_time );
|
116 |
$last_end->setTime( $end_time[0], $end_time[1] );
|
@@ -121,63 +136,69 @@ class Controller extends Lib\Base\Controller
|
|
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->
|
125 |
-
$sp_days = $special_days[ $staff->
|
126 |
-
$
|
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->
|
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' => $
|
149 |
-
'end' => $
|
150 |
'rendering' => 'background',
|
151 |
-
'staffId' => $staff->
|
152 |
);
|
153 |
}
|
154 |
-
$end_time = explode( ':', $
|
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->
|
161 |
-
$end = $day->format( 'Y-m-d ' . $item->
|
162 |
if ( $start < $end ) {
|
163 |
$result[] = array(
|
164 |
'start' => $start,
|
165 |
'end' => $end,
|
166 |
'rendering' => 'background',
|
167 |
-
'staffId' => $staff->
|
168 |
);
|
169 |
}
|
170 |
$last_end = clone $day;
|
171 |
-
$end_time = explode( ':', $item->
|
172 |
$last_end->setTime( $end_time[0], $end_time[1] );
|
173 |
|
174 |
// Breaks.
|
175 |
foreach ( $item->getBreaksList() as $break ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
176 |
$result[] = array(
|
177 |
-
'start' => $
|
178 |
-
'end' => $
|
179 |
'rendering' => 'background',
|
180 |
-
'staffId' => $staff->
|
181 |
);
|
182 |
}
|
183 |
} else {
|
@@ -185,7 +206,7 @@ class Controller extends Lib\Base\Controller
|
|
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->
|
189 |
);
|
190 |
$last_end = clone $day;
|
191 |
$last_end->setTime( 24, 0 );
|
@@ -200,7 +221,7 @@ class Controller extends Lib\Base\Controller
|
|
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->
|
204 |
);
|
205 |
}
|
206 |
}
|
@@ -213,18 +234,21 @@ class Controller extends Lib\Base\Controller
|
|
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'
|
225 |
-
'approved'
|
226 |
-
'cancelled'
|
227 |
-
'rejected'
|
|
|
228 |
),
|
229 |
'default' => get_option( 'bookly_gen_default_appointment_status' ),
|
230 |
),
|
@@ -238,34 +262,56 @@ class Controller extends Lib\Base\Controller
|
|
238 |
/** @var Lib\Entities\Staff $staff_member */
|
239 |
foreach ( $staff_members as $staff_member ) {
|
240 |
$services = array();
|
241 |
-
|
242 |
$services[] = array(
|
243 |
-
'id'
|
244 |
-
'title'
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
251 |
);
|
252 |
}
|
253 |
$result['staff'][] = array(
|
254 |
-
'id' => $staff_member->
|
255 |
-
'full_name' => $staff_member->
|
256 |
-
'services' => $services
|
|
|
257 |
);
|
258 |
}
|
259 |
|
|
|
260 |
// Customers list.
|
261 |
-
foreach ( Lib\Entities\Customer::query()->sortBy( '
|
262 |
-
$name = $customer->
|
263 |
-
if ( $customer->
|
264 |
-
$name .= ' (' . trim( $customer->
|
265 |
}
|
266 |
|
267 |
$result['customers'][] = array(
|
268 |
-
'id' => $customer->
|
269 |
'name' => $name,
|
270 |
'custom_fields' => array(),
|
271 |
'number_of_persons' => 1,
|
@@ -281,7 +327,7 @@ class Controller extends Lib\Base\Controller
|
|
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;
|
@@ -290,6 +336,12 @@ class Controller extends Lib\Base\Controller
|
|
290 |
$time_start += $ts_length;
|
291 |
}
|
292 |
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
wp_send_json( $result );
|
294 |
}
|
295 |
|
@@ -305,44 +357,64 @@ class Controller extends Lib\Base\Controller
|
|
305 |
$response['success'] = true;
|
306 |
|
307 |
$info = Lib\Entities\Appointment::query( 'a' )
|
308 |
-
->select( 'ss.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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->
|
312 |
->fetchRow();
|
313 |
|
314 |
$response['data']['total_number_of_persons'] = $info['total_number_of_persons'];
|
315 |
-
$response['data']['
|
316 |
-
$response['data']['
|
317 |
-
$response['data']['
|
318 |
-
$response['data']['
|
319 |
-
$response['data']['
|
320 |
-
$response['data']['
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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->
|
339 |
->fetchArray();
|
340 |
foreach ( $customers as $customer ) {
|
341 |
$payment_title = '';
|
342 |
if ( $customer['payment'] !== null ) {
|
343 |
-
$payment_title = Lib\Utils\
|
344 |
if ( $customer['payment'] != $customer['payment_total'] ) {
|
345 |
-
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\
|
346 |
}
|
347 |
$payment_title .= sprintf(
|
348 |
' %s <span%s>%s</span>',
|
@@ -355,18 +427,19 @@ class Controller extends Lib\Base\Controller
|
|
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->
|
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,
|
@@ -384,20 +457,34 @@ class Controller extends Lib\Base\Controller
|
|
384 |
{
|
385 |
$response = array( 'success' => false );
|
386 |
|
387 |
-
$
|
388 |
-
$
|
389 |
-
$
|
390 |
-
$
|
391 |
-
$
|
392 |
-
$
|
393 |
-
$
|
394 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
|
396 |
-
$
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
401 |
|
402 |
// Check for errors.
|
403 |
if ( ! $start_date ) {
|
@@ -407,140 +494,193 @@ class Controller extends Lib\Base\Controller
|
|
407 |
} elseif ( $start_date == $end_date ) {
|
408 |
$response['errors']['time_interval'] = __( 'End time must not be equal to start time', 'bookly' );
|
409 |
}
|
410 |
-
if (
|
411 |
$response['errors']['service_required'] = true;
|
412 |
-
}
|
413 |
-
|
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 |
-
|
421 |
-
&& ( $customer['status'] != Lib\Entities\CustomerAppointment::STATUS_REJECTED )
|
422 |
) {
|
423 |
$total_number_of_persons += $customer['number_of_persons'];
|
424 |
-
$extras_duration =
|
425 |
if ( $extras_duration > $max_extras_duration ) {
|
426 |
$max_extras_duration = $extras_duration;
|
427 |
}
|
428 |
}
|
|
|
429 |
}
|
430 |
-
if ( $
|
431 |
-
$
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
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 |
-
->
|
454 |
-
->
|
455 |
->save();
|
456 |
|
457 |
-
$
|
458 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
459 |
|
460 |
foreach ( $schedule as $slot ) {
|
461 |
$slot = json_decode( $slot );
|
462 |
$appointment = new Lib\Entities\Appointment();
|
463 |
$appointment
|
464 |
-
->
|
465 |
-
->
|
466 |
-
->
|
467 |
-
->
|
468 |
-
->
|
469 |
-
->
|
470 |
-
->
|
|
|
471 |
;
|
472 |
|
473 |
if ( $appointment->save() !== false ) {
|
|
|
|
|
474 |
// Google Calendar.
|
475 |
$appointment->handleGoogleCalendar();
|
476 |
-
|
|
|
477 |
|
478 |
if ( $notification != 'no' ) {
|
479 |
-
|
480 |
-
|
|
|
|
|
|
|
|
|
|
|
481 |
}
|
482 |
}
|
483 |
}
|
484 |
-
|
|
|
|
|
|
|
|
|
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
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
|
|
|
|
|
|
|
|
|
|
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
|
511 |
-
foreach ( $
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
|
|
|
|
516 |
}
|
517 |
}
|
518 |
|
519 |
$response['success'] = true;
|
520 |
-
$response['data'] = $this->_getAppointmentForFC(
|
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
|
531 |
{
|
532 |
$start_date = $this->getParameter( 'start_date' );
|
533 |
$end_date = $this->getParameter( 'end_date' );
|
534 |
-
$
|
535 |
-
$
|
|
|
536 |
$timestamp_diff = strtotime( $end_date ) - strtotime( $start_date );
|
|
|
537 |
|
538 |
$result = array(
|
539 |
-
'date_interval_not_available'
|
540 |
-
'date_interval_warning'
|
|
|
541 |
);
|
542 |
|
543 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
544 |
$result['date_interval_not_available'] = true;
|
545 |
}
|
546 |
|
@@ -548,10 +688,20 @@ class Controller extends Lib\Base\Controller
|
|
548 |
$service = new Lib\Entities\Service();
|
549 |
$service->load( $service_id );
|
550 |
|
551 |
-
$duration = $service->
|
552 |
|
553 |
// Service duration interval is not equal to.
|
554 |
$result['date_interval_warning'] = ( $timestamp_diff != $duration );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
555 |
}
|
556 |
|
557 |
wp_send_json( $result );
|
@@ -571,21 +721,24 @@ class Controller extends Lib\Base\Controller
|
|
571 |
->find();
|
572 |
/** @var Lib\Entities\CustomerAppointment $ca */
|
573 |
foreach ( $ca_list as $ca ) {
|
574 |
-
switch ( $ca->
|
575 |
case Lib\Entities\CustomerAppointment::STATUS_PENDING:
|
576 |
-
|
|
|
577 |
break;
|
578 |
case Lib\Entities\CustomerAppointment::STATUS_APPROVED:
|
579 |
-
$ca->
|
580 |
break;
|
581 |
}
|
582 |
-
Lib\NotificationSender::
|
|
|
|
|
|
|
|
|
583 |
}
|
584 |
}
|
585 |
|
586 |
-
|
587 |
-
$appointment->load( $appointment_id );
|
588 |
-
$appointment->delete();
|
589 |
|
590 |
wp_send_json_success();
|
591 |
}
|
@@ -600,13 +753,10 @@ class Controller extends Lib\Base\Controller
|
|
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 |
-
->
|
607 |
-
->
|
608 |
-
->whereLt( 'start_date', $end_date )
|
609 |
-
->whereGt( 'end_date', $start_date )
|
610 |
->count() == 0;
|
611 |
}
|
612 |
|
@@ -653,96 +803,130 @@ class Controller extends Lib\Base\Controller
|
|
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
|
659 |
-
ss.
|
|
|
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.
|
666 |
-
|
667 |
-
|
668 |
-
p.type
|
669 |
-
|
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 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
685 |
-
|
|
|
686 |
if ( $appointment[ $data_entry ] ) {
|
687 |
-
$
|
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 |
-
$
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
);
|
710 |
}
|
711 |
// Status.
|
712 |
-
$
|
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 |
-
$
|
720 |
-
$
|
721 |
}
|
|
|
|
|
|
|
722 |
$appointments[ $key ] = array(
|
723 |
-
'id'
|
724 |
-
'
|
725 |
-
'
|
726 |
-
'
|
727 |
-
'
|
728 |
-
'
|
729 |
-
'
|
730 |
-
'
|
|
|
|
|
|
|
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 |
}
|
2 |
namespace BooklyLite\Backend\Modules\Calendar;
|
3 |
|
4 |
use BooklyLite\Lib;
|
5 |
+
use BooklyLite\Lib\DataHolders\Booking as DataHolders;
|
6 |
|
7 |
/**
|
8 |
* Class Controller
|
24 |
|
25 |
$this->enqueueStyles( array(
|
26 |
'module' => array( 'css/fullcalendar.min.css', ),
|
27 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css' ),
|
28 |
) );
|
29 |
|
30 |
$this->enqueueScripts( array(
|
32 |
'module' => array(
|
33 |
'js/fullcalendar.min.js' => array( 'bookly-moment.min.js' ),
|
34 |
'js/fc-multistaff-view.js' => array( 'bookly-fullcalendar.min.js' ),
|
35 |
+
'js/calendar-common.js' => array( 'bookly-fc-multistaff-view.js' ),
|
36 |
+
'js/calendar.js' => array( 'bookly-calendar-common.js' ),
|
37 |
),
|
38 |
) );
|
39 |
|
41 |
$slot = new \DateInterval( 'PT' . $slot_length_minutes . 'M' );
|
42 |
|
43 |
$staff_members = Lib\Utils\Common::isCurrentUserAdmin()
|
44 |
+
? Lib\Entities\Staff::query()->where( 'id', 1 )->find()
|
45 |
: Lib\Entities\Staff::query()->where( 'wp_user_id', get_current_user_id() )->find();
|
46 |
|
47 |
wp_localize_script( 'bookly-calendar.js', 'BooklyL10n', array(
|
48 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
49 |
'slotDuration' => $slot->format( '%H:%I:%S' ),
|
50 |
'calendar' => array(
|
51 |
'shortMonths' => array_values( $wp_locale->month_abbrev ),
|
65 |
'noStaffSelected' => __( 'No staff selected', 'bookly' ),
|
66 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
67 |
'startOfWeek' => (int) get_option( 'start_of_week' ),
|
68 |
+
'recurring_appointments' => array(
|
69 |
+
'active' => (int) Lib\Config::recurringAppointmentsActive(),
|
70 |
+
'title' => __( 'Recurring appointments', 'bookly' ),
|
71 |
+
),
|
72 |
+
'waiting_list' => array(
|
73 |
+
'active' => (int) Lib\Config::waitingListActive(),
|
74 |
+
'title' => __( 'On waiting list', 'bookly' ),
|
75 |
+
),
|
76 |
+
'packages' => array(
|
77 |
+
'active' => (int) Lib\Config::packagesActive(),
|
78 |
+
'title' => __( 'Package', 'bookly' ),
|
79 |
+
),
|
80 |
) );
|
81 |
|
82 |
$this->render( 'calendar', compact( 'staff_members' ) );
|
97 |
// FullCalendar sends end date as 1 day further.
|
98 |
$end_date->sub( $one_day );
|
99 |
|
100 |
+
$staff_ids = array( 1 );
|
101 |
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
102 |
$staff_members = Lib\Entities\Staff::query()
|
103 |
->where( 'id', 1 )
|
104 |
->find();
|
105 |
} else {
|
106 |
+
$staff_member = Lib\Entities\Staff::query()
|
107 |
->where( 'wp_user_id', get_current_user_id() )
|
108 |
->findOne();
|
109 |
+
$staff_members[] = $staff_member;
|
110 |
}
|
111 |
// Load special days.
|
112 |
$special_days = array();
|
113 |
+
foreach ( (array) Lib\Proxy\SpecialDays::getSchedule( $staff_ids, $start_date, $end_date ) as $day ) {
|
114 |
$special_days[ $day['staff_id'] ][ $day['date'] ][] = $day;
|
115 |
}
|
116 |
|
117 |
foreach ( $staff_members as $staff ) {
|
118 |
/** @var Lib\Entities\Staff $staff */
|
119 |
+
$result = array_merge( $result, $this->_getAppointmentsForFC( $staff->getId(), $start_date, $end_date ) );
|
120 |
|
121 |
// Schedule.
|
122 |
$items = $staff->getScheduleItems();
|
125 |
$last_end = clone $day;
|
126 |
$last_end->sub( $one_day );
|
127 |
$w = (int) $day->format( 'w' );
|
128 |
+
$end_time = $items[ $w > 0 ? $w : 7 ]->getEndTime();
|
129 |
if ( $end_time !== null ) {
|
130 |
$end_time = explode( ':', $end_time );
|
131 |
$last_end->setTime( $end_time[0], $end_time[1] );
|
136 |
while ( $day <= $end_date ) {
|
137 |
$start = $last_end->format( 'Y-m-d H:i:s' );
|
138 |
// Check if $day is Special Day for current staff.
|
139 |
+
if ( isset( $special_days[ $staff->getId() ][ $day->format( 'Y-m-d' ) ] ) ) {
|
140 |
+
$sp_days = $special_days[ $staff->getId() ][ $day->format( 'Y-m-d' ) ];
|
141 |
+
$end = $sp_days[0]['date'] . ' ' . $sp_days[0]['start_time'];
|
|
|
142 |
if ( $start < $end ) {
|
143 |
$result[] = array(
|
144 |
'start' => $start,
|
145 |
'end' => $end,
|
146 |
'rendering' => 'background',
|
147 |
+
'staffId' => $staff->getId(),
|
148 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
}
|
150 |
// Breaks.
|
151 |
foreach ( $sp_days as $sp_day ) {
|
152 |
+
$break_start = date(
|
153 |
+
'Y-m-d H:i:s',
|
154 |
+
strtotime( $sp_day['date'] ) + Lib\Utils\DateTime::timeToSeconds( $sp_day['break_start'] )
|
155 |
+
);
|
156 |
+
$break_end = date(
|
157 |
+
'Y-m-d H:i:s',
|
158 |
+
strtotime( $sp_day['date'] ) + Lib\Utils\DateTime::timeToSeconds( $sp_day['break_end'] )
|
159 |
+
);
|
160 |
$result[] = array(
|
161 |
+
'start' => $break_start,
|
162 |
+
'end' => $break_end,
|
163 |
'rendering' => 'background',
|
164 |
+
'staffId' => $staff->getId(),
|
165 |
);
|
166 |
}
|
167 |
+
$end_time = explode( ':', $sp_days[0]['end_time'] );
|
168 |
$last_end = clone $day;
|
169 |
$last_end->setTime( $end_time[0], $end_time[1] );
|
170 |
} else {
|
171 |
/** @var Lib\Entities\StaffScheduleItem $item */
|
172 |
$item = $items[ (int) $day->format( 'w' ) + 1 ];
|
173 |
+
if ( $item->getStartTime() && ! $staff->isOnHoliday( $day ) ) {
|
174 |
+
$end = $day->format( 'Y-m-d ' . $item->getStartTime() );
|
175 |
if ( $start < $end ) {
|
176 |
$result[] = array(
|
177 |
'start' => $start,
|
178 |
'end' => $end,
|
179 |
'rendering' => 'background',
|
180 |
+
'staffId' => $staff->getId(),
|
181 |
);
|
182 |
}
|
183 |
$last_end = clone $day;
|
184 |
+
$end_time = explode( ':', $item->getEndTime() );
|
185 |
$last_end->setTime( $end_time[0], $end_time[1] );
|
186 |
|
187 |
// Breaks.
|
188 |
foreach ( $item->getBreaksList() as $break ) {
|
189 |
+
$break_start = date(
|
190 |
+
'Y-m-d H:i:s',
|
191 |
+
$day->getTimestamp() + Lib\Utils\DateTime::timeToSeconds( $break['start_time'] )
|
192 |
+
);
|
193 |
+
$break_end = date(
|
194 |
+
'Y-m-d H:i:s',
|
195 |
+
$day->getTimestamp() + Lib\Utils\DateTime::timeToSeconds( $break['end_time'] )
|
196 |
+
);
|
197 |
$result[] = array(
|
198 |
+
'start' => $break_start,
|
199 |
+
'end' => $break_end,
|
200 |
'rendering' => 'background',
|
201 |
+
'staffId' => $staff->getId(),
|
202 |
);
|
203 |
}
|
204 |
} else {
|
206 |
'start' => $last_end->format( 'Y-m-d H:i:s' ),
|
207 |
'end' => $day->format( 'Y-m-d 24:00:00' ),
|
208 |
'rendering' => 'background',
|
209 |
+
'staffId' => $staff->getId(),
|
210 |
);
|
211 |
$last_end = clone $day;
|
212 |
$last_end->setTime( 24, 0 );
|
221 |
'start' => $last_end->format( 'Y-m-d H:i:s' ),
|
222 |
'end' => $last_end->format( 'Y-m-d 24:00:00' ),
|
223 |
'rendering' => 'background',
|
224 |
+
'staffId' => $staff->getId(),
|
225 |
);
|
226 |
}
|
227 |
}
|
234 |
*/
|
235 |
public function executeGetDataForAppointmentForm()
|
236 |
{
|
237 |
+
$type = $this->getParameter( 'type', false ) == 'package' ? Lib\Entities\Service::TYPE_PACKAGE : Lib\Entities\Service::TYPE_SIMPLE;
|
238 |
$result = array(
|
239 |
'staff' => array(),
|
240 |
'customers' => array(),
|
241 |
'start_time' => array(),
|
242 |
'end_time' => array(),
|
243 |
+
'week_days' => array(),
|
244 |
'time_interval' => Lib\Config::getTimeSlotLength(),
|
245 |
'status' => array(
|
246 |
'items' => array(
|
247 |
+
'pending' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_PENDING ),
|
248 |
+
'approved' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_APPROVED ),
|
249 |
+
'cancelled' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_CANCELLED ),
|
250 |
+
'rejected' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_REJECTED ),
|
251 |
+
'waitlisted' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_WAITLISTED ),
|
252 |
),
|
253 |
'default' => get_option( 'bookly_gen_default_appointment_status' ),
|
254 |
),
|
262 |
/** @var Lib\Entities\Staff $staff_member */
|
263 |
foreach ( $staff_members as $staff_member ) {
|
264 |
$services = array();
|
265 |
+
if ( $type == Lib\Entities\Service::TYPE_SIMPLE ) {
|
266 |
$services[] = array(
|
267 |
+
'id' => null,
|
268 |
+
'title' => __( 'Custom', 'bookly' ),
|
269 |
+
'duration' => Lib\Config::getTimeSlotLength(),
|
270 |
+
'capacity_min' => 1,
|
271 |
+
'capacity_max' => 1,
|
272 |
+
);
|
273 |
+
}
|
274 |
+
foreach ( $staff_member->getStaffServices( $type ) as $staff_service ) {
|
275 |
+
$sub_services = $staff_service->service->getSubServices();
|
276 |
+
if ( $type == Lib\Entities\Service::TYPE_SIMPLE || ! empty( $sub_services ) ) {
|
277 |
+
$services[] = array(
|
278 |
+
'id' => $staff_service->service->getId(),
|
279 |
+
'title' => sprintf(
|
280 |
+
'%s (%s)',
|
281 |
+
$staff_service->service->getTitle(),
|
282 |
+
Lib\Utils\DateTime::secondsToInterval( $staff_service->service->getDuration() )
|
283 |
+
),
|
284 |
+
'duration' => $staff_service->service->getDuration(),
|
285 |
+
'capacity_min' => 1,
|
286 |
+
'capacity_max' => 1,
|
287 |
+
);
|
288 |
+
}
|
289 |
+
}
|
290 |
+
$locations = array();
|
291 |
+
foreach ( (array) Lib\Proxy\Locations::findByStaffId( $staff_member->getId() ) as $location ) {
|
292 |
+
$locations[] = array(
|
293 |
+
'id' => $location->getId(),
|
294 |
+
'name' => $location->getName(),
|
295 |
);
|
296 |
}
|
297 |
$result['staff'][] = array(
|
298 |
+
'id' => $staff_member->getId(),
|
299 |
+
'full_name' => $staff_member->getFullName(),
|
300 |
+
'services' => $services,
|
301 |
+
'locations' => $locations,
|
302 |
);
|
303 |
}
|
304 |
|
305 |
+
/** @var Lib\Entities\Customer $customer */
|
306 |
// Customers list.
|
307 |
+
foreach ( Lib\Entities\Customer::query()->sortBy( 'full_name' )->find() as $customer ) {
|
308 |
+
$name = $customer->getFullName();
|
309 |
+
if ( $customer->getEmail() != '' || $customer->getPhone() != '' ) {
|
310 |
+
$name .= ' (' . trim( $customer->getEmail() . ', ' . $customer->getPhone(), ', ' ) . ')';
|
311 |
}
|
312 |
|
313 |
$result['customers'][] = array(
|
314 |
+
'id' => $customer->getId(),
|
315 |
'name' => $name,
|
316 |
'custom_fields' => array(),
|
317 |
'number_of_persons' => 1,
|
327 |
while ( $time_start <= $time_end ) {
|
328 |
$slot = array(
|
329 |
'value' => Lib\Utils\DateTime::buildTimeString( $time_start, false ),
|
330 |
+
'title' => Lib\Utils\DateTime::formatTime( $time_start ),
|
331 |
);
|
332 |
if ( $time_start < DAY_IN_SECONDS ) {
|
333 |
$result['start_time'][] = $slot;
|
336 |
$time_start += $ts_length;
|
337 |
}
|
338 |
|
339 |
+
$days_times = Lib\Config::getDaysAndTimes();
|
340 |
+
$weekdays = array( 1 => 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', );
|
341 |
+
foreach ( $days_times['days'] as $index => $abbrev ) {
|
342 |
+
$result['week_days'][] = $weekdays[ $index ];
|
343 |
+
}
|
344 |
+
|
345 |
wp_send_json( $result );
|
346 |
}
|
347 |
|
357 |
$response['success'] = true;
|
358 |
|
359 |
$info = Lib\Entities\Appointment::query( 'a' )
|
360 |
+
->select( 'ss.capacity_min as min_capacity,
|
361 |
+
ss.capacity_max AS max_capacity,
|
362 |
+
SUM(ca.number_of_persons) AS total_number_of_persons,
|
363 |
+
a.staff_id,
|
364 |
+
a.staff_any,
|
365 |
+
a.service_id,
|
366 |
+
a.custom_service_name,
|
367 |
+
a.custom_service_price,
|
368 |
+
a.start_date,
|
369 |
+
a.end_date,
|
370 |
+
a.internal_note,
|
371 |
+
a.series_id,
|
372 |
+
a.location_id' )
|
373 |
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
374 |
->leftJoin( 'StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id' )
|
375 |
+
->where( 'a.id', $appointment->getId() )
|
376 |
->fetchRow();
|
377 |
|
378 |
$response['data']['total_number_of_persons'] = $info['total_number_of_persons'];
|
379 |
+
$response['data']['min_capacity'] = $info['min_capacity'];
|
380 |
+
$response['data']['max_capacity'] = $info['max_capacity'];
|
381 |
+
$response['data']['start_date'] = $info['start_date'];
|
382 |
+
$response['data']['end_date'] = $info['end_date'];
|
383 |
+
$response['data']['staff_id'] = $info['staff_id'];
|
384 |
+
$response['data']['staff_any'] = (int) $info['staff_any'];
|
385 |
+
$response['data']['service_id'] = $info['service_id'];
|
386 |
+
$response['data']['custom_service_name'] = $info['custom_service_name'];
|
387 |
+
$response['data']['custom_service_price'] = (float) $info['custom_service_price'];
|
388 |
+
$response['data']['internal_note'] = $info['internal_note'];
|
389 |
+
$response['data']['series_id'] = $info['series_id'];
|
390 |
+
$response['data']['location_id'] = $info['location_id'];
|
391 |
+
|
392 |
$customers = Lib\Entities\CustomerAppointment::query( 'ca' )
|
393 |
->select( 'ca.id,
|
394 |
ca.customer_id,
|
395 |
+
ca.package_id,
|
396 |
ca.custom_fields,
|
397 |
ca.extras,
|
398 |
ca.number_of_persons,
|
399 |
+
ca.notes,
|
400 |
ca.status,
|
401 |
ca.payment_id,
|
402 |
ca.compound_service_id,
|
403 |
ca.compound_token,
|
|
|
404 |
p.paid AS payment,
|
405 |
p.total AS payment_total,
|
406 |
p.type AS payment_type,
|
407 |
p.details AS payment_details,
|
408 |
p.status AS payment_status' )
|
409 |
->leftJoin( 'Payment', 'p', 'p.id = ca.payment_id' )
|
410 |
+
->where( 'ca.appointment_id', $appointment->getId() )
|
411 |
->fetchArray();
|
412 |
foreach ( $customers as $customer ) {
|
413 |
$payment_title = '';
|
414 |
if ( $customer['payment'] !== null ) {
|
415 |
+
$payment_title = Lib\Utils\Price::format( $customer['payment'] );
|
416 |
if ( $customer['payment'] != $customer['payment_total'] ) {
|
417 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $customer['payment_total'] ) );
|
418 |
}
|
419 |
$payment_title .= sprintf(
|
420 |
' %s <span%s>%s</span>',
|
427 |
if ( $customer['compound_service_id'] !== null ) {
|
428 |
$service = new Lib\Entities\Service();
|
429 |
if ( $service->load( $customer['compound_service_id'] ) ) {
|
430 |
+
$compound_service = $service->getTranslatedTitle();
|
431 |
}
|
432 |
}
|
433 |
$response['data']['customers'][] = array(
|
434 |
'id' => $customer['customer_id'],
|
435 |
'ca_id' => $customer['id'],
|
436 |
+
'package_id' => $customer['package_id'],
|
437 |
'compound_service' => $compound_service,
|
438 |
'compound_token' => $customer['compound_token'],
|
439 |
'custom_fields' => (array) json_decode( $customer['custom_fields'], true ),
|
440 |
'extras' => (array) json_decode( $customer['extras'], true ),
|
|
|
441 |
'number_of_persons' => $customer['number_of_persons'],
|
442 |
+
'notes' => $customer['notes'],
|
443 |
'payment_id' => $customer['payment_id'],
|
444 |
'payment_type' => $customer['payment'] != $customer['payment_total'] ? 'partial' : 'full',
|
445 |
'payment_title' => $payment_title,
|
457 |
{
|
458 |
$response = array( 'success' => false );
|
459 |
|
460 |
+
$appointment_id = (int) $this->getParameter( 'id', 0 );
|
461 |
+
$staff_id = (int) $this->getParameter( 'staff_id', 0 );
|
462 |
+
$service_id = (int) $this->getParameter( 'service_id', -1 );
|
463 |
+
$custom_service_name = trim( $this->getParameter( 'custom_service_name' ) );
|
464 |
+
$custom_service_price = trim( $this->getParameter( 'custom_service_price' ) );
|
465 |
+
$location_id = (int) $this->getParameter( 'location_id', 0 );
|
466 |
+
$start_date = $this->getParameter( 'start_date' );
|
467 |
+
$end_date = $this->getParameter( 'end_date' );
|
468 |
+
$repeat = json_decode( $this->getParameter( 'repeat', '[]' ), true );
|
469 |
+
$schedule = $this->getParameter( 'schedule', array() );
|
470 |
+
$customers = json_decode( $this->getParameter( 'customers', '[]' ), true );
|
471 |
+
$notification = $this->getParameter( 'notification', 'no' );
|
472 |
+
$internal_note = $this->getParameter( 'internal_note' );
|
473 |
+
$created_from = $this->getParameter( 'created_from' );
|
474 |
|
475 |
+
if ( ! $service_id ) {
|
476 |
+
// Custom service.
|
477 |
+
$service_id = null;
|
478 |
+
}
|
479 |
+
if ( $service_id || $custom_service_name == '' ) {
|
480 |
+
$custom_service_name = null;
|
481 |
+
}
|
482 |
+
if ( $service_id || $custom_service_price == '' ) {
|
483 |
+
$custom_service_price = null;
|
484 |
+
}
|
485 |
+
if ( ! $location_id ) {
|
486 |
+
$location_id = null;
|
487 |
+
}
|
488 |
|
489 |
// Check for errors.
|
490 |
if ( ! $start_date ) {
|
494 |
} elseif ( $start_date == $end_date ) {
|
495 |
$response['errors']['time_interval'] = __( 'End time must not be equal to start time', 'bookly' );
|
496 |
}
|
497 |
+
if ( $service_id == -1 ) {
|
498 |
$response['errors']['service_required'] = true;
|
499 |
+
} else if ( $service_id === null && $custom_service_name === null ) {
|
500 |
+
$response['errors']['custom_service_name_required'] = true;
|
|
|
501 |
}
|
502 |
$total_number_of_persons = 0;
|
503 |
$max_extras_duration = 0;
|
504 |
+
foreach ( $customers as $i => $customer ) {
|
505 |
+
if ( $customer['status'] == Lib\Entities\CustomerAppointment::STATUS_PENDING ||
|
506 |
+
$customer['status'] == Lib\Entities\CustomerAppointment::STATUS_APPROVED
|
|
|
507 |
) {
|
508 |
$total_number_of_persons += $customer['number_of_persons'];
|
509 |
+
$extras_duration = Lib\Proxy\ServiceExtras::getTotalDuration( $customer['extras'] );
|
510 |
if ( $extras_duration > $max_extras_duration ) {
|
511 |
$max_extras_duration = $extras_duration;
|
512 |
}
|
513 |
}
|
514 |
+
$customers[ $i ]['created_from'] = ( $created_from == 'backend' ) ? 'backend' : 'frontend';
|
515 |
}
|
516 |
+
if ( $service_id ) {
|
517 |
+
$staff_service = new Lib\Entities\StaffService();
|
518 |
+
$staff_service->loadBy( array(
|
519 |
+
'staff_id' => 1,
|
520 |
+
'service_id' => $service_id
|
521 |
+
) );
|
522 |
+
if ( $total_number_of_persons > $staff_service->getCapacityMax() ) {
|
523 |
+
$response['errors']['overflow_capacity'] = sprintf(
|
524 |
+
__( 'The number of customers should not be more than %d', 'bookly' ),
|
525 |
+
$staff_service->getCapacityMax()
|
526 |
+
);
|
527 |
+
}
|
528 |
}
|
|
|
529 |
|
530 |
// If no errors then try to save the appointment.
|
531 |
if ( ! isset ( $response['errors'] ) ) {
|
532 |
if ( $repeat['enabled'] ) {
|
533 |
+
// Series.
|
534 |
if ( ! empty ( $schedule ) ) {
|
|
|
535 |
// Create new series.
|
536 |
$series = new Lib\Entities\Series();
|
537 |
$series
|
538 |
+
->setRepeat( $this->getParameter( 'repeat' ) )
|
539 |
+
->setToken( Lib\Utils\Common::generateToken( get_class( $series ), 'token' ) )
|
540 |
->save();
|
541 |
|
542 |
+
if ( $notification != 'no' ) {
|
543 |
+
// Create order per each customer to send notifications.
|
544 |
+
/** @var DataHolders\Order[] $orders */
|
545 |
+
$orders = array();
|
546 |
+
foreach ( $customers as $customer ) {
|
547 |
+
$order = DataHolders\Order::create( Lib\Entities\Customer::find( $customer['id'] ) )
|
548 |
+
->addItem( 0, DataHolders\Series::create( $series ) )
|
549 |
+
;
|
550 |
+
$orders[ $customer['id'] ] = $order;
|
551 |
+
}
|
552 |
+
}
|
553 |
+
|
554 |
+
$service = Lib\Entities\Service::find( $service_id );
|
555 |
|
556 |
foreach ( $schedule as $slot ) {
|
557 |
$slot = json_decode( $slot );
|
558 |
$appointment = new Lib\Entities\Appointment();
|
559 |
$appointment
|
560 |
+
->setSeries( $series )
|
561 |
+
->setLocationId( $location_id )
|
562 |
+
->setStaffId( $staff_id )
|
563 |
+
->setServiceId( $service_id )
|
564 |
+
->setStartDate( $slot[0][2] )
|
565 |
+
->setEndDate( date( 'Y-m-d H:i:s', strtotime( $slot[0][2] ) + $service->getDuration() ) )
|
566 |
+
->setInternalNote( $internal_note )
|
567 |
+
->setExtrasDuration( $max_extras_duration )
|
568 |
;
|
569 |
|
570 |
if ( $appointment->save() !== false ) {
|
571 |
+
// Save customer appointments.
|
572 |
+
$ca_list = $appointment->saveCustomerAppointments( $customers );
|
573 |
// Google Calendar.
|
574 |
$appointment->handleGoogleCalendar();
|
575 |
+
// Waiting list.
|
576 |
+
Lib\Proxy\WaitingList::handleParticipantsChange( $appointment );
|
577 |
|
578 |
if ( $notification != 'no' ) {
|
579 |
+
foreach ( $ca_list as $ca ) {
|
580 |
+
$item = DataHolders\Simple::create( $ca )
|
581 |
+
->setService( $service )
|
582 |
+
->setAppointment( $appointment )
|
583 |
+
;
|
584 |
+
$orders[ $ca->getCustomerId() ]->getItem( 0 )->addItem( $item );
|
585 |
+
}
|
586 |
}
|
587 |
}
|
588 |
}
|
589 |
+
if ( $notification != 'no' ) {
|
590 |
+
foreach ( $orders as $order ) {
|
591 |
+
Lib\Proxy\RecurringAppointments::sendRecurring( $order->getItem( 0 ), $order );
|
592 |
+
}
|
593 |
+
}
|
594 |
}
|
595 |
$response['success'] = true;
|
596 |
$response['data'] = array( 'staffId' => 1 ); // make FullCalendar refetch events
|
597 |
} else {
|
598 |
+
// Single appointment.
|
599 |
$appointment = new Lib\Entities\Appointment();
|
600 |
if ( $appointment_id ) {
|
601 |
// Edit.
|
602 |
$appointment->load( $appointment_id );
|
603 |
+
if ( $appointment->getStaffId() != $staff_id ) {
|
604 |
+
$appointment->setStaffAny( 0 );
|
605 |
+
}
|
606 |
}
|
607 |
+
$appointment
|
608 |
+
->setLocationId( $location_id )
|
609 |
+
->setStaffId( 1 )
|
610 |
+
->setServiceId( $service_id )
|
611 |
+
->setCustomServiceName( $custom_service_name )
|
612 |
+
->setCustomServicePrice( $custom_service_price )
|
613 |
+
->setStartDate( $start_date )
|
614 |
+
->setEndDate( $end_date )
|
615 |
+
->setInternalNote( $internal_note )
|
616 |
+
->setExtrasDuration( $max_extras_duration )
|
617 |
+
;
|
618 |
|
619 |
if ( $appointment->save() !== false ) {
|
620 |
// Save customer appointments.
|
621 |
$ca_status_changed = $appointment->saveCustomerAppointments( $customers );
|
|
|
622 |
|
623 |
// Google Calendar.
|
624 |
$appointment->handleGoogleCalendar();
|
625 |
+
// Waiting list.
|
626 |
+
Lib\Proxy\WaitingList::handleParticipantsChange( $appointment );
|
627 |
|
628 |
// Send notifications.
|
629 |
+
if ( $notification == 'changed_status' ) {
|
630 |
+
foreach ( $ca_status_changed as $ca ) {
|
631 |
+
Lib\NotificationSender::sendSingle( DataHolders\Simple::create( $ca )->setAppointment( $appointment ) );
|
632 |
+
}
|
633 |
+
} else if ( $notification == 'all' ) {
|
634 |
+
$ca_list = $appointment->getCustomerAppointments( true );
|
635 |
+
foreach ( $ca_list as $ca ) {
|
636 |
+
Lib\NotificationSender::sendSingle( DataHolders\Simple::create( $ca )->setAppointment( $appointment ) );
|
637 |
}
|
638 |
}
|
639 |
|
640 |
$response['success'] = true;
|
641 |
+
$response['data'] = $this->_getAppointmentForFC( $staff_id, $appointment->getId() );
|
642 |
} else {
|
643 |
$response['errors'] = array( 'db' => __( 'Could not save appointment in database.', 'bookly' ) );
|
644 |
}
|
645 |
}
|
646 |
}
|
647 |
+
update_user_meta( get_current_user_id(), 'bookly_appointment_form_send_notifications', $notification );
|
648 |
wp_send_json( $response );
|
649 |
}
|
650 |
|
651 |
+
public function executeCheckAppointmentErrors()
|
652 |
{
|
653 |
$start_date = $this->getParameter( 'start_date' );
|
654 |
$end_date = $this->getParameter( 'end_date' );
|
655 |
+
$staff_id = (int) $this->getParameter( 'staff_id' );
|
656 |
+
$service_id = (int) $this->getParameter( 'service_id' );
|
657 |
+
$appointment_id = (int) $this->getParameter( 'appointment_id' );
|
658 |
$timestamp_diff = strtotime( $end_date ) - strtotime( $start_date );
|
659 |
+
$customers = json_decode( $this->getParameter( 'customers', '[]' ), true );
|
660 |
|
661 |
$result = array(
|
662 |
+
'date_interval_not_available' => false,
|
663 |
+
'date_interval_warning' => false,
|
664 |
+
'customers_appointments_limit' => array(),
|
665 |
);
|
666 |
|
667 |
+
$max_extras_duration = 0;
|
668 |
+
foreach ( $customers as $customer ) {
|
669 |
+
if ( $customer['status'] == Lib\Entities\CustomerAppointment::STATUS_PENDING ||
|
670 |
+
$customer['status'] == Lib\Entities\CustomerAppointment::STATUS_APPROVED
|
671 |
+
) {
|
672 |
+
$extras_duration = Lib\Proxy\ServiceExtras::getTotalDuration( $customer['extras'] );
|
673 |
+
if ( $extras_duration > $max_extras_duration ) {
|
674 |
+
$max_extras_duration = $extras_duration;
|
675 |
+
}
|
676 |
+
}
|
677 |
+
}
|
678 |
+
|
679 |
+
$total_end_date = $end_date;
|
680 |
+
if ( $max_extras_duration > 0 ) {
|
681 |
+
$total_end_date = date_create( $end_date )->modify( '+' . $max_extras_duration . ' sec' )->format( 'Y-m-d H:i:s' );
|
682 |
+
}
|
683 |
+
if ( ! $this->dateIntervalIsAvailableForAppointment( $start_date, $total_end_date, 1, $appointment_id ) ) {
|
684 |
$result['date_interval_not_available'] = true;
|
685 |
}
|
686 |
|
688 |
$service = new Lib\Entities\Service();
|
689 |
$service->load( $service_id );
|
690 |
|
691 |
+
$duration = $service->getDuration();
|
692 |
|
693 |
// Service duration interval is not equal to.
|
694 |
$result['date_interval_warning'] = ( $timestamp_diff != $duration );
|
695 |
+
|
696 |
+
// Check customers for appointments limit
|
697 |
+
if ( $start_date ) {
|
698 |
+
foreach ( $customers as $index => $customer ) {
|
699 |
+
if ( $service->appointmentsLimitReached( $customer['id'], $start_date ) ) {
|
700 |
+
$customer_error = Lib\Entities\Customer::find( $customer['id'] );
|
701 |
+
$result['customers_appointments_limit'][] = sprintf( __( '%s has reached the limit of bookings for this service', 'bookly' ), $customer_error->getFullName() );
|
702 |
+
}
|
703 |
+
}
|
704 |
+
}
|
705 |
}
|
706 |
|
707 |
wp_send_json( $result );
|
721 |
->find();
|
722 |
/** @var Lib\Entities\CustomerAppointment $ca */
|
723 |
foreach ( $ca_list as $ca ) {
|
724 |
+
switch ( $ca->getStatus() ) {
|
725 |
case Lib\Entities\CustomerAppointment::STATUS_PENDING:
|
726 |
+
case Lib\Entities\CustomerAppointment::STATUS_WAITLISTED:
|
727 |
+
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_REJECTED );
|
728 |
break;
|
729 |
case Lib\Entities\CustomerAppointment::STATUS_APPROVED:
|
730 |
+
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_CANCELLED );
|
731 |
break;
|
732 |
}
|
733 |
+
Lib\NotificationSender::sendSingle(
|
734 |
+
DataHolders\Simple::create( $ca ),
|
735 |
+
null,
|
736 |
+
array( 'cancellation_reason' => $reason )
|
737 |
+
);
|
738 |
}
|
739 |
}
|
740 |
|
741 |
+
Lib\Entities\Appointment::find( $appointment_id )->delete();
|
|
|
|
|
742 |
|
743 |
wp_send_json_success();
|
744 |
}
|
753 |
private function dateIntervalIsAvailableForAppointment( $start_date, $end_date, $staff_id, $appointment_id )
|
754 |
{
|
755 |
return Lib\Entities\Appointment::query( 'a' )
|
|
|
756 |
->whereNot( 'a.id', $appointment_id )
|
757 |
->where( 'a.staff_id', $staff_id )
|
758 |
+
->whereLt( 'a.start_date', $end_date )
|
759 |
+
->whereGt( 'a.end_date', $start_date )
|
|
|
|
|
760 |
->count() == 0;
|
761 |
}
|
762 |
|
803 |
*/
|
804 |
private function _buildAppointmentsForFC( $staff_id, Lib\Query $query )
|
805 |
{
|
806 |
+
$one_participant = '<div>' . str_replace( "\n", '</div><div>', get_option( 'bookly_cal_one_participant' ) ) . '</div>';
|
807 |
+
$many_participants = '<div>' . str_replace( "\n", '</div><div>', get_option( 'bookly_cal_many_participants' ) ) . '</div>';
|
808 |
+
$postfix_any = sprintf( ' (%s)', get_option( 'bookly_l10n_option_employee' ) );
|
809 |
+
$participants = null;
|
810 |
+
$default_codes = array(
|
811 |
+
'{amount_due}' => '',
|
812 |
+
'{amount_paid}' => '',
|
813 |
+
'{appointment_date}' => '',
|
814 |
+
'{appointment_time}' => '',
|
815 |
+
'{booking_number}' => '',
|
816 |
+
'{category_name}' => '',
|
817 |
+
'{client_email}' => '',
|
818 |
+
'{client_name}' => '',
|
819 |
+
'{client_first_name}' => '',
|
820 |
+
'{client_last_name}' => '',
|
821 |
+
'{client_phone}' => '',
|
822 |
+
'{company_address}' => get_option( 'bookly_co_address' ),
|
823 |
+
'{company_name}' => get_option( 'bookly_co_name' ),
|
824 |
+
'{company_phone}' => get_option( 'bookly_co_phone' ),
|
825 |
+
'{company_website}' => get_option( 'bookly_co_website' ),
|
826 |
+
'{custom_fields}' => '',
|
827 |
+
'{extras}' => '',
|
828 |
+
'{extras_total_price}'=> 0,
|
829 |
+
'{location_name}' => '',
|
830 |
+
'{location_info}' => '',
|
831 |
+
'{on_waiting_list}' => '',
|
832 |
+
'{payment_status}' => '',
|
833 |
+
'{payment_type}' => '',
|
834 |
+
'{service_capacity}' => '',
|
835 |
+
'{service_info}' => '',
|
836 |
+
'{service_name}' => '',
|
837 |
+
'{service_price}' => '',
|
838 |
+
'{signed_up}' => '',
|
839 |
+
'{staff_email}' => '',
|
840 |
+
'{staff_info}' => '',
|
841 |
+
'{staff_name}' => '',
|
842 |
+
'{staff_phone}' => '',
|
843 |
+
'{status}' => '',
|
844 |
+
'{total_price}' => '',
|
845 |
+
);
|
846 |
$appointments = $query
|
847 |
+
->select( 'a.id, a.series_id, a.staff_any, a.location_id, a.start_date, DATE_ADD(a.end_date, INTERVAL a.extras_duration SECOND) AS end_date,
|
848 |
+
COALESCE(s.title,a.custom_service_name) AS service_name, COALESCE(s.color,"silver") AS service_color, s.info AS service_info,
|
849 |
+
1 AS service_capacity, COALESCE(ss.price,a.custom_service_price) AS service_price,
|
850 |
+
st.full_name AS staff_name, st.email AS staff_email, st.info AS staff_info, st.phone AS staff_phone,
|
851 |
(SELECT SUM(ca.number_of_persons) FROM ' . Lib\Entities\CustomerAppointment::getTableName() . ' ca WHERE ca.appointment_id = a.id) AS total_number_of_persons,
|
852 |
ca.number_of_persons,
|
853 |
ca.custom_fields,
|
854 |
ca.status AS appointment_status,
|
855 |
ca.extras,
|
856 |
+
ca.package_id,
|
857 |
+
ct.name AS category_name,
|
858 |
+
c.full_name AS client_name, c.first_name AS client_first_name, c.last_name AS client_last_name, c.phone AS client_phone, c.email AS client_email, c.id AS customer_id,
|
859 |
+
p.total, p.type AS payment_gateway, p.status AS payment_status, p.paid,
|
860 |
+
(SELECT SUM(ca.number_of_persons) FROM ' . Lib\Entities\CustomerAppointment::getTableName() . ' ca WHERE ca.appointment_id = a.id AND ca.status = "waitlisted") AS on_waiting_list' )
|
861 |
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
862 |
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
863 |
->leftJoin( 'Payment', 'p', 'p.id = ca.payment_id' )
|
864 |
->leftJoin( 'Service', 's', 's.id = a.service_id' )
|
865 |
+
->leftJoin( 'Category', 'ct', 'ct.id = s.category_id' )
|
866 |
->leftJoin( 'Staff', 'st', 'st.id = a.staff_id' )
|
867 |
->leftJoin( 'StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id' )
|
|
|
868 |
->groupBy( 'a.id' )
|
869 |
->fetchArray();
|
870 |
|
871 |
foreach ( $appointments as $key => $appointment ) {
|
872 |
+
$codes = $default_codes;
|
873 |
+
$codes['{appointment_date}'] = Lib\Utils\DateTime::formatDate( $appointment['start_date'] );
|
874 |
+
$codes['{appointment_time}'] = Lib\Utils\DateTime::formatTime( $appointment['start_date'] );
|
875 |
+
$codes['{booking_number}'] = $appointment['id'];
|
876 |
+
$codes['{on_waiting_list}'] = $appointment['on_waiting_list'];
|
877 |
+
$codes['{service_name}'] = $appointment['service_name'] ? esc_html( $appointment['service_name'] ) : __( 'Untitled', 'bookly' );
|
878 |
+
$codes['{service_price}'] = Lib\Utils\Price::format( $appointment['service_price'] );
|
879 |
+
$codes['{signed_up}'] = $appointment['total_number_of_persons'];
|
880 |
+
foreach ( array( 'staff_name', 'staff_phone', 'staff_info', 'staff_email', 'service_info', 'service_capacity', 'category_name' ) as $field ) {
|
881 |
+
$codes[ '{' . $field . '}' ] = esc_html( $appointment[ $field ] );
|
882 |
+
}
|
883 |
+
if ( $appointment['staff_any'] ) {
|
884 |
+
$codes['{staff_name}'] .= $postfix_any;
|
885 |
+
}
|
886 |
// Display customer information only if there is 1 customer. Don't confuse with number_of_persons.
|
887 |
if ( $appointment['number_of_persons'] == $appointment['total_number_of_persons'] ) {
|
888 |
+
$participants = 'one';
|
889 |
+
$template = $one_participant;
|
890 |
+
foreach ( array( 'client_name', 'client_first_name', 'client_last_name', 'client_phone', 'client_email' ) as $data_entry ) {
|
891 |
if ( $appointment[ $data_entry ] ) {
|
892 |
+
$codes[ '{' . $data_entry . '}' ] = esc_html( $appointment[ $data_entry ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
893 |
}
|
894 |
}
|
895 |
+
|
896 |
// Payment.
|
897 |
if ( $appointment['total'] ) {
|
898 |
+
$codes['{total_price}'] = Lib\Utils\Price::format( $appointment['total'] );
|
899 |
+
$codes['{amount_paid}'] = Lib\Utils\Price::format( $appointment['paid'] );
|
900 |
+
$codes['{amount_due}'] = Lib\Utils\Price::format( $appointment['total'] - $appointment['paid'] );
|
901 |
+
$codes['{total_price}'] = Lib\Utils\Price::format( $appointment['total'] );
|
902 |
+
$codes['{payment_type}'] = Lib\Entities\Payment::typeToString( $appointment['payment_gateway'] );
|
903 |
+
$codes['{payment_status}'] = Lib\Entities\Payment::statusToString( $appointment['payment_status'] );
|
|
|
904 |
}
|
905 |
// Status.
|
906 |
+
$codes['{status}'] = Lib\Entities\CustomerAppointment::statusToString( $appointment['appointment_status'] );
|
|
|
|
|
|
|
|
|
|
|
907 |
} else {
|
908 |
+
$participants = 'many';
|
909 |
+
$template = $many_participants;
|
910 |
}
|
911 |
+
|
912 |
+
$codes = Lib\Proxy\Shared::prepareCalendarAppointmentCodesData( $codes, $appointment, $participants );
|
913 |
+
|
914 |
$appointments[ $key ] = array(
|
915 |
+
'id' => $appointment['id'],
|
916 |
+
'start' => $appointment['start_date'],
|
917 |
+
'end' => $appointment['end_date'],
|
918 |
+
'title' => ' ',
|
919 |
+
'desc' => strtr( $template, $codes ),
|
920 |
+
'color' => $appointment['service_color'],
|
921 |
+
'staffId' => $staff_id,
|
922 |
+
'series_id' => (int) $appointment['series_id'],
|
923 |
+
'package_id' => (int) $appointment['package_id'],
|
924 |
+
'waitlisted' => (int) $appointment['on_waiting_list'],
|
925 |
+
'staff_any' => (int) $appointment['staff_any'],
|
926 |
);
|
927 |
}
|
928 |
|
929 |
return $appointments;
|
930 |
}
|
931 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
932 |
}
|
backend/modules/calendar/resources/js/calendar-common.js
ADDED
@@ -0,0 +1,279 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
var Calendar = function($container, options) {
|
4 |
+
var obj = this;
|
5 |
+
jQuery.extend(obj.options, options);
|
6 |
+
|
7 |
+
// settings for fullcalendar.
|
8 |
+
var settings = {
|
9 |
+
firstDay: obj.options.l10n.startOfWeek,
|
10 |
+
allDayText: obj.options.l10n.allDay,
|
11 |
+
buttonText: {
|
12 |
+
today: obj.options.l10n.today,
|
13 |
+
month: obj.options.l10n.month,
|
14 |
+
week: obj.options.l10n.week,
|
15 |
+
day: obj.options.l10n.day
|
16 |
+
},
|
17 |
+
axisFormat: obj.options.l10n.mjsTimeFormat,
|
18 |
+
slotDuration: obj.options.l10n.slotDuration,
|
19 |
+
// Text/Time Customization.
|
20 |
+
timeFormat: obj.options.l10n.mjsTimeFormat,
|
21 |
+
monthNames: obj.options.l10n.calendar.longMonths,
|
22 |
+
monthNamesShort: obj.options.l10n.calendar.shortMonths,
|
23 |
+
dayNames: obj.options.l10n.calendar.longDays,
|
24 |
+
dayNamesShort: obj.options.l10n.calendar.shortDays,
|
25 |
+
allDaySlot: false,
|
26 |
+
eventBackgroundColor: 'silver',
|
27 |
+
// Agenda Options.
|
28 |
+
displayEventEnd: true,
|
29 |
+
// Event Dragging & Resizing.
|
30 |
+
editable: false,
|
31 |
+
// Event Data.
|
32 |
+
eventSources: [{
|
33 |
+
url: ajaxurl,
|
34 |
+
data: {
|
35 |
+
action: 'bookly_get_staff_appointments',
|
36 |
+
csrf_token : obj.options.l10n.csrf_token,
|
37 |
+
staff_ids: function () {
|
38 |
+
var ids = [];
|
39 |
+
if (obj.options.is_backend && obj.options.getCurrentStaffId() == 0) {
|
40 |
+
var staffMembers = obj.options.getStaffMembers();
|
41 |
+
for (var i = 0; i < staffMembers.length; ++i) {
|
42 |
+
ids.push(staffMembers[i].id);
|
43 |
+
}
|
44 |
+
} else {
|
45 |
+
ids.push(obj.options.getCurrentStaffId());
|
46 |
+
}
|
47 |
+
return ids;
|
48 |
+
}
|
49 |
+
}
|
50 |
+
}],
|
51 |
+
eventAfterRender: function (calEvent, $calEventList, calendar) {
|
52 |
+
if (calEvent.rendering !== 'background') {
|
53 |
+
$calEventList.each(function () {
|
54 |
+
var $calEvent = $(this),
|
55 |
+
titleHeight = $calEvent.find('.fc-title').height(),
|
56 |
+
origHeight = $calEvent.outerHeight()
|
57 |
+
;
|
58 |
+
$calEvent.removeClass('fc-short');
|
59 |
+
if (origHeight < titleHeight) {
|
60 |
+
var z_index = $calEvent.zIndex();
|
61 |
+
// Mouse handlers.
|
62 |
+
$calEvent.on('mouseenter', function () {
|
63 |
+
$calEvent.css({'z-index': 64, bottom: '', height: ''});
|
64 |
+
}).on('mouseleave', function () {
|
65 |
+
$calEvent.css({'z-index': z_index, height: origHeight});
|
66 |
+
});
|
67 |
+
}
|
68 |
+
});
|
69 |
+
}
|
70 |
+
},
|
71 |
+
// Clicking & Hovering.
|
72 |
+
dayClick: function (date, jsEvent, view) {
|
73 |
+
var staff_id, visible_staff_id;
|
74 |
+
if (view.type == 'multiStaffDay') {
|
75 |
+
var cell = view.coordMap.getCell(jsEvent.pageX, jsEvent.pageY),
|
76 |
+
staffMembers = view.opt('staffMembers');
|
77 |
+
staff_id = staffMembers[cell.col].id;
|
78 |
+
visible_staff_id = 0;
|
79 |
+
} else {
|
80 |
+
staff_id = visible_staff_id = obj.options.getCurrentStaffId();
|
81 |
+
}
|
82 |
+
showAppointmentDialog(
|
83 |
+
null,
|
84 |
+
staff_id,
|
85 |
+
date,
|
86 |
+
function (event) {
|
87 |
+
if (event == 'refresh') {
|
88 |
+
$container.fullCalendar('refetchEvents');
|
89 |
+
} else {
|
90 |
+
if (visible_staff_id == event.staffId || visible_staff_id == 0) {
|
91 |
+
if (event.id) {
|
92 |
+
// Create event in calendar.
|
93 |
+
$container.fullCalendar('renderEvent', event);
|
94 |
+
} else {
|
95 |
+
$container.fullCalendar('refetchEvents');
|
96 |
+
}
|
97 |
+
} else {
|
98 |
+
// Switch to the event owner tab.
|
99 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
100 |
+
}
|
101 |
+
}
|
102 |
+
}
|
103 |
+
);
|
104 |
+
},
|
105 |
+
// Event Rendering.
|
106 |
+
eventRender: function (calEvent, $event, view) {
|
107 |
+
if (calEvent.rendering !== 'background') {
|
108 |
+
var $body = $event.find('.fc-title');
|
109 |
+
if (calEvent.desc) {
|
110 |
+
$body.append(calEvent.desc);
|
111 |
+
}
|
112 |
+
|
113 |
+
var $time = $event.find('.fc-time');
|
114 |
+
if (obj.options.l10n.recurring_appointments.active == '1' && calEvent.series_id) {
|
115 |
+
$time.prepend(
|
116 |
+
$('<a class="bookly-fc-icon dashicons dashicons-admin-links"></a>')
|
117 |
+
.attr('title', obj.options.l10n.recurring_appointments.title)
|
118 |
+
.on('click', function (e) {
|
119 |
+
e.stopPropagation();
|
120 |
+
$(document.body).trigger('recurring_appointments.series_dialog', [calEvent.series_id, function (event) {
|
121 |
+
// Switch to the event owner tab.
|
122 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
123 |
+
}]);
|
124 |
+
})
|
125 |
+
);
|
126 |
+
}
|
127 |
+
if (obj.options.l10n.waiting_list.active == '1' && calEvent.waitlisted > 0) {
|
128 |
+
$time.prepend(
|
129 |
+
$('<span class="bookly-fc-icon dashicons dashicons-list-view"></span>')
|
130 |
+
.attr('title', obj.options.l10n.waiting_list.title)
|
131 |
+
);
|
132 |
+
}
|
133 |
+
if (obj.options.l10n.packages.active == '1' && calEvent.package_id > 0) {
|
134 |
+
$time.prepend(
|
135 |
+
$('<span class="bookly-fc-icon dashicons dashicons-calendar" style="padding:0 2px;"></span>')
|
136 |
+
.attr('title', obj.options.l10n.packages.title)
|
137 |
+
.on('click', function (e) {
|
138 |
+
e.stopPropagation();
|
139 |
+
if (obj.options.l10n.packages.active == '1' && calEvent.package_id) {
|
140 |
+
$(document.body).trigger('bookly_packages.schedule_dialog', [calEvent.package_id, function () {
|
141 |
+
$container.fullCalendar('refetchEvents');
|
142 |
+
}]);
|
143 |
+
}
|
144 |
+
})
|
145 |
+
);
|
146 |
+
}
|
147 |
+
$time.prepend(
|
148 |
+
$('<a class="bookly-fc-icon dashicons dashicons-trash"></a>')
|
149 |
+
.attr('title', obj.options.l10n.delete)
|
150 |
+
.on('click', function (e) {
|
151 |
+
e.stopPropagation();
|
152 |
+
// Localize contains only string values
|
153 |
+
if (obj.options.l10n.recurring_appointments.active == '1' && calEvent.series_id) {
|
154 |
+
$(document.body).trigger('recurring_appointments.delete_dialog', [$container, calEvent]);
|
155 |
+
} else {
|
156 |
+
obj.$deleteDialog.data('calEvent', calEvent).modal('show');
|
157 |
+
}
|
158 |
+
})
|
159 |
+
);
|
160 |
+
}
|
161 |
+
},
|
162 |
+
eventClick: function (calEvent, jsEvent, view) {
|
163 |
+
var visible_staff_id;
|
164 |
+
if (view.type == 'multiStaffDay') {
|
165 |
+
visible_staff_id = 0;
|
166 |
+
} else {
|
167 |
+
visible_staff_id = calEvent.staffId;
|
168 |
+
}
|
169 |
+
|
170 |
+
showAppointmentDialog(
|
171 |
+
calEvent.id,
|
172 |
+
null,
|
173 |
+
null,
|
174 |
+
function (event) {
|
175 |
+
if (event == 'refresh') {
|
176 |
+
$container.fullCalendar('refetchEvents');
|
177 |
+
} else {
|
178 |
+
if (visible_staff_id == event.staffId || visible_staff_id == 0) {
|
179 |
+
// Update event in calendar.
|
180 |
+
jQuery.extend(calEvent, event);
|
181 |
+
$container.fullCalendar('updateEvent', calEvent);
|
182 |
+
} else {
|
183 |
+
// Switch to the event owner tab.
|
184 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
185 |
+
}
|
186 |
+
}
|
187 |
+
}
|
188 |
+
);
|
189 |
+
},
|
190 |
+
loading: function (isLoading) {
|
191 |
+
if (isLoading) {
|
192 |
+
$('.fc-loading-inner').show();
|
193 |
+
}
|
194 |
+
},
|
195 |
+
eventAfterAllRender: function () {
|
196 |
+
$('.fc-loading-inner').hide();
|
197 |
+
}
|
198 |
+
};
|
199 |
+
|
200 |
+
// Init fullcalendar
|
201 |
+
$container.fullCalendar($.extend({}, settings, obj.options.fullcalendar));
|
202 |
+
|
203 |
+
var $fcDatePicker = $('<input type=hidden />');
|
204 |
+
|
205 |
+
$('.fc-toolbar .fc-center h2', $container).before($fcDatePicker).on('click', function () {
|
206 |
+
$fcDatePicker.datepicker('setDate', $container.fullCalendar('getDate').toDate()).datepicker('show');
|
207 |
+
});
|
208 |
+
|
209 |
+
// Init date picker for fast navigation in FullCalendar.
|
210 |
+
$fcDatePicker.datepicker({
|
211 |
+
dayNamesMin: settings.dayNamesShort,
|
212 |
+
monthNames: settings.monthNames,
|
213 |
+
monthNamesShort: settings.monthNamesShort,
|
214 |
+
firstDay: settings.firstDay,
|
215 |
+
beforeShow: function (input, inst) {
|
216 |
+
inst.dpDiv.queue(function () {
|
217 |
+
inst.dpDiv.css({marginTop: '35px', 'font-size': '13.5px'});
|
218 |
+
inst.dpDiv.dequeue();
|
219 |
+
});
|
220 |
+
},
|
221 |
+
onSelect: function (dateText, inst) {
|
222 |
+
var d = new Date(dateText);
|
223 |
+
$container.fullCalendar('gotoDate', d);
|
224 |
+
if ($container.fullCalendar('getView').type != 'agendaDay' &&
|
225 |
+
$container.fullCalendar('getView').type != 'multiStaffDay') {
|
226 |
+
$container.find('.fc-day').removeClass('bookly-fc-day-active');
|
227 |
+
$container.find('.fc-day[data-date="' + moment(d).format('YYYY-MM-DD') + '"]').addClass('bookly-fc-day-active');
|
228 |
+
}
|
229 |
+
},
|
230 |
+
onClose: function (dateText, inst) {
|
231 |
+
inst.dpDiv.queue(function () {
|
232 |
+
inst.dpDiv.css({marginTop: '0'});
|
233 |
+
inst.dpDiv.dequeue();
|
234 |
+
});
|
235 |
+
}
|
236 |
+
});
|
237 |
+
|
238 |
+
/**
|
239 |
+
* On delete appointment click.
|
240 |
+
*/
|
241 |
+
if (obj.$deleteDialog.data('events') == undefined) {
|
242 |
+
obj.$deleteDialog.on('click', '#bookly-delete', function (e) {
|
243 |
+
var calEvent = obj.$deleteDialog.data('calEvent'),
|
244 |
+
ladda = Ladda.create(this);
|
245 |
+
ladda.start();
|
246 |
+
$.ajax({
|
247 |
+
type : 'POST',
|
248 |
+
url : ajaxurl,
|
249 |
+
data : {
|
250 |
+
'action': 'bookly_delete_appointment',
|
251 |
+
'csrf_token': obj.options.l10n.csrf_token,
|
252 |
+
'appointment_id': calEvent.id,
|
253 |
+
'notify': $('#bookly-delete-notify').prop('checked') ? 1 : 0,
|
254 |
+
'reason': $('#bookly-delete-reason').val()
|
255 |
+
},
|
256 |
+
dataType : 'json',
|
257 |
+
xhrFields : {withCredentials: true},
|
258 |
+
crossDomain: 'withCredentials' in new XMLHttpRequest(),
|
259 |
+
success : function (response) {
|
260 |
+
ladda.stop();
|
261 |
+
$container.fullCalendar('removeEvents', calEvent.id);
|
262 |
+
obj.$deleteDialog.modal('hide');
|
263 |
+
}
|
264 |
+
});
|
265 |
+
});
|
266 |
+
}
|
267 |
+
};
|
268 |
+
|
269 |
+
Calendar.prototype.$deleteDialog = $('#bookly-delete-dialog');
|
270 |
+
Calendar.prototype.options = {
|
271 |
+
fullcalendar: {},
|
272 |
+
getCurrentStaffId: function () { return -1; },
|
273 |
+
getStaffMembers: function () { return []; },
|
274 |
+
l10n: {},
|
275 |
+
is_backend: true
|
276 |
+
};
|
277 |
+
|
278 |
+
window.BooklyCalendar = Calendar;
|
279 |
+
});
|
backend/modules/calendar/resources/js/calendar.js
CHANGED
@@ -5,14 +5,12 @@ jQuery(function ($) {
|
|
5 |
$staff = $('input.bookly-js-check-entity'),
|
6 |
$showAll = $('input#bookly-check-all-entities'),
|
7 |
firstHour = new Date().getHours(),
|
8 |
-
$staffButton = $('#
|
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';
|
@@ -39,168 +37,65 @@ jQuery(function ($) {
|
|
39 |
}
|
40 |
updateStaffButton();
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
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 |
-
|
107 |
-
|
108 |
-
|
109 |
|
110 |
-
|
|
|
|
|
111 |
|
112 |
-
|
113 |
-
$time.attr('data-start', $time.find('span').text());
|
114 |
|
115 |
-
|
116 |
-
|
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 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
|
|
|
|
170 |
}
|
171 |
-
|
172 |
-
|
173 |
-
|
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 |
-
|
198 |
-
$('.
|
199 |
},
|
200 |
-
|
201 |
-
|
202 |
-
}
|
203 |
-
|
|
|
|
|
|
|
204 |
|
205 |
$('.fc-agendaDay-button').addClass('fc-corner-right');
|
206 |
if ($tabs.filter('.active').data('staff_id') == 0) {
|
@@ -209,40 +104,6 @@ jQuery(function ($) {
|
|
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 |
});
|
@@ -252,7 +113,6 @@ jQuery(function ($) {
|
|
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 |
|
@@ -304,29 +164,6 @@ jQuery(function ($) {
|
|
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 |
|
@@ -373,29 +210,4 @@ jQuery(function ($) {
|
|
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 |
});
|
5 |
$staff = $('input.bookly-js-check-entity'),
|
6 |
$showAll = $('input#bookly-check-all-entities'),
|
7 |
firstHour = new Date().getHours(),
|
8 |
+
$staffButton = $('#bookly-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 |
if (views.indexOf(lastView) == -1) {
|
16 |
lastView = 'multiStaffDay';
|
37 |
}
|
38 |
updateStaffButton();
|
39 |
|
40 |
+
/**
|
41 |
+
* Calculate height of FullCalendar.
|
42 |
+
*
|
43 |
+
* @return {number}
|
44 |
+
*/
|
45 |
+
function heightFC() {
|
46 |
+
var window_height = $(window).height(),
|
47 |
+
wp_admin_bar_height = $('#wpadminbar').height(),
|
48 |
+
bookly_calendar_tabs_height = $('#bookly-fc-wrapper .tabbable').outerHeight(true),
|
49 |
+
height_to_reduce = wp_admin_bar_height + bookly_calendar_tabs_height,
|
50 |
+
$wrap = $('#wpbody-content .wrap');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
|
52 |
+
if ($wrap.css('margin-top')) {
|
53 |
+
height_to_reduce += parseInt($wrap.css('margin-top').replace('px', ''), 10);
|
54 |
+
}
|
55 |
|
56 |
+
if ($wrap.css('margin-bottom')) {
|
57 |
+
height_to_reduce += parseInt($wrap.css('margin-bottom').replace('px', ''), 10);
|
58 |
+
}
|
59 |
|
60 |
+
var res = window_height - height_to_reduce - 130;
|
|
|
61 |
|
62 |
+
return res > 620 ? res : 620;
|
63 |
+
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
|
65 |
+
var options = {
|
66 |
+
fullcalendar: {
|
67 |
+
// General Display.
|
68 |
+
header: {
|
69 |
+
left: 'prev,next today',
|
70 |
+
center: 'title',
|
71 |
+
right: views
|
72 |
+
},
|
73 |
+
height: heightFC(),
|
74 |
+
// Views.
|
75 |
+
defaultView: lastView,
|
76 |
+
scrollTime: firstHour + ':00:00',
|
77 |
+
views: {
|
78 |
+
agendaWeek: {
|
79 |
+
columnFormat: 'ddd, D'
|
80 |
+
},
|
81 |
+
multiStaffDay: {
|
82 |
+
staffMembers: staffMembers
|
83 |
}
|
84 |
+
},
|
85 |
+
viewRender: function (view, element) {
|
86 |
+
setCookie('bookly_cal_view', view.type);
|
|
|
|
|
|
|
|
|
|
|
87 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
},
|
89 |
+
getCurrentStaffId: function () {
|
90 |
+
return $tabs.filter('.active').data('staff_id');
|
91 |
},
|
92 |
+
getStaffMembers: function () {
|
93 |
+
return staffMembers;
|
94 |
+
},
|
95 |
+
l10n: BooklyL10n
|
96 |
+
};
|
97 |
+
|
98 |
+
var calendar = new BooklyCalendar($fullCalendar, options);
|
99 |
|
100 |
$('.fc-agendaDay-button').addClass('fc-corner-right');
|
101 |
if ($tabs.filter('.active').data('staff_id') == 0) {
|
104 |
$('.fc-multiStaffDay-button').hide();
|
105 |
}
|
106 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
107 |
$(window).on('resize', function () {
|
108 |
$fullCalendar.fullCalendar('option', 'height', heightFC());
|
109 |
});
|
113 |
e.preventDefault();
|
114 |
$tabs.removeClass('active');
|
115 |
$(this).addClass('active');
|
|
|
116 |
var staff_id = $(this).data('staff_id');
|
117 |
setCookie('bookly_cal_tab_id', staff_id);
|
118 |
|
164 |
}
|
165 |
});
|
166 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
167 |
function updateStaffButton() {
|
168 |
$showAll.prop('checked', $staff.filter(':not(:checked)').length == 0);
|
169 |
|
210 |
return keyValue ? keyValue[2] : null;
|
211 |
}
|
212 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
213 |
});
|
backend/modules/calendar/resources/js/ng-appointment_dialog.js
CHANGED
@@ -20,12 +20,18 @@
|
|
20 |
}
|
21 |
},
|
22 |
form : {
|
23 |
-
screen
|
24 |
-
id
|
25 |
-
staff
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
enabled : null,
|
30 |
repeat : null,
|
31 |
daily : { every : null },
|
@@ -34,28 +40,29 @@
|
|
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 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
|
|
|
|
|
|
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];
|
@@ -96,6 +103,20 @@
|
|
96 |
}
|
97 |
return result;
|
98 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
99 |
findTime : function(source, date) {
|
100 |
var result = null,
|
101 |
value_to_find = $filter('date')(date, 'HH:mm'),
|
@@ -125,11 +146,12 @@
|
|
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() {
|
@@ -151,10 +173,7 @@
|
|
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 (
|
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;
|
@@ -167,18 +186,25 @@
|
|
167 |
}
|
168 |
},
|
169 |
getStartAndEndDates : function() {
|
170 |
-
var start_date =
|
171 |
-
|
172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
173 |
end_time = ds.form.end_time.value.split(':');
|
174 |
-
|
175 |
-
start_date.
|
176 |
-
|
177 |
-
end_date.
|
|
|
178 |
|
179 |
return {
|
180 |
-
start_date :
|
181 |
-
end_date :
|
182 |
};
|
183 |
},
|
184 |
getTotalNumberOfPersons : function () {
|
@@ -189,10 +215,10 @@
|
|
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 |
});
|
@@ -202,7 +228,7 @@
|
|
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 |
});
|
@@ -226,7 +252,7 @@
|
|
226 |
// Error messages.
|
227 |
$scope.errors = {};
|
228 |
// Callback to be called after editing appointment.
|
229 |
-
var callback
|
230 |
|
231 |
/**
|
232 |
* Prepare the form for new event.
|
@@ -236,16 +262,25 @@
|
|
236 |
* @param function _callback
|
237 |
*/
|
238 |
$scope.configureNewForm = function(staff_id, start_date, _callback) {
|
239 |
-
var weekday
|
|
|
|
|
|
|
|
|
240 |
jQuery.extend($scope.form, {
|
241 |
-
screen
|
242 |
-
id
|
243 |
-
staff
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
|
|
|
|
|
|
|
|
|
|
249 |
enabled : 0,
|
250 |
repeat : 'daily',
|
251 |
daily : { every: 1 },
|
@@ -254,24 +289,24 @@
|
|
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 |
-
|
265 |
-
|
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 |
/**
|
@@ -281,23 +316,28 @@
|
|
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
|
292 |
-
id
|
293 |
-
staff
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
|
|
|
|
|
|
|
|
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 },
|
@@ -312,15 +352,16 @@
|
|
312 |
page : 0,
|
313 |
another_time : []
|
314 |
},
|
315 |
-
customers
|
316 |
-
|
317 |
-
|
|
|
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) {
|
@@ -334,11 +375,12 @@
|
|
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.
|
342 |
clone.payment_id = item.payment_id;
|
343 |
clone.payment_type = item.payment_type;
|
344 |
clone.payment_title = item.payment_title;
|
@@ -356,51 +398,108 @@
|
|
356 |
callback = _callback;
|
357 |
};
|
358 |
|
359 |
-
var
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
});
|
375 |
-
}
|
376 |
-
|
377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
378 |
};
|
379 |
|
380 |
$scope.onServiceChange = function() {
|
381 |
$scope.dataSource.setEndTimeBasedOnService();
|
382 |
-
$scope.reInitChosen();
|
383 |
$scope.prepareExtras();
|
384 |
$scope.prepareCustomFields();
|
385 |
-
|
386 |
};
|
387 |
|
388 |
$scope.onStaffChange = function() {
|
389 |
-
$scope.form.
|
|
|
|
|
|
|
|
|
|
|
|
|
390 |
};
|
391 |
|
392 |
$scope.onStartTimeChange = function() {
|
393 |
$scope.dataSource.setEndTimeBasedOnService();
|
394 |
-
|
395 |
};
|
396 |
|
397 |
$scope.onEndTimeChange = function() {
|
398 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
399 |
};
|
400 |
|
401 |
$scope.processForm = function() {
|
402 |
$scope.loading = true;
|
403 |
|
|
|
|
|
404 |
var dates = $scope.dataSource.getStartAndEndDates(),
|
405 |
schedule = [],
|
406 |
customers = []
|
@@ -427,26 +526,30 @@
|
|
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
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
|
|
|
|
|
|
|
|
|
|
450 |
},
|
451 |
function (response) {
|
452 |
$scope.$apply(function($scope) {
|
@@ -473,16 +576,6 @@
|
|
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 |
};
|
@@ -497,15 +590,22 @@
|
|
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.
|
503 |
custom_fields : customer.custom_fields,
|
504 |
extras : customer.extras,
|
505 |
status : customer.status,
|
506 |
-
number_of_persons :
|
|
|
507 |
compound_token : null,
|
508 |
-
location_id : null,
|
509 |
payment_id : null,
|
510 |
payment_type : null,
|
511 |
payment_title : null
|
@@ -518,15 +618,19 @@
|
|
518 |
dataSource.data.customers.push(new_customer);
|
519 |
|
520 |
// Make it selected.
|
521 |
-
if (!dataSource.form.service || dataSource.form.customers.length < dataSource.form.service.
|
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 |
/**************************************************************************************************************
|
@@ -535,27 +639,27 @@
|
|
535 |
|
536 |
$scope.editCustomerDetails = function(customer) {
|
537 |
var $dialog = jQuery('#bookly-customer-details-dialog');
|
538 |
-
$dialog.find('input.
|
539 |
-
$dialog.find('input.
|
540 |
$dialog.find('#bookly-extras :checkbox').prop('checked', false);
|
541 |
|
542 |
customer.custom_fields.forEach(function (field) {
|
543 |
-
var $custom_field = $dialog.find('#
|
544 |
switch ($custom_field.data('type')) {
|
545 |
case 'checkboxes':
|
546 |
field.value.forEach(function (value) {
|
547 |
-
$custom_field.find('.
|
548 |
return this.value == value;
|
549 |
}).prop('checked', true);
|
550 |
});
|
551 |
break;
|
552 |
case 'radio-buttons':
|
553 |
-
$custom_field.find('.
|
554 |
return this.value == field.value;
|
555 |
}).prop('checked', true);
|
556 |
break;
|
557 |
default:
|
558 |
-
$custom_field.find('.
|
559 |
break;
|
560 |
}
|
561 |
});
|
@@ -566,10 +670,12 @@
|
|
566 |
});
|
567 |
|
568 |
// Prepare select for number of persons.
|
569 |
-
var $number_of_persons = $dialog.find('#
|
570 |
|
571 |
var max = $scope.form.service
|
572 |
-
?
|
|
|
|
|
573 |
: 1;
|
574 |
$number_of_persons.empty();
|
575 |
for (var i = 1; i <= max; ++i) {
|
@@ -579,12 +685,12 @@
|
|
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('#
|
583 |
-
$dialog.find('#
|
584 |
-
$dialog.find('#
|
585 |
$scope.edit_customer = customer;
|
586 |
|
587 |
-
$dialog.modal({show: true
|
588 |
.on('hidden.bs.modal', function () {
|
589 |
jQuery('body').addClass('modal-open');
|
590 |
});
|
@@ -609,7 +715,7 @@
|
|
609 |
$scope.prepareCustomFields = function () {
|
610 |
if (BooklyL10nAppDialog.cf_per_service == 1) {
|
611 |
var show = false;
|
612 |
-
jQuery('#
|
613 |
var $this = jQuery(this);
|
614 |
if (dataSource.form.service !== null) {
|
615 |
var services = $this.data('services');
|
@@ -624,9 +730,9 @@
|
|
624 |
}
|
625 |
});
|
626 |
if (show) {
|
627 |
-
jQuery('#
|
628 |
} else {
|
629 |
-
jQuery('#
|
630 |
}
|
631 |
}
|
632 |
};
|
@@ -634,8 +740,11 @@
|
|
634 |
$scope.saveCustomFields = function() {
|
635 |
var result = [],
|
636 |
extras = {},
|
637 |
-
$fields = jQuery('#
|
638 |
-
$
|
|
|
|
|
|
|
639 |
;
|
640 |
|
641 |
$fields.each(function () {
|
@@ -645,15 +754,15 @@
|
|
645 |
switch ($this.data('type')) {
|
646 |
case 'checkboxes':
|
647 |
value = [];
|
648 |
-
$this.find('.
|
649 |
value.push(this.value);
|
650 |
});
|
651 |
break;
|
652 |
case 'radio-buttons':
|
653 |
-
value = $this.find('.
|
654 |
break;
|
655 |
default:
|
656 |
-
value = $this.find('.
|
657 |
break;
|
658 |
}
|
659 |
result.push({id: $this.data('id'), value: value});
|
@@ -661,20 +770,24 @@
|
|
661 |
});
|
662 |
|
663 |
if ($scope.form.service) {
|
664 |
-
|
665 |
if (this.value > 0) {
|
666 |
extras[jQuery(this).data('id')] = this.value;
|
667 |
}
|
668 |
});
|
669 |
}
|
670 |
|
671 |
-
$scope.edit_customer.
|
672 |
$scope.edit_customer.number_of_persons = $number_of_persons.val();
|
673 |
-
$scope.edit_customer.
|
|
|
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 |
/**************************************************************************************************************
|
@@ -690,6 +803,91 @@
|
|
690 |
});
|
691 |
};
|
692 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
693 |
/**************************************************************************************************************
|
694 |
* Schedule of Recurring Appointments *
|
695 |
**************************************************************************************************************/
|
@@ -713,14 +911,16 @@
|
|
713 |
jQuery.post(
|
714 |
ajaxurl,
|
715 |
{
|
716 |
-
action
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
|
|
|
|
724 |
},
|
725 |
function (response) {
|
726 |
$scope.$apply(function($scope) {
|
@@ -749,7 +949,7 @@
|
|
749 |
month = m.format('M'),
|
750 |
day = m.format('DD');
|
751 |
|
752 |
-
return BooklyL10nAppDialog.
|
753 |
};
|
754 |
$scope.schFormatTime = function(slots, options) {
|
755 |
for (var i = 0; i < options.length; ++ i) {
|
@@ -790,6 +990,7 @@
|
|
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 = [];
|
@@ -807,6 +1008,7 @@
|
|
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',
|
@@ -844,25 +1046,18 @@
|
|
844 |
return item.deleted;
|
845 |
});
|
846 |
};
|
847 |
-
$scope.schDateOptions = {
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
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 |
/**
|
@@ -882,30 +1077,6 @@
|
|
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 |
*/
|
@@ -941,6 +1112,15 @@
|
|
941 |
return input;
|
942 |
};
|
943 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
944 |
})();
|
945 |
|
946 |
/**
|
20 |
}
|
21 |
},
|
22 |
form : {
|
23 |
+
screen : null,
|
24 |
+
id : null,
|
25 |
+
staff : null,
|
26 |
+
staff_any : null,
|
27 |
+
service : null,
|
28 |
+
custom_service_name : null,
|
29 |
+
custom_service_price : null,
|
30 |
+
location : null,
|
31 |
+
date : null,
|
32 |
+
start_time : null,
|
33 |
+
end_time : null,
|
34 |
+
repeat : {
|
35 |
enabled : null,
|
36 |
repeat : null,
|
37 |
daily : { every : null },
|
40 |
monthly : { on : null, day : null, weekday : null },
|
41 |
until : null
|
42 |
},
|
43 |
+
schedule : {
|
44 |
items : [],
|
45 |
edit : null,
|
46 |
page : null,
|
47 |
another_time : []
|
48 |
},
|
49 |
+
customers : [],
|
50 |
+
notification : null,
|
51 |
+
series_id : null,
|
52 |
+
expand_customers_list : false
|
53 |
+
},
|
54 |
+
l10n : {
|
55 |
+
staff_any: BooklyL10nAppDialog.staff_any
|
56 |
},
|
57 |
loadData : function() {
|
58 |
var deferred = $q.defer();
|
59 |
if (!ds.loaded) {
|
60 |
jQuery.get(
|
61 |
ajaxurl,
|
62 |
+
{ action : 'bookly_get_data_for_appointment_form', csrf_token : BooklyL10nAppDialog.csrf_token },
|
63 |
function(data) {
|
64 |
ds.loaded = true;
|
65 |
ds.data = data;
|
|
|
|
|
66 |
|
67 |
if (data.staff.length) {
|
68 |
ds.form.staff = data.staff[0];
|
103 |
}
|
104 |
return result;
|
105 |
},
|
106 |
+
findLocation : function(staff_id, id) {
|
107 |
+
var result = null,
|
108 |
+
staff = ds.findStaff(staff_id);
|
109 |
+
|
110 |
+
if (staff !== null) {
|
111 |
+
jQuery.each(staff.locations, function(key, item) {
|
112 |
+
if (item.id == id) {
|
113 |
+
result = item;
|
114 |
+
return false;
|
115 |
+
}
|
116 |
+
});
|
117 |
+
}
|
118 |
+
return result;
|
119 |
+
},
|
120 |
findTime : function(source, date) {
|
121 |
var result = null,
|
122 |
value_to_find = $filter('date')(date, 'HH:mm'),
|
146 |
customer.extras = [];
|
147 |
customer.status = ds.data.status.default;
|
148 |
customer.number_of_persons = 1;
|
149 |
+
customer.notes = null;
|
150 |
customer.compound_token = null;
|
|
|
151 |
customer.payment_id = null;
|
152 |
customer.payment_type = null;
|
153 |
customer.payment_title = null;
|
154 |
+
customer.package_id = null;
|
155 |
});
|
156 |
},
|
157 |
getDataForEndTime : function() {
|
173 |
setEndTimeBasedOnService : function() {
|
174 |
var i = jQuery.inArray(ds.form.start_time, ds.data.start_time),
|
175 |
d = ds.form.service ? ds.form.service.duration : ds.data.time_interval;
|
176 |
+
if (d < 86400) {
|
|
|
|
|
|
|
177 |
if (i !== -1) {
|
178 |
for (; i < ds.data.end_time.length; ++i) {
|
179 |
d -= ds.data.time_interval;
|
186 |
}
|
187 |
},
|
188 |
getStartAndEndDates : function() {
|
189 |
+
var start_date = moment(ds.form.date.getTime()),
|
190 |
+
end_date = moment(ds.form.date.getTime()),
|
191 |
+
start_time = [0,0],
|
192 |
+
end_time = [0,0]
|
193 |
+
;
|
194 |
+
if (ds.form.service && ds.form.service.duration >= 86400) {
|
195 |
+
end_date.add(ds.form.service.duration, 'seconds');
|
196 |
+
} else {
|
197 |
+
start_time = ds.form.start_time.value.split(':');
|
198 |
end_time = ds.form.end_time.value.split(':');
|
199 |
+
}
|
200 |
+
start_date.hours(start_time[0]);
|
201 |
+
start_date.minutes(start_time[1]);
|
202 |
+
end_date.hours(end_time[0]);
|
203 |
+
end_date.minutes(end_time[1]);
|
204 |
|
205 |
return {
|
206 |
+
start_date : start_date.format('YYYY-MM-DD HH:mm:00'),
|
207 |
+
end_date : end_date.format('YYYY-MM-DD HH:mm:00')
|
208 |
};
|
209 |
},
|
210 |
getTotalNumberOfPersons : function () {
|
215 |
|
216 |
return result;
|
217 |
},
|
218 |
+
getTotalNumberOfNotCancelledPersons: function (exceptCustomer) {
|
219 |
var result = 0;
|
220 |
ds.form.customers.forEach(function (item) {
|
221 |
+
if ((!exceptCustomer || item.id != exceptCustomer.id) && item.status != 'cancelled' && item.status != 'rejected' && item.status != 'waitlisted') {
|
222 |
result += parseInt(item.number_of_persons);
|
223 |
}
|
224 |
});
|
228 |
getTotalNumberOfCancelledPersons: function () {
|
229 |
var result = 0;
|
230 |
ds.form.customers.forEach(function (item) {
|
231 |
+
if (item.status == 'cancelled' || item.status == 'rejected' || item.status == 'waitlisted') {
|
232 |
result += parseInt(item.number_of_persons);
|
233 |
}
|
234 |
});
|
252 |
// Error messages.
|
253 |
$scope.errors = {};
|
254 |
// Callback to be called after editing appointment.
|
255 |
+
var callback = null;
|
256 |
|
257 |
/**
|
258 |
* Prepare the form for new event.
|
262 |
* @param function _callback
|
263 |
*/
|
264 |
$scope.configureNewForm = function(staff_id, start_date, _callback) {
|
265 |
+
var weekday = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][start_date.format('d')],
|
266 |
+
staff = dataSource.findStaff(staff_id),
|
267 |
+
service = staff && staff.services.length == 2 ? staff.services[1] : null,
|
268 |
+
location = staff && staff.locations.length == 1 ? staff.locations[0] : null
|
269 |
+
;
|
270 |
jQuery.extend($scope.form, {
|
271 |
+
screen : 'main',
|
272 |
+
id : null,
|
273 |
+
staff : staff,
|
274 |
+
staff_any : null,
|
275 |
+
service : service,
|
276 |
+
custom_service_name : null,
|
277 |
+
custom_service_price : 0,
|
278 |
+
location : location,
|
279 |
+
date : start_date.clone().local().toDate(),
|
280 |
+
start_time : dataSource.findTime('start', start_date.format('HH:mm')),
|
281 |
+
end_time : null,
|
282 |
+
series_id : null,
|
283 |
+
repeat : {
|
284 |
enabled : 0,
|
285 |
repeat : 'daily',
|
286 |
daily : { every: 1 },
|
289 |
monthly : { on : 'day', day : start_date.format('D'), weekday : weekday },
|
290 |
until : start_date.clone().add(1, 'month').format('YYYY-MM-DD')
|
291 |
},
|
292 |
+
schedule : {
|
293 |
items : [],
|
294 |
edit : 0,
|
295 |
page : 0,
|
296 |
another_time : []
|
297 |
},
|
298 |
+
customers : [],
|
299 |
+
internal_note : null,
|
300 |
+
expand_customers_list : false
|
301 |
});
|
302 |
$scope.errors = {};
|
303 |
dataSource.setEndTimeBasedOnService();
|
304 |
callback = _callback;
|
305 |
|
|
|
306 |
$scope.prepareExtras();
|
307 |
$scope.prepareCustomFields();
|
308 |
$scope.dataSource.resetCustomers();
|
309 |
+
$scope.onRepeatChange();
|
310 |
};
|
311 |
|
312 |
/**
|
316 |
$scope.loading = true;
|
317 |
jQuery.post(
|
318 |
ajaxurl,
|
319 |
+
{action: 'bookly_get_data_for_appointment', id: appointment_id, csrf_token : BooklyL10nAppDialog.csrf_token},
|
320 |
function(response) {
|
321 |
$scope.$apply(function($scope) {
|
322 |
if (response.success) {
|
323 |
var start_date = moment(response.data.start_date),
|
324 |
+
end_date = moment(response.data.end_date),
|
325 |
+
staff = $scope.dataSource.findStaff(response.data.staff_id);
|
326 |
jQuery.extend($scope.form, {
|
327 |
+
screen : 'main',
|
328 |
+
id : appointment_id,
|
329 |
+
staff : staff,
|
330 |
+
staff_any : response.data.staff_any ? staff : null,
|
331 |
+
service : $scope.dataSource.findService(response.data.staff_id, response.data.service_id),
|
332 |
+
custom_service_name : response.data.custom_service_name,
|
333 |
+
custom_service_price : response.data.custom_service_price,
|
334 |
+
location : $scope.dataSource.findLocation(response.data.staff_id, response.data.location_id),
|
335 |
+
date : start_date.clone().local().toDate(),
|
336 |
+
start_time : $scope.dataSource.findTime('start', start_date.format('HH:mm')),
|
337 |
+
end_time : start_date.format('YYYY-MM-DD') == end_date.format('YYYY-MM-DD')
|
338 |
? $scope.dataSource.findTime('end', end_date.format('HH:mm'))
|
339 |
: $scope.dataSource.findTime('end', (24 + end_date.hour()) + end_date.format(':mm')),
|
340 |
+
repeat : {
|
341 |
enabled : 0,
|
342 |
repeat : 'daily',
|
343 |
daily : { every: 1 },
|
352 |
page : 0,
|
353 |
another_time : []
|
354 |
},
|
355 |
+
customers : [],
|
356 |
+
internal_note : response.data.internal_note,
|
357 |
+
series_id : response.data.series_id,
|
358 |
+
expand_customers_list : false
|
359 |
});
|
360 |
|
|
|
361 |
$scope.prepareExtras();
|
362 |
$scope.prepareCustomFields();
|
363 |
$scope.dataSource.resetCustomers();
|
364 |
+
$scope.onRepeatChange();
|
365 |
|
366 |
var customers_ids = [];
|
367 |
response.data.customers.forEach(function (item, i, arr) {
|
375 |
angular.copy(customer, clone);
|
376 |
}
|
377 |
clone.ca_id = item.ca_id;
|
378 |
+
clone.package_id = item.package_id;
|
379 |
clone.extras = item.extras;
|
380 |
clone.status = item.status;
|
381 |
clone.custom_fields = item.custom_fields;
|
382 |
clone.number_of_persons = item.number_of_persons;
|
383 |
+
clone.notes = item.notes;
|
384 |
clone.payment_id = item.payment_id;
|
385 |
clone.payment_type = item.payment_type;
|
386 |
clone.payment_title = item.payment_title;
|
398 |
callback = _callback;
|
399 |
};
|
400 |
|
401 |
+
var checkAppointmentErrors = function() {
|
402 |
+
if ($scope.form.staff) {
|
403 |
+
var dates = $scope.dataSource.getStartAndEndDates(),
|
404 |
+
customers = [];
|
405 |
+
|
406 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
407 |
+
var customer_extras = {};
|
408 |
+
if ($scope.form.service) {
|
409 |
+
jQuery('#bookly-extras .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
410 |
+
var extra_id = jQuery(this).data('id');
|
411 |
+
if (item.extras[extra_id] !== undefined) {
|
412 |
+
customer_extras[extra_id] = item.extras[extra_id];
|
413 |
+
}
|
414 |
+
});
|
415 |
+
}
|
416 |
+
customers.push({
|
417 |
+
id: item.id,
|
418 |
+
ca_id: item.ca_id,
|
419 |
+
custom_fields: item.custom_fields,
|
420 |
+
extras: customer_extras,
|
421 |
+
number_of_persons: item.number_of_persons,
|
422 |
+
status: item.status
|
423 |
});
|
424 |
+
});
|
425 |
+
|
426 |
+
jQuery.post(
|
427 |
+
ajaxurl,
|
428 |
+
{
|
429 |
+
action : 'bookly_check_appointment_errors',
|
430 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
431 |
+
start_date : dates.start_date,
|
432 |
+
end_date : dates.end_date,
|
433 |
+
appointment_id : $scope.form.id,
|
434 |
+
customers : JSON.stringify(customers),
|
435 |
+
staff_id : $scope.form.staff.id,
|
436 |
+
service_id : $scope.form.service ? $scope.form.service.id : null
|
437 |
+
},
|
438 |
+
function (response) {
|
439 |
+
$scope.$apply(function ($scope) {
|
440 |
+
angular.forEach(response, function (value, error) {
|
441 |
+
$scope.errors[error] = value;
|
442 |
+
});
|
443 |
+
});
|
444 |
+
},
|
445 |
+
'json'
|
446 |
+
);
|
447 |
+
}
|
448 |
};
|
449 |
|
450 |
$scope.onServiceChange = function() {
|
451 |
$scope.dataSource.setEndTimeBasedOnService();
|
|
|
452 |
$scope.prepareExtras();
|
453 |
$scope.prepareCustomFields();
|
454 |
+
checkAppointmentErrors();
|
455 |
};
|
456 |
|
457 |
$scope.onStaffChange = function() {
|
458 |
+
if ($scope.form.staff.services.length == 2) {
|
459 |
+
$scope.form.service = $scope.form.staff.services[1];
|
460 |
+
$scope.onServiceChange();
|
461 |
+
} else {
|
462 |
+
$scope.form.service = null;
|
463 |
+
}
|
464 |
+
$scope.form.location = $scope.form.staff.locations.length == 1 ? $scope.form.staff.locations[0] : null;
|
465 |
};
|
466 |
|
467 |
$scope.onStartTimeChange = function() {
|
468 |
$scope.dataSource.setEndTimeBasedOnService();
|
469 |
+
checkAppointmentErrors();
|
470 |
};
|
471 |
|
472 |
$scope.onEndTimeChange = function() {
|
473 |
+
checkAppointmentErrors();
|
474 |
+
};
|
475 |
+
|
476 |
+
$scope.onDateChange = function() {
|
477 |
+
checkAppointmentErrors();
|
478 |
+
$scope.onRepeatChange();
|
479 |
+
};
|
480 |
+
|
481 |
+
$scope.onCustomersChange = function(old_customers, old_nop) {
|
482 |
+
if (dataSource.form.service && dataSource.form.customers.length > old_customers.length) {
|
483 |
+
var ids = jQuery.map(old_customers, function(customer) {
|
484 |
+
return customer.id;
|
485 |
+
});
|
486 |
+
var nop = dataSource.form.service.capacity_min - old_nop;
|
487 |
+
dataSource.form.customers.some(function (item) {
|
488 |
+
if (jQuery.inArray(item.id, ids) == -1) {
|
489 |
+
item.number_of_persons = nop > 0 ? nop : 1;
|
490 |
+
return true;
|
491 |
+
}
|
492 |
+
});
|
493 |
+
}
|
494 |
+
$scope.errors.customers_appointments_limit = [];
|
495 |
+
checkAppointmentErrors();
|
496 |
};
|
497 |
|
498 |
$scope.processForm = function() {
|
499 |
$scope.loading = true;
|
500 |
|
501 |
+
$scope.errors = {};
|
502 |
+
|
503 |
var dates = $scope.dataSource.getStartAndEndDates(),
|
504 |
schedule = [],
|
505 |
customers = []
|
526 |
ca_id : item.ca_id,
|
527 |
custom_fields : item.custom_fields,
|
528 |
extras : customer_extras,
|
|
|
529 |
number_of_persons : item.number_of_persons,
|
530 |
+
notes : item.notes,
|
531 |
status : item.status
|
532 |
});
|
533 |
});
|
|
|
534 |
jQuery.post(
|
535 |
ajaxurl,
|
536 |
{
|
537 |
+
action : 'bookly_save_appointment_form',
|
538 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
539 |
+
id : $scope.form.id || undefined,
|
540 |
+
staff_id : $scope.form.staff ? $scope.form.staff.id : undefined,
|
541 |
+
service_id : $scope.form.service ? $scope.form.service.id : undefined,
|
542 |
+
custom_service_name : $scope.form.custom_service_name,
|
543 |
+
custom_service_price : $scope.form.custom_service_price,
|
544 |
+
location_id : $scope.form.location ? $scope.form.location.id : undefined,
|
545 |
+
start_date : dates.start_date,
|
546 |
+
end_date : dates.end_date,
|
547 |
+
repeat : JSON.stringify($scope.form.repeat),
|
548 |
+
schedule : schedule,
|
549 |
+
customers : JSON.stringify(customers),
|
550 |
+
notification : $scope.form.notification,
|
551 |
+
internal_note : $scope.form.internal_note,
|
552 |
+
created_from : typeof BooklySCCalendarL10n !== 'undefined' ? 'staff-cabinet' : 'backend'
|
553 |
},
|
554 |
function (response) {
|
555 |
$scope.$apply(function($scope) {
|
576 |
$element.children().modal('hide');
|
577 |
};
|
578 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
579 |
$scope.statusToString = function (status) {
|
580 |
return dataSource.data.status.items[status];
|
581 |
};
|
590 |
*/
|
591 |
$scope.createCustomer = function(customer) {
|
592 |
// Add new customer to the list.
|
593 |
+
var nop = 1;
|
594 |
+
if (dataSource.form.service) {
|
595 |
+
nop = dataSource.form.service.capacity_min - dataSource.getTotalNumberOfNotCancelledPersons();
|
596 |
+
if (nop < 1) {
|
597 |
+
nop = 1;
|
598 |
+
}
|
599 |
+
}
|
600 |
var new_customer = {
|
601 |
id : customer.id.toString(),
|
602 |
+
name : customer.full_name,
|
603 |
custom_fields : customer.custom_fields,
|
604 |
extras : customer.extras,
|
605 |
status : customer.status,
|
606 |
+
number_of_persons : nop,
|
607 |
+
notes : null,
|
608 |
compound_token : null,
|
|
|
609 |
payment_id : null,
|
610 |
payment_type : null,
|
611 |
payment_title : null
|
618 |
dataSource.data.customers.push(new_customer);
|
619 |
|
620 |
// Make it selected.
|
621 |
+
if (!dataSource.form.service || dataSource.form.customers.length < dataSource.form.service.capacity_max) {
|
622 |
dataSource.form.customers.push(new_customer);
|
623 |
}
|
|
|
|
|
624 |
};
|
625 |
|
626 |
$scope.removeCustomer = function(customer) {
|
627 |
$scope.form.customers.splice($scope.form.customers.indexOf(customer), 1);
|
628 |
+
checkAppointmentErrors();
|
629 |
+
};
|
630 |
+
|
631 |
+
$scope.openNewCustomerDialog = function() {
|
632 |
+
var $dialog = jQuery('#bookly-customer-dialog');
|
633 |
+
$dialog.modal({show: true});
|
634 |
};
|
635 |
|
636 |
/**************************************************************************************************************
|
639 |
|
640 |
$scope.editCustomerDetails = function(customer) {
|
641 |
var $dialog = jQuery('#bookly-customer-details-dialog');
|
642 |
+
$dialog.find('input.bookly-custom-field:text, textarea.bookly-custom-field, select.bookly-custom-field').val('');
|
643 |
+
$dialog.find('input.bookly-custom-field:checkbox, input.bookly-custom-field:radio').prop('checked', false);
|
644 |
$dialog.find('#bookly-extras :checkbox').prop('checked', false);
|
645 |
|
646 |
customer.custom_fields.forEach(function (field) {
|
647 |
+
var $custom_field = $dialog.find('#bookly-js-custom-fields > *[data-id="' + field.id + '"]');
|
648 |
switch ($custom_field.data('type')) {
|
649 |
case 'checkboxes':
|
650 |
field.value.forEach(function (value) {
|
651 |
+
$custom_field.find('.bookly-custom-field').filter(function () {
|
652 |
return this.value == value;
|
653 |
}).prop('checked', true);
|
654 |
});
|
655 |
break;
|
656 |
case 'radio-buttons':
|
657 |
+
$custom_field.find('.bookly-custom-field').filter(function () {
|
658 |
return this.value == field.value;
|
659 |
}).prop('checked', true);
|
660 |
break;
|
661 |
default:
|
662 |
+
$custom_field.find('.bookly-custom-field').val(field.value);
|
663 |
break;
|
664 |
}
|
665 |
});
|
670 |
});
|
671 |
|
672 |
// Prepare select for number of persons.
|
673 |
+
var $number_of_persons = $dialog.find('#bookly-number-of-persons');
|
674 |
|
675 |
var max = $scope.form.service
|
676 |
+
? ($scope.form.service.id
|
677 |
+
? parseInt($scope.form.service.capacity_max) - $scope.dataSource.getTotalNumberOfNotCancelledPersons(customer)
|
678 |
+
: 1)
|
679 |
: 1;
|
680 |
$number_of_persons.empty();
|
681 |
for (var i = 1; i <= max; ++i) {
|
685 |
$number_of_persons.append('<option value="' + customer.number_of_persons + '">' + customer.number_of_persons + '</option>');
|
686 |
}
|
687 |
$number_of_persons.val(customer.number_of_persons);
|
688 |
+
$dialog.find('#bookly-appointment-status').val(customer.status);
|
689 |
+
$dialog.find('#bookly-appointment-notes').val(customer.notes);
|
690 |
+
$dialog.find('#bookly-deposit-due').val(customer.due);
|
691 |
$scope.edit_customer = customer;
|
692 |
|
693 |
+
$dialog.modal({show: true})
|
694 |
.on('hidden.bs.modal', function () {
|
695 |
jQuery('body').addClass('modal-open');
|
696 |
});
|
715 |
$scope.prepareCustomFields = function () {
|
716 |
if (BooklyL10nAppDialog.cf_per_service == 1) {
|
717 |
var show = false;
|
718 |
+
jQuery('#bookly-js-custom-fields div[data-services]').each(function() {
|
719 |
var $this = jQuery(this);
|
720 |
if (dataSource.form.service !== null) {
|
721 |
var services = $this.data('services');
|
730 |
}
|
731 |
});
|
732 |
if (show) {
|
733 |
+
jQuery('#bookly-js-custom-fields').show();
|
734 |
} else {
|
735 |
+
jQuery('#bookly-js-custom-fields').hide();
|
736 |
}
|
737 |
}
|
738 |
};
|
740 |
$scope.saveCustomFields = function() {
|
741 |
var result = [],
|
742 |
extras = {},
|
743 |
+
$fields = jQuery('#bookly-js-custom-fields > *'),
|
744 |
+
$status = jQuery('#bookly-appointment-status'),
|
745 |
+
$number_of_persons = jQuery('#bookly-number-of-persons'),
|
746 |
+
$notes = jQuery('#bookly-appointment-notes'),
|
747 |
+
$extras = jQuery('#bookly-extras')
|
748 |
;
|
749 |
|
750 |
$fields.each(function () {
|
754 |
switch ($this.data('type')) {
|
755 |
case 'checkboxes':
|
756 |
value = [];
|
757 |
+
$this.find('.bookly-custom-field:checked').each(function () {
|
758 |
value.push(this.value);
|
759 |
});
|
760 |
break;
|
761 |
case 'radio-buttons':
|
762 |
+
value = $this.find('.bookly-custom-field:checked').val();
|
763 |
break;
|
764 |
default:
|
765 |
+
value = $this.find('.bookly-custom-field').val();
|
766 |
break;
|
767 |
}
|
768 |
result.push({id: $this.data('id'), value: value});
|
770 |
});
|
771 |
|
772 |
if ($scope.form.service) {
|
773 |
+
$extras.find(' .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
774 |
if (this.value > 0) {
|
775 |
extras[jQuery(this).data('id')] = this.value;
|
776 |
}
|
777 |
});
|
778 |
}
|
779 |
|
780 |
+
$scope.edit_customer.status = $status.val();
|
781 |
$scope.edit_customer.number_of_persons = $number_of_persons.val();
|
782 |
+
$scope.edit_customer.notes = $notes.val();
|
783 |
+
$scope.edit_customer.custom_fields = result;
|
784 |
$scope.edit_customer.extras = extras;
|
|
|
785 |
|
786 |
jQuery('#bookly-customer-details-dialog').modal('hide');
|
787 |
+
if ($extras.length > 0) {
|
788 |
+
// Check if intersection with another appointment exists.
|
789 |
+
checkAppointmentErrors();
|
790 |
+
}
|
791 |
};
|
792 |
|
793 |
/**************************************************************************************************************
|
803 |
});
|
804 |
};
|
805 |
|
806 |
+
/**************************************************************************************************************
|
807 |
+
* Package Schedule *
|
808 |
+
**************************************************************************************************************/
|
809 |
+
|
810 |
+
$scope.editPackageSchedule = function(customer) {
|
811 |
+
jQuery(document.body).trigger('bookly_packages.schedule_dialog', [customer.package_id, function (deleted) {
|
812 |
+
if (jQuery.inArray(Number(customer.ca_id), deleted) != -1) {
|
813 |
+
$scope.removeCustomer(customer);
|
814 |
+
}
|
815 |
+
if (callback) {
|
816 |
+
// Call callback.
|
817 |
+
callback('refresh');
|
818 |
+
}
|
819 |
+
}, true]);
|
820 |
+
}
|
821 |
+
|
822 |
+
/**************************************************************************************************************
|
823 |
+
* Repeat Times in Recurring Appointments *
|
824 |
+
**************************************************************************************************************/
|
825 |
+
$scope.isDateMatchesSelections = function (current_date) {
|
826 |
+
switch ($scope.form.repeat.repeat) {
|
827 |
+
case 'daily':
|
828 |
+
if (($scope.form.repeat.daily.every > 6 || jQuery.inArray(current_date.format('ddd').toLowerCase(), $scope.dataSource.data.week_days) != -1) && (current_date.diff(moment($scope.dataSource.form.date.getTime()), 'days') % $scope.form.repeat.daily.every == 0)) {
|
829 |
+
return true;
|
830 |
+
}
|
831 |
+
break;
|
832 |
+
case 'weekly':
|
833 |
+
case 'biweekly':
|
834 |
+
if (($scope.form.repeat.repeat == 'weekly' || current_date.diff(moment($scope.dataSource.form.date.getTime()).startOf('isoWeek'), 'weeks') % 2 == 0) && (jQuery.inArray(current_date.format('ddd').toLowerCase(), $scope.form.repeat.weekly.on) != -1)) {
|
835 |
+
return true;
|
836 |
+
}
|
837 |
+
break;
|
838 |
+
case 'monthly':
|
839 |
+
switch ($scope.form.repeat.monthly.on) {
|
840 |
+
case 'day':
|
841 |
+
if (current_date.format('D') == $scope.form.repeat.monthly.day) {
|
842 |
+
return true;
|
843 |
+
}
|
844 |
+
break;
|
845 |
+
case 'last':
|
846 |
+
if (current_date.format('ddd').toLowerCase() == $scope.form.repeat.monthly.weekday && current_date.clone().endOf('month').diff(current_date, 'days') < 7) {
|
847 |
+
return true;
|
848 |
+
}
|
849 |
+
break;
|
850 |
+
default:
|
851 |
+
var month_diff = current_date.diff(current_date.clone().startOf('month'), 'days'),
|
852 |
+
weeks = ['first', 'second', 'third', 'fourth'],
|
853 |
+
week_number = weeks.indexOf($scope.form.repeat.monthly.on);
|
854 |
+
|
855 |
+
if (current_date.format('ddd').toLowerCase() == $scope.form.repeat.monthly.weekday && month_diff >= week_number * 7 && month_diff < (week_number + 1) * 7) {
|
856 |
+
return true;
|
857 |
+
}
|
858 |
+
}
|
859 |
+
break;
|
860 |
+
}
|
861 |
+
|
862 |
+
return false;
|
863 |
+
};
|
864 |
+
$scope.onRepeatChange = function () {
|
865 |
+
if (jQuery('#bookly-repeat-enabled').length) {
|
866 |
+
var number_of_times = 0,
|
867 |
+
date_until = moment($scope.form.repeat.until).add(1, 'days'),
|
868 |
+
current_date = moment($scope.dataSource.form.date.getTime());
|
869 |
+
do {
|
870 |
+
if ($scope.isDateMatchesSelections(current_date)) {
|
871 |
+
number_of_times++
|
872 |
+
}
|
873 |
+
current_date.add(1, 'days');
|
874 |
+
} while (current_date.isBefore(date_until));
|
875 |
+
$scope.form.repeat.times = number_of_times;
|
876 |
+
}
|
877 |
+
};
|
878 |
+
$scope.onRepeatChangeTimes = function () {
|
879 |
+
var number_of_times = 0,
|
880 |
+
date_until = moment($scope.dataSource.form.date.getTime()).add(5, 'years'),
|
881 |
+
current_date = moment($scope.dataSource.form.date.getTime());
|
882 |
+
do {
|
883 |
+
if ($scope.isDateMatchesSelections(current_date)) {
|
884 |
+
number_of_times++
|
885 |
+
}
|
886 |
+
current_date.add(1, 'days');
|
887 |
+
} while (number_of_times < $scope.form.repeat.times && current_date.isBefore(date_until));
|
888 |
+
$scope.form.repeat.until = current_date.subtract(1, 'days').format('YYYY-MM-DD');
|
889 |
+
};
|
890 |
+
|
891 |
/**************************************************************************************************************
|
892 |
* Schedule of Recurring Appointments *
|
893 |
**************************************************************************************************************/
|
911 |
jQuery.post(
|
912 |
ajaxurl,
|
913 |
{
|
914 |
+
action : 'bookly_recurring_appointments_get_schedule',
|
915 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
916 |
+
staff_id : $scope.form.staff.id,
|
917 |
+
service_id : $scope.form.service.id,
|
918 |
+
location_id : $scope.form.location ? $scope.form.location.id : null,
|
919 |
+
datetime : dates.start_date,
|
920 |
+
until : $scope.form.repeat.until,
|
921 |
+
repeat : $scope.form.repeat.repeat,
|
922 |
+
params : $scope.form.repeat[$scope.form.repeat.repeat],
|
923 |
+
extras : extras
|
924 |
},
|
925 |
function (response) {
|
926 |
$scope.$apply(function($scope) {
|
949 |
month = m.format('M'),
|
950 |
day = m.format('DD');
|
951 |
|
952 |
+
return BooklyL10nAppDialog.dateOptions.dayNamesMin[weekday] + ', ' + BooklyL10nAppDialog.dateOptions.monthNamesShort[month-1] + ' ' + day;
|
953 |
};
|
954 |
$scope.schFormatTime = function(slots, options) {
|
955 |
for (var i = 0; i < options.length; ++ i) {
|
990 |
}
|
991 |
// copy weekly to biweekly
|
992 |
$scope.form.repeat.biweekly.on = $scope.form.repeat.weekly.on.slice();
|
993 |
+
$scope.onRepeatChange();
|
994 |
};
|
995 |
$scope.schOnDateChange = function(item) {
|
996 |
var extras = [];
|
1008 |
ajaxurl,
|
1009 |
{
|
1010 |
action : 'bookly_recurring_appointments_get_schedule',
|
1011 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
1012 |
staff_id : $scope.form.staff.id,
|
1013 |
service_id : $scope.form.service.id,
|
1014 |
datetime : item.date + ' 00:00',
|
1046 |
return item.deleted;
|
1047 |
});
|
1048 |
};
|
1049 |
+
$scope.schDateOptions = jQuery.extend({}, BooklyL10nAppDialog.dateOptions, {dateFormat: 'D, M dd, yy'});
|
1050 |
+
$scope.schViewSeries = function () {
|
1051 |
+
jQuery(document.body).trigger( 'recurring_appointments.series_dialog', [ $scope.form.series_id, function (event) {
|
1052 |
+
// Switch to the event owner tab.
|
1053 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
1054 |
+
} ] );
|
|
|
1055 |
};
|
1056 |
|
1057 |
/**
|
1058 |
* Datepicker options.
|
1059 |
*/
|
1060 |
+
$scope.dateOptions = BooklyL10nAppDialog.dateOptions;
|
|
|
|
|
|
|
|
|
|
|
|
|
1061 |
});
|
1062 |
|
1063 |
/**
|
1077 |
};
|
1078 |
});
|
1079 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1080 |
/**
|
1081 |
* Directive for Popover jQuery plugin.
|
1082 |
*/
|
1112 |
return input;
|
1113 |
};
|
1114 |
});
|
1115 |
+
|
1116 |
+
jQuery('#bookly-select2').select2({
|
1117 |
+
width: '100%',
|
1118 |
+
theme: 'bootstrap',
|
1119 |
+
allowClear: false,
|
1120 |
+
language : {
|
1121 |
+
noResults: function() { return BooklyL10nAppDialog.no_result_found; }
|
1122 |
+
}
|
1123 |
+
});
|
1124 |
})();
|
1125 |
|
1126 |
/**
|
backend/modules/calendar/templates/_appointment_dialog.php
CHANGED
@@ -1,4 +1,9 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
|
|
|
|
|
|
2 |
<div ng-app="appointmentDialog" ng-controller="appointmentDialogCtrl">
|
3 |
<div id=bookly-appointment-dialog class="modal fade" tabindex=-1 role="dialog">
|
4 |
<div class="modal-dialog">
|
@@ -13,13 +18,13 @@
|
|
13 |
</div>
|
14 |
<div ng-hide="loading || form.screen != 'main'" class="modal-body">
|
15 |
<div class=form-group>
|
16 |
-
<label for="
|
17 |
-
<select id="
|
18 |
</div>
|
19 |
|
20 |
<div class=form-group>
|
21 |
-
<label for="
|
22 |
-
<select id="
|
23 |
ng-options="s.title for s in form.staff.services" ng-change="onServiceChange()">
|
24 |
<option value=""><?php _e( '-- Select a service --', 'bookly' ) ?></option>
|
25 |
</select>
|
@@ -28,21 +33,43 @@
|
|
28 |
</p>
|
29 |
</div>
|
30 |
|
31 |
-
<div class="
|
32 |
-
<
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
38 |
</div>
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
<div class="bookly-flexbox">
|
44 |
<div class="bookly-flex-cell">
|
45 |
-
<select id="
|
46 |
ng-options="t.title for t in dataSource.data.start_time"
|
47 |
ng-change=onStartTimeChange()></select>
|
48 |
</div>
|
@@ -59,63 +86,114 @@
|
|
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 |
-
|
|
|
|
|
70 |
<div class=form-group>
|
71 |
-
<label for="bookly-
|
72 |
-
<span ng-show="form.service" title="<?php esc_attr_e( 'Selected / maximum', 'bookly' ) ?>">
|
73 |
-
({{dataSource.getTotalNumberOfPersons()}}/{{form.service.
|
|
|
|
|
|
|
74 |
</span>
|
75 |
-
<
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
<span
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
94 |
<div class="form-group">
|
95 |
<div class="input-group">
|
96 |
-
<select id="bookly-
|
97 |
-
class="
|
98 |
-
ng-model="form.customers" ng-options="c.name for c in dataSource.data.customers"
|
|
|
99 |
</select>
|
100 |
<span class="input-group-btn">
|
101 |
-
<a
|
102 |
<i class="glyphicon glyphicon-plus"></i>
|
103 |
<?php _e( 'New customer', 'bookly' ) ?>
|
104 |
</a>
|
105 |
</span>
|
106 |
</div>
|
107 |
-
<p class="text-danger" my-slide-up="errors.customers_required">
|
108 |
-
<?php _e( 'Please select a customer', 'bookly' ) ?>
|
109 |
-
</p>
|
110 |
-
<p class="text-danger" my-slide-up="errors.overflow_capacity" ng-bind="errors.overflow_capacity"></p>
|
111 |
</div>
|
112 |
</div>
|
|
|
|
|
|
|
|
|
113 |
</div>
|
114 |
|
115 |
<div class=form-group>
|
116 |
-
<label for="
|
117 |
-
<p class="help-block"><?php
|
118 |
-
|
|
|
|
|
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>
|
@@ -123,27 +201,27 @@
|
|
123 |
</div>
|
124 |
|
125 |
<div class=form-group>
|
126 |
-
<label for="
|
127 |
-
<textarea class="form-control" ng-model=form.internal_note id="
|
128 |
</div>
|
129 |
</div>
|
130 |
-
<?php
|
131 |
<div class="modal-footer">
|
132 |
<div ng-hide=loading>
|
133 |
-
<?php
|
134 |
-
<?php
|
135 |
-
<?php
|
136 |
</div>
|
137 |
</div>
|
138 |
</form>
|
139 |
</div><!-- /.modal-content -->
|
140 |
</div><!-- /.modal-dialog -->
|
141 |
</div><!-- /.modal -->
|
142 |
-
<?php ?>
|
143 |
<div customer-dialog=createCustomer(customer)></div>
|
144 |
<div payment-details-dialog="completePayment(payment_id, payment_title)"></div>
|
145 |
|
146 |
-
<?php
|
147 |
<?php \BooklyLite\Backend\Modules\Customers\Components::getInstance()->renderCustomerDialog() ?>
|
148 |
<?php \BooklyLite\Backend\Modules\Payments\Components::getInstance()->renderPaymentDetailsDialog() ?>
|
149 |
</div>
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Entities\CustomerAppointment;
|
3 |
+
use BooklyLite\Lib\Config;
|
4 |
+
use BooklyLite\Lib\Proxy;
|
5 |
+
use BooklyLite\Lib\Utils\Common;
|
6 |
+
?>
|
7 |
<div ng-app="appointmentDialog" ng-controller="appointmentDialogCtrl">
|
8 |
<div id=bookly-appointment-dialog class="modal fade" tabindex=-1 role="dialog">
|
9 |
<div class="modal-dialog">
|
18 |
</div>
|
19 |
<div ng-hide="loading || form.screen != 'main'" class="modal-body">
|
20 |
<div class=form-group>
|
21 |
+
<label for="bookly-provider"><?php _e( 'Provider', 'bookly' ) ?></label>
|
22 |
+
<select id="bookly-provider" class="form-control" ng-model="form.staff" ng-options="s.full_name + (form.staff_any == s ? ' (' + dataSource.l10n.staff_any + ')' : '') for s in dataSource.data.staff" ng-change="onStaffChange()"></select>
|
23 |
</div>
|
24 |
|
25 |
<div class=form-group>
|
26 |
+
<label for="bookly-service"><?php _e( 'Service', 'bookly' ) ?></label>
|
27 |
+
<select id="bookly-service" class="form-control" ng-model="form.service"
|
28 |
ng-options="s.title for s in form.staff.services" ng-change="onServiceChange()">
|
29 |
<option value=""><?php _e( '-- Select a service --', 'bookly' ) ?></option>
|
30 |
</select>
|
33 |
</p>
|
34 |
</div>
|
35 |
|
36 |
+
<div class=form-group ng-show="form.service && !form.service.id">
|
37 |
+
<label for="bookly-custom-service-name"><?php _e( 'Custom service name', 'bookly' ) ?></label>
|
38 |
+
<input type="text" id="bookly-custom-service-name" class="form-control" ng-model="form.custom_service_name" />
|
39 |
+
<p class="text-danger" my-slide-up="errors.custom_service_name_required">
|
40 |
+
<?php _e( 'Please enter a service name', 'bookly' ) ?>
|
41 |
+
</p>
|
42 |
+
</div>
|
43 |
+
|
44 |
+
<div class=form-group ng-show="form.service && !form.service.id">
|
45 |
+
<label for="bookly-custom-service-price"><?php _e( 'Custom service price', 'bookly' ) ?></label>
|
46 |
+
<input type="number" id="bookly-custom-service-price" class="form-control" ng-model="form.custom_service_price" min="0" step="1" />
|
47 |
+
</div>
|
48 |
+
|
49 |
+
<?php if ( Config::locationsActive() ): ?>
|
50 |
+
<div class="form-group">
|
51 |
+
<label for="bookly-appointment-location"><?php _e( 'Location', 'bookly' ) ?></label>
|
52 |
+
<select id="bookly-appointment-location" class="form-control" ng-model="form.location"
|
53 |
+
ng-options="l.name for l in form.staff.locations">
|
54 |
+
<option value=""></option>
|
55 |
+
</select>
|
56 |
</div>
|
57 |
+
<?php endif ?>
|
58 |
+
|
59 |
+
<div class=form-group>
|
60 |
+
<div class="row">
|
61 |
+
<div class="col-sm-4">
|
62 |
+
<label for="bookly-date"><?php _e( 'Date', 'bookly' ) ?></label>
|
63 |
+
<input id="bookly-date" class="form-control" type=text
|
64 |
+
ng-model=form.date ui-date="dateOptions" autocomplete="off"
|
65 |
+
ng-change=onDateChange()>
|
66 |
+
</div>
|
67 |
+
<div class="col-sm-8">
|
68 |
+
<div ng-hide="form.service.duration >= 86400">
|
69 |
+
<label for="bookly-period"><?php _e( 'Period', 'bookly' ) ?></label>
|
70 |
<div class="bookly-flexbox">
|
71 |
<div class="bookly-flex-cell">
|
72 |
+
<select id="bookly-period" class="form-control" ng-model=form.start_time
|
73 |
ng-options="t.title for t in dataSource.data.start_time"
|
74 |
ng-change=onStartTimeChange()></select>
|
75 |
</div>
|
86 |
<?php _e( 'Selected period doesn\'t match service duration', 'bookly' ) ?>
|
87 |
</p>
|
88 |
<p class="text-success" my-slide-up="errors.time_interval" ng-bind="errors.time_interval"></p>
|
|
|
|
|
|
|
89 |
</div>
|
90 |
</div>
|
91 |
+
<div class="text-success col-sm-12" my-slide-up=errors.date_interval_not_available id=date_interval_not_available_msg>
|
92 |
+
<?php _e( 'The selected period is occupied by another appointment', 'bookly' ) ?>
|
93 |
+
</div>
|
94 |
</div>
|
95 |
</div>
|
96 |
+
|
97 |
+
<?php Proxy\RecurringAppointments::renderRecurringSubForm() ?>
|
98 |
+
|
99 |
<div class=form-group>
|
100 |
+
<label for="bookly-select2"><?php _e( 'Customers', 'bookly' ) ?></label>
|
101 |
+
<span ng-show="form.service && form.service.id" title="<?php esc_attr_e( 'Selected / maximum', 'bookly' ) ?>">
|
102 |
+
({{dataSource.getTotalNumberOfPersons()}}/{{form.service.capacity_max}})
|
103 |
+
</span>
|
104 |
+
<span ng-show="form.customers.length > 5" ng-click="form.expand_customers_list = !form.expand_customers_list" role="button">
|
105 |
+
<i class="dashicons" ng-class="{'dashicons-arrow-down-alt2':!form.expand_customers_list, 'dashicons-arrow-up-alt2':form.expand_customers_list}"></i>
|
106 |
</span>
|
107 |
+
<p class="text-success" ng-show=form.service my-slide-up="form.service.capacity_min > 1 && form.service.capacity_min > dataSource.getTotalNumberOfPersons()">
|
108 |
+
<?php _e( 'Minimum capacity', 'bookly' ) ?>: {{form.service.capacity_min}}
|
109 |
+
</p>
|
110 |
+
<ul class="bookly-flexbox">
|
111 |
+
<li ng-repeat="customer in form.customers" class="bookly-flex-row" ng-hide="$index > 4 && !form.expand_customers_list">
|
112 |
+
<a ng-click="editCustomerDetails(customer)" title="<?php esc_attr_e( 'Edit booking details', 'bookly' ) ?>" class="bookly-flex-cell bookly-padding-bottom-sm" href>{{customer.name}}</a>
|
113 |
+
<span class="bookly-flex-cell text-right text-nowrap bookly-padding-bottom-sm">
|
114 |
+
<?php Proxy\Shared::renderAppointmentDialogCustomerList() ?>
|
115 |
+
<span class="dropdown">
|
116 |
+
<button type="button" class="btn btn-sm btn-default bookly-margin-left-xs" data-toggle="dropdown" popover="<?php esc_attr_e( 'Status', 'bookly' ) ?>: {{statusToString(customer.status)}}">
|
117 |
+
<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', 'dashicons-list-view': customer.status == 'waitlisted'}"></span>
|
118 |
+
<span class="caret"></span>
|
119 |
+
</button>
|
120 |
+
<ul class="dropdown-menu">
|
121 |
+
<li>
|
122 |
+
<a href ng-click="customer.status = 'pending'">
|
123 |
+
<span class="dashicons dashicons-clock"></span>
|
124 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?>
|
125 |
+
</a>
|
126 |
+
</li>
|
127 |
+
<li>
|
128 |
+
<a href ng-click="customer.status = 'approved'">
|
129 |
+
<span class="dashicons dashicons-yes"></span>
|
130 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?>
|
131 |
+
</a>
|
132 |
+
</li>
|
133 |
+
<li>
|
134 |
+
<a href ng-click="customer.status = 'cancelled'">
|
135 |
+
<span class="dashicons dashicons-no"></span>
|
136 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?>
|
137 |
+
</a>
|
138 |
+
</li>
|
139 |
+
<li>
|
140 |
+
<a href ng-click="customer.status = 'rejected'">
|
141 |
+
<span class="dashicons dashicons-dismiss"></span>
|
142 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ) ?>
|
143 |
+
</a>
|
144 |
+
</li>
|
145 |
+
<?php if ( Config::waitingListActive() ): ?>
|
146 |
+
<li>
|
147 |
+
<a href ng-click="customer.status = 'waitlisted'">
|
148 |
+
<span class="dashicons dashicons-list-view"></span>
|
149 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_WAITLISTED ) ) ?>
|
150 |
+
</a>
|
151 |
+
</li>
|
152 |
+
<?php endif ?>
|
153 |
+
</ul>
|
154 |
+
</span>
|
155 |
+
<button type="button" class="btn btn-sm btn-default bookly-margin-left-xs" data-toggle="modal" href="#bookly-payment-details-modal" data-payment_id="{{customer.payment_id}}" ng-show="customer.payment_id" popover="<?php esc_attr_e( 'Payment', 'bookly' ) ?>: {{customer.payment_title}}">
|
156 |
+
<span ng-class="{'bookly-js-toggle-popover dashicons': true, 'dashicons-thumbs-up': customer.payment_type == 'full', 'dashicons-warning': customer.payment_type == 'partial'}"></span>
|
157 |
+
</button>
|
158 |
+
<span class="btn btn-sm btn-default disabled bookly-margin-left-xs" style="opacity:1;cursor:default;"><i class="glyphicon glyphicon-user"></i>×{{customer.number_of_persons}}</span>
|
159 |
+
<button type="button" class="btn btn-sm btn-default bookly-margin-left-xs" ng-click="editPackageSchedule(customer)" ng-show="customer.package_id" popover="<?php esc_attr_e( 'Package schedule', 'bookly' ) ?>">
|
160 |
+
<span class="dashicons dashicons-calendar"></span>
|
161 |
+
</button>
|
162 |
+
<a ng-click="removeCustomer(customer)" class="dashicons dashicons-trash text-danger bookly-vertical-middle" href="#"
|
163 |
+
popover="<?php esc_attr_e( 'Remove customer', 'bookly' ) ?>"></a>
|
164 |
</span>
|
|
|
|
|
165 |
</li>
|
166 |
</ul>
|
167 |
+
<span class="btn btn-default" ng-show="form.customers.length > 5 && !form.expand_customers_list" ng-click="form.expand_customers_list = !form.expand_customers_list" style="width: 100%; line-height: 0; padding-top: 0; padding-bottom: 8px; margin-bottom: 10px;" role="button">...</span>
|
168 |
+
<div <?php if ( ! Config::waitingListActive() ): ?>ng-show="!form.service || dataSource.getTotalNumberOfNotCancelledPersons() < form.service.capacity_max"<?php endif ?>>
|
169 |
<div class="form-group">
|
170 |
<div class="input-group">
|
171 |
+
<select id="bookly-select2" multiple data-placeholder="<?php esc_attr_e( '-- Search customers --', 'bookly' ) ?>"
|
172 |
+
class="form-control"
|
173 |
+
ng-model="form.customers" ng-options="c.name for c in dataSource.data.customers"
|
174 |
+
ng-change="onCustomersChange({{form.customers}}, {{dataSource.getTotalNumberOfNotCancelledPersons()}})">
|
175 |
</select>
|
176 |
<span class="input-group-btn">
|
177 |
+
<a class="btn btn-success" ng-click="openNewCustomerDialog()">
|
178 |
<i class="glyphicon glyphicon-plus"></i>
|
179 |
<?php _e( 'New customer', 'bookly' ) ?>
|
180 |
</a>
|
181 |
</span>
|
182 |
</div>
|
|
|
|
|
|
|
|
|
183 |
</div>
|
184 |
</div>
|
185 |
+
<p class="text-danger" my-slide-up="errors.overflow_capacity" ng-bind="errors.overflow_capacity"></p>
|
186 |
+
<p class="text-success" my-slide-up="errors.customers_appointments_limit" ng-repeat="customer_error in errors.customers_appointments_limit">
|
187 |
+
{{customer_error}}
|
188 |
+
</p>
|
189 |
</div>
|
190 |
|
191 |
<div class=form-group>
|
192 |
+
<label for="bookly-notification"><?php _e( 'Send notifications', 'bookly' ) ?></label>
|
193 |
+
<p class="help-block"><?php is_admin() ?
|
194 |
+
_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' ) :
|
195 |
+
_e( 'If email or SMS notifications are enabled and you want customers or yourself 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>
|
196 |
+
<select class="form-control" style="margin-top: 0" ng-model=form.notification id="bookly-notification" ng-init="form.notification = '<?php echo get_user_meta( get_current_user_id(), 'bookly_appointment_form_send_notifications', true ) ?>' || 'no'" >
|
197 |
<option value="no"><?php _e( 'Don\'t send', 'bookly' ) ?></option>
|
198 |
<option value="changed_status"><?php _e( 'If status changed', 'bookly' ) ?></option>
|
199 |
<option value="all"><?php _e( 'To all customers', 'bookly' ) ?></option>
|
201 |
</div>
|
202 |
|
203 |
<div class=form-group>
|
204 |
+
<label for="bookly-internal-note"><?php _e( 'Internal note', 'bookly' ) ?></label>
|
205 |
+
<textarea class="form-control" ng-model=form.internal_note id="bookly-internal-note"></textarea>
|
206 |
</div>
|
207 |
</div>
|
208 |
+
<?php Proxy\RecurringAppointments::renderSchedule() ?>
|
209 |
<div class="modal-footer">
|
210 |
<div ng-hide=loading>
|
211 |
+
<?php Proxy\Shared::renderAppointmentDialogFooter() ?>
|
212 |
+
<?php Common::customButton( 'bookly-save', 'btn-lg btn-success', null, array( 'ng-hide' => 'form.repeat.enabled && form.screen == \'main\'', 'ng-disabled' => 'form.repeat.enabled && schIsScheduleEmpty()', 'formnovalidate' => '' ), 'submit' ) ?>
|
213 |
+
<?php Common::customButton( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'ng-click' => 'closeDialog()', 'data-dismiss' => 'modal' ) ) ?>
|
214 |
</div>
|
215 |
</div>
|
216 |
</form>
|
217 |
</div><!-- /.modal-content -->
|
218 |
</div><!-- /.modal-dialog -->
|
219 |
</div><!-- /.modal -->
|
|
|
220 |
<div customer-dialog=createCustomer(customer)></div>
|
221 |
<div payment-details-dialog="completePayment(payment_id, payment_title)"></div>
|
222 |
|
223 |
+
<?php $this->render( '_customer_details_dialog' ) ?>
|
224 |
<?php \BooklyLite\Backend\Modules\Customers\Components::getInstance()->renderCustomerDialog() ?>
|
225 |
<?php \BooklyLite\Backend\Modules\Payments\Components::getInstance()->renderPaymentDetailsDialog() ?>
|
226 |
</div>
|
227 |
+
<?php Proxy\Packages::renderPackageScheduleDialog() ?>
|
backend/modules/calendar/templates/_customer_details_dialog.php
CHANGED
@@ -1,5 +1,8 @@
|
|
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">
|
@@ -11,87 +14,33 @@ use BooklyLite\Lib\Entities\CustomerAppointment;
|
|
11 |
<form ng-hide=loading style="z-index: 1050">
|
12 |
<div class="modal-body">
|
13 |
<div class="form-group">
|
14 |
-
<label for="
|
15 |
-
<select class="
|
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 |
-
<
|
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 |
-
|
75 |
-
|
76 |
-
|
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 |
-
|
94 |
-
|
95 |
</div>
|
96 |
</form>
|
97 |
</div><!-- /.modal-content -->
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
use BooklyLite\Lib\Entities\CustomerAppointment;
|
3 |
+
use BooklyLite\Lib\Utils\Common;
|
4 |
+
use BooklyLite\Lib\Config;
|
5 |
+
use BooklyLite\Lib\Proxy;
|
6 |
?>
|
7 |
<div id="bookly-customer-details-dialog" class="modal fade" tabindex=-1 role="dialog">
|
8 |
<div class="modal-dialog">
|
14 |
<form ng-hide=loading style="z-index: 1050">
|
15 |
<div class="modal-body">
|
16 |
<div class="form-group">
|
17 |
+
<label for="bookly-appointment-status"><?php _e( 'Status', 'bookly' ) ?></label>
|
18 |
+
<select class="bookly-custom-field form-control" id="bookly-appointment-status">
|
19 |
<option value="<?php echo CustomerAppointment::STATUS_PENDING ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?></option>
|
20 |
<option value="<?php echo CustomerAppointment::STATUS_APPROVED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?></option>
|
21 |
<option value="<?php echo CustomerAppointment::STATUS_CANCELLED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?></option>
|
22 |
<option value="<?php echo CustomerAppointment::STATUS_REJECTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ) ?></option>
|
23 |
+
<?php if ( Config::waitingListActive() ) : ?>
|
24 |
+
<option value="<?php echo CustomerAppointment::STATUS_WAITLISTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_WAITLISTED ) ) ?></option>
|
25 |
+
<?php endif ?>
|
26 |
</select>
|
27 |
</div>
|
28 |
+
<div class="form-group" style="display: none">
|
29 |
+
<select class="bookly-custom-field form-control" id="bookly-number-of-persons"></select>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
</div>
|
31 |
+
<?php if ( Config::showNotes() ): ?>
|
32 |
+
<div class="form-group">
|
33 |
+
<label for="bookly-appointment-notes"><?php echo Common::getTranslatedOption( 'bookly_l10n_label_notes' ) ?></label>
|
34 |
+
<textarea class="bookly-custom-field form-control" id="bookly-appointment-notes"></textarea>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
</div>
|
36 |
<?php endif ?>
|
37 |
+
|
38 |
+
<?php Proxy\CustomFields::renderCustomerDetails() ?>
|
39 |
+
<?php Proxy\ServiceExtras::renderCustomerDetails() ?>
|
40 |
</div>
|
41 |
<div class="modal-footer">
|
42 |
+
<?php Common::customButton( null, 'btn-lg btn-lg btn-success', __( 'Apply', 'bookly' ), array( 'ng-click' => 'saveCustomFields()' ) ) ?>
|
43 |
+
<?php Common::customButton( null, 'btn btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
44 |
</div>
|
45 |
</form>
|
46 |
</div><!-- /.modal-content -->
|
backend/modules/calendar/templates/calendar.php
CHANGED
@@ -1,4 +1,6 @@
|
|
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; }
|
@@ -23,15 +25,15 @@
|
|
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->
|
27 |
-
<?php echo $staff->
|
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="
|
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">
|
@@ -44,8 +46,8 @@
|
|
44 |
<li>
|
45 |
<a class="checkbox" href="javascript:void(0)">
|
46 |
<label>
|
47 |
-
<input type="checkbox" id="
|
48 |
-
<?php echo $staff->
|
49 |
</label>
|
50 |
</a>
|
51 |
</li>
|
@@ -56,7 +58,6 @@
|
|
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>
|
@@ -65,7 +66,7 @@
|
|
65 |
<div class="bookly-js-calendar-element"></div>
|
66 |
</div>
|
67 |
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderAppointmentDialog() ?>
|
68 |
-
<?php
|
69 |
<?php else : ?>
|
70 |
<div class="well">
|
71 |
<div class="h1"><?php _e( 'Welcome to Bookly!', 'bookly' ) ?></div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var \BooklyLite\Lib\Entities\Staff[] $staff_members */
|
3 |
+
?>
|
4 |
<style>
|
5 |
.fc-slats tr { height: <?php echo max( 21, (int) ( 0.43 * get_option( 'bookly_gen_time_slot_length' ) ) ) ?>px; }
|
6 |
.fc-time-grid-event.fc-short .fc-time::after { content: '' !important; }
|
25 |
</li>
|
26 |
<?php endif ?>
|
27 |
<?php foreach ( $staff_members as $staff ) : ?>
|
28 |
+
<li class="bookly-nav-item bookly-js-calendar-tab" data-staff_id="<?php echo $staff->getId() ?>" style="display: none">
|
29 |
+
<?php echo $staff->getFullName() ?>
|
30 |
</li>
|
31 |
<?php endforeach ?>
|
32 |
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
33 |
<div class="btn-group pull-right" style="margin-top: 5px;">
|
34 |
<button class="btn btn-default dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
35 |
<div class="bookly-flex-cell"><i class="dashicons dashicons-admin-users bookly-margin-right-md"></i></div>
|
36 |
+
<div class="bookly-flex-cell text-left"><span id="bookly-staff-button"></span></div>
|
37 |
<div class="bookly-flex-cell"><div class="bookly-margin-left-md"><span class="caret"></span></div></div>
|
38 |
</button>
|
39 |
<ul class="dropdown-menu bookly-entity-selector">
|
46 |
<li>
|
47 |
<a class="checkbox" href="javascript:void(0)">
|
48 |
<label>
|
49 |
+
<input type="checkbox" id="bookly-filter-staff-<?php echo $staff->getId() ?>" value="<?php echo $staff->getId() ?>" data-staff_name="<?php echo esc_attr( $staff->getFullName() ) ?>" class="bookly-js-check-entity">
|
50 |
+
<?php echo $staff->getFullName() ?>
|
51 |
</label>
|
52 |
</a>
|
53 |
</li>
|
58 |
</ul>
|
59 |
<?php endif ?>
|
60 |
<div class="bookly-margin-top-xlg">
|
|
|
61 |
<?php if ( $staff_members ) : ?>
|
62 |
<div class="fc-loading-inner" style="display: none">
|
63 |
<div class="fc-loading"></div>
|
66 |
<div class="bookly-js-calendar-element"></div>
|
67 |
</div>
|
68 |
<?php \BooklyLite\Backend\Modules\Calendar\Components::getInstance()->renderAppointmentDialog() ?>
|
69 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderComponentCalendar() ?>
|
70 |
<?php else : ?>
|
71 |
<div class="well">
|
72 |
<div class="h1"><?php _e( 'Welcome to Bookly!', 'bookly' ) ?></div>
|
backend/modules/coupons/Controller.php
DELETED
@@ -1,66 +0,0 @@
|
|
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>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', '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
DELETED
@@ -1,19 +0,0 @@
|
|
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
DELETED
@@ -1,63 +0,0 @@
|
|
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
DELETED
@@ -1,66 +0,0 @@
|
|
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
DELETED
@@ -1,44 +0,0 @@
|
|
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
DELETED
@@ -1,90 +0,0 @@
|
|
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>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', '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
DELETED
@@ -1,233 +0,0 @@
|
|
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',
|
8 |
-
handle : '.bookly-js-handle'
|
9 |
-
});
|
10 |
-
|
11 |
-
$cf_per_service.change(function() {
|
12 |
-
if($(this).val() == 1){
|
13 |
-
$(this).val('0');
|
14 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
15 |
-
$(this).find('option:gt(0)').prop('disabled', true);
|
16 |
-
}
|
17 |
-
});
|
18 |
-
|
19 |
-
/**
|
20 |
-
* Build initial fields.
|
21 |
-
*/
|
22 |
-
restoreFields();
|
23 |
-
|
24 |
-
/**
|
25 |
-
* On "Add new field" button click.
|
26 |
-
*/
|
27 |
-
$('#ab-add-fields').on('click', 'button', function() {
|
28 |
-
addField($(this).data('type'));
|
29 |
-
});
|
30 |
-
|
31 |
-
/**
|
32 |
-
* On "Add new item" button click.
|
33 |
-
*/
|
34 |
-
$fields.on('click', 'button', function() {
|
35 |
-
addItem($(this).prev('ul'), $(this).data('type'));
|
36 |
-
});
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Delete field or checkbox/radio button/drop-down option.
|
40 |
-
*/
|
41 |
-
$fields.on('click', '.ab-delete', function(e) {
|
42 |
-
e.preventDefault();
|
43 |
-
$(this).closest('li').fadeOut('fast', function() { $(this).remove(); });
|
44 |
-
});
|
45 |
-
|
46 |
-
/**
|
47 |
-
* Submit custom fields form.
|
48 |
-
*/
|
49 |
-
$('#ajax-send-custom-fields').on('click', function(e) {
|
50 |
-
e.preventDefault();
|
51 |
-
var data = [];
|
52 |
-
$fields.children('li').each(function() {
|
53 |
-
var $this = $(this),
|
54 |
-
field = {};
|
55 |
-
switch ($this.data('type')) {
|
56 |
-
case 'checkboxes':
|
57 |
-
case 'radio-buttons':
|
58 |
-
case 'drop-down':
|
59 |
-
field.items = [];
|
60 |
-
$this.find('ul.ab-items li').each(function() {
|
61 |
-
field.items.push($(this).find('input').val());
|
62 |
-
});
|
63 |
-
case 'textarea':
|
64 |
-
case 'text-field':
|
65 |
-
case 'text-content':
|
66 |
-
case 'captcha':
|
67 |
-
field.type = $this.data('type');
|
68 |
-
field.label = $this.find('.ab-label').val();
|
69 |
-
field.required = $this.find('.ab-required').prop('checked');
|
70 |
-
field.id = $this.data('ab-field-id');
|
71 |
-
field.services = $this.find('.ab--services-holder input:checked')
|
72 |
-
.map(function() { return this.value; })
|
73 |
-
.get();
|
74 |
-
}
|
75 |
-
data.push(field);
|
76 |
-
});
|
77 |
-
|
78 |
-
var ladda = Ladda.create(this);
|
79 |
-
ladda.start();
|
80 |
-
$.ajax({
|
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]});
|
88 |
-
}
|
89 |
-
});
|
90 |
-
});
|
91 |
-
|
92 |
-
/**
|
93 |
-
* On 'Reset' click.
|
94 |
-
*/
|
95 |
-
$('button[type=reset]').on('click', function() {
|
96 |
-
$fields.empty();
|
97 |
-
restoreFields();
|
98 |
-
});
|
99 |
-
|
100 |
-
/**
|
101 |
-
* Add new field.
|
102 |
-
*
|
103 |
-
* @param type
|
104 |
-
* @param id
|
105 |
-
* @param label
|
106 |
-
* @param required
|
107 |
-
* @param services
|
108 |
-
* @returns {*|jQuery}
|
109 |
-
*/
|
110 |
-
function addField(type, id, label, required, services) {
|
111 |
-
var $new_field = $('ul#ab-templates > li[data-type=' + type + ']').clone();
|
112 |
-
// Set id, label and required.
|
113 |
-
if (typeof id == 'undefined') {
|
114 |
-
id = Math.floor((Math.random() * 100000) + 1);
|
115 |
-
}
|
116 |
-
if (typeof label == 'undefined') {
|
117 |
-
label = '';
|
118 |
-
}
|
119 |
-
if (typeof required == 'undefined') {
|
120 |
-
required = false;
|
121 |
-
}
|
122 |
-
$new_field
|
123 |
-
.hide()
|
124 |
-
.data('ab-field-id', id)
|
125 |
-
.find('.ab-required').prop({
|
126 |
-
id : 'required-' + id,
|
127 |
-
checked : required
|
128 |
-
})
|
129 |
-
.next('label').attr('for', 'required-' + id)
|
130 |
-
.end().end()
|
131 |
-
.find('.ab-label').val(label)
|
132 |
-
.end()
|
133 |
-
.find('.ab--services-holder input:checkbox').each(function (index) {
|
134 |
-
if (services && $.inArray(this.value, services) > -1) {
|
135 |
-
this.checked = true;
|
136 |
-
}
|
137 |
-
this.id = 'check-' + id + '-' + index;
|
138 |
-
$(this).next().attr('for', 'check-' + id + '-' + index);
|
139 |
-
});
|
140 |
-
// Add new field to the list.
|
141 |
-
$fields.append($new_field);
|
142 |
-
$new_field.fadeIn('fast');
|
143 |
-
// Make it sortable.
|
144 |
-
$new_field.find('ul.ab-items').sortable({
|
145 |
-
axis : 'y',
|
146 |
-
handle : '.bookly-js-handle'
|
147 |
-
});
|
148 |
-
// Set focus to label field.
|
149 |
-
$new_field.find('.ab-label').focus();
|
150 |
-
|
151 |
-
return $new_field;
|
152 |
-
}
|
153 |
-
|
154 |
-
/**
|
155 |
-
* Add new checkbox/radio button/drop-down option.
|
156 |
-
*
|
157 |
-
* @param $ul
|
158 |
-
* @param type
|
159 |
-
* @param value
|
160 |
-
* @return {*|jQuery}
|
161 |
-
*/
|
162 |
-
function addItem($ul, type, value) {
|
163 |
-
var $new_item = $('ul#ab-templates > li[data-type=' + type + ']').clone();
|
164 |
-
if (typeof value != 'undefined') {
|
165 |
-
$new_item.find('input').val(value);
|
166 |
-
}
|
167 |
-
$new_item.hide().appendTo($ul).fadeIn('fast').find('input').focus();
|
168 |
-
|
169 |
-
return $new_item;
|
170 |
-
}
|
171 |
-
|
172 |
-
/**
|
173 |
-
* Restore fields from BooklyL10n.custom_fields.
|
174 |
-
*/
|
175 |
-
function restoreFields() {
|
176 |
-
if (BooklyL10n.custom_fields) {
|
177 |
-
var custom_fields = jQuery.parseJSON(BooklyL10n.custom_fields);
|
178 |
-
$.each(custom_fields, function (i, field) {
|
179 |
-
var $new_field = addField(field.type, field.id, field.label, field.required, field.services);
|
180 |
-
// add children
|
181 |
-
if (field.items) {
|
182 |
-
$.each(field.items, function (i, value) {
|
183 |
-
addItem($new_field.find('ul.ab-items'), field.type + '-item', value);
|
184 |
-
});
|
185 |
-
}
|
186 |
-
});
|
187 |
-
}
|
188 |
-
$cf_per_service.change();
|
189 |
-
$('.ab--services-holder').each(function (id, elem) {
|
190 |
-
updateServiceButton($(elem));
|
191 |
-
});
|
192 |
-
$(':focus').blur();
|
193 |
-
}
|
194 |
-
|
195 |
-
$('.ab-popover').popover({trigger: 'hover'});
|
196 |
-
|
197 |
-
function updateServiceButton($holder) {
|
198 |
-
var service_checked = $holder.find('.bookly-js-check-entity:checked').length;
|
199 |
-
if (service_checked == 0) {
|
200 |
-
$holder.find('.ab-count').text(BooklyL10n.selector.nothing_selected);
|
201 |
-
$holder.find('.bookly-check-all-entities').prop('checked', false);
|
202 |
-
} else if (service_checked == 1) {
|
203 |
-
$holder.find('.ab-count').text($holder.find('.bookly-js-check-entity:checked').data('title'));
|
204 |
-
$holder.find('.bookly-check-all-entities').prop('checked', (service_checked == $holder.find('.bookly-js-check-entity').length));
|
205 |
-
} else {
|
206 |
-
if( service_checked == $holder.find('.bookly-js-check-entity').length) {
|
207 |
-
$holder.find('.bookly-check-all-entities').prop('checked', true);
|
208 |
-
$holder.find('.ab-count').text(BooklyL10n.selector.all_selected);
|
209 |
-
} else {
|
210 |
-
$holder.find('.bookly-check-all-entities').prop('checked', false);
|
211 |
-
$holder.find('.ab-count').text(service_checked + '/' + $holder.find('.bookly-js-check-entity').length);
|
212 |
-
}
|
213 |
-
}
|
214 |
-
}
|
215 |
-
|
216 |
-
$(document).on('click', '.bookly-check-all-entities', function () {
|
217 |
-
var $holder = $(this).parents('.ab--services-holder');
|
218 |
-
$holder.find('.bookly-js-check-entity').prop('checked', $(this).prop('checked'));
|
219 |
-
updateServiceButton($holder);
|
220 |
-
});
|
221 |
-
|
222 |
-
$(document).on('click', '.ab--services-holder ul.dropdown-menu li a[href]', function (e) {
|
223 |
-
updateServiceButton($(this).parents('.ab--services-holder'));
|
224 |
-
e.stopPropagation();
|
225 |
-
});
|
226 |
-
|
227 |
-
$('[data-toggle="popover"]').popover({
|
228 |
-
html: true,
|
229 |
-
placement: 'top',
|
230 |
-
trigger: 'hover',
|
231 |
-
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>'
|
232 |
-
});
|
233 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/custom_fields/templates/_services.php
DELETED
@@ -1,32 +0,0 @@
|
|
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
DELETED
@@ -1,303 +0,0 @@
|
|
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( '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 |
-
|
18 |
-
<hr />
|
19 |
-
|
20 |
-
<ul id="ab-custom-fields"></ul>
|
21 |
-
|
22 |
-
<div id="ab-add-fields">
|
23 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="text-field"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Text Field', 'bookly' ) ?></button>
|
24 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="textarea"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Text Area', 'bookly' ) ?></button>
|
25 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="text-content"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Text Content', 'bookly' ) ?></button>
|
26 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="checkboxes"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Checkbox Group', 'bookly' ) ?></button>
|
27 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="radio-buttons"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Radio Button Group', 'bookly' ) ?></button>
|
28 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="drop-down"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Drop Down', 'bookly' ) ?></button>
|
29 |
-
<button class="btn btn-default bookly-margin-bottom-sm bookly-margin-right-sm" data-type="captcha"><i class="glyphicon glyphicon-plus"></i> <?php _e( 'Captcha', 'bookly' ) ?></button>
|
30 |
-
</div>
|
31 |
-
<p class="help-block"><?php _e( 'HTML allowed in all texts and labels.', 'bookly' ) ?></p>
|
32 |
-
|
33 |
-
<ul id="ab-templates" style="display:none">
|
34 |
-
|
35 |
-
<li data-type="textarea">
|
36 |
-
<div class="bookly-flexbox">
|
37 |
-
<div class="bookly-flex-cell">
|
38 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
39 |
-
</div>
|
40 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
41 |
-
<p><b><?php _e( 'Text Area', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
42 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
43 |
-
<div class="row">
|
44 |
-
<div class="col-md-8">
|
45 |
-
<div class="input-group">
|
46 |
-
<input class="ab-label form-control" type="text" value="" placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
47 |
-
<label class="input-group-addon">
|
48 |
-
<input class="ab-required" type="checkbox">
|
49 |
-
<span class="hidden-xs"><?php _e( 'Required field', 'bookly' ) ?></span>
|
50 |
-
<i class="visible-xs-inline-block glyphicon glyphicon-warning"></i>
|
51 |
-
</label>
|
52 |
-
</div>
|
53 |
-
</div>
|
54 |
-
<div class="col-md-4">
|
55 |
-
<?php echo $services_html ?>
|
56 |
-
</div>
|
57 |
-
</div>
|
58 |
-
</div>
|
59 |
-
</div>
|
60 |
-
<hr>
|
61 |
-
</li>
|
62 |
-
|
63 |
-
<li data-type="text-content">
|
64 |
-
<div class="bookly-flexbox">
|
65 |
-
<div class="bookly-flex-cell">
|
66 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
67 |
-
</div>
|
68 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
69 |
-
<p><b><?php _e( 'Text Content', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
70 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
71 |
-
<div class="row">
|
72 |
-
<div class="col-md-8">
|
73 |
-
<textarea class="ab-label form-control" type="text" rows="3"
|
74 |
-
placeholder="<?php esc_attr_e( 'Enter a content', 'bookly' ) ?>"></textarea>
|
75 |
-
<input class="ab-required hidden" type="checkbox" disabled="disabled">
|
76 |
-
</div>
|
77 |
-
<div class="col-md-4">
|
78 |
-
<?php echo $services_html ?>
|
79 |
-
</div>
|
80 |
-
</div>
|
81 |
-
</div>
|
82 |
-
</div>
|
83 |
-
<hr>
|
84 |
-
</li>
|
85 |
-
|
86 |
-
<li data-type="text-field">
|
87 |
-
<div class="bookly-flexbox">
|
88 |
-
<div class="bookly-flex-cell">
|
89 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
90 |
-
</div>
|
91 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
92 |
-
<p><b><?php _e( 'Text Field', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
93 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
94 |
-
<div class="row">
|
95 |
-
<div class="col-md-8">
|
96 |
-
<div class="input-group">
|
97 |
-
<input class="ab-label form-control" type="text" value=""
|
98 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
99 |
-
<label class="input-group-addon">
|
100 |
-
<input class="ab-required" type="checkbox">
|
101 |
-
<span class="hidden-xs"><?php _e( 'Required field', 'bookly' ) ?></span>
|
102 |
-
<i class="visible-xs-inline-block glyphicon glyphicon-warning"></i>
|
103 |
-
</label>
|
104 |
-
</div>
|
105 |
-
</div>
|
106 |
-
<div class="col-md-4">
|
107 |
-
<?php echo $services_html ?>
|
108 |
-
</div>
|
109 |
-
</div>
|
110 |
-
</div>
|
111 |
-
</div>
|
112 |
-
<hr>
|
113 |
-
</li>
|
114 |
-
|
115 |
-
<li data-type="checkboxes">
|
116 |
-
<div class="bookly-flexbox">
|
117 |
-
<div class="bookly-flex-cell">
|
118 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
119 |
-
</div>
|
120 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
121 |
-
<p><b><?php _e( 'Checkbox Group', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
122 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
123 |
-
<div class="row">
|
124 |
-
<div class="col-md-8">
|
125 |
-
<div class="input-group">
|
126 |
-
<input class="ab-label form-control" type="text" value=""
|
127 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
128 |
-
<label class="input-group-addon">
|
129 |
-
<input class="ab-required" type="checkbox">
|
130 |
-
<span class="hidden-xs"><?php _e( 'Required field', 'bookly' ) ?></span>
|
131 |
-
<i class="visible-xs-inline-block glyphicon glyphicon-warning"></i>
|
132 |
-
</label>
|
133 |
-
</div>
|
134 |
-
|
135 |
-
<ul class="ab-items bookly-margin-top-sm"></ul>
|
136 |
-
<button class="btn btn-sm btn-default" data-type="checkboxes-item">
|
137 |
-
<i class="glyphicon glyphicon-plus"></i> <?php _e( 'Checkbox', 'bookly' ) ?>
|
138 |
-
</button>
|
139 |
-
</div>
|
140 |
-
<div class="col-md-4">
|
141 |
-
<?php echo $services_html ?>
|
142 |
-
</div>
|
143 |
-
</div>
|
144 |
-
</div>
|
145 |
-
</div>
|
146 |
-
<hr>
|
147 |
-
</li>
|
148 |
-
|
149 |
-
<li data-type="radio-buttons">
|
150 |
-
<div class="bookly-flexbox">
|
151 |
-
<div class="bookly-flex-cell">
|
152 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
153 |
-
</div>
|
154 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
155 |
-
<p><b><?php _e( 'Radio Button Group', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
156 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
157 |
-
<div class="row">
|
158 |
-
<div class="col-md-8">
|
159 |
-
<div class="input-group">
|
160 |
-
<input class="ab-label form-control" type="text" value=""
|
161 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
162 |
-
<label class="input-group-addon">
|
163 |
-
<input class="ab-required" type="checkbox">
|
164 |
-
<span class="hidden-xs"><?php _e( 'Required field', 'bookly' ) ?></span>
|
165 |
-
<i class="visible-xs-inline-block glyphicon glyphicon-warning"></i>
|
166 |
-
</label>
|
167 |
-
</div>
|
168 |
-
|
169 |
-
<ul class="ab-items bookly-margin-top-sm"></ul>
|
170 |
-
<button class="btn btn-sm btn-default" data-type="radio-buttons-item">
|
171 |
-
<i class="glyphicon glyphicon-plus"></i> <?php _e( 'Radio Button', 'bookly' ) ?>
|
172 |
-
</button>
|
173 |
-
</div>
|
174 |
-
<div class="col-md-4">
|
175 |
-
<?php echo $services_html ?>
|
176 |
-
</div>
|
177 |
-
</div>
|
178 |
-
</div>
|
179 |
-
</div>
|
180 |
-
<hr>
|
181 |
-
</li>
|
182 |
-
|
183 |
-
<li data-type="drop-down">
|
184 |
-
<div class="bookly-flexbox">
|
185 |
-
<div class="bookly-flex-cell">
|
186 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
187 |
-
</div>
|
188 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
189 |
-
<p><b><?php _e( 'Drop Down', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
190 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
191 |
-
<div class="row">
|
192 |
-
<div class="col-md-8">
|
193 |
-
<div class="input-group">
|
194 |
-
<input class="ab-label form-control" type="text" value=""
|
195 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
196 |
-
<label class="input-group-addon">
|
197 |
-
<input class="ab-required" type="checkbox">
|
198 |
-
<span class="hidden-xs"><?php _e( 'Required field', 'bookly' ) ?></span>
|
199 |
-
<i class="visible-xs-inline-block glyphicon glyphicon-warning"></i>
|
200 |
-
</label>
|
201 |
-
</div>
|
202 |
-
|
203 |
-
<ul class="ab-items bookly-margin-top-sm"></ul>
|
204 |
-
<button class="btn btn-sm btn-default" data-type="drop-down-item">
|
205 |
-
<i class="glyphicon glyphicon-plus"></i> <?php _e( 'Option', 'bookly' ) ?>
|
206 |
-
</button>
|
207 |
-
</div>
|
208 |
-
<div class="col-md-4">
|
209 |
-
<?php echo $services_html ?>
|
210 |
-
</div>
|
211 |
-
</div>
|
212 |
-
</div>
|
213 |
-
</div>
|
214 |
-
<hr>
|
215 |
-
</li>
|
216 |
-
|
217 |
-
<li data-type="captcha">
|
218 |
-
<div class="bookly-flexbox">
|
219 |
-
<div class="bookly-flex-cell">
|
220 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
221 |
-
</div>
|
222 |
-
<div class="bookly-flex-cell" style="width: 100%">
|
223 |
-
<p><b><?php _e( 'Captcha', 'bookly' ) ?></b><a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
224 |
-
title="<?php esc_attr_e( 'Remove field', 'bookly' ) ?>"></a></p>
|
225 |
-
<div class="row">
|
226 |
-
<div class="col-md-8">
|
227 |
-
<div class="input-group">
|
228 |
-
<input class="ab-label form-control" type="text" value=""
|
229 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
230 |
-
<label class="input-group-addon">
|
231 |
-
<input class="ab-required hidden" type="checkbox">
|
232 |
-
<input type="checkbox" disabled="disabled" checked="checked">
|
233 |
-
<span class="hidden-xs"><?php _e( 'Required field', 'bookly' ) ?></span>
|
234 |
-
<i class="visible-xs-inline-block glyphicon glyphicon-warning"></i>
|
235 |
-
</label>
|
236 |
-
</div>
|
237 |
-
</div>
|
238 |
-
<div class="col-md-4">
|
239 |
-
<?php echo $services_html ?>
|
240 |
-
</div>
|
241 |
-
</div>
|
242 |
-
</div>
|
243 |
-
</div>
|
244 |
-
<hr>
|
245 |
-
</li>
|
246 |
-
|
247 |
-
<li data-type="checkboxes-item">
|
248 |
-
<div class="bookly-flexbox">
|
249 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
250 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
251 |
-
</div>
|
252 |
-
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 100%">
|
253 |
-
<input class="form-control" type="text" value=""
|
254 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
255 |
-
</div>
|
256 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
257 |
-
<a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
258 |
-
title="<?php esc_attr_e( 'Remove item', 'bookly' ) ?>"></a>
|
259 |
-
</div>
|
260 |
-
</div>
|
261 |
-
</li>
|
262 |
-
|
263 |
-
<li data-type="radio-buttons-item">
|
264 |
-
<div class="bookly-flexbox">
|
265 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
266 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
267 |
-
</div>
|
268 |
-
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 100%">
|
269 |
-
<input class="form-control" type="text" value=""
|
270 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
271 |
-
</div>
|
272 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
273 |
-
<a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
274 |
-
title="<?php esc_attr_e( 'Remove item', 'bookly' ) ?>"></a>
|
275 |
-
</div>
|
276 |
-
</div>
|
277 |
-
</li>
|
278 |
-
|
279 |
-
<li data-type="drop-down-item">
|
280 |
-
<div class="bookly-flexbox">
|
281 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
282 |
-
<i title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>" class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"></i>
|
283 |
-
</div>
|
284 |
-
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 100%">
|
285 |
-
<input class="form-control" type="text" value=""
|
286 |
-
placeholder="<?php esc_attr_e( 'Enter a label', 'bookly' ) ?>">
|
287 |
-
</div>
|
288 |
-
<div class="bookly-flex-cell bookly-vertical-middle">
|
289 |
-
<a class="ab-delete glyphicon glyphicon-trash text-danger bookly-margin-left-sm" href="#"
|
290 |
-
title="<?php esc_attr_e( 'Remove item', 'bookly' ) ?>"></a>
|
291 |
-
</div>
|
292 |
-
</div>
|
293 |
-
</li>
|
294 |
-
</ul>
|
295 |
-
</div>
|
296 |
-
|
297 |
-
<div class="panel-footer">
|
298 |
-
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'ajax-send-custom-fields' ) ?>
|
299 |
-
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
300 |
-
</div>
|
301 |
-
</div>
|
302 |
-
</div>
|
303 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/customers/Components.php
CHANGED
@@ -15,14 +15,20 @@ class Components extends Lib\Base\Components
|
|
15 |
*/
|
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(
|
|
|
|
|
|
|
26 |
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
27 |
? array()
|
28 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) ),
|
@@ -30,12 +36,21 @@ class Components extends Lib\Base\Components
|
|
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 |
|
41 |
$this->render( '_customer_dialog' );
|
15 |
*/
|
16 |
public function renderCustomerDialog()
|
17 |
{
|
18 |
+
global $wp_locale;
|
19 |
+
|
20 |
$this->enqueueStyles( array(
|
21 |
+
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', ),
|
22 |
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
23 |
? array()
|
24 |
: array( 'css/intlTelInput.css' ),
|
25 |
) );
|
26 |
|
27 |
$this->enqueueScripts( array(
|
28 |
+
'backend' => array(
|
29 |
+
'js/angular.min.js' => array( 'jquery' ),
|
30 |
+
'js/angular-ui-date-0.0.8.js' => array( 'bookly-angular.min.js', 'jquery-ui-datepicker' ),
|
31 |
+
),
|
32 |
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
33 |
? array()
|
34 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) ),
|
36 |
) );
|
37 |
|
38 |
wp_localize_script( 'bookly-ng-customer_dialog.js', 'BooklyL10nCustDialog', array(
|
39 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
40 |
'default_status' => get_option( 'bookly_gen_default_appointment_status' ),
|
41 |
'intlTelInput' => array(
|
42 |
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
43 |
'utils' => plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
44 |
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
45 |
),
|
46 |
+
'dateOptions' => array(
|
47 |
+
'dateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_JQUERY_DATEPICKER ),
|
48 |
+
'monthNamesShort' => array_values( $wp_locale->month_abbrev ),
|
49 |
+
'monthNames' => array_values( $wp_locale->month ),
|
50 |
+
'dayNamesMin' => array_values( $wp_locale->weekday_abbrev ),
|
51 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
52 |
+
'firstDay' => (int) get_option( 'start_of_week' ),
|
53 |
+
),
|
54 |
) );
|
55 |
|
56 |
$this->render( '_customer_dialog' );
|
backend/modules/customers/Controller.php
CHANGED
@@ -33,7 +33,6 @@ class Controller extends Lib\Base\Controller
|
|
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' ),
|
@@ -45,6 +44,8 @@ class Controller extends Lib\Base\Controller
|
|
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' ) ),
|
@@ -55,7 +56,7 @@ class Controller extends Lib\Base\Controller
|
|
55 |
'create_customer' => __( 'Create customer', 'bookly' ),
|
56 |
'save' => __( 'Save', 'bookly' ),
|
57 |
'search' => __( 'Quick search customer', 'bookly' ),
|
58 |
-
'limitations' => __( '<b class="h4">This function is
|
59 |
) );
|
60 |
|
61 |
$this->render( 'index' );
|
@@ -101,7 +102,7 @@ class Controller extends Lib\Base\Controller
|
|
101 |
if ( $filter != '' ) {
|
102 |
$search_value = Lib\Query::escape( $filter );
|
103 |
$query
|
104 |
-
->whereLike( 'c.
|
105 |
->whereLike( 'c.phone', "%{$search_value}%", 'OR' )
|
106 |
->whereLike( 'c.email', "%{$search_value}%", 'OR' );
|
107 |
}
|
@@ -117,15 +118,18 @@ class Controller extends Lib\Base\Controller
|
|
117 |
foreach ( $query->fetchArray() as $row ) {
|
118 |
$data[] = array(
|
119 |
'id' => $row['id'],
|
120 |
-
'
|
|
|
|
|
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\
|
129 |
);
|
130 |
}
|
131 |
|
@@ -146,35 +150,45 @@ class Controller extends Lib\Base\Controller
|
|
146 |
$form = new Forms\Customer();
|
147 |
|
148 |
do {
|
149 |
-
if ( $this->getParameter( '
|
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'
|
161 |
-
'
|
162 |
-
'
|
163 |
-
'
|
164 |
-
'
|
165 |
-
'
|
166 |
-
'
|
167 |
-
|
168 |
-
|
169 |
-
'email' => $customer->get( 'email' ),
|
170 |
-
'notes' => $customer->get( 'notes' )
|
171 |
-
) )
|
172 |
);
|
173 |
break;
|
174 |
}
|
175 |
}
|
176 |
$response['success'] = false;
|
177 |
-
$response['errors']
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
} while ( 0 );
|
179 |
|
180 |
wp_send_json( $response );
|
@@ -186,17 +200,28 @@ class Controller extends Lib\Base\Controller
|
|
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 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
200 |
}
|
201 |
$customer->save();
|
202 |
}
|
@@ -221,15 +246,4 @@ class Controller extends Lib\Base\Controller
|
|
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 |
}
|
33 |
'backend' => array(
|
34 |
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
35 |
'js/datatables.min.js' => array( 'jquery' ),
|
|
|
36 |
),
|
37 |
'frontend' => array(
|
38 |
'js/spin.min.js' => array( 'jquery' ),
|
44 |
) );
|
45 |
|
46 |
wp_localize_script( 'bookly-customers.js', 'BooklyL10n', array(
|
47 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
48 |
+
'first_last_name' => (int) Lib\Config::showFirstLastName(),
|
49 |
'edit' => __( 'Edit', 'bookly' ),
|
50 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
51 |
'wp_users' => get_users( array( 'fields' => array( 'ID', 'display_name' ), 'orderby' => 'display_name' ) ),
|
56 |
'create_customer' => __( 'Create customer', 'bookly' ),
|
57 |
'save' => __( 'Save', 'bookly' ),
|
58 |
'search' => __( 'Quick search customer', 'bookly' ),
|
59 |
+
'limitations' => __( '<b class="h4">This function is not available in the Lite version of Bookly.</b><br><br>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', 'bookly' ) . ' <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
60 |
) );
|
61 |
|
62 |
$this->render( 'index' );
|
102 |
if ( $filter != '' ) {
|
103 |
$search_value = Lib\Query::escape( $filter );
|
104 |
$query
|
105 |
+
->whereLike( 'c.full_name', "%{$search_value}%" )
|
106 |
->whereLike( 'c.phone', "%{$search_value}%", 'OR' )
|
107 |
->whereLike( 'c.email', "%{$search_value}%", 'OR' );
|
108 |
}
|
118 |
foreach ( $query->fetchArray() as $row ) {
|
119 |
$data[] = array(
|
120 |
'id' => $row['id'],
|
121 |
+
'full_name' => $row['full_name'],
|
122 |
+
'first_name' => $row['first_name'],
|
123 |
+
'last_name' => $row['last_name'],
|
124 |
'wp_user' => $row['wp_user'],
|
125 |
'wp_user_id' => $row['wp_user_id'],
|
126 |
'phone' => $row['phone'],
|
127 |
'email' => $row['email'],
|
128 |
'notes' => $row['notes'],
|
129 |
+
'birthday' => $row['birthday'],
|
130 |
'last_appointment' => $row['last_appointment'] ? Lib\Utils\DateTime::formatDateTime( $row['last_appointment'] ) : '',
|
131 |
'total_appointments' => $row['total_appointments'],
|
132 |
+
'payments' => Lib\Utils\Price::format( $row['payments'] ),
|
133 |
);
|
134 |
}
|
135 |
|
150 |
$form = new Forms\Customer();
|
151 |
|
152 |
do {
|
153 |
+
if ( ( get_option( 'bookly_cst_first_last_name' ) && $this->getParameter( 'first_name' ) !== '' && $this->getParameter( 'last_name' ) !== '' ) || ( ! get_option( 'bookly_cst_first_last_name' ) && $this->getParameter( 'full_name' ) !== '' ) ) {
|
154 |
$params = $this->getPostParameters();
|
155 |
if ( ! $params['wp_user_id'] ) {
|
156 |
$params['wp_user_id'] = null;
|
157 |
}
|
158 |
+
if ( ! $params['birthday'] ) {
|
159 |
+
$params['birthday'] = null;
|
160 |
+
}
|
161 |
$form->bind( $params );
|
162 |
/** @var Lib\Entities\Customer $customer */
|
163 |
$customer = $form->save();
|
164 |
if ( $customer ) {
|
165 |
$response['success'] = true;
|
166 |
$response['customer'] = array(
|
167 |
+
'id' => $customer->getId(),
|
168 |
+
'wp_user_id' => $customer->getWpUserId(),
|
169 |
+
'full_name' => $customer->getFullName(),
|
170 |
+
'first_name' => $customer->getFirstName(),
|
171 |
+
'last_name' => $customer->getLastName(),
|
172 |
+
'phone' => $customer->getPhone(),
|
173 |
+
'email' => $customer->getEmail(),
|
174 |
+
'notes' => $customer->getNotes(),
|
175 |
+
'birthday' => $customer->getBirthday(),
|
|
|
|
|
|
|
176 |
);
|
177 |
break;
|
178 |
}
|
179 |
}
|
180 |
$response['success'] = false;
|
181 |
+
$response['errors'] = array();
|
182 |
+
if (get_option( 'bookly_cst_first_last_name' )) {
|
183 |
+
if ( $this->getParameter( 'first_name' ) == '' ) {
|
184 |
+
$response['errors']['first_name'] = array( 'required' );
|
185 |
+
}
|
186 |
+
if ( $this->getParameter( 'last_name' ) == '' ) {
|
187 |
+
$response['errors']['last_name'] = array( 'required' );
|
188 |
+
}
|
189 |
+
} else {
|
190 |
+
$response['errors'] = array( 'full_name' => array( 'required' ) );
|
191 |
+
}
|
192 |
} while ( 0 );
|
193 |
|
194 |
wp_send_json( $response );
|
200 |
private function importCustomers()
|
201 |
{
|
202 |
@ini_set( 'auto_detect_line_endings', true );
|
203 |
+
$fields = array();
|
204 |
+
foreach ( array( 'full_name', 'first_name', 'last_name', 'phone', 'email', 'birthday' ) as $field ) {
|
205 |
+
if ( $this->getParameter( $field ) ) {
|
206 |
+
$fields[] = $field;
|
207 |
+
}
|
208 |
+
}
|
209 |
$file = fopen( $_FILES['import_customers_file']['tmp_name'], 'r' );
|
210 |
while ( $line = fgetcsv( $file, null, $this->getParameter( 'import_customers_delimiter' ) ) ) {
|
211 |
if ( $line[0] != '' ) {
|
212 |
$customer = new Lib\Entities\Customer();
|
213 |
+
foreach ( $line as $number => $value ) {
|
214 |
+
if ( $number < count( $fields ) ) {
|
215 |
+
if ( $fields[ $number ] == 'birthday' ) {
|
216 |
+
$dob = date_create( $value );
|
217 |
+
if ( $dob !== false ) {
|
218 |
+
$customer->setBirthday( $dob->format( 'Y-m-d' ) );
|
219 |
+
}
|
220 |
+
} else {
|
221 |
+
$method = 'set' . implode( '', array_map( 'ucfirst', explode( '_', $fields[ $number ] ) ) );
|
222 |
+
$customer->$method( $value );
|
223 |
+
}
|
224 |
+
}
|
225 |
}
|
226 |
$customer->save();
|
227 |
}
|
246 |
*/
|
247 |
public function executeExportCustomers() { exit; }
|
248 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
249 |
}
|
backend/modules/customers/forms/Customer.php
CHANGED
@@ -14,11 +14,14 @@ class Customer extends Lib\Base\Form
|
|
14 |
public function configure()
|
15 |
{
|
16 |
$this->setFields( array(
|
17 |
-
'name',
|
18 |
'wp_user_id',
|
|
|
|
|
|
|
19 |
'phone',
|
20 |
'email',
|
21 |
-
'notes'
|
|
|
22 |
) );
|
23 |
}
|
24 |
|
14 |
public function configure()
|
15 |
{
|
16 |
$this->setFields( array(
|
|
|
17 |
'wp_user_id',
|
18 |
+
'full_name',
|
19 |
+
'first_name',
|
20 |
+
'last_name',
|
21 |
'phone',
|
22 |
'email',
|
23 |
+
'notes',
|
24 |
+
'birthday',
|
25 |
) );
|
26 |
}
|
27 |
|
backend/modules/customers/resources/js/customers.js
CHANGED
@@ -29,16 +29,20 @@ jQuery(function($) {
|
|
29 |
responsive: true,
|
30 |
serverSide: true,
|
31 |
ajax: {
|
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: '
|
|
|
|
|
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() },
|
@@ -73,14 +77,14 @@ jQuery(function($) {
|
|
73 |
});
|
74 |
|
75 |
/**
|
76 |
-
* Select all
|
77 |
*/
|
78 |
$check_all_button.on('change', function () {
|
79 |
$customers_list.find('tbody input:checkbox').prop('checked', this.checked);
|
80 |
});
|
81 |
|
82 |
/**
|
83 |
-
* On
|
84 |
*/
|
85 |
$customers_list.on('change', 'tbody input:checkbox', function () {
|
86 |
$check_all_button.prop('checked', $customers_list.find('tbody input:not(:checked)').length == 0);
|
@@ -94,7 +98,7 @@ jQuery(function($) {
|
|
94 |
});
|
95 |
|
96 |
/**
|
97 |
-
* New
|
98 |
*/
|
99 |
$add_button.on('click', function () {
|
100 |
row = null;
|
@@ -108,30 +112,28 @@ jQuery(function($) {
|
|
108 |
var $button = $customer_dialog.find('.modal-footer button:first');
|
109 |
var customer;
|
110 |
if (row) {
|
111 |
-
customer = row.data();
|
112 |
$title.text(BooklyL10n.edit_customer);
|
113 |
$button.text(BooklyL10n.save);
|
114 |
} else {
|
115 |
customer = {
|
116 |
id : '',
|
117 |
wp_user_id : '',
|
118 |
-
|
|
|
|
|
119 |
phone : '',
|
120 |
email : '',
|
121 |
-
notes : ''
|
|
|
122 |
};
|
123 |
$title.text(BooklyL10n.new_customer);
|
124 |
-
$button.text(BooklyL10n.
|
125 |
}
|
126 |
|
127 |
var $scope = angular.element(this).scope();
|
128 |
$scope.$apply(function ($scope) {
|
129 |
-
$scope.customer
|
130 |
-
$scope.customer.wp_user_id = customer.wp_user_id;
|
131 |
-
$scope.customer.name = customer.name;
|
132 |
-
$scope.customer.phone = customer.phone;
|
133 |
-
$scope.customer.email = customer.email;
|
134 |
-
$scope.customer.notes = customer.notes;
|
135 |
setTimeout(function() {
|
136 |
$customer_dialog.find('#phone').intlTelInput('setNumber', customer.phone);
|
137 |
}, 0);
|
@@ -142,7 +144,7 @@ jQuery(function($) {
|
|
142 |
* Delete customers.
|
143 |
*/
|
144 |
$delete_button.on('click', function () {
|
145 |
-
if (
|
146 |
$delete_dialog.modal('show');
|
147 |
} else {
|
148 |
deleteCustomers(this, remembered_choice);
|
@@ -178,8 +180,9 @@ jQuery(function($) {
|
|
178 |
type : 'POST',
|
179 |
data : {
|
180 |
action : 'bookly_delete_customers',
|
|
|
181 |
data : data,
|
182 |
-
with_wp_user : with_wp_user
|
183 |
},
|
184 |
dataType : 'json',
|
185 |
success : function(response) {
|
@@ -210,10 +213,13 @@ jQuery(function($) {
|
|
210 |
$scope.customer = {
|
211 |
id : '',
|
212 |
wp_user_id : '',
|
213 |
-
|
|
|
|
|
214 |
phone : '',
|
215 |
email : '',
|
216 |
-
notes : ''
|
|
|
217 |
};
|
218 |
$scope.saveCustomer = function(customer) {
|
219 |
jQuery('#bookly-customers-list').DataTable().ajax.reload(null, false);
|
29 |
responsive: true,
|
30 |
serverSide: true,
|
31 |
ajax: {
|
32 |
+
url : ajaxurl,
|
33 |
+
type: 'POST',
|
34 |
data: function (d) {
|
35 |
return $.extend({}, d, {
|
36 |
action: 'bookly_get_customers',
|
37 |
+
csrf_token : BooklyL10n.csrf_token,
|
38 |
filter: $filter.val()
|
39 |
});
|
40 |
}
|
41 |
},
|
42 |
columns: [
|
43 |
+
{ data: 'full_name', render: $.fn.dataTable.render.text(), visible: BooklyL10n.first_last_name == 0 },
|
44 |
+
{ data: 'first_name', render: $.fn.dataTable.render.text(), visible: BooklyL10n.first_last_name == 1 },
|
45 |
+
{ data: 'last_name', render: $.fn.dataTable.render.text(), visible: BooklyL10n.first_last_name == 1 },
|
46 |
{ data: 'wp_user', render: $.fn.dataTable.render.text() },
|
47 |
{ data: 'phone', render: $.fn.dataTable.render.text() },
|
48 |
{ data: 'email', render: $.fn.dataTable.render.text() },
|
77 |
});
|
78 |
|
79 |
/**
|
80 |
+
* Select all customers.
|
81 |
*/
|
82 |
$check_all_button.on('change', function () {
|
83 |
$customers_list.find('tbody input:checkbox').prop('checked', this.checked);
|
84 |
});
|
85 |
|
86 |
/**
|
87 |
+
* On customer select.
|
88 |
*/
|
89 |
$customers_list.on('change', 'tbody input:checkbox', function () {
|
90 |
$check_all_button.prop('checked', $customers_list.find('tbody input:not(:checked)').length == 0);
|
98 |
});
|
99 |
|
100 |
/**
|
101 |
+
* New customer.
|
102 |
*/
|
103 |
$add_button.on('click', function () {
|
104 |
row = null;
|
112 |
var $button = $customer_dialog.find('.modal-footer button:first');
|
113 |
var customer;
|
114 |
if (row) {
|
115 |
+
customer = $.extend({}, row.data());
|
116 |
$title.text(BooklyL10n.edit_customer);
|
117 |
$button.text(BooklyL10n.save);
|
118 |
} else {
|
119 |
customer = {
|
120 |
id : '',
|
121 |
wp_user_id : '',
|
122 |
+
full_name : '',
|
123 |
+
first_name : '',
|
124 |
+
last_name : '',
|
125 |
phone : '',
|
126 |
email : '',
|
127 |
+
notes : '',
|
128 |
+
birthday : ''
|
129 |
};
|
130 |
$title.text(BooklyL10n.new_customer);
|
131 |
+
$button.text(BooklyL10n.create_customer);
|
132 |
}
|
133 |
|
134 |
var $scope = angular.element(this).scope();
|
135 |
$scope.$apply(function ($scope) {
|
136 |
+
$scope.customer = customer;
|
|
|
|
|
|
|
|
|
|
|
137 |
setTimeout(function() {
|
138 |
$customer_dialog.find('#phone').intlTelInput('setNumber', customer.phone);
|
139 |
}, 0);
|
144 |
* Delete customers.
|
145 |
*/
|
146 |
$delete_button.on('click', function () {
|
147 |
+
if (remembered_choice === undefined) {
|
148 |
$delete_dialog.modal('show');
|
149 |
} else {
|
150 |
deleteCustomers(this, remembered_choice);
|
180 |
type : 'POST',
|
181 |
data : {
|
182 |
action : 'bookly_delete_customers',
|
183 |
+
csrf_token : BooklyL10n.csrf_token,
|
184 |
data : data,
|
185 |
+
with_wp_user : with_wp_user ? 1 : 0
|
186 |
},
|
187 |
dataType : 'json',
|
188 |
success : function(response) {
|
213 |
$scope.customer = {
|
214 |
id : '',
|
215 |
wp_user_id : '',
|
216 |
+
full_name : '',
|
217 |
+
first_name : '',
|
218 |
+
last_name : '',
|
219 |
phone : '',
|
220 |
email : '',
|
221 |
+
notes : '',
|
222 |
+
birthday : ''
|
223 |
};
|
224 |
$scope.saveCustomer = function(customer) {
|
225 |
jQuery('#bookly-customers-list').DataTable().ajax.reload(null, false);
|
backend/modules/customers/resources/js/ng-customer_dialog.js
CHANGED
@@ -1,68 +1,65 @@
|
|
1 |
;(function() {
|
2 |
|
3 |
-
angular.module('customerDialog', []).directive('customerDialog', function() {
|
4 |
return {
|
5 |
restrict : 'A',
|
6 |
replace : true,
|
7 |
scope : {
|
8 |
-
callback
|
9 |
-
form
|
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 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
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 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
.on('hidden.bs.modal', function () {
|
50 |
-
if (jQuery('#bookly-appointment-dialog').length) {
|
51 |
-
jQuery('body').addClass('modal-open');
|
52 |
-
}
|
53 |
-
});
|
54 |
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
55 |
|
56 |
-
//
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
-
//
|
60 |
-
|
61 |
-
//
|
62 |
-
jQuery('
|
63 |
-
|
64 |
-
|
65 |
-
};
|
66 |
|
67 |
/**
|
68 |
* Send form to server.
|
@@ -76,7 +73,7 @@
|
|
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) {
|
@@ -89,13 +86,16 @@
|
|
89 |
scope.form = {
|
90 |
id : '',
|
91 |
wp_user_id : '',
|
92 |
-
|
|
|
|
|
93 |
phone : '',
|
94 |
email : '',
|
95 |
-
notes : ''
|
|
|
96 |
};
|
97 |
// Close the dialog.
|
98 |
-
|
99 |
} else {
|
100 |
// Set errors.
|
101 |
jQuery.each(response.errors, function(field, errors) {
|
@@ -115,6 +115,11 @@
|
|
115 |
}
|
116 |
});
|
117 |
};
|
|
|
|
|
|
|
|
|
|
|
118 |
}
|
119 |
};
|
120 |
});
|
1 |
;(function() {
|
2 |
|
3 |
+
angular.module('customerDialog', ['ui.date']).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 |
+
// Form fields.
|
16 |
+
if (!scope.form) {
|
17 |
+
scope.form = {
|
18 |
+
id : '',
|
19 |
+
wp_user_id : '',
|
20 |
+
full_name : '',
|
21 |
+
first_name : '',
|
22 |
+
last_name : '',
|
23 |
+
phone : '',
|
24 |
+
email : '',
|
25 |
+
notes : '',
|
26 |
+
birthday : ''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
27 |
};
|
28 |
+
}
|
29 |
+
// Form errors.
|
30 |
+
scope.errors = {
|
31 |
+
name: {required: false}
|
|
|
|
|
|
|
|
|
|
|
32 |
};
|
33 |
+
scope.$watch('form', function(newValue, oldValue) {
|
34 |
+
if (newValue.name) {
|
35 |
+
scope.errors.name.required = false;
|
36 |
+
}
|
37 |
+
});
|
38 |
+
// Loading indicator.
|
39 |
+
scope.loading = false;
|
40 |
|
41 |
+
// Init intlTelInput.
|
42 |
+
if (BooklyL10nCustDialog.intlTelInput.enabled) {
|
43 |
+
element.find('#phone').intlTelInput({
|
44 |
+
preferredCountries: [BooklyL10nCustDialog.intlTelInput.country],
|
45 |
+
initialCountry: BooklyL10nCustDialog.intlTelInput.country,
|
46 |
+
geoIpLookup: function (callback) {
|
47 |
+
jQuery.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
48 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
49 |
+
callback(countryCode);
|
50 |
+
});
|
51 |
+
},
|
52 |
+
utilsScript: BooklyL10nCustDialog.intlTelInput.utils
|
53 |
+
});
|
54 |
+
}
|
55 |
|
56 |
+
// Do stuff on modal hide.
|
57 |
+
element.on('hidden.bs.modal', function () {
|
58 |
+
// Fix scroll issues when another modal is shown.
|
59 |
+
if (jQuery('.modal-backdrop').length) {
|
60 |
+
jQuery('body').addClass('modal-open');
|
61 |
+
}
|
62 |
+
});
|
63 |
|
64 |
/**
|
65 |
* Send form to server.
|
73 |
jQuery.ajax({
|
74 |
url : ajaxurl,
|
75 |
type : 'POST',
|
76 |
+
data : jQuery.extend({ action : 'bookly_save_customer', csrf_token : BooklyL10nCustDialog.csrf_token }, scope.form),
|
77 |
dataType : 'json',
|
78 |
success : function ( response ) {
|
79 |
scope.$apply(function(scope) {
|
86 |
scope.form = {
|
87 |
id : '',
|
88 |
wp_user_id : '',
|
89 |
+
full_name : '',
|
90 |
+
first_name : '',
|
91 |
+
last_name : '',
|
92 |
phone : '',
|
93 |
email : '',
|
94 |
+
notes : '',
|
95 |
+
birthday : ''
|
96 |
};
|
97 |
// Close the dialog.
|
98 |
+
element.modal('hide');
|
99 |
} else {
|
100 |
// Set errors.
|
101 |
jQuery.each(response.errors, function(field, errors) {
|
115 |
}
|
116 |
});
|
117 |
};
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Datepicker options.
|
121 |
+
*/
|
122 |
+
scope.dateOptions = BooklyL10nCustDialog.dateOptions;
|
123 |
}
|
124 |
};
|
125 |
});
|
backend/modules/customers/templates/_customer_dialog.php
CHANGED
@@ -1,4 +1,7 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
|
|
2 |
<script type="text/ng-template" id="bookly-customer-dialog.tpl">
|
3 |
<div id="bookly-customer-dialog" class="modal fade" tabindex=-1 role="dialog">
|
4 |
<div class="modal-dialog">
|
@@ -23,31 +26,54 @@
|
|
23 |
</select>
|
24 |
</div>
|
25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
<div class="form-group">
|
27 |
-
<label for="
|
28 |
-
<input class="form-control" type="text" ng-model="form.
|
29 |
-
<span style="font-size: 11px;color: red" ng-show="errors.
|
30 |
</div>
|
|
|
31 |
|
32 |
<div class="form-group">
|
33 |
<label for="phone"><?php _e( 'Phone', 'bookly' ) ?></label>
|
34 |
-
<input class="form-control" type="text" ng-model=form.phone id="phone"
|
35 |
</div>
|
36 |
|
37 |
<div class="form-group">
|
38 |
<label for="email"><?php _e( 'Email', 'bookly' ) ?></label>
|
39 |
-
<input class="form-control" type="text" ng-model=form.email id="email"
|
40 |
</div>
|
41 |
|
42 |
<div class="form-group">
|
43 |
<label for="notes"><?php _e( 'Notes', 'bookly' ) ?></label>
|
44 |
<textarea class="form-control" ng-model=form.notes id="notes"></textarea>
|
45 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
</div>
|
47 |
<div class="modal-footer">
|
48 |
<div ng-hide=loading>
|
49 |
-
<?php
|
50 |
-
<?php
|
51 |
</div>
|
52 |
</div>
|
53 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Common;
|
3 |
+
use BooklyLite\Lib\Config;
|
4 |
+
?>
|
5 |
<script type="text/ng-template" id="bookly-customer-dialog.tpl">
|
6 |
<div id="bookly-customer-dialog" class="modal fade" tabindex=-1 role="dialog">
|
7 |
<div class="modal-dialog">
|
26 |
</select>
|
27 |
</div>
|
28 |
|
29 |
+
<?php if ( Config::showFirstLastName() ) : ?>
|
30 |
+
<div class="form-group">
|
31 |
+
<div class="row">
|
32 |
+
<div class="col-sm-6">
|
33 |
+
<label for="first_name"><?php _e( 'First name', 'bookly' ) ?></label>
|
34 |
+
<input class="form-control" type="text" ng-model="form.first_name" id="first_name" />
|
35 |
+
<span style="font-size: 11px;color: red" ng-show="errors.first_name.required"><?php _e( 'Required', 'bookly' ) ?></span>
|
36 |
+
</div>
|
37 |
+
<div class="col-sm-6">
|
38 |
+
<label for="last_name"><?php _e( 'Last name', 'bookly' ) ?></label>
|
39 |
+
<input class="form-control" type="text" ng-model="form.last_name" id="last_name" />
|
40 |
+
<span style="font-size: 11px;color: red" ng-show="errors.last_name.required"><?php _e( 'Required', 'bookly' ) ?></span>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
<?php else : ?>
|
45 |
<div class="form-group">
|
46 |
+
<label for="full_name"><?php _e( 'Name', 'bookly' ) ?></label>
|
47 |
+
<input class="form-control" type="text" ng-model="form.full_name" id="full_name" />
|
48 |
+
<span style="font-size: 11px;color: red" ng-show="errors.full_name.required"><?php _e( 'Required', 'bookly' ) ?></span>
|
49 |
</div>
|
50 |
+
<?php endif ?>
|
51 |
|
52 |
<div class="form-group">
|
53 |
<label for="phone"><?php _e( 'Phone', 'bookly' ) ?></label>
|
54 |
+
<input class="form-control" type="text" ng-model=form.phone id="phone" />
|
55 |
</div>
|
56 |
|
57 |
<div class="form-group">
|
58 |
<label for="email"><?php _e( 'Email', 'bookly' ) ?></label>
|
59 |
+
<input class="form-control" type="text" ng-model=form.email id="email" />
|
60 |
</div>
|
61 |
|
62 |
<div class="form-group">
|
63 |
<label for="notes"><?php _e( 'Notes', 'bookly' ) ?></label>
|
64 |
<textarea class="form-control" ng-model=form.notes id="notes"></textarea>
|
65 |
</div>
|
66 |
+
|
67 |
+
<div class="form-group">
|
68 |
+
<label for="birthday"><?php _e( 'Date of birth', 'bookly' ) ?></label>
|
69 |
+
<input class="form-control" type="text" ng-model=form.birthday id="birthday"
|
70 |
+
ui-date="dateOptions" ui-date-format="yy-mm-dd" autocomplete="off" />
|
71 |
+
</div>
|
72 |
</div>
|
73 |
<div class="modal-footer">
|
74 |
<div ng-hide=loading>
|
75 |
+
<?php Common::customButton( null, 'btn-success btn-lg', '', array( 'ng-click' => 'processForm()' ) ) ?>
|
76 |
+
<?php Common::customButton( null, 'btn-default btn-lg', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
77 |
</div>
|
78 |
</div>
|
79 |
</div>
|
backend/modules/customers/templates/_import.php
CHANGED
@@ -10,12 +10,20 @@
|
|
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.
|
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">
|
@@ -26,7 +34,7 @@
|
|
26 |
<input type="hidden" name="import">
|
27 |
</div>
|
28 |
<div class="modal-footer">
|
29 |
-
<button type="submit" class="btn btn-lg btn-success
|
30 |
<?php _e( 'Import', 'bookly' ) ?>
|
31 |
</button>
|
32 |
</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. You can choose the columns contained in your file. The sequence of columns should coincide with the specified one.', '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 |
+
<div class="checkbox"><label><input checked name="full_name" type="checkbox"> <?php echo esc_html( get_option( 'bookly_l10n_label_name' ) ) ?></label></div>
|
21 |
+
<div class="checkbox"><label><input name="first_name" type="checkbox"> <?php echo esc_html( get_option( 'bookly_l10n_label_first_name' ) ) ?></label></div>
|
22 |
+
<div class="checkbox"><label><input name="last_name" type="checkbox"> <?php echo esc_html( get_option( 'bookly_l10n_label_last_name' ) ) ?></label></div>
|
23 |
+
<div class="checkbox"><label><input checked name="phone" type="checkbox"><?php echo esc_html( get_option( 'bookly_l10n_label_phone' ) ) ?></label></div>
|
24 |
+
<div class="checkbox"><label><input checked name="email" type="checkbox"><?php echo esc_html( get_option( 'bookly_l10n_label_email' ) ) ?></label></div>
|
25 |
+
<div class="checkbox"><label><input checked name="birthday" type="checkbox"><?php _e( 'Date of birth', 'bookly' ) ?></label></div>
|
26 |
+
</div>
|
27 |
<div class="form-group">
|
28 |
<label for="import_customers_delimiter"><?php _e( 'Delimiter', 'bookly' ) ?></label>
|
29 |
<select name="import_customers_delimiter" id="import_customers_delimiter" class="form-control">
|
34 |
<input type="hidden" name="import">
|
35 |
</div>
|
36 |
<div class="modal-footer">
|
37 |
+
<button type="submit" class="btn btn-lg btn-success" name="import-customers">
|
38 |
<?php _e( 'Import', 'bookly' ) ?>
|
39 |
</button>
|
40 |
</div>
|
backend/modules/customers/templates/index.php
CHANGED
@@ -31,10 +31,12 @@
|
|
31 |
<table id="bookly-customers-list" class="table table-striped" width="100%">
|
32 |
<thead>
|
33 |
<tr>
|
34 |
-
<th><?php echo
|
|
|
|
|
35 |
<th><?php _e( 'User', 'bookly' ) ?></th>
|
36 |
-
<th><?php echo
|
37 |
-
<th><?php echo
|
38 |
<th><?php _e( 'Notes', 'bookly' ) ?></th>
|
39 |
<th><?php _e( 'Last appointment', 'bookly' ) ?></th>
|
40 |
<th><?php _e( 'Total appointments', 'bookly' ) ?></th>
|
@@ -52,7 +54,6 @@
|
|
52 |
</div>
|
53 |
|
54 |
<?php include '_import.php' ?>
|
55 |
-
<?php include '_export.php' ?>
|
56 |
|
57 |
<div id="bookly-delete-dialog" class="modal fade" tabindex=-1 role="dialog">
|
58 |
<div class="modal-dialog">
|
31 |
<table id="bookly-customers-list" class="table table-striped" width="100%">
|
32 |
<thead>
|
33 |
<tr>
|
34 |
+
<th><?php echo esc_html( get_option( 'bookly_l10n_label_name' ) ) ?></th>
|
35 |
+
<th><?php echo esc_html( get_option( 'bookly_l10n_label_first_name' ) ) ?></th>
|
36 |
+
<th><?php echo esc_html( get_option( 'bookly_l10n_label_last_name' ) ) ?></th>
|
37 |
<th><?php _e( 'User', 'bookly' ) ?></th>
|
38 |
+
<th><?php echo esc_html( get_option( 'bookly_l10n_label_phone' ) ) ?></th>
|
39 |
+
<th><?php echo esc_html( get_option( 'bookly_l10n_label_email' ) ) ?></th>
|
40 |
<th><?php _e( 'Notes', 'bookly' ) ?></th>
|
41 |
<th><?php _e( 'Last appointment', 'bookly' ) ?></th>
|
42 |
<th><?php _e( 'Total appointments', 'bookly' ) ?></th>
|
54 |
</div>
|
55 |
|
56 |
<?php include '_import.php' ?>
|
|
|
57 |
|
58 |
<div id="bookly-delete-dialog" class="modal fade" tabindex=-1 role="dialog">
|
59 |
<div class="modal-dialog">
|
backend/modules/debug/Controller.php
CHANGED
@@ -86,19 +86,16 @@ class Controller extends Lib\Base\Controller
|
|
86 |
global $wpdb;
|
87 |
|
88 |
$result = array();
|
|
|
89 |
|
90 |
-
|
91 |
-
/** @var Lib\Base\Installer $installer */
|
92 |
-
$installer = new $installer_class();
|
93 |
-
|
94 |
-
foreach ( Lib\Plugin::getEntityClasses() as $entity_class ) {
|
95 |
$table_name = $entity_class::getTableName();
|
96 |
$result['entities'][ $entity_class ] = array(
|
97 |
'fields' => $this->_getTableStructure( $table_name ),
|
98 |
'values' => $wpdb->get_results( 'SELECT * FROM ' . $table_name, ARRAY_N )
|
99 |
);
|
100 |
}
|
101 |
-
$plugin_prefix =
|
102 |
$options_postfix = array( 'data_loaded', 'grace_start', 'db_version', 'installation_time' );
|
103 |
if ( $plugin_prefix != 'bookly_' ) {
|
104 |
$options_postfix[] = 'enabled';
|
@@ -108,7 +105,7 @@ class Controller extends Lib\Base\Controller
|
|
108 |
$result['options'][ $option_name ] = get_option( $option_name );
|
109 |
}
|
110 |
|
111 |
-
$result['options'][
|
112 |
foreach ( $installer->getOptions() as $option_name => $option_value ) {
|
113 |
$result['options'][ $option_name ] = get_option( $option_name );
|
114 |
}
|
@@ -130,14 +127,12 @@ class Controller extends Lib\Base\Controller
|
|
130 |
|
131 |
if ( $file = $_FILES['import']['name'] ) {
|
132 |
$json = file_get_contents( $_FILES['import']['tmp_name'] );
|
133 |
-
if ( $json !== false
|
134 |
$wpdb->query( 'SET FOREIGN_KEY_CHECKS = 0' );
|
135 |
|
136 |
$data = json_decode( $json, true );
|
137 |
|
138 |
-
$
|
139 |
-
/** @var Lib\Base\Installer $installer */
|
140 |
-
$installer = new $installer_class();
|
141 |
|
142 |
// Drop all data and options.
|
143 |
$installer->removeData();
|
@@ -147,8 +142,8 @@ class Controller extends Lib\Base\Controller
|
|
147 |
// Insert tables data.
|
148 |
foreach ( Lib\Plugin::getEntityClasses() as $entity_class ) {
|
149 |
if ( isset ( $data['entities'][ $entity_class ]['values'][0] ) ) {
|
150 |
-
$table_name
|
151 |
-
$query
|
152 |
'INSERT INTO `%s` (`%s`) VALUES (%%s)',
|
153 |
$table_name,
|
154 |
implode( '`,`', $data['entities'][ $entity_class ]['fields'] )
|
@@ -195,9 +190,9 @@ class Controller extends Lib\Base\Controller
|
|
195 |
$option_name = $plugin_prefix . $option;
|
196 |
add_option( $option_name, $data['options'][ $option_name ] );
|
197 |
}
|
198 |
-
}
|
199 |
|
200 |
-
|
|
|
201 |
}
|
202 |
|
203 |
header( 'Location: ' . admin_url( 'admin.php?page=bookly-debug' ) );
|
@@ -276,18 +271,4 @@ class Controller extends Lib\Base\Controller
|
|
276 |
|
277 |
return $wpdb->query( 'SHOW TABLES LIKE "' . $tableName . '"' );
|
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 |
}
|
86 |
global $wpdb;
|
87 |
|
88 |
$result = array();
|
89 |
+
$installer = new Lib\Installer();
|
90 |
|
91 |
+
foreach ( Lib\Plugin::getEntityClasses() as $entity_class ) {
|
|
|
|
|
|
|
|
|
92 |
$table_name = $entity_class::getTableName();
|
93 |
$result['entities'][ $entity_class ] = array(
|
94 |
'fields' => $this->_getTableStructure( $table_name ),
|
95 |
'values' => $wpdb->get_results( 'SELECT * FROM ' . $table_name, ARRAY_N )
|
96 |
);
|
97 |
}
|
98 |
+
$plugin_prefix = Lib\Plugin::getPrefix();
|
99 |
$options_postfix = array( 'data_loaded', 'grace_start', 'db_version', 'installation_time' );
|
100 |
if ( $plugin_prefix != 'bookly_' ) {
|
101 |
$options_postfix[] = 'enabled';
|
105 |
$result['options'][ $option_name ] = get_option( $option_name );
|
106 |
}
|
107 |
|
108 |
+
$result['options'][ Lib\Plugin::getPurchaseCodeOption() ] = Lib\Plugin::getPurchaseCode();
|
109 |
foreach ( $installer->getOptions() as $option_name => $option_value ) {
|
110 |
$result['options'][ $option_name ] = get_option( $option_name );
|
111 |
}
|
127 |
|
128 |
if ( $file = $_FILES['import']['name'] ) {
|
129 |
$json = file_get_contents( $_FILES['import']['tmp_name'] );
|
130 |
+
if ( $json !== false) {
|
131 |
$wpdb->query( 'SET FOREIGN_KEY_CHECKS = 0' );
|
132 |
|
133 |
$data = json_decode( $json, true );
|
134 |
|
135 |
+
$installer = new Lib\Installer();
|
|
|
|
|
136 |
|
137 |
// Drop all data and options.
|
138 |
$installer->removeData();
|
142 |
// Insert tables data.
|
143 |
foreach ( Lib\Plugin::getEntityClasses() as $entity_class ) {
|
144 |
if ( isset ( $data['entities'][ $entity_class ]['values'][0] ) ) {
|
145 |
+
$table_name = $entity_class::getTableName();
|
146 |
+
$query = sprintf(
|
147 |
'INSERT INTO `%s` (`%s`) VALUES (%%s)',
|
148 |
$table_name,
|
149 |
implode( '`,`', $data['entities'][ $entity_class ]['fields'] )
|
190 |
$option_name = $plugin_prefix . $option;
|
191 |
add_option( $option_name, $data['options'][ $option_name ] );
|
192 |
}
|
|
|
193 |
|
194 |
+
header( 'Location: ' . admin_url( 'admin.php?page=bookly-debug&status=imported' ) );
|
195 |
+
}
|
196 |
}
|
197 |
|
198 |
header( 'Location: ' . admin_url( 'admin.php?page=bookly-debug' ) );
|
271 |
|
272 |
return $wpdb->query( 'SHOW TABLES LIKE "' . $tableName . '"' );
|
273 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
}
|
backend/modules/debug/templates/index.php
CHANGED
@@ -15,6 +15,7 @@
|
|
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>
|
@@ -22,6 +23,7 @@
|
|
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">
|
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 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
19 |
<button id="bookly-export" type="submit" class="btn btn-lg btn-success">
|
20 |
<span class="ladda-label">Export data</span>
|
21 |
</button>
|
23 |
</div>
|
24 |
<div class="bookly-data-button">
|
25 |
<form id="bookly_import" action="<?php echo admin_url( 'admin-ajax.php?action=bookly_import_data' ) ?>" method="POST" enctype="multipart/form-data">
|
26 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
27 |
<div id="bookly-import" class="btn btn-lg btn-primary btn-file">
|
28 |
<span class="ladda-label">Import data</span>
|
29 |
<input type="file" id="bookly_import_file" name="import">
|
backend/modules/message/Controller.php
ADDED
@@ -0,0 +1,100 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Message;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Controller
|
8 |
+
* @package BooklyLite\Backend\Modules\Message
|
9 |
+
*/
|
10 |
+
class Controller extends Lib\Base\Controller
|
11 |
+
{
|
12 |
+
const page_slug = 'bookly-messages';
|
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 |
+
) );
|
22 |
+
|
23 |
+
$this->enqueueScripts( array(
|
24 |
+
'backend' => array(
|
25 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
26 |
+
'js/datatables.min.js' => array( 'jquery' ),
|
27 |
+
),
|
28 |
+
'module' => array( 'js/message.js' => array( 'jquery' ) ),
|
29 |
+
) );
|
30 |
+
|
31 |
+
wp_localize_script( 'bookly-message.js', 'BooklyL10n', array(
|
32 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
33 |
+
'datatable' => array(
|
34 |
+
'zeroRecords' => __( 'No records.', 'bookly' ),
|
35 |
+
'processing' => __( 'Processing...', 'bookly' ),
|
36 |
+
'per_page' => __( 'messages', 'bookly' ),
|
37 |
+
'paginate' => array(
|
38 |
+
'first' => __( 'First', 'bookly' ),
|
39 |
+
'previous' => __( 'Previous', 'bookly' ),
|
40 |
+
'next' => __( 'Next', 'bookly' ),
|
41 |
+
'last' => __( 'Last', 'bookly' ),
|
42 |
+
)
|
43 |
+
)
|
44 |
+
) );
|
45 |
+
$this->render( 'index' );
|
46 |
+
}
|
47 |
+
|
48 |
+
/**
|
49 |
+
* Get messages
|
50 |
+
*/
|
51 |
+
public function executeGetMessages()
|
52 |
+
{
|
53 |
+
$query = Lib\Entities\Message::query( 'm' );
|
54 |
+
$total = $query->count();
|
55 |
+
|
56 |
+
$query->select( 'm.created, m.subject, m.seen, m.body, m.message_id' )
|
57 |
+
->sortBy( 'm.seen, m.message_id' )->order( 'DESC' );
|
58 |
+
|
59 |
+
$query->limit( $this->getParameter( 'length' ) )->offset( $this->getParameter( 'start' ) );
|
60 |
+
|
61 |
+
$data = $query->fetchArray();
|
62 |
+
foreach ( $data as &$row ) {
|
63 |
+
$row['created'] = Lib\Utils\DateTime::formatDateTime( $row['created'] );
|
64 |
+
}
|
65 |
+
|
66 |
+
wp_send_json( array(
|
67 |
+
'draw' => ( int ) $this->getParameter( 'draw' ),
|
68 |
+
'recordsTotal' => $total,
|
69 |
+
'recordsFiltered' => count( $data ),
|
70 |
+
'data' => $data,
|
71 |
+
) );
|
72 |
+
}
|
73 |
+
|
74 |
+
/**
|
75 |
+
* Mark all messages was read
|
76 |
+
*/
|
77 |
+
public function executeMarkReadAllMessages()
|
78 |
+
{
|
79 |
+
$messages = Lib\Entities\Message::query( 'm' )->select( 'm.message_id' )->whereNot( 'm.seen', 1 )->fetchArray();
|
80 |
+
$message_ids = array();
|
81 |
+
foreach ( $messages as $message ) {
|
82 |
+
$message_ids[] = $message['message_id'];
|
83 |
+
}
|
84 |
+
|
85 |
+
if ( $message_ids ) {
|
86 |
+
Lib\API::seenMessages( $message_ids );
|
87 |
+
}
|
88 |
+
wp_send_json_success();
|
89 |
+
}
|
90 |
+
|
91 |
+
/**
|
92 |
+
* Mark some massages was read
|
93 |
+
*/
|
94 |
+
public function executeMarkReadMessages()
|
95 |
+
{
|
96 |
+
Lib\API::seenMessages( (array) $this->getParameter( 'message_ids' ) );
|
97 |
+
wp_send_json_success();
|
98 |
+
}
|
99 |
+
|
100 |
+
}
|
backend/modules/message/resources/js/message.js
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function($) {
|
2 |
+
|
3 |
+
var $message_list = $('#bookly-messages-list');
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Init DataTables.
|
7 |
+
*/
|
8 |
+
var dt = $message_list.DataTable({
|
9 |
+
paging: true,
|
10 |
+
ordering: false,
|
11 |
+
info: false,
|
12 |
+
searching: false,
|
13 |
+
processing: true,
|
14 |
+
responsive: true,
|
15 |
+
ajax: {
|
16 |
+
url: ajaxurl,
|
17 |
+
data: { action: 'bookly_get_messages', csrf_token : BooklyL10n.csrf_token }
|
18 |
+
},
|
19 |
+
fnFooterCallback: function( nFoot, aData, iStart, iEnd, aiDisplay ) {
|
20 |
+
var message_ids =[];
|
21 |
+
for (var i = iStart; i < iEnd; i++) {
|
22 |
+
if (aData[i].seen == 0) {
|
23 |
+
// Add new messages
|
24 |
+
message_ids.push(aData[i].message_id)
|
25 |
+
}
|
26 |
+
}
|
27 |
+
if (message_ids.length > 0) {
|
28 |
+
$.ajax({
|
29 |
+
url : ajaxurl,
|
30 |
+
type : 'POST',
|
31 |
+
data : {
|
32 |
+
action : 'bookly_mark_read_messages',
|
33 |
+
message_ids: message_ids,
|
34 |
+
csrf_token : BooklyL10n.csrf_token
|
35 |
+
},
|
36 |
+
dataType : 'json',
|
37 |
+
success : function (response) {
|
38 |
+
if (response.success) {
|
39 |
+
|
40 |
+
}
|
41 |
+
}
|
42 |
+
});
|
43 |
+
}
|
44 |
+
},
|
45 |
+
columns: [
|
46 |
+
{ data: 'created' },
|
47 |
+
{
|
48 |
+
data: 'subject',
|
49 |
+
render: function (data, type, row, meta) {
|
50 |
+
if (row.seen != 1) {
|
51 |
+
return '<b>' + data + '</b>';
|
52 |
+
}
|
53 |
+
return data;
|
54 |
+
}
|
55 |
+
},
|
56 |
+
{ data: 'body' }
|
57 |
+
],
|
58 |
+
language: {
|
59 |
+
zeroRecords: BooklyL10n.datatable.zeroRecords,
|
60 |
+
processing: BooklyL10n.datatable.processing,
|
61 |
+
sLengthMenu: '_MENU_ ' + BooklyL10n.datatable.per_page,
|
62 |
+
paginate: {
|
63 |
+
first: BooklyL10n.datatable.paginate.first,
|
64 |
+
previous: BooklyL10n.datatable.paginate.previous,
|
65 |
+
next: BooklyL10n.datatable.paginate.next,
|
66 |
+
last: BooklyL10n.datatable.paginate.last
|
67 |
+
}
|
68 |
+
}
|
69 |
+
});
|
70 |
+
|
71 |
+
});
|
backend/modules/message/templates/index.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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( 'Messages', '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 |
+
<table id="bookly-messages-list" class="table table-striped" width="100%">
|
13 |
+
<thead>
|
14 |
+
<tr>
|
15 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
16 |
+
<th><?php _e( 'Subject', 'bookly' ) ?></th>
|
17 |
+
<th><?php _e( 'Message', 'bookly' ) ?></th>
|
18 |
+
</tr>
|
19 |
+
</thead>
|
20 |
+
</table>
|
21 |
+
</div>
|
22 |
+
</div>
|
23 |
+
</div>
|
24 |
+
</div>
|
backend/modules/notifications/Components.php
ADDED
@@ -0,0 +1,357 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Notifications;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
use BooklyLite\Lib\Entities\Notification;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Components
|
9 |
+
* @package BooklyLite\Backend\Modules\Notifications
|
10 |
+
*/
|
11 |
+
class Components extends Lib\Base\Components
|
12 |
+
{
|
13 |
+
protected $css_prefix = 'bookly-js-codes-';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Codes for all notifications.
|
17 |
+
*
|
18 |
+
* @return array
|
19 |
+
*/
|
20 |
+
private function getCommonCodes()
|
21 |
+
{
|
22 |
+
return array(
|
23 |
+
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
24 |
+
array( 'code' => 'company_logo', 'description' => __( 'company logo', 'bookly' ) ),
|
25 |
+
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
26 |
+
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
27 |
+
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
28 |
+
);
|
29 |
+
}
|
30 |
+
|
31 |
+
/**
|
32 |
+
* Render codes for notifications
|
33 |
+
*
|
34 |
+
* @param string $notification_type
|
35 |
+
*/
|
36 |
+
public function renderCodes( $notification_type )
|
37 |
+
{
|
38 |
+
switch ( $notification_type ) {
|
39 |
+
case Notification::TYPE_APPOINTMENT_START_TIME:
|
40 |
+
case Notification::TYPE_CUSTOMER_APPOINTMENT_CREATED:
|
41 |
+
case Notification::TYPE_LAST_CUSTOMER_APPOINTMENT:
|
42 |
+
case Notification::TYPE_CUSTOMER_APPOINTMENT_STATUS_CHANGED:
|
43 |
+
$this->renderCustomerAppointmentCodesForCN( $notification_type );
|
44 |
+
break;
|
45 |
+
case 'staff_agenda':
|
46 |
+
case Notification::TYPE_STAFF_DAY_AGENDA:
|
47 |
+
$this->renderStaffDayAgendaCodes();
|
48 |
+
break;
|
49 |
+
case 'client_birthday_greeting':
|
50 |
+
case Notification::TYPE_CUSTOMER_BIRTHDAY:
|
51 |
+
$this->renderBirthdayGreetingCodes();
|
52 |
+
break;
|
53 |
+
case 'client_new_wp_user':
|
54 |
+
$this->renderNewWpUserCodes();
|
55 |
+
break;
|
56 |
+
case 'client_pending_appointment_cart':
|
57 |
+
case 'client_approved_appointment_cart':
|
58 |
+
$this->renderCompoundCodes();
|
59 |
+
break;
|
60 |
+
case 'staff_waiting_list':
|
61 |
+
$this->renderWaitingListCodes();
|
62 |
+
break;
|
63 |
+
case 'client_pending_appointment':
|
64 |
+
case 'staff_pending_appointment':
|
65 |
+
case 'client_approved_appointment':
|
66 |
+
case 'staff_approved_appointment':
|
67 |
+
case 'client_cancelled_appointment':
|
68 |
+
case 'staff_cancelled_appointment':
|
69 |
+
case 'client_rejected_appointment':
|
70 |
+
case 'staff_rejected_appointment':
|
71 |
+
case 'client_waitlisted_appointment':
|
72 |
+
case 'staff_waitlisted_appointment':
|
73 |
+
case 'client_reminder':
|
74 |
+
case 'client_reminder_1st':
|
75 |
+
case 'client_reminder_2nd':
|
76 |
+
case 'client_reminder_3rd':
|
77 |
+
case 'client_follow_up':
|
78 |
+
$this->renderBaseCodes();
|
79 |
+
break;
|
80 |
+
case 'staff_package_purchased':
|
81 |
+
case 'client_package_purchased':
|
82 |
+
case 'staff_package_deleted':
|
83 |
+
case 'client_package_deleted':
|
84 |
+
$this->renderPackageCodes( $notification_type );
|
85 |
+
break;
|
86 |
+
case 'client_pending_recurring_appointment':
|
87 |
+
case 'staff_pending_recurring_appointment':
|
88 |
+
case 'client_approved_recurring_appointment':
|
89 |
+
case 'staff_approved_recurring_appointment':
|
90 |
+
case 'client_cancelled_recurring_appointment':
|
91 |
+
case 'staff_cancelled_recurring_appointment':
|
92 |
+
case 'client_rejected_recurring_appointment':
|
93 |
+
case 'staff_rejected_recurring_appointment':
|
94 |
+
case 'client_waitlisted_recurring_appointment':
|
95 |
+
case 'staff_waitlisted_recurring_appointment':
|
96 |
+
$this->renderRecurringCodes();
|
97 |
+
break;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
/**
|
102 |
+
* Render codes for custom notifications with appointment(s)
|
103 |
+
*
|
104 |
+
* @param string $notification_type
|
105 |
+
*/
|
106 |
+
private function renderCustomerAppointmentCodesForCN( $notification_type )
|
107 |
+
{
|
108 |
+
$codes = $this->getCommonCodes();
|
109 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
110 |
+
$codes[] = array( 'code' => 'appointment_end_date', 'description' => __( 'end date of appointment', 'bookly' ) );
|
111 |
+
$codes[] = array( 'code' => 'appointment_end_time', 'description' => __( 'end time of appointment', 'bookly' ) );
|
112 |
+
$codes[] = array( 'code' => 'appointment_notes', 'description' => __( 'customer notes for appointment', 'bookly' ) );
|
113 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
114 |
+
$codes[] = array( 'code' => 'approve_appointment_url', 'description' => esc_html__( 'URL of approve appointment link (to use inside <a> tag)', 'bookly' ) );
|
115 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
116 |
+
$codes[] = array( 'code' => 'cancel_appointment', 'description' => __( 'cancel appointment link', 'bookly' ) );
|
117 |
+
$codes[] = array( 'code' => 'cancel_appointment_confirm_url', 'description' => esc_html__( 'URL of cancel appointment link with confirmation (to use inside <a> tag)', 'bookly' ) );
|
118 |
+
$codes[] = array( 'code' => 'cancel_appointment_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) );
|
119 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
120 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
121 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
122 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
123 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
124 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
125 |
+
$codes[] = array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) );
|
126 |
+
$codes[] = array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) );
|
127 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
128 |
+
$codes[] = array( 'code' => 'reject_appointment_url', 'description' => esc_html__( 'URL of reject appointment link (to use inside <a> tag)', 'bookly' ) );
|
129 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
130 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
131 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
132 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
133 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
134 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
135 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
136 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
137 |
+
$codes[] = array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) );
|
138 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
139 |
+
|
140 |
+
$codes = Lib\Proxy\Packages::prepareNotificationCodesList( $codes );
|
141 |
+
$codes = Lib\Proxy\RecurringAppointments::prepareNotificationCodesList( $codes );
|
142 |
+
|
143 |
+
Lib\Utils\Common::codes(
|
144 |
+
Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'customer' ),
|
145 |
+
array( 'type' => $notification_type )
|
146 |
+
);
|
147 |
+
}
|
148 |
+
|
149 |
+
/**
|
150 |
+
* Render codes for staff agenda.
|
151 |
+
*/
|
152 |
+
private function renderStaffDayAgendaCodes()
|
153 |
+
{
|
154 |
+
$codes = $this->getCommonCodes();
|
155 |
+
$codes[] = array( 'code' => 'agenda_date', 'description' => __( 'agenda date', 'bookly' ) );
|
156 |
+
$codes[] = array( 'code' => 'next_day_agenda', 'description' => __( 'staff agenda for next day', 'bookly' ) );
|
157 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
158 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
159 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
160 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
161 |
+
$codes[] = array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) );
|
162 |
+
$codes[] = array( 'code' => 'tomorrow_date', 'description' => __( 'date of next day', 'bookly' ) );
|
163 |
+
|
164 |
+
Lib\Utils\Common::codes(
|
165 |
+
$codes,
|
166 |
+
array( 'type' => Notification::TYPE_STAFF_DAY_AGENDA )
|
167 |
+
);
|
168 |
+
}
|
169 |
+
|
170 |
+
/**
|
171 |
+
* Render codes for Greeting notifications
|
172 |
+
*/
|
173 |
+
private function renderBirthdayGreetingCodes()
|
174 |
+
{
|
175 |
+
$codes = $this->getCommonCodes();
|
176 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
177 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
178 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
179 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
180 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
181 |
+
|
182 |
+
Lib\Utils\Common::codes(
|
183 |
+
$codes,
|
184 |
+
array( 'type' => Notification::TYPE_CUSTOMER_BIRTHDAY )
|
185 |
+
);
|
186 |
+
}
|
187 |
+
|
188 |
+
/**
|
189 |
+
* Render codes for new WordPress users.
|
190 |
+
*/
|
191 |
+
private function renderNewWpUserCodes()
|
192 |
+
{
|
193 |
+
$codes = $this->getCommonCodes();
|
194 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
195 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
196 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
197 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
198 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
199 |
+
$codes[] = array( 'code' => 'new_password', 'description' => __( 'customer new password', 'bookly' ) );
|
200 |
+
$codes[] = array( 'code' => 'new_username', 'description' => __( 'customer new username', 'bookly' ) );
|
201 |
+
$codes[] = array( 'code' => 'site_address', 'description' => __( 'site address', 'bookly' ) );
|
202 |
+
|
203 |
+
Lib\Utils\Common::codes( $codes );
|
204 |
+
}
|
205 |
+
|
206 |
+
/**
|
207 |
+
* Render codes for compound (cart) notifications.
|
208 |
+
*/
|
209 |
+
private function renderCompoundCodes()
|
210 |
+
{
|
211 |
+
$codes = $this->getCommonCodes();
|
212 |
+
$codes[] = array( 'code' => 'cart_info', 'description' => __( 'cart information', 'bookly' ) );
|
213 |
+
$codes[] = array( 'code' => 'cart_info_c', 'description' => __( 'cart information with cancel', 'bookly' ) );
|
214 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
215 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
216 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
217 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
218 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
219 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
220 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
221 |
+
|
222 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareCartNotificationShortCodes( $codes ) );
|
223 |
+
}
|
224 |
+
|
225 |
+
/**
|
226 |
+
* Render base codes
|
227 |
+
*/
|
228 |
+
private function renderBaseCodes()
|
229 |
+
{
|
230 |
+
$codes = $this->getCommonCodes();
|
231 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
232 |
+
$codes[] = array( 'code' => 'appointment_end_date', 'description' => __( 'end date of appointment', 'bookly' ) );
|
233 |
+
$codes[] = array( 'code' => 'appointment_end_time', 'description' => __( 'end time of appointment', 'bookly' ) );
|
234 |
+
$codes[] = array( 'code' => 'appointment_notes', 'description' => __( 'customer notes for appointment', 'bookly' ) );
|
235 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
236 |
+
$codes[] = array( 'code' => 'approve_appointment_url', 'description' => esc_html__( 'URL of approve appointment link (to use inside <a> tag)', 'bookly' ) );
|
237 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
238 |
+
$codes[] = array( 'code' => 'cancel_appointment', 'description' => __( 'cancel appointment link', 'bookly' ) );
|
239 |
+
$codes[] = array( 'code' => 'cancel_appointment_confirm_url', 'description' => esc_html__( 'URL of cancel appointment link with confirmation (to use inside <a> tag)', 'bookly' ) );
|
240 |
+
$codes[] = array( 'code' => 'cancel_appointment_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) );
|
241 |
+
$codes[] = array( 'code' => 'cancellation_reason', 'description' => __( 'reason you mentioned while deleting appointment', 'bookly' ) );
|
242 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
243 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
244 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
245 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
246 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
247 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
248 |
+
$codes[] = array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) );
|
249 |
+
$codes[] = array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) );
|
250 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
251 |
+
$codes[] = array( 'code' => 'reject_appointment_url', 'description' => esc_html__( 'URL of reject appointment link (to use inside <a> tag)', 'bookly' ) );
|
252 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
253 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
254 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
255 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
256 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
257 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
258 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
259 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
260 |
+
$codes[] = array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) );
|
261 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
262 |
+
|
263 |
+
Lib\Utils\Common::codes(
|
264 |
+
Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'customer' )
|
265 |
+
);
|
266 |
+
}
|
267 |
+
|
268 |
+
/**
|
269 |
+
* Render codes notifications about package appointments
|
270 |
+
*
|
271 |
+
* @param string $notification_type
|
272 |
+
*/
|
273 |
+
private function renderPackageCodes( $notification_type )
|
274 |
+
{
|
275 |
+
$codes = $this->getCommonCodes();
|
276 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
277 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
278 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
279 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
280 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
281 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
282 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
283 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
284 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
285 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
286 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
287 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
288 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
289 |
+
$codes[] = array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) );
|
290 |
+
|
291 |
+
$codes = Lib\Proxy\Packages::prepareNotificationCodesList( $codes, '', $notification_type );
|
292 |
+
|
293 |
+
Lib\Utils\Common::codes( $codes );
|
294 |
+
}
|
295 |
+
|
296 |
+
/**
|
297 |
+
* Render codes notifications wor appointments in waiting list
|
298 |
+
*/
|
299 |
+
private function renderWaitingListCodes()
|
300 |
+
{
|
301 |
+
$codes = $this->getCommonCodes();
|
302 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
303 |
+
$codes[] = array( 'code' => 'appointment_end_date', 'description' => __( 'end date of appointment', 'bookly' ) );
|
304 |
+
$codes[] = array( 'code' => 'appointment_end_time', 'description' => __( 'end time of appointment', 'bookly' ) );
|
305 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
306 |
+
$codes[] = array( 'code' => 'appointment_waiting_list', 'description' => __( 'waiting list of appointment', 'bookly-waiting-list' ) );
|
307 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
308 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
309 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
310 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
311 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
312 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
313 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
314 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
315 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
316 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
317 |
+
$codes[] = array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) );
|
318 |
+
|
319 |
+
$codes = Lib\Proxy\WaitingList::prepareNotificationCodesList( $codes );
|
320 |
+
|
321 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'appointment' ) );
|
322 |
+
}
|
323 |
+
|
324 |
+
private function renderRecurringCodes()
|
325 |
+
{
|
326 |
+
$codes = $this->getCommonCodes();
|
327 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
328 |
+
$codes[] = array( 'code' => 'appointment_end_date','description' => __( 'end date of appointment', 'bookly' ) );
|
329 |
+
$codes[] = array( 'code' => 'appointment_end_time','description' => __( 'end time of appointment', 'bookly' ) );
|
330 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
331 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
332 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
333 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
334 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
335 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
336 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
337 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
338 |
+
$codes[] = array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) );
|
339 |
+
$codes[] = array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) );
|
340 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
341 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
342 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
343 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
344 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
345 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
346 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
347 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
348 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
349 |
+
$codes[] = array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ) );
|
350 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
351 |
+
|
352 |
+
$codes = Lib\Proxy\RecurringAppointments::prepareNotificationCodesList( $codes );
|
353 |
+
|
354 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'customer' ) );
|
355 |
+
}
|
356 |
+
|
357 |
+
}
|
backend/modules/notifications/Controller.php
CHANGED
@@ -35,34 +35,46 @@ class Controller extends Lib\Base\Controller
|
|
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 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
}
|
52 |
-
update_option( 'bookly_cron_reminder_times', $cron_reminder );
|
53 |
}
|
54 |
-
$
|
55 |
wp_localize_script( 'bookly-alert.js', 'BooklyL10n', array(
|
56 |
-
'
|
|
|
|
|
57 |
'sent_successfully' => __( 'Sent successfully.', 'bookly' ),
|
58 |
-
'limitations'
|
59 |
) );
|
60 |
-
$
|
|
|
|
|
|
|
|
|
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' );
|
@@ -72,9 +84,15 @@ class Controller extends Lib\Base\Controller
|
|
72 |
|
73 |
$notifications = array();
|
74 |
foreach ( $form->getData() as $notification ) {
|
|
|
|
|
|
|
|
|
|
|
|
|
75 |
$notifications[] = array(
|
76 |
'type' => $notification['type'],
|
77 |
-
'name' => $
|
78 |
'active' => $notification['active'],
|
79 |
);
|
80 |
}
|
@@ -90,21 +108,26 @@ class Controller extends Lib\Base\Controller
|
|
90 |
wp_send_json_success( $result );
|
91 |
}
|
92 |
|
93 |
-
public function executeTestEmailNotifications()
|
94 |
-
{
|
95 |
-
}
|
96 |
|
97 |
-
|
|
|
|
|
|
|
98 |
|
99 |
/**
|
100 |
-
*
|
101 |
-
* so current 'execute*' methods look nicer.
|
102 |
-
*
|
103 |
-
* @param string $prefix
|
104 |
*/
|
105 |
-
|
106 |
{
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
|
110 |
}
|
35 |
)
|
36 |
) );
|
37 |
$cron_reminder = (array) get_option( 'bookly_cron_reminder_times' );
|
38 |
+
$form = new Forms\Notifications( 'email', Components::getInstance() );
|
39 |
$alert = array( 'success' => array() );
|
40 |
// Save action.
|
41 |
if ( ! empty ( $_POST ) ) {
|
42 |
+
if ( $this->csrfTokenValid() ) {
|
43 |
+
$form->bind( $this->getPostParameters() );
|
44 |
+
$form->save();
|
45 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
46 |
+
update_option( 'bookly_email_send_as', $this->getParameter( 'bookly_email_send_as' ) );
|
47 |
+
update_option( 'bookly_email_reply_to_customers', $this->getParameter( 'bookly_email_reply_to_customers' ) );
|
48 |
+
update_option( 'bookly_email_sender', $this->getParameter( 'bookly_email_sender' ) );
|
49 |
+
update_option( 'bookly_email_sender_name', $this->getParameter( 'bookly_email_sender_name' ) );
|
50 |
+
update_option( 'bookly_ntf_processing_interval', (int) $this->getParameter( 'bookly_ntf_processing_interval' ) );
|
51 |
+
foreach ( array( 'staff_agenda', 'client_follow_up', 'client_reminder', 'client_birthday_greeting' ) as $type ) {
|
52 |
+
$cron_reminder[ $type ] = $this->getParameter( $type . '_cron_hour' );
|
53 |
+
}
|
54 |
+
foreach ( array( 'client_reminder_1st', 'client_reminder_2nd', 'client_reminder_3rd', ) as $type ) {
|
55 |
+
$cron_reminder[ $type ] = $this->getParameter( $type . '_cron_before_hour' );
|
56 |
+
}
|
57 |
+
update_option( 'bookly_cron_reminder_times', $cron_reminder );
|
58 |
}
|
|
|
59 |
}
|
60 |
+
$cron_uri = plugins_url( 'lib/utils/send_notifications_cron.php', Lib\Plugin::getMainFile() );
|
61 |
wp_localize_script( 'bookly-alert.js', 'BooklyL10n', array(
|
62 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
63 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
64 |
+
'alert' => $alert,
|
65 |
'sent_successfully' => __( 'Sent successfully.', 'bookly' ),
|
66 |
+
'limitations' => __( '<b class="h4">This function is not available in the Lite version of Bookly.</b><br><br>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', 'bookly' ) . ' <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
67 |
) );
|
68 |
+
$statuses = Lib\Entities\CustomerAppointment::getStatuses();
|
69 |
+
foreach ( range( 1, 23 ) as $hours ) {
|
70 |
+
$bookly_ntf_processing_interval_values[] = array( $hours, Lib\Utils\DateTime::secondsToInterval( $hours * HOUR_IN_SECONDS ) );
|
71 |
+
}
|
72 |
+
$this->render( 'index', compact( 'form', 'cron_uri', 'cron_reminder', 'statuses', 'bookly_ntf_processing_interval_values' ) );
|
73 |
}
|
74 |
|
75 |
public function executeGetEmailNotificationsData()
|
76 |
{
|
77 |
+
$form = new Forms\Notifications( 'email', Components::getInstance() );
|
78 |
|
79 |
$bookly_email_sender_name = get_option( 'bookly_email_sender_name' ) == '' ?
|
80 |
get_option( 'blogname' ) : get_option( 'bookly_email_sender_name' );
|
84 |
|
85 |
$notifications = array();
|
86 |
foreach ( $form->getData() as $notification ) {
|
87 |
+
$name = Lib\Entities\Notification::getName( $notification['type'] );
|
88 |
+
if ( in_array( $notification['type'], Lib\Entities\Notification::getCustomNotificationTypes() ) && $notification['subject'] != '' ) {
|
89 |
+
// In window Test Email Notification
|
90 |
+
// for custom notification, subject is name.
|
91 |
+
$name = $notification['subject'];
|
92 |
+
}
|
93 |
$notifications[] = array(
|
94 |
'type' => $notification['type'],
|
95 |
+
'name' => $name,
|
96 |
'active' => $notification['active'],
|
97 |
);
|
98 |
}
|
108 |
wp_send_json_success( $result );
|
109 |
}
|
110 |
|
111 |
+
public function executeTestEmailNotifications(){}
|
|
|
|
|
112 |
|
113 |
+
/**
|
114 |
+
* Create new custom notification
|
115 |
+
*/
|
116 |
+
public function executeCreateCustomNotification(){}
|
117 |
|
118 |
/**
|
119 |
+
* Delete custom notification
|
|
|
|
|
|
|
120 |
*/
|
121 |
+
public function executeDeleteCustomNotification()
|
122 |
{
|
123 |
+
$id = $this->getParameter( 'id' );
|
124 |
+
Lib\Entities\Notification::query()
|
125 |
+
->delete()
|
126 |
+
->where( 'id', $id )
|
127 |
+
->whereIN( 'type', Lib\Entities\Notification::getCustomNotificationTypes() )
|
128 |
+
->execute();
|
129 |
+
|
130 |
+
wp_send_json_success();
|
131 |
}
|
132 |
|
133 |
}
|
backend/modules/notifications/forms/Notifications.php
CHANGED
@@ -21,49 +21,52 @@ class Notifications extends Lib\Base\Form
|
|
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 |
-
*
|
37 |
*
|
38 |
-
* @param string
|
|
|
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 =
|
48 |
$this->gateway = $gateway;
|
49 |
-
if ( ! Lib\Config::
|
50 |
$this->types['combined'] = array();
|
51 |
}
|
52 |
-
$this->
|
|
|
|
|
53 |
$this->load();
|
54 |
}
|
55 |
|
56 |
public function bind( array $_post = array(), array $files = array() )
|
57 |
{
|
58 |
-
|
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 |
/**
|
@@ -72,62 +75,74 @@ class Notifications extends Lib\Base\Form
|
|
72 |
public function save()
|
73 |
{
|
74 |
/** @var Lib\Entities\Notification[] $notifications */
|
75 |
-
$notifications = Lib\Entities\Notification::query(
|
76 |
->where( 'gateway', $this->gateway )
|
77 |
-
->indexBy( '
|
78 |
->find();
|
79 |
-
foreach ( $this->
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
}
|
84 |
}
|
85 |
}
|
86 |
|
87 |
public function load()
|
88 |
{
|
89 |
-
$notifications = Lib\Entities\Notification::query(
|
90 |
-
->select( 'active, subject, message, copy, type' )
|
91 |
->where( 'gateway', $this->gateway )
|
92 |
-
->indexBy( 'type' )
|
93 |
->fetchArray();
|
94 |
-
foreach ( $
|
95 |
-
|
96 |
-
|
97 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
98 |
}
|
99 |
}
|
|
|
|
|
100 |
}
|
101 |
|
102 |
/**
|
103 |
* Render subject.
|
104 |
*
|
105 |
-
* @param
|
106 |
*/
|
107 |
-
public function renderSubject( $
|
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 |
-
|
115 |
__( 'Subject', 'bookly' ),
|
116 |
-
$
|
117 |
-
esc_attr( $this->data[ $
|
118 |
);
|
119 |
}
|
120 |
|
121 |
/**
|
122 |
* Render message editor.
|
123 |
*
|
124 |
-
* @param
|
125 |
*/
|
126 |
-
public function renderEditor( $
|
127 |
{
|
128 |
-
$
|
129 |
-
$name
|
130 |
-
$value
|
131 |
|
132 |
if ( $this->gateway == 'sms' ) {
|
133 |
printf(
|
@@ -135,7 +150,7 @@ class Notifications extends Lib\Base\Form
|
|
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 |
-
$
|
139 |
__( 'Message', 'bookly' ),
|
140 |
$name,
|
141 |
esc_textarea( $value )
|
@@ -154,62 +169,130 @@ class Notifications extends Lib\Base\Form
|
|
154 |
);
|
155 |
|
156 |
echo '<div class="form-group"><label>' . __( 'Message', 'bookly' ) . '</label>';
|
157 |
-
wp_editor( $value, $
|
158 |
echo '</div>';
|
159 |
}
|
160 |
}
|
161 |
|
162 |
/**
|
163 |
-
* Render
|
164 |
*
|
165 |
-
* @param
|
166 |
*/
|
167 |
-
public function renderCopy( $
|
168 |
{
|
169 |
-
if (
|
|
|
|
|
|
|
|
|
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 |
-
$
|
176 |
-
$
|
177 |
-
checked( $
|
178 |
__( 'Send copy to administrators', 'bookly' )
|
179 |
);
|
180 |
}
|
181 |
}
|
182 |
|
183 |
/**
|
184 |
-
* Render
|
185 |
*
|
186 |
-
* @param
|
187 |
*/
|
188 |
-
public function
|
189 |
{
|
190 |
-
if ( in_array( $type, array(
|
191 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
192 |
printf(
|
193 |
'<div class="form-group">
|
194 |
-
<
|
195 |
-
<
|
196 |
-
<select class="form-control" name="%1$s" id="%1$s">
|
197 |
-
%4$s
|
198 |
-
</select>
|
199 |
</div>',
|
200 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
201 |
__( 'Sending time', 'bookly' ),
|
202 |
__( 'Set the time you want the notification to be sent.', 'bookly' ),
|
203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
}
|
21 |
'staff_rejected_appointment',
|
22 |
'client_new_wp_user',
|
23 |
'client_reminder',
|
24 |
+
'client_reminder_1st',
|
25 |
+
'client_reminder_2nd',
|
26 |
+
'client_reminder_3rd',
|
27 |
'client_follow_up',
|
28 |
+
'client_birthday_greeting',
|
29 |
'staff_agenda',
|
30 |
),
|
31 |
'combined' => array(
|
32 |
'client_pending_appointment_cart',
|
33 |
'client_approved_appointment_cart',
|
34 |
),
|
35 |
+
'custom' => array(),
|
36 |
);
|
37 |
|
38 |
public $gateway;
|
39 |
|
40 |
+
/** @var \BooklyLite\Backend\Modules\Notifications\Components|\BooklyLite\Backend\Modules\Sms\Components|Lib\Base\Components */
|
41 |
+
protected $codes;
|
42 |
+
|
43 |
/**
|
44 |
+
* Notifications constructor.
|
45 |
*
|
46 |
+
* @param string $gateway
|
47 |
+
* @param \BooklyLite\Backend\Modules\Notifications\Components|\BooklyLite\Backend\Modules\Sms\Components $components
|
48 |
*/
|
49 |
+
public function __construct( $gateway = 'email', Lib\Base\Components $components )
|
50 |
{
|
51 |
/*
|
52 |
* make Visual Mode as default (instead of Text Mode)
|
53 |
* allowed: tinymce - Visual Mode, html - Text Mode, test - no one Mode selected
|
54 |
*/
|
55 |
add_filter( 'wp_default_editor', create_function( '', 'return \'tinymce\';' ) );
|
56 |
+
$this->types = Lib\Proxy\Shared::prepareNotificationTypes( $this->types );
|
57 |
$this->gateway = $gateway;
|
58 |
+
if ( ! Lib\Config::combinedNotificationsEnabled() ) {
|
59 |
$this->types['combined'] = array();
|
60 |
}
|
61 |
+
$this->types['custom'] = Lib\Entities\Notification::getCustomNotificationTypes();
|
62 |
+
$this->codes = $components;
|
63 |
+
$this->setFields( array( 'id', 'active', 'type', 'subject', 'message', 'to_customer', 'to_staff', 'to_admin', 'attach_ics', 'settings' ) );
|
64 |
$this->load();
|
65 |
}
|
66 |
|
67 |
public function bind( array $_post = array(), array $files = array() )
|
68 |
{
|
69 |
+
$this->data = $_post['notification'];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
}
|
71 |
|
72 |
/**
|
75 |
public function save()
|
76 |
{
|
77 |
/** @var Lib\Entities\Notification[] $notifications */
|
78 |
+
$notifications = Lib\Entities\Notification::query()
|
79 |
->where( 'gateway', $this->gateway )
|
80 |
+
->indexBy( 'id' )
|
81 |
->find();
|
82 |
+
foreach ( $this->data as $id => $fields ) {
|
83 |
+
$notifications[ $id ]->setFields( $fields )->save();
|
84 |
+
$data = array_merge( $this->data[ $id ], $notifications[ $id ]->getFields() );
|
85 |
+
$this->data[ $id ] = $data;
|
|
|
86 |
}
|
87 |
}
|
88 |
|
89 |
public function load()
|
90 |
{
|
91 |
+
$notifications = Lib\Entities\Notification::query()
|
|
|
92 |
->where( 'gateway', $this->gateway )
|
|
|
93 |
->fetchArray();
|
94 |
+
foreach ( $notifications as $notification ) {
|
95 |
+
$this->data[ $notification['id'] ] = $notification;
|
96 |
+
}
|
97 |
+
}
|
98 |
+
|
99 |
+
/**
|
100 |
+
* @param string $group
|
101 |
+
* @return array
|
102 |
+
*/
|
103 |
+
public function getNotifications( $group )
|
104 |
+
{
|
105 |
+
$notifications = array();
|
106 |
+
foreach ( $this->types[ $group ] as $type ) {
|
107 |
+
foreach ( $this->data as $notification ) {
|
108 |
+
if ( $notification['type'] == $type ) {
|
109 |
+
$notifications[] = $notification;
|
110 |
+
}
|
111 |
}
|
112 |
}
|
113 |
+
|
114 |
+
return $notifications;
|
115 |
}
|
116 |
|
117 |
/**
|
118 |
* Render subject.
|
119 |
*
|
120 |
+
* @param int $id
|
121 |
*/
|
122 |
+
public function renderSubject( $id )
|
123 |
{
|
124 |
printf(
|
125 |
'<div class="form-group">
|
126 |
<label for="%1$s">%2$s</label>
|
127 |
+
<input type="text" class="form-control" id="%1$s" name="%3$s" value="%4$s"/>
|
128 |
</div>',
|
129 |
+
'notification_'.$id.'_subject',
|
130 |
__( 'Subject', 'bookly' ),
|
131 |
+
'notification[' . $id . '][subject]',
|
132 |
+
esc_attr( $this->data[ $id ]['subject'] )
|
133 |
);
|
134 |
}
|
135 |
|
136 |
/**
|
137 |
* Render message editor.
|
138 |
*
|
139 |
+
* @param int $id
|
140 |
*/
|
141 |
+
public function renderEditor( $id )
|
142 |
{
|
143 |
+
$attr_id = 'notification_' . $id . '_message';
|
144 |
+
$name = 'notification[' . $id . '][message]';
|
145 |
+
$value = $this->data[ $id ]['message'];
|
146 |
|
147 |
if ( $this->gateway == 'sms' ) {
|
148 |
printf(
|
150 |
<label for="%1$s">%2$s</label>
|
151 |
<textarea rows="6" id="%1$s" name="%3$s" class="form-control">%4$s</textarea>
|
152 |
</div>',
|
153 |
+
$attr_id,
|
154 |
__( 'Message', 'bookly' ),
|
155 |
$name,
|
156 |
esc_textarea( $value )
|
169 |
);
|
170 |
|
171 |
echo '<div class="form-group"><label>' . __( 'Message', 'bookly' ) . '</label>';
|
172 |
+
wp_editor( $value, $attr_id, $settings );
|
173 |
echo '</div>';
|
174 |
}
|
175 |
}
|
176 |
|
177 |
/**
|
178 |
+
* Render to admin.
|
179 |
*
|
180 |
+
* @param array $notification
|
181 |
*/
|
182 |
+
public function renderCopy( array $notification )
|
183 |
{
|
184 |
+
if ( strpos( $notification['type'], 'staff' ) === 0
|
185 |
+
|| strpos( $notification['type'], 'custom_notification' ) === 0
|
186 |
+
) {
|
187 |
+
$id = $notification['id'];
|
188 |
+
$name = 'notification[' . $notification['id'] . '][to_admin]';
|
189 |
printf(
|
190 |
'<div class="form-group">
|
191 |
<input name="%1$s" type="hidden" value="0">
|
192 |
<div class="checkbox"><label for="%2$s"><input id="%2$s" name="%1$s" type="checkbox" value="1" %3$s> %4$s</label></div>
|
193 |
</div>',
|
194 |
+
$name,
|
195 |
+
'notification_' . $id . '_copy',
|
196 |
+
checked( $notification['to_admin'], true, false ),
|
197 |
__( 'Send copy to administrators', 'bookly' )
|
198 |
);
|
199 |
}
|
200 |
}
|
201 |
|
202 |
/**
|
203 |
+
* Render attach ICS file.
|
204 |
*
|
205 |
+
* @param array $notification
|
206 |
*/
|
207 |
+
public function renderAttachIcs( array $notification )
|
208 |
{
|
209 |
+
if ( in_array( $notification['type'], array(
|
210 |
+
'client_pending_appointment',
|
211 |
+
'staff_pending_appointment',
|
212 |
+
'client_approved_appointment',
|
213 |
+
'staff_approved_appointment',
|
214 |
+
'client_cancelled_appointment',
|
215 |
+
'staff_cancelled_appointment',
|
216 |
+
'client_rejected_appointment',
|
217 |
+
'staff_rejected_appointment',
|
218 |
+
'client_waitlisted_appointment',
|
219 |
+
'staff_waitlisted_appointment',
|
220 |
+
'client_reminder',
|
221 |
+
'client_reminder_1st',
|
222 |
+
'client_reminder_2nd',
|
223 |
+
'client_reminder_3rd',
|
224 |
+
'client_follow_up',
|
225 |
+
) ) ) {
|
226 |
+
$id = $notification['id'];
|
227 |
+
$name = sprintf( 'notification[%d][attach_ics]', $id );
|
228 |
printf(
|
229 |
'<div class="form-group">
|
230 |
+
<input name="%1$s" type="hidden" value="0">
|
231 |
+
<div class="checkbox"><label for="%2$s"><input id="%2$s" name="%1$s" type="checkbox" value="1" %3$s> %4$s</label></div>
|
|
|
|
|
|
|
232 |
</div>',
|
233 |
+
$name,
|
234 |
+
'notification_' . $id . '_ics',
|
235 |
+
checked( $notification['attach_ics'], true, false ),
|
236 |
+
__( 'Attach ICS file', 'bookly' )
|
237 |
+
);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
/**
|
242 |
+
* Render sending time.
|
243 |
+
*
|
244 |
+
* @param array $notification
|
245 |
+
*/
|
246 |
+
public function renderSendingTime( array $notification )
|
247 |
+
{
|
248 |
+
$type = $notification['type'];
|
249 |
+
if ( in_array( $type, array( 'staff_agenda', 'client_follow_up', 'client_reminder', 'client_reminder_1st', 'client_reminder_2nd', 'client_reminder_3rd', 'client_birthday_greeting' ) ) ) {
|
250 |
+
$cron_reminder = (array) get_option( 'bookly_cron_reminder_times' );
|
251 |
+
$before_hour = strpos( $type, 'client_reminder_' ) !== false;
|
252 |
+
$data = array(
|
253 |
+
$before_hour ? $type . '_cron_before_hour' : $type . '_cron_hour',
|
254 |
__( 'Sending time', 'bookly' ),
|
255 |
__( 'Set the time you want the notification to be sent.', 'bookly' ),
|
256 |
+
);
|
257 |
+
if ( $before_hour ) {
|
258 |
+
$data[] = implode( '', array_map( function ( $hour ) use ( $type, $cron_reminder ) {
|
259 |
+
return sprintf(
|
260 |
+
'<option value="%s" %s>%s</option>',
|
261 |
+
$hour,
|
262 |
+
selected( $cron_reminder[ $type ], $hour, false ),
|
263 |
+
sprintf( __( '%s before', 'bookly' ), \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) )
|
264 |
+
);
|
265 |
+
}, array_merge( range( 1, 24 ), range( 48, 336, 24 ) ) ) );
|
266 |
+
} else {
|
267 |
+
$data[] = implode( '', array_map( function ( $hour ) use ( $type, $cron_reminder ) {
|
268 |
return sprintf(
|
269 |
'<option value="%s" %s>%s</option>',
|
270 |
$hour,
|
271 |
selected( $cron_reminder[ $type ], $hour, false ),
|
272 |
Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false )
|
273 |
);
|
274 |
+
}, range( 0, 23 ) ) );
|
275 |
+
}
|
276 |
+
|
277 |
+
vprintf(
|
278 |
+
'<div class="form-group">
|
279 |
+
<label for="%1$s">%2$s</label>
|
280 |
+
<p class="help-block">%3$s</p>
|
281 |
+
<select class="form-control" name="%1$s" id="%1$s">
|
282 |
+
%4$s
|
283 |
+
</select>
|
284 |
+
</div>',
|
285 |
+
$data
|
286 |
);
|
287 |
}
|
288 |
}
|
289 |
|
290 |
+
/**
|
291 |
+
* @param string $notification_type
|
292 |
+
*/
|
293 |
+
public function renderCodes( $notification_type )
|
294 |
+
{
|
295 |
+
$this->codes->renderCodes( $notification_type );
|
296 |
+
}
|
297 |
+
|
298 |
}
|
backend/modules/notifications/resources/js/ng-app.js
CHANGED
@@ -13,7 +13,7 @@
|
|
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) {
|
@@ -85,6 +85,31 @@
|
|
85 |
};
|
86 |
|
87 |
$scope.testEmailNotifications = function(){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
};
|
89 |
|
90 |
});
|
@@ -92,5 +117,5 @@
|
|
92 |
})();
|
93 |
|
94 |
var showTestEmailNotificationDialog = function () {
|
95 |
-
jQuery('#
|
96 |
};
|
13 |
jQuery.ajax({
|
14 |
url : ajaxurl,
|
15 |
type : 'POST',
|
16 |
+
data : jQuery.extend({ action : 'bookly_get_email_notifications_data', csrf_token : BooklyL10n.csrf_token }, params),
|
17 |
dataType : 'json',
|
18 |
success : function(response) {
|
19 |
if (response.success) {
|
85 |
};
|
86 |
|
87 |
$scope.testEmailNotifications = function(){
|
88 |
+
var data = {
|
89 |
+
action: 'bookly_test_email_notifications',
|
90 |
+
csrf_token : BooklyL10n.csrf_token,
|
91 |
+
notifications: [],
|
92 |
+
to_email : $scope.toEmail,
|
93 |
+
sender_name : $scope.dataSource.sender_name,
|
94 |
+
sender_email : $scope.dataSource.sender_email,
|
95 |
+
reply_to_customers : $scope.dataSource.reply_to_customers,
|
96 |
+
send_as : $scope.dataSource.send_as
|
97 |
+
};
|
98 |
+
angular.forEach($scope.dataSource.notifications, function(notification) {
|
99 |
+
if (notification.active == '1') {
|
100 |
+
data.notifications.push(notification.type);
|
101 |
+
}
|
102 |
+
});
|
103 |
+
jQuery.ajax({
|
104 |
+
url: ajaxurl,
|
105 |
+
type: 'POST',
|
106 |
+
data: data,
|
107 |
+
dataType: 'json',
|
108 |
+
success: function (response) {
|
109 |
+
booklyAlert({success : [BooklyL10n.sent_successfully]});
|
110 |
+
Ladda.stopAll();
|
111 |
+
}
|
112 |
+
});
|
113 |
};
|
114 |
|
115 |
});
|
117 |
})();
|
118 |
|
119 |
var showTestEmailNotificationDialog = function () {
|
120 |
+
jQuery('#bookly-test-email-notifications-dialog').modal('show');
|
121 |
};
|
backend/modules/notifications/resources/js/notification.js
CHANGED
@@ -19,6 +19,11 @@ jQuery(function($) {
|
|
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 () {
|
@@ -28,7 +33,8 @@ jQuery(function($) {
|
|
28 |
}
|
29 |
});
|
30 |
|
31 |
-
$('.
|
32 |
booklyAlert({error: [BooklyL10n.limitations]});
|
|
|
33 |
});
|
34 |
});
|
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 |
+
$("#bookly-js-new-notification").on('click', function () {
|
23 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
24 |
+
$(this).prop('disabled', true);
|
25 |
+
});
|
26 |
+
|
27 |
booklyAlert(BooklyL10n.alert);
|
28 |
|
29 |
$(':checkbox').on('change', function () {
|
33 |
}
|
34 |
});
|
35 |
|
36 |
+
$('.bookly-test-email-notifications').on('click',function () {
|
37 |
booklyAlert({error: [BooklyL10n.limitations]});
|
38 |
+
$(this).prop('disabled', true);
|
39 |
});
|
40 |
});
|
backend/modules/notifications/templates/_codes.php
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) ),
|
4 |
-
array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) ),
|
5 |
-
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) ),
|
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' ) ),
|
13 |
-
array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) ),
|
14 |
-
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
15 |
-
array( 'code' => 'company_logo', 'description' => __( 'company logo', 'bookly' ) ),
|
16 |
-
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
17 |
-
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
18 |
-
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
19 |
-
array( 'code' => 'custom_fields', 'description' => __( 'combined values of all custom fields', 'bookly' ) ),
|
20 |
-
array( 'code' => 'custom_fields_2c', 'description' => __( 'combined values of all custom fields (formatted in 2 columns)', 'bookly' ) ),
|
21 |
-
array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) ),
|
22 |
-
array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) ),
|
23 |
-
array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) ),
|
24 |
-
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) ),
|
25 |
-
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) ),
|
26 |
-
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) ),
|
27 |
-
array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) ),
|
28 |
-
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) ),
|
29 |
-
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
30 |
-
array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', '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
DELETED
@@ -1,16 +0,0 @@
|
|
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/_codes_client_new_wp_user.php
DELETED
@@ -1,15 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
4 |
-
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
5 |
-
array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) ),
|
6 |
-
array( 'code' => 'company_name', 'description' => __( 'name of your company', 'bookly' ) ),
|
7 |
-
array( 'code' => 'company_logo', 'description' => __( 'your company logo', 'bookly' ) ),
|
8 |
-
array( 'code' => 'company_address', 'description' => __( 'address of your company', 'bookly' ) ),
|
9 |
-
array( 'code' => 'company_phone', 'description' => __( 'your company phone', 'bookly' ) ),
|
10 |
-
array( 'code' => 'company_website', 'description' => __( 'this web-site address', 'bookly' ) ),
|
11 |
-
array( 'code' => 'new_username', 'description' => __( 'customer new username', 'bookly' ) ),
|
12 |
-
array( 'code' => 'new_password', 'description' => __( 'customer new password', 'bookly' ) ),
|
13 |
-
array( 'code' => 'site_address', 'description' => __( 'site address', 'bookly' ) ),
|
14 |
-
);
|
15 |
-
\BooklyLite\Lib\Utils\Common::Codes( $codes );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/notifications/templates/_codes_staff_agenda.php
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'tomorrow_date', 'description' => __( 'date of next day', 'bookly' ) ),
|
4 |
-
array( 'code' => 'next_day_agenda', 'description' => __( 'staff agenda for next day', 'bookly' ) ),
|
5 |
-
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
6 |
-
);
|
7 |
-
\BooklyLite\Lib\Utils\Common::Codes( $codes );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/{customers/templates/_export.php → notifications/templates/_custom_notification.php}
RENAMED
@@ -1 +1 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
backend/modules/notifications/templates/_test_email_notifications_modal.php
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<div ng-controller=testEmailNotificationsDialogCtrl>
|
3 |
-
<div id=
|
4 |
<div class="modal-dialog">
|
5 |
<div class="modal-content">
|
6 |
<div ng-show=loading class="bookly-loading"></div>
|
@@ -83,6 +83,7 @@
|
|
83 |
</div>
|
84 |
</div>
|
85 |
<div class="modal-footer">
|
|
|
86 |
<?php \BooklyLite\Lib\Utils\Common::submitButton( '', '', __( 'Send', 'bookly' ) ) ?>
|
87 |
</div>
|
88 |
</form>
|
@@ -91,7 +92,7 @@
|
|
91 |
</div><!-- /.modal-dialog -->
|
92 |
</div><!-- /.modal -->
|
93 |
|
94 |
-
<div class="modal fade" id="
|
95 |
<div class="modal-dialog" role="document">
|
96 |
<div class="modal-content">
|
97 |
<div class="modal-header">
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<div ng-controller=testEmailNotificationsDialogCtrl>
|
3 |
+
<div id=bookly-test-email-notifications-dialog class="modal fade" tabindex=-1 role="dialog">
|
4 |
<div class="modal-dialog">
|
5 |
<div class="modal-content">
|
6 |
<div ng-show=loading class="bookly-loading"></div>
|
83 |
</div>
|
84 |
</div>
|
85 |
<div class="modal-footer">
|
86 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
87 |
<?php \BooklyLite\Lib\Utils\Common::submitButton( '', '', __( 'Send', 'bookly' ) ) ?>
|
88 |
</div>
|
89 |
</form>
|
92 |
</div><!-- /.modal-dialog -->
|
93 |
</div><!-- /.modal -->
|
94 |
|
95 |
+
<div class="modal fade" id="bookly-modal" tabindex="-1" role="dialog">
|
96 |
<div class="modal-dialog" role="document">
|
97 |
<div class="modal-content">
|
98 |
<div class="modal-header">
|
backend/modules/notifications/templates/index.php
CHANGED
@@ -1,10 +1,15 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
|
|
|
|
|
|
|
|
|
|
8 |
?>
|
9 |
<div id="bookly-tbs" class="wrap">
|
10 |
<div class="bookly-tbs-body" ng-app="notifications">
|
@@ -12,9 +17,9 @@
|
|
12 |
<div class="bookly-page-title">
|
13 |
<?php _e( 'Email Notifications', 'bookly' ) ?>
|
14 |
</div>
|
15 |
-
<?php
|
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">
|
@@ -27,50 +32,48 @@
|
|
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
|
31 |
</div>
|
32 |
</div>
|
33 |
<div class="col-md-6">
|
34 |
-
<?php
|
35 |
array( array( 'html', __( 'HTML', 'bookly' ) ), array( 'text', __( 'Text', 'bookly' ) ) )
|
36 |
) ?>
|
37 |
</div>
|
38 |
<div class="col-md-6">
|
39 |
-
<?php
|
40 |
</div>
|
41 |
</div>
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
<div class="panel-group bookly-margin-vertical-xlg" id="single">
|
46 |
-
<?php foreach ( $form->
|
|
|
|
|
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 $
|
52 |
-
<input id="<?php echo $
|
53 |
-
<a href="#collapse_<?php echo
|
54 |
-
<?php echo
|
55 |
</a>
|
56 |
</label>
|
57 |
</div>
|
58 |
</div>
|
59 |
-
<div id="collapse_<?php echo $
|
60 |
<div class="panel-body">
|
61 |
|
62 |
-
<?php $form->renderSendingTime( $
|
63 |
-
<?php $form->renderSubject( $
|
64 |
-
<?php $form->renderEditor( $
|
65 |
-
<?php $form->
|
66 |
-
|
67 |
<div class="form-group">
|
68 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
69 |
-
<?php
|
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>
|
@@ -80,31 +83,35 @@
|
|
80 |
</div>
|
81 |
|
82 |
<?php if ( $form->types['combined'] ) : ?>
|
|
|
83 |
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Combined', 'bookly' ) ?></h4>
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
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 $
|
91 |
-
<input id="<?php echo $
|
92 |
-
<a href="#collapse_<?php echo
|
93 |
-
<?php echo
|
94 |
</a>
|
95 |
</label>
|
96 |
</div>
|
97 |
</div>
|
98 |
-
<div id="collapse_<?php echo $
|
99 |
<div class="panel-body">
|
100 |
-
|
101 |
-
<?php $form->
|
102 |
-
<?php $form->
|
|
|
103 |
|
104 |
<div class="form-group">
|
105 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
106 |
-
<?php
|
107 |
-
|
108 |
</div>
|
109 |
</div>
|
110 |
</div>
|
@@ -113,24 +120,51 @@
|
|
113 |
</div>
|
114 |
<?php endif ?>
|
115 |
|
116 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
|
118 |
<div class="alert alert-info">
|
119 |
-
|
120 |
-
<
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
125 |
</div>
|
126 |
</div>
|
127 |
|
128 |
<div class="panel-footer">
|
129 |
-
<?php
|
130 |
-
<?php
|
|
|
131 |
|
132 |
<div class="pull-left">
|
133 |
-
<button type="button" class="btn btn-default
|
134 |
<?php _e( 'Test Email Notifications', 'bookly' ) ?>
|
135 |
</button>
|
136 |
</div>
|
@@ -139,5 +173,24 @@
|
|
139 |
</form>
|
140 |
|
141 |
<?php include '_test_email_notifications_modal.php' ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
142 |
</div>
|
143 |
</div>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Entities\Notification;
|
3 |
+
use BooklyLite\Lib\Utils\Common;
|
4 |
+
use BooklyLite\Lib\Proxy;
|
5 |
+
use BooklyLite\Backend\Modules\Support;
|
6 |
+
|
7 |
+
$bookly_email_sender_name = get_option( 'bookly_email_sender_name' ) == '' ?
|
8 |
+
get_option( 'blogname' ) : get_option( 'bookly_email_sender_name' );
|
9 |
+
$bookly_email_sender = get_option( 'bookly_email_sender' ) == '' ?
|
10 |
+
get_option( 'admin_email' ) : get_option( 'bookly_email_sender' );
|
11 |
+
|
12 |
+
/** @var BooklyLite\Backend\Modules\Notifications\Forms\Notifications $form */
|
13 |
?>
|
14 |
<div id="bookly-tbs" class="wrap">
|
15 |
<div class="bookly-tbs-body" ng-app="notifications">
|
17 |
<div class="bookly-page-title">
|
18 |
<?php _e( 'Email Notifications', 'bookly' ) ?>
|
19 |
</div>
|
20 |
+
<?php Support\Components::getInstance()->renderButtons( $this::page_slug ) ?>
|
21 |
</div>
|
22 |
+
<form method="post" action="<?php echo Common::escAdminUrl( $this::page_slug ) ?>">
|
23 |
<div class="panel panel-default bookly-main" ng-controller="emailNotifications">
|
24 |
<div class="panel-body">
|
25 |
<div class="row">
|
32 |
<div class="col-md-6">
|
33 |
<div class="form-group">
|
34 |
<label for="sender_email"><?php _e( 'Sender email', 'bookly' ) ?></label>
|
35 |
+
<input id="sender_email" name="bookly_email_sender" class="form-control bookly-sender" type="text" value="<?php echo esc_attr( $bookly_email_sender ) ?>">
|
36 |
</div>
|
37 |
</div>
|
38 |
<div class="col-md-6">
|
39 |
+
<?php 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' ),
|
40 |
array( array( 'html', __( 'HTML', 'bookly' ) ), array( 'text', __( 'Text', 'bookly' ) ) )
|
41 |
) ?>
|
42 |
</div>
|
43 |
<div class="col-md-6">
|
44 |
+
<?php 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' ) ) ?>
|
45 |
</div>
|
46 |
</div>
|
47 |
+
|
48 |
+
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Single', 'bookly' ) ?></h4>
|
49 |
+
|
50 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="bookly-js-single-notifications">
|
51 |
+
<?php foreach ( $form->getNotifications( 'single' ) as $notification ) :
|
52 |
+
$id = $notification['id'];
|
53 |
+
?>
|
54 |
<div class="panel panel-default bookly-js-collapse">
|
55 |
<div class="panel-heading" role="tab">
|
56 |
<div class="checkbox bookly-margin-remove">
|
57 |
<label>
|
58 |
+
<input name="notification[<?php echo $id ?>][active]" value="0" type="checkbox" checked="checked" class="hidden">
|
59 |
+
<input id="<?php echo $id ?>_active" name="notification[<?php echo $id ?>][active]" value="1" type="checkbox" <?php checked( $notification['active'] ) ?>>
|
60 |
+
<a href="#collapse_<?php echo $id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#bookly-js-single-notifications">
|
61 |
+
<?php echo Notification::getName( $notification['type'] ) ?>
|
62 |
</a>
|
63 |
</label>
|
64 |
</div>
|
65 |
</div>
|
66 |
+
<div id="collapse_<?php echo $id ?>" class="panel-collapse collapse">
|
67 |
<div class="panel-body">
|
68 |
|
69 |
+
<?php $form->renderSendingTime( $notification ) ?>
|
70 |
+
<?php $form->renderSubject( $id ) ?>
|
71 |
+
<?php $form->renderEditor( $id ) ?>
|
72 |
+
<?php $form->renderAttachIcs( $notification ) ?>
|
73 |
+
<?php $form->renderCopy( $notification ) ?>
|
74 |
<div class="form-group">
|
75 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
76 |
+
<?php $form->renderCodes( $notification['type'] ) ?>
|
|
|
|
|
|
|
|
|
77 |
</div>
|
78 |
|
79 |
</div>
|
83 |
</div>
|
84 |
|
85 |
<?php if ( $form->types['combined'] ) : ?>
|
86 |
+
|
87 |
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Combined', 'bookly' ) ?></h4>
|
88 |
+
|
89 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="bookly-js-combined-notifications">
|
90 |
+
<?php foreach ( $form->getNotifications( 'combined' ) as $notification ) :
|
91 |
+
$id = $notification['id'];
|
92 |
+
?>
|
93 |
<div class="panel panel-default bookly-js-collapse">
|
94 |
<div class="panel-heading" role="tab">
|
95 |
<div class="checkbox bookly-margin-remove">
|
96 |
<label>
|
97 |
+
<input name="notification[<?php echo $id ?>][active]" value="0" type="checkbox" checked="checked" class="hidden">
|
98 |
+
<input id="<?php echo $id ?>_active" name="notification[<?php echo $id ?>][active]" value="1" type="checkbox" <?php checked( $notification['active'] ) ?>>
|
99 |
+
<a href="#collapse_<?php echo $id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#bookly-js-combined-notifications">
|
100 |
+
<?php echo Notification::getName( $notification['type'] ) ?>
|
101 |
</a>
|
102 |
</label>
|
103 |
</div>
|
104 |
</div>
|
105 |
+
<div id="collapse_<?php echo $id ?>" class="panel-collapse collapse">
|
106 |
<div class="panel-body">
|
107 |
+
|
108 |
+
<?php $form->renderSubject( $id ) ?>
|
109 |
+
<?php $form->renderEditor( $id ) ?>
|
110 |
+
<?php $form->renderCopy( $notification ) ?>
|
111 |
|
112 |
<div class="form-group">
|
113 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
114 |
+
<?php $form->renderCodes( $notification['type'] ) ?>
|
|
|
115 |
</div>
|
116 |
</div>
|
117 |
</div>
|
120 |
</div>
|
121 |
<?php endif ?>
|
122 |
|
123 |
+
<?php Proxy\Shared::renderEmailNotifications( $form ) ?>
|
124 |
+
|
125 |
+
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Custom', 'bookly' ) ?></h4>
|
126 |
+
|
127 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="bookly-js-custom-notifications">
|
128 |
+
<?php foreach ( $form->getNotifications( 'custom' ) as $notification ) :
|
129 |
+
$this->render( '_custom_notification', compact( 'form', 'notification', 'statuses' ) );
|
130 |
+
endforeach ?>
|
131 |
+
</div>
|
132 |
+
<div class="row">
|
133 |
+
<div class="col-sm-12">
|
134 |
+
<div class="form-group">
|
135 |
+
<button id="bookly-js-new-notification" type="button" class="btn btn-xlg btn-block btn-success-outline">
|
136 |
+
<span class="ladda-label"><i class="dashicons dashicons-plus-alt"></i>
|
137 |
+
<?php _e( 'New Notification', 'bookly' ) ?>
|
138 |
+
</span>
|
139 |
+
</button>
|
140 |
+
</div>
|
141 |
+
</div>
|
142 |
+
</div>
|
143 |
|
144 |
<div class="alert alert-info">
|
145 |
+
<div class="row">
|
146 |
+
<div class="col-md-10">
|
147 |
+
<?php if ( is_multisite() ) : ?>
|
148 |
+
<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>
|
149 |
+
<?php else : ?>
|
150 |
+
<p><?php _e( 'To send scheduled notifications please execute the following command hourly with your cron:', 'bookly' ) ?></p><br/>
|
151 |
+
<code class="bookly-text-wrap">wget -q -O - <?php echo $cron_uri ?></code>
|
152 |
+
<?php endif ?>
|
153 |
+
</div>
|
154 |
+
<div class="col-md-2">
|
155 |
+
<?php Common::optionToggle( 'bookly_ntf_processing_interval', __( 'Notification period', 'bookly' ), __( 'Set period of time when system will attempt to deliver notification to user. Notification will be discarded after period expiration.', 'bookly' ), $bookly_ntf_processing_interval_values ) ?>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
</div>
|
159 |
</div>
|
160 |
|
161 |
<div class="panel-footer">
|
162 |
+
<?php Common::csrf() ?>
|
163 |
+
<?php Common::submitButton() ?>
|
164 |
+
<?php Common::resetButton() ?>
|
165 |
|
166 |
<div class="pull-left">
|
167 |
+
<button type="button" class="btn btn-default bookly-test-email-notifications btn-lg">
|
168 |
<?php _e( 'Test Email Notifications', 'bookly' ) ?>
|
169 |
</button>
|
170 |
</div>
|
173 |
</form>
|
174 |
|
175 |
<?php include '_test_email_notifications_modal.php' ?>
|
176 |
+
|
177 |
+
<div class="modal fade" tabindex="-1" role="dialog" id="bookly-js-continue-confirm">
|
178 |
+
<div class="modal-dialog modal-lg" role="document">
|
179 |
+
<div class="modal-content">
|
180 |
+
<div class="modal-header">
|
181 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
182 |
+
<div class="modal-title h4"><?php _e( 'Are you sure?', 'bookly' ) ?></div>
|
183 |
+
</div>
|
184 |
+
<div class="modal-body">
|
185 |
+
<p><?php _e( 'When creating a new notification, the page will be reloaded, and all unsaved changes will be lost.', 'bookly' ) ?></p>
|
186 |
+
</div>
|
187 |
+
<div class="modal-footer">
|
188 |
+
<?php Common::customButton( null, 'btn-lg btn-success bookly-js-save', __( 'Save changes', 'bookly' ) ) ?>
|
189 |
+
<?php Common::customButton( null, 'btn-lg btn-danger bookly-js-continue', __( 'Continue without saving', 'bookly' ) ) ?>
|
190 |
+
<?php Common::customButton( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
191 |
+
</div>
|
192 |
+
</div>
|
193 |
+
</div>
|
194 |
+
</div>
|
195 |
</div>
|
196 |
</div>
|
backend/modules/payments/Controller.php
CHANGED
@@ -28,11 +28,12 @@ class Controller extends Lib\Base\Controller
|
|
28 |
global $wp_locale;
|
29 |
|
30 |
$this->enqueueStyles( array(
|
31 |
-
'
|
32 |
-
|
|
|
|
|
33 |
'css/daterangepicker.css',
|
34 |
),
|
35 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
36 |
) );
|
37 |
|
38 |
$this->enqueueScripts( array(
|
@@ -41,7 +42,7 @@ class Controller extends Lib\Base\Controller
|
|
41 |
'js/datatables.min.js' => array( 'jquery' ),
|
42 |
'js/moment.min.js',
|
43 |
'js/daterangepicker.js' => array( 'jquery' ),
|
44 |
-
'js/
|
45 |
),
|
46 |
'frontend' => array(
|
47 |
'js/spin.min.js' => array( 'jquery' ),
|
@@ -51,6 +52,7 @@ class Controller extends Lib\Base\Controller
|
|
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' ),
|
@@ -74,6 +76,7 @@ class Controller extends Lib\Base\Controller
|
|
74 |
'processing' => __( 'Processing...', 'bookly' ),
|
75 |
'details' => __( 'Details', 'bookly' ),
|
76 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
|
|
77 |
) );
|
78 |
|
79 |
$types = array(
|
@@ -86,7 +89,7 @@ class Controller extends Lib\Base\Controller
|
|
86 |
Lib\Entities\Payment::TYPE_PAYSON,
|
87 |
Lib\Entities\Payment::TYPE_MOLLIE,
|
88 |
Lib\Entities\Payment::TYPE_COUPON,
|
89 |
-
Lib\Entities\Payment::
|
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();
|
@@ -104,7 +107,7 @@ class Controller extends Lib\Base\Controller
|
|
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.
|
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' )
|
@@ -118,15 +121,15 @@ class Controller extends Lib\Base\Controller
|
|
118 |
|
119 |
$query->whereBetween( 'p.created', $start, $end );
|
120 |
|
121 |
-
if ( $filter['type'] !=
|
122 |
$query->where( 'p.type', $filter['type'] );
|
123 |
}
|
124 |
|
125 |
-
if ( $filter['staff'] !=
|
126 |
$query->where( 'st.id', $filter['staff'] );
|
127 |
}
|
128 |
|
129 |
-
if ( $filter['service']
|
130 |
$query->where( 's.id', $filter['service'] );
|
131 |
}
|
132 |
|
@@ -145,9 +148,9 @@ class Controller extends Lib\Base\Controller
|
|
145 |
? ' <span class="glyphicon glyphicon-shopping-cart" title="' . esc_attr( __( 'See details for more items', 'bookly' ) ) . '"></span>'
|
146 |
: '' ;
|
147 |
|
148 |
-
$paid_title = Lib\Utils\
|
149 |
if ( $payment['paid'] != $payment['total'] ) {
|
150 |
-
$paid_title = sprintf( __( '%s of %s', 'bookly' ), $paid_title, Lib\Utils\
|
151 |
}
|
152 |
|
153 |
$data[] = array(
|
@@ -173,7 +176,7 @@ class Controller extends Lib\Base\Controller
|
|
173 |
'recordsTotal' => count( $data ),
|
174 |
'recordsFiltered' => count( $data ),
|
175 |
'data' => $data,
|
176 |
-
'total' => Lib\Utils\
|
177 |
) );
|
178 |
}
|
179 |
|
@@ -192,7 +195,7 @@ class Controller extends Lib\Base\Controller
|
|
192 |
p.type,
|
193 |
p.details,
|
194 |
p.paid,
|
195 |
-
c.
|
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' ) )
|
@@ -210,7 +213,7 @@ class Controller extends Lib\Base\Controller
|
|
210 |
'paid' => $payment['paid'],
|
211 |
),
|
212 |
'items' => $details['items'],
|
213 |
-
'deposit_enabled' => Lib\Config::
|
214 |
);
|
215 |
}
|
216 |
|
@@ -234,33 +237,21 @@ class Controller extends Lib\Base\Controller
|
|
234 |
{
|
235 |
$payment = Lib\Entities\Payment::find( $this->getParameter( 'payment_id' ) );
|
236 |
$payment
|
237 |
-
->
|
238 |
-
->
|
239 |
->save();
|
240 |
|
241 |
-
$payment_title = Lib\Utils\
|
242 |
-
if ( $payment->
|
243 |
-
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\
|
244 |
}
|
245 |
$payment_title .= sprintf(
|
246 |
' %s <span%s>%s</span>',
|
247 |
-
Lib\Entities\Payment::typeToString( $payment->
|
248 |
-
$payment->
|
249 |
-
Lib\Entities\Payment::statusToString( $payment->
|
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 |
}
|
28 |
global $wp_locale;
|
29 |
|
30 |
$this->enqueueStyles( array(
|
31 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
32 |
+
'backend' => array(
|
33 |
+
'css/select2.min.css',
|
34 |
+
'bootstrap/css/bootstrap-theme.min.css' => array( 'bookly-select2.min.css' ),
|
35 |
'css/daterangepicker.css',
|
36 |
),
|
|
|
37 |
) );
|
38 |
|
39 |
$this->enqueueScripts( array(
|
42 |
'js/datatables.min.js' => array( 'jquery' ),
|
43 |
'js/moment.min.js',
|
44 |
'js/daterangepicker.js' => array( 'jquery' ),
|
45 |
+
'js/select2.full.min.js' => array( 'jquery' ),
|
46 |
),
|
47 |
'frontend' => array(
|
48 |
'js/spin.min.js' => array( 'jquery' ),
|
52 |
) );
|
53 |
|
54 |
wp_localize_script( 'bookly-daterangepicker.js', 'BooklyL10n', array(
|
55 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
56 |
'today' => __( 'Today', 'bookly' ),
|
57 |
'yesterday' => __( 'Yesterday', 'bookly' ),
|
58 |
'last_7' => __( 'Last 7 Days', 'bookly' ),
|
76 |
'processing' => __( 'Processing...', 'bookly' ),
|
77 |
'details' => __( 'Details', 'bookly' ),
|
78 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
79 |
+
'no_result_found' => __( 'No result found', 'bookly' )
|
80 |
) );
|
81 |
|
82 |
$types = array(
|
89 |
Lib\Entities\Payment::TYPE_PAYSON,
|
90 |
Lib\Entities\Payment::TYPE_MOLLIE,
|
91 |
Lib\Entities\Payment::TYPE_COUPON,
|
92 |
+
Lib\Entities\Payment::TYPE_WOOCOMMERCE,
|
93 |
);
|
94 |
$providers = Lib\Entities\Staff::query()->select( 'id, full_name' )->sortBy( 'full_name' )->fetchArray();
|
95 |
$services = Lib\Entities\Service::query()->select( 'id, title' )->sortBy( 'title' )->fetchArray();
|
107 |
$filter = $this->getParameter( 'filter' );
|
108 |
|
109 |
$query = Lib\Entities\Payment::query( 'p' )
|
110 |
+
->select( 'p.id, p.created, p.type, p.paid, p.total, p.status, p.details, c.full_name customer, st.full_name provider, s.title service, a.start_date' )
|
111 |
->leftJoin( 'CustomerAppointment', 'ca', 'ca.payment_id = p.id' )
|
112 |
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
113 |
->leftJoin( 'Appointment', 'a', 'a.id = ca.appointment_id' )
|
121 |
|
122 |
$query->whereBetween( 'p.created', $start, $end );
|
123 |
|
124 |
+
if ( $filter['type'] != '' ) {
|
125 |
$query->where( 'p.type', $filter['type'] );
|
126 |
}
|
127 |
|
128 |
+
if ( $filter['staff'] != '' ) {
|
129 |
$query->where( 'st.id', $filter['staff'] );
|
130 |
}
|
131 |
|
132 |
+
if ( $filter['service'] != '' ) {
|
133 |
$query->where( 's.id', $filter['service'] );
|
134 |
}
|
135 |
|
148 |
? ' <span class="glyphicon glyphicon-shopping-cart" title="' . esc_attr( __( 'See details for more items', 'bookly' ) ) . '"></span>'
|
149 |
: '' ;
|
150 |
|
151 |
+
$paid_title = Lib\Utils\Price::format( $payment['paid'] );
|
152 |
if ( $payment['paid'] != $payment['total'] ) {
|
153 |
+
$paid_title = sprintf( __( '%s of %s', 'bookly' ), $paid_title, Lib\Utils\Price::format( $payment['total'] ) );
|
154 |
}
|
155 |
|
156 |
$data[] = array(
|
176 |
'recordsTotal' => count( $data ),
|
177 |
'recordsFiltered' => count( $data ),
|
178 |
'data' => $data,
|
179 |
+
'total' => Lib\Utils\Price::format( $total ),
|
180 |
) );
|
181 |
}
|
182 |
|
195 |
p.type,
|
196 |
p.details,
|
197 |
p.paid,
|
198 |
+
c.full_name AS customer' )
|
199 |
->leftJoin( 'CustomerAppointment', 'ca', 'ca.payment_id = p.id' )
|
200 |
->leftJoin( 'Customer', 'c', 'c.id = ca.customer_id' )
|
201 |
->where( 'p.id', $this->getParameter( 'payment_id' ) )
|
213 |
'paid' => $payment['paid'],
|
214 |
),
|
215 |
'items' => $details['items'],
|
216 |
+
'deposit_enabled' => Lib\Config::depositPaymentsEnabled()
|
217 |
);
|
218 |
}
|
219 |
|
237 |
{
|
238 |
$payment = Lib\Entities\Payment::find( $this->getParameter( 'payment_id' ) );
|
239 |
$payment
|
240 |
+
->setPaid( $payment->getTotal() )
|
241 |
+
->setStatus( Lib\Entities\Payment::STATUS_COMPLETED )
|
242 |
->save();
|
243 |
|
244 |
+
$payment_title = Lib\Utils\Price::format( $payment->getPaid() );
|
245 |
+
if ( $payment->getPaid() != $payment->getTotal() ) {
|
246 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $payment->getTotal() ) );
|
247 |
}
|
248 |
$payment_title .= sprintf(
|
249 |
' %s <span%s>%s</span>',
|
250 |
+
Lib\Entities\Payment::typeToString( $payment->getType() ),
|
251 |
+
$payment->getStatus() == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
252 |
+
Lib\Entities\Payment::statusToString( $payment->getStatus() )
|
253 |
);
|
254 |
|
255 |
wp_send_json_success( array( 'payment_title' => $payment_title ) );
|
256 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
257 |
}
|
backend/modules/payments/resources/js/ng-payment_details_dialog.js
CHANGED
@@ -20,7 +20,7 @@
|
|
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,7 +30,7 @@
|
|
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) {
|
20 |
}
|
21 |
jQuery.ajax({
|
22 |
url: ajaxurl,
|
23 |
+
data: {action: 'bookly_get_payment_details', payment_id: payment_id, csrf_token : BooklyL10n.csrf_token},
|
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, csrf_token : BooklyL10n.csrf_token},
|
34 |
dataType: 'json',
|
35 |
type: 'POST',
|
36 |
success: function (response) {
|
backend/modules/payments/resources/js/payments.js
CHANGED
@@ -10,7 +10,19 @@ jQuery(function($) {
|
|
10 |
$payment_total = $('#bookly-payment-total'),
|
11 |
$delete_button = $('#bookly-delete')
|
12 |
;
|
13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
/**
|
15 |
* Init DataTables.
|
16 |
*/
|
@@ -24,9 +36,11 @@ jQuery(function($) {
|
|
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(),
|
@@ -131,13 +145,7 @@ jQuery(function($) {
|
|
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(); });
|
@@ -162,16 +170,17 @@ jQuery(function($) {
|
|
162 |
type : 'POST',
|
163 |
data : {
|
164 |
action : 'bookly_delete_payments',
|
165 |
-
|
|
|
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 |
}
|
10 |
$payment_total = $('#bookly-payment-total'),
|
11 |
$delete_button = $('#bookly-delete')
|
12 |
;
|
13 |
+
$('.bookly-js-select')
|
14 |
+
.val(null)
|
15 |
+
.on('select2:unselecting', function(e) {
|
16 |
+
e.preventDefault();
|
17 |
+
$(this).val(null).trigger('change');
|
18 |
+
})
|
19 |
+
.select2({
|
20 |
+
allowClear: true,
|
21 |
+
theme: 'bootstrap',
|
22 |
+
language: {
|
23 |
+
noResults: function() { return BooklyL10n.no_result_found; }
|
24 |
+
}
|
25 |
+
});
|
26 |
/**
|
27 |
* Init DataTables.
|
28 |
*/
|
36 |
serverSide: true,
|
37 |
ajax: {
|
38 |
url: ajaxurl,
|
39 |
+
type: 'POST',
|
40 |
data: function ( d ) {
|
41 |
return $.extend( {}, d, {
|
42 |
action: 'bookly_get_payments',
|
43 |
+
csrf_token: BooklyL10n.csrf_token,
|
44 |
filter: {
|
45 |
created: $date_filter.data('date'),
|
46 |
type: $type_filter.val(),
|
145 |
}
|
146 |
);
|
147 |
|
148 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
149 |
$date_filter.on('apply.daterangepicker', function () { dt.ajax.reload(); });
|
150 |
$type_filter.on('change', function () { dt.ajax.reload(); });
|
151 |
$staff_filter.on('change', function () { dt.ajax.reload(); });
|
170 |
type : 'POST',
|
171 |
data : {
|
172 |
action : 'bookly_delete_payments',
|
173 |
+
csrf_token : BooklyL10n.csrf_token,
|
174 |
+
data : data
|
175 |
},
|
176 |
dataType : 'json',
|
177 |
success : function(response) {
|
|
|
178 |
if (response.success) {
|
179 |
dt.rows($checkboxes.closest('td')).remove().draw();
|
180 |
} else {
|
181 |
alert(response.data.message);
|
182 |
}
|
183 |
+
ladda.stop();
|
184 |
}
|
185 |
});
|
186 |
}
|
backend/modules/payments/templates/details.php
CHANGED
@@ -1,6 +1,11 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
4 |
?>
|
5 |
<?php if ( $payment ) : ?>
|
6 |
<div class="table-responsive">
|
@@ -15,9 +20,9 @@
|
|
15 |
<tr>
|
16 |
<td><?php echo $payment['customer'] ?></td>
|
17 |
<td>
|
18 |
-
<div><?php _e( 'Date', 'bookly' ) ?>: <?php echo
|
19 |
-
<div><?php _e( 'Type', 'bookly' ) ?>: <?php echo
|
20 |
-
<div><?php _e( 'Status', 'bookly' ) ?>: <?php echo
|
21 |
</td>
|
22 |
</tr>
|
23 |
</tbody>
|
@@ -52,14 +57,14 @@
|
|
52 |
</ul>
|
53 |
<?php endif ?>
|
54 |
</td>
|
55 |
-
<td><?php echo
|
56 |
<td><?php echo $item['staff_name'] ?></td>
|
57 |
-
<?php $deposit =
|
58 |
<?php if ( $deposit_enabled ) : ?>
|
59 |
-
<td class="text-right"><?php echo
|
60 |
<?php endif ?>
|
61 |
<td class="text-right">
|
62 |
-
<?php $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">
|
@@ -68,7 +73,7 @@
|
|
68 |
<?php printf( '%s%s%s',
|
69 |
( $item['number_of_persons'] > 1 ) ? $item['number_of_persons'] . ' × ' : '',
|
70 |
( $extra['quantity'] > 1 ) ? $extra['quantity'] . ' × ' : '',
|
71 |
-
|
72 |
) ?>
|
73 |
</li>
|
74 |
<?php $subtotal += $item['number_of_persons'] * $extra['price'] * $extra['quantity'] ?>
|
@@ -85,9 +90,9 @@
|
|
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
|
89 |
<?php endif ?>
|
90 |
-
<th class="text-right"><?php echo
|
91 |
</tr>
|
92 |
<tr>
|
93 |
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>">
|
@@ -100,26 +105,26 @@
|
|
100 |
<div>-<?php echo $payment['coupon']['discount'] ?>%</div>
|
101 |
<?php endif ?>
|
102 |
<?php if ( $payment['coupon']['deduction'] ) : ?>
|
103 |
-
<div><?php echo
|
104 |
<?php endif ?>
|
105 |
<?php else : ?>
|
106 |
-
<?php echo
|
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
|
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
|
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
|
123 |
</tr>
|
124 |
<tr>
|
125 |
<td style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Price;
|
3 |
+
use BooklyLite\Lib\Utils\DateTime;
|
4 |
+
use BooklyLite\Lib\Entities;
|
5 |
+
use BooklyLite\Lib\Proxy;
|
6 |
+
|
7 |
+
$subtotal = 0;
|
8 |
+
$subtotal_deposit = 0;
|
9 |
?>
|
10 |
<?php if ( $payment ) : ?>
|
11 |
<div class="table-responsive">
|
20 |
<tr>
|
21 |
<td><?php echo $payment['customer'] ?></td>
|
22 |
<td>
|
23 |
+
<div><?php _e( 'Date', 'bookly' ) ?>: <?php echo DateTime::formatDateTime( $payment['created'] ) ?></div>
|
24 |
+
<div><?php _e( 'Type', 'bookly' ) ?>: <?php echo Entities\Payment::typeToString( $payment['type'] ) ?></div>
|
25 |
+
<div><?php _e( 'Status', 'bookly' ) ?>: <?php echo Entities\Payment::statusToString( $payment['status'] ) ?></div>
|
26 |
</td>
|
27 |
</tr>
|
28 |
</tbody>
|
57 |
</ul>
|
58 |
<?php endif ?>
|
59 |
</td>
|
60 |
+
<td><?php echo DateTime::formatDateTime( $item['appointment_date'] ) ?></td>
|
61 |
<td><?php echo $item['staff_name'] ?></td>
|
62 |
+
<?php $deposit = Proxy\DepositPayments::prepareAmount( $item['number_of_persons'] * ( $item['service_price'] + $extras_price ), $item['deposit'], $item['number_of_persons'] ) ?>
|
63 |
<?php if ( $deposit_enabled ) : ?>
|
64 |
+
<td class="text-right"><?php echo Proxy\DepositPayments::formatDeposit( $deposit, $item['deposit'] ) ?></td>
|
65 |
<?php endif ?>
|
66 |
<td class="text-right">
|
67 |
+
<?php $service_price = Price::format( $item['service_price'] ) ?>
|
68 |
<?php if ( $item['number_of_persons'] > 1 ) $service_price = $item['number_of_persons'] . ' × ' . $service_price ?>
|
69 |
<?php echo $service_price ?>
|
70 |
<ul class="bookly-list">
|
73 |
<?php printf( '%s%s%s',
|
74 |
( $item['number_of_persons'] > 1 ) ? $item['number_of_persons'] . ' × ' : '',
|
75 |
( $extra['quantity'] > 1 ) ? $extra['quantity'] . ' × ' : '',
|
76 |
+
Price::format( $extra['price'] )
|
77 |
) ?>
|
78 |
</li>
|
79 |
<?php $subtotal += $item['number_of_persons'] * $extra['price'] * $extra['quantity'] ?>
|
90 |
<th rowspan="3" style="border-left-color: white; border-bottom-color: white;"></th>
|
91 |
<th colspan="2"><?php _e( 'Subtotal', 'bookly' ) ?></th>
|
92 |
<?php if ( $deposit_enabled ) : ?>
|
93 |
+
<th class="text-right"><?php echo Price::format( $subtotal_deposit ) ?></th>
|
94 |
<?php endif ?>
|
95 |
+
<th class="text-right"><?php echo Price::format( $subtotal ) ?></th>
|
96 |
</tr>
|
97 |
<tr>
|
98 |
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>">
|
105 |
<div>-<?php echo $payment['coupon']['discount'] ?>%</div>
|
106 |
<?php endif ?>
|
107 |
<?php if ( $payment['coupon']['deduction'] ) : ?>
|
108 |
+
<div><?php echo Price::format( -$payment['coupon']['deduction'] ) ?></div>
|
109 |
<?php endif ?>
|
110 |
<?php else : ?>
|
111 |
+
<?php echo Price::format( 0 ) ?>
|
112 |
<?php endif ?>
|
113 |
</th>
|
114 |
</tr>
|
115 |
<tr>
|
116 |
<th colspan="<?php echo 2 + (int) $deposit_enabled ?>"><?php _e( 'Total', 'bookly' ) ?></th>
|
117 |
+
<th class="text-right"><?php echo Price::format( $payment['total'] ) ?></th>
|
118 |
</tr>
|
119 |
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
120 |
<tr>
|
121 |
<td rowspan="2" style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
122 |
<td colspan="<?php echo 2 + (int) $deposit_enabled ?>"><i><?php _e( 'Paid', 'bookly' ) ?></i></td>
|
123 |
+
<td class="text-right"><i><?php echo Price::format( $payment['paid'] ) ?></i></td>
|
124 |
</tr>
|
125 |
<tr>
|
126 |
<td colspan="<?php echo 2 + (int) $deposit_enabled ?>"><i><?php _e( 'Due', 'bookly' ) ?></i></td>
|
127 |
+
<td class="text-right"><i><?php echo Price::format( $payment['total'] - $payment['paid'] ) ?></i></td>
|
128 |
</tr>
|
129 |
<tr>
|
130 |
<td style="border-left-color:#fff;border-bottom-color:#fff;"></td>
|
backend/modules/payments/templates/index.php
CHANGED
@@ -22,8 +22,7 @@
|
|
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-
|
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 ) ?>
|
@@ -34,8 +33,7 @@
|
|
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-
|
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 ?>
|
@@ -44,8 +42,7 @@
|
|
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-
|
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 ?>
|
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-select" data-placeholder="<?php esc_attr_e( 'Type', 'bookly' ) ?>">
|
|
|
26 |
<?php foreach ( $types as $type ) : ?>
|
27 |
<option value="<?php echo esc_attr( $type ) ?>">
|
28 |
<?php echo \BooklyLite\Lib\Entities\Payment::typeToString( $type ) ?>
|
33 |
</div>
|
34 |
<div class="col-md-3 col-lg-2">
|
35 |
<div class="form-group">
|
36 |
+
<select id="bookly-filter-staff" class="form-control bookly-js-select" data-placeholder="<?php esc_attr_e( 'Provider', 'bookly' ) ?>">
|
|
|
37 |
<?php foreach ( $providers as $provider ) : ?>
|
38 |
<option value="<?php echo $provider['id'] ?>"><?php echo esc_html( $provider['full_name'] ) ?></option>
|
39 |
<?php endforeach ?>
|
42 |
</div>
|
43 |
<div class="col-md-3 col-lg-2">
|
44 |
<div class="form-group">
|
45 |
+
<select id="bookly-filter-service" class="form-control bookly-js-select" data-placeholder="<?php esc_attr_e( 'Service', 'bookly' ) ?>">
|
|
|
46 |
<?php foreach ( $services as $service ) : ?>
|
47 |
<option value="<?php echo $service['id'] ?>"><?php echo esc_html( $service['title'] ) ?></option>
|
48 |
<?php endforeach ?>
|
backend/modules/services/Controller.php
CHANGED
@@ -38,20 +38,26 @@ class Controller extends Lib\Base\Controller
|
|
38 |
)
|
39 |
) );
|
40 |
|
|
|
|
|
|
|
|
|
|
|
|
|
41 |
wp_localize_script( 'bookly-service.js', 'BooklyL10n', array(
|
42 |
-
'
|
43 |
-
'
|
44 |
-
'
|
45 |
-
'
|
|
|
|
|
|
|
46 |
) );
|
47 |
|
48 |
// Allow add-ons to enqueue their assets.
|
49 |
-
|
50 |
|
51 |
-
$
|
52 |
-
$category_collection = $this->getCategoryCollection();
|
53 |
-
$service_collection = $this->getServiceCollection();
|
54 |
-
$this->render( 'index', compact( 'staff_collection', 'category_collection', 'service_collection' ) );
|
55 |
}
|
56 |
|
57 |
/**
|
@@ -59,23 +65,25 @@ class Controller extends Lib\Base\Controller
|
|
59 |
*/
|
60 |
public function executeGetCategoryServices()
|
61 |
{
|
62 |
-
$this->
|
63 |
-
wp_send_json_success( $this->render( '_list', array(), false ) );
|
64 |
}
|
65 |
|
66 |
/**
|
67 |
*
|
68 |
*/
|
69 |
-
public function
|
70 |
{
|
|
|
71 |
if ( ! empty ( $_POST ) ) {
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
|
|
|
|
76 |
}
|
77 |
}
|
78 |
-
|
79 |
}
|
80 |
|
81 |
/**
|
@@ -97,7 +105,7 @@ class Controller extends Lib\Base\Controller
|
|
97 |
foreach ( $category_sorts as $position => $category_id ) {
|
98 |
$category_sort = new Lib\Entities\Category();
|
99 |
$category_sort->load( $category_id );
|
100 |
-
$category_sort->
|
101 |
$category_sort->save();
|
102 |
}
|
103 |
}
|
@@ -111,18 +119,46 @@ class Controller extends Lib\Base\Controller
|
|
111 |
foreach ( $services_sorts as $position => $service_ids ) {
|
112 |
$services_sort = new Lib\Entities\Service();
|
113 |
$services_sort->load( $service_ids );
|
114 |
-
$services_sort->
|
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->
|
126 |
$category->delete();
|
127 |
}
|
128 |
|
@@ -130,19 +166,23 @@ class Controller extends Lib\Base\Controller
|
|
130 |
{
|
131 |
$form = new Forms\Service();
|
132 |
$form->bind( $this->getPostParameters() );
|
133 |
-
$form->getObject()->
|
134 |
$service = $form->save();
|
135 |
-
$this->
|
136 |
-
|
137 |
-
wp_send_json_success( array( 'html' => $this->render( '_list',
|
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 |
/**
|
@@ -158,82 +198,80 @@ class Controller extends Lib\Base\Controller
|
|
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->
|
163 |
} else {
|
164 |
-
Lib\Entities\StaffService::query()->delete()->where( 'service_id', $service->
|
165 |
-
if ( $
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
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 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
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 |
-
|
216 |
-
|
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 |
-
|
|
|
|
|
|
|
|
|
223 |
}
|
224 |
|
225 |
/**
|
|
|
|
|
226 |
* @param int $category_id
|
|
|
227 |
*/
|
228 |
-
private function
|
229 |
{
|
230 |
if ( ! $category_id ) {
|
231 |
$category_id = $this->getParameter( 'category_id', 0 );
|
232 |
}
|
233 |
|
234 |
-
|
235 |
-
|
236 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
237 |
}
|
238 |
|
239 |
/**
|
@@ -259,35 +297,36 @@ class Controller extends Lib\Base\Controller
|
|
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 $
|
271 |
}
|
272 |
|
273 |
public function executeUpdateExtraPosition()
|
274 |
{
|
275 |
-
|
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 |
}
|
38 |
)
|
39 |
) );
|
40 |
|
41 |
+
$data = $this->getCaSeStSpCollections();
|
42 |
+
$staff = array();
|
43 |
+
foreach ( $data['staff_collection'] as $employee ) {
|
44 |
+
$staff[ $employee['id'] ] = $employee['full_name'];
|
45 |
+
}
|
46 |
+
|
47 |
wp_localize_script( 'bookly-service.js', 'BooklyL10n', array(
|
48 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
49 |
+
'capacity_error' => __( 'Min capacity should not be greater than max capacity.', 'bookly' ),
|
50 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
51 |
+
'service_special_day' => Lib\Config::specialDaysEnabled() && Lib\Config::specialDaysEnabled(),
|
52 |
+
'reorder' => esc_attr__( 'Reorder', 'bookly' ),
|
53 |
+
'staff' => $staff,
|
54 |
+
'limitations' => __( '<b class="h4">This function is not available in the Lite version of Bookly.</b><br><br>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', 'bookly' ) . ' <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
55 |
) );
|
56 |
|
57 |
// Allow add-ons to enqueue their assets.
|
58 |
+
Lib\Proxy\Shared::enqueueAssetsForServices();
|
59 |
|
60 |
+
$this->render( 'index', $data );
|
|
|
|
|
|
|
61 |
}
|
62 |
|
63 |
/**
|
65 |
*/
|
66 |
public function executeGetCategoryServices()
|
67 |
{
|
68 |
+
wp_send_json_success( $this->render( '_list', $this->getCaSeStSpCollections(), false ) );
|
|
|
69 |
}
|
70 |
|
71 |
/**
|
72 |
*
|
73 |
*/
|
74 |
+
public function executeAddCategory()
|
75 |
{
|
76 |
+
$html = '';
|
77 |
if ( ! empty ( $_POST ) ) {
|
78 |
+
if ( $this->csrfTokenValid() ) {
|
79 |
+
$form = new Forms\Category();
|
80 |
+
$form->bind( $this->getPostParameters() );
|
81 |
+
if ( $category = $form->save() ) {
|
82 |
+
$html = $this->render( '_category_item', array( 'category' => $category->getFields() ), false );
|
83 |
+
}
|
84 |
}
|
85 |
}
|
86 |
+
wp_send_json_success( compact( 'html' ) );
|
87 |
}
|
88 |
|
89 |
/**
|
105 |
foreach ( $category_sorts as $position => $category_id ) {
|
106 |
$category_sort = new Lib\Entities\Category();
|
107 |
$category_sort->load( $category_id );
|
108 |
+
$category_sort->setPosition( $position );
|
109 |
$category_sort->save();
|
110 |
}
|
111 |
}
|
119 |
foreach ( $services_sorts as $position => $service_ids ) {
|
120 |
$services_sort = new Lib\Entities\Service();
|
121 |
$services_sort->load( $service_ids );
|
122 |
+
$services_sort->setPosition( $position );
|
123 |
$services_sort->save();
|
124 |
}
|
125 |
}
|
126 |
|
127 |
+
/**
|
128 |
+
* Reorder staff preferences for service
|
129 |
+
*/
|
130 |
+
public function executeUpdateServiceStaffPreferenceOrders()
|
131 |
+
{
|
132 |
+
$service_id = $this->getParameter( 'service_id' );
|
133 |
+
$positions = (array) $this->getParameter( 'positions' );
|
134 |
+
/** @var Lib\Entities\StaffPreferenceOrder[] $staff_preferences */
|
135 |
+
$staff_preferences = Lib\Entities\StaffPreferenceOrder::query()
|
136 |
+
->where( 'service_id', $service_id )
|
137 |
+
->indexBy( 'staff_id' )
|
138 |
+
->find();
|
139 |
+
foreach ( $positions as $position => $staff_id ) {
|
140 |
+
if ( array_key_exists( $staff_id, $staff_preferences ) ) {
|
141 |
+
$staff_preferences[ $staff_id ]->setPosition( $position )->save();
|
142 |
+
} else {
|
143 |
+
$preference = new Lib\Entities\StaffPreferenceOrder();
|
144 |
+
$preference
|
145 |
+
->setServiceId( $service_id )
|
146 |
+
->setStaffId( $staff_id )
|
147 |
+
->setPosition( $position )
|
148 |
+
->save();
|
149 |
+
}
|
150 |
+
}
|
151 |
+
|
152 |
+
wp_send_json_success();
|
153 |
+
}
|
154 |
+
|
155 |
/**
|
156 |
* Delete category.
|
157 |
*/
|
158 |
public function executeDeleteCategory()
|
159 |
{
|
160 |
$category = new Lib\Entities\Category();
|
161 |
+
$category->setId( $this->getParameter( 'id', 0 ) );
|
162 |
$category->delete();
|
163 |
}
|
164 |
|
166 |
{
|
167 |
$form = new Forms\Service();
|
168 |
$form->bind( $this->getPostParameters() );
|
169 |
+
$form->getObject()->setDuration( Lib\Config::getTimeSlotLength() );
|
170 |
$service = $form->save();
|
171 |
+
$data = $this->getCaSeStSpCollections( $service->getCategoryId() );
|
172 |
+
Lib\Proxy\Shared::serviceCreated( $service, $this->getPostParameters() );
|
173 |
+
wp_send_json_success( array( 'html' => $this->render( '_list', $data, false ), 'service_id' => $service->getId() ) );
|
174 |
}
|
175 |
|
176 |
public function executeRemoveServices()
|
177 |
{
|
178 |
$service_ids = $this->getParameter( 'service_ids', array() );
|
179 |
if ( is_array( $service_ids ) && ! empty ( $service_ids ) ) {
|
180 |
+
foreach ( $service_ids as $service_id ) {
|
181 |
+
Lib\Proxy\Shared::serviceDeleted( $service_id );
|
182 |
+
}
|
183 |
Lib\Entities\Service::query( 's' )->delete()->whereIn( 's.id', $service_ids )->execute();
|
184 |
}
|
185 |
+
wp_send_json_success();
|
186 |
}
|
187 |
|
188 |
/**
|
198 |
$service = $form->save();
|
199 |
|
200 |
$staff_ids = $this->getParameter( 'staff_ids', array() );
|
201 |
+
if ( empty ( $staff_ids ) ) {
|
202 |
+
Lib\Entities\StaffService::query()->delete()->where( 'service_id', $service->getId() )->execute();
|
203 |
} else {
|
204 |
+
Lib\Entities\StaffService::query()->delete()->where( 'service_id', $service->getId() )->whereNotIn( 'staff_id', $staff_ids )->execute();
|
205 |
+
if ( $service->getType() == Lib\Entities\Service::TYPE_SIMPLE ) {
|
206 |
+
if ( $this->getParameter( 'update_staff', false ) ) {
|
207 |
+
$data = array(
|
208 |
+
'price' => $this->getParameter( 'price' ),
|
209 |
+
'capacity_min' => 1,
|
210 |
+
'capacity_max' => 1,
|
211 |
+
);
|
212 |
+
$wpdb->update(
|
213 |
+
Lib\Entities\StaffService::getTableName(),
|
214 |
+
$data,
|
215 |
+
array( 'service_id' => $this->getParameter( 'id' ) )
|
216 |
+
);
|
|
|
|
|
|
|
|
|
|
|
217 |
}
|
218 |
+
// Create records for newly linked staff.
|
219 |
+
$existing_staff_ids = array();
|
220 |
+
$res = Lib\Entities\StaffService::query()
|
221 |
+
->select( 'staff_id' )
|
222 |
+
->where( 'service_id', $service->getId() )
|
223 |
+
->fetchArray();
|
224 |
+
foreach ( $res as $staff ) {
|
225 |
+
$existing_staff_ids[] = $staff['staff_id'];
|
226 |
+
}
|
227 |
+
foreach ( $staff_ids as $staff_id ) {
|
228 |
+
if ( ! in_array( $staff_id, $existing_staff_ids ) ) {
|
229 |
+
$staff_service = new Lib\Entities\StaffService();
|
230 |
+
$staff_service->setStaffId( $staff_id )
|
231 |
+
->setServiceId( $service->getId() )
|
232 |
+
->setPrice( $service->getPrice() )
|
233 |
+
->setCapacityMin( 1 )
|
234 |
+
->setCapacityMax( 1 )
|
235 |
+
->save();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
236 |
}
|
237 |
}
|
238 |
}
|
239 |
}
|
240 |
|
241 |
+
// Update services in addons.
|
242 |
+
$alert = Lib\Proxy\Shared::updateService( array( 'success' => array( __( 'Settings saved.', 'bookly' ) ) ), $service, $this->getPostParameters() );
|
|
|
|
|
|
|
|
|
243 |
|
244 |
+
$price = Lib\Utils\Price::format( $service->getPrice() );
|
245 |
+
$nice_duration = Lib\Utils\DateTime::secondsToInterval( $service->getDuration() );
|
246 |
+
$title = $service->getTitle();
|
247 |
+
$colors = array_fill( 0, 3, $service->getColor() );
|
248 |
+
wp_send_json_success( Lib\Proxy\Shared::prepareUpdateServiceResponse( compact( 'title', 'price', 'colors', 'nice_duration', 'alert' ), $service, $this->getPostParameters() ) );
|
249 |
}
|
250 |
|
251 |
/**
|
252 |
+
* Array for rendering service list.
|
253 |
+
*
|
254 |
* @param int $category_id
|
255 |
+
* @return array
|
256 |
*/
|
257 |
+
private function getCaSeStSpCollections( $category_id = 0 )
|
258 |
{
|
259 |
if ( ! $category_id ) {
|
260 |
$category_id = $this->getParameter( 'category_id', 0 );
|
261 |
}
|
262 |
|
263 |
+
return array(
|
264 |
+
'service_collection' => $this->getServiceCollection( $category_id ),
|
265 |
+
'staff_collection' => $this->getStaffCollection(),
|
266 |
+
'category_collection' => $this->getCategoryCollection(),
|
267 |
+
'staff_preference' => array(
|
268 |
+
Lib\Entities\Service::PREFERRED_ORDER => __( 'Specified order', 'bookly' ),
|
269 |
+
Lib\Entities\Service::PREFERRED_LEAST_OCCUPIED => __( 'Least occupied that day', 'bookly' ),
|
270 |
+
Lib\Entities\Service::PREFERRED_MOST_OCCUPIED => __( 'Most occupied that day', 'bookly' ),
|
271 |
+
Lib\Entities\Service::PREFERRED_LEAST_EXPENSIVE => __( 'Least expensive', 'bookly' ),
|
272 |
+
Lib\Entities\Service::PREFERRED_MOST_EXPENSIVE => __( 'Most expensive', 'bookly' ),
|
273 |
+
),
|
274 |
+
);
|
275 |
}
|
276 |
|
277 |
/**
|
297 |
private function getServiceCollection( $id = 0 )
|
298 |
{
|
299 |
$services = Lib\Entities\Service::query( 's' )
|
300 |
+
->select( 's.*, COUNT(staff.id) AS total_staff, GROUP_CONCAT(DISTINCT staff.id) AS staff_ids, GROUP_CONCAT(DISTINCT sp.staff_id ORDER BY sp.position ASC) AS pref_staff_ids' )
|
301 |
->leftJoin( 'StaffService', 'ss', 'ss.service_id = s.id' )
|
302 |
+
->leftJoin( 'StaffPreferenceOrder', 'sp', 'sp.service_id = s.id' )
|
303 |
->leftJoin( 'Staff', 'staff', 'staff.id = ss.staff_id' )
|
304 |
->whereRaw( 's.category_id = %d OR !%d', array( $id, $id ) )
|
305 |
->groupBy( 's.id' )
|
306 |
->indexBy( 'id' )
|
307 |
->sortBy( 's.position' );
|
308 |
+
if ( ! Lib\Config::packagesActive() ) {
|
309 |
+
$services->whereNot( 's.type', Lib\Entities\Service::TYPE_PACKAGE );
|
310 |
+
}
|
311 |
+
$result = $services->fetchArray();
|
312 |
+
foreach ( $result as &$service ) {
|
313 |
+
$service['sub_services'] = Lib\Entities\SubService::query()
|
314 |
+
->where( 'service_id', $service['id'] )
|
315 |
+
->sortBy( 'position' )
|
316 |
+
->fetchArray()
|
317 |
+
;
|
318 |
+
$service['sub_services_count'] = array_sum( array_map( function ( $sub_service ) {
|
319 |
+
return (int) ( $sub_service['type'] == Lib\Entities\SubService::TYPE_SERVICE );
|
320 |
+
}, $service['sub_services'] ) );
|
321 |
+
$service['colors'] = Lib\Proxy\Shared::prepareServiceColors( array_fill( 0, 3, $service['color'] ), $service['id'], $service['type'] );
|
322 |
+
}
|
323 |
|
324 |
+
return $result;
|
325 |
}
|
326 |
|
327 |
public function executeUpdateExtraPosition()
|
328 |
{
|
329 |
+
Lib\Proxy\ServiceExtras::reorder( $this->getParameter( 'position' ) );
|
|
|
330 |
wp_send_json_success();
|
331 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
332 |
}
|
backend/modules/services/forms/Category.php
CHANGED
@@ -5,6 +5,8 @@ use BooklyLite\Lib;
|
|
5 |
|
6 |
/**
|
7 |
* Class Category
|
|
|
|
|
8 |
* @package BooklyLite\Backend\Modules\Services\Forms
|
9 |
*/
|
10 |
class Category extends Lib\Base\Form
|
5 |
|
6 |
/**
|
7 |
* Class Category
|
8 |
+
* @method Lib\Entities\Category save()
|
9 |
+
*
|
10 |
* @package BooklyLite\Backend\Modules\Services\Forms
|
11 |
*/
|
12 |
class Category extends Lib\Base\Form
|
backend/modules/services/forms/Service.php
CHANGED
@@ -5,6 +5,8 @@ use BooklyLite\Lib;
|
|
5 |
|
6 |
/**
|
7 |
* Class Service
|
|
|
|
|
8 |
* @package BooklyLite\Backend\Modules\Services\Forms
|
9 |
*/
|
10 |
class Service extends Lib\Base\Form
|
@@ -20,18 +22,25 @@ class Service extends Lib\Base\Form
|
|
20 |
'price',
|
21 |
'category_id',
|
22 |
'color',
|
23 |
-
'
|
|
|
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 |
}
|
@@ -44,12 +53,11 @@ class Service extends Lib\Base\Form
|
|
44 |
*/
|
45 |
public function bind( array $_post, array $files = array() )
|
46 |
{
|
47 |
-
//
|
48 |
-
|
49 |
-
|
50 |
-
$_post[ $field_name ] = null;
|
51 |
-
}
|
52 |
}
|
|
|
53 |
parent::bind( $_post, $files );
|
54 |
}
|
55 |
|
@@ -63,13 +71,40 @@ class Service extends Lib\Base\Form
|
|
63 |
$this->data['color'] = sprintf( '#%06X', mt_rand( 0, 0x64FFFF ) );
|
64 |
}
|
65 |
|
66 |
-
if ( $this->data['type'] == Lib\Entities\Service::TYPE_SIMPLE
|
67 |
-
$this->data['
|
68 |
-
}
|
69 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
}
|
71 |
|
72 |
-
return
|
73 |
}
|
74 |
|
75 |
}
|
5 |
|
6 |
/**
|
7 |
* Class Service
|
8 |
+
* @method Lib\Entities\Service getObject
|
9 |
+
*
|
10 |
* @package BooklyLite\Backend\Modules\Services\Forms
|
11 |
*/
|
12 |
class Service extends Lib\Base\Form
|
22 |
'price',
|
23 |
'category_id',
|
24 |
'color',
|
25 |
+
'capacity_min',
|
26 |
+
'capacity_max',
|
27 |
'padding_left',
|
28 |
'padding_right',
|
29 |
+
'package_life_time',
|
30 |
+
'package_size',
|
31 |
+
'appointments_limit',
|
32 |
+
'limit_period',
|
33 |
'info',
|
34 |
+
'start_time_info',
|
35 |
+
'end_time_info',
|
36 |
'type',
|
37 |
'sub_services',
|
38 |
+
'staff_preference',
|
39 |
+
'recurrence_enabled',
|
40 |
+
'recurrence_frequencies',
|
41 |
'visibility',
|
42 |
+
'positions',
|
43 |
);
|
|
|
|
|
|
|
|
|
44 |
|
45 |
$this->setFields( $fields );
|
46 |
}
|
53 |
*/
|
54 |
public function bind( array $_post, array $files = array() )
|
55 |
{
|
56 |
+
// Field with NULL
|
57 |
+
if ( array_key_exists( 'category_id', $_post ) && ! $_post['category_id'] ) {
|
58 |
+
$_post['category_id'] = null;
|
|
|
|
|
59 |
}
|
60 |
+
|
61 |
parent::bind( $_post, $files );
|
62 |
}
|
63 |
|
71 |
$this->data['color'] = sprintf( '#%06X', mt_rand( 0, 0x64FFFF ) );
|
72 |
}
|
73 |
|
74 |
+
if ( $this->data['type'] == Lib\Entities\Service::TYPE_SIMPLE ) {
|
75 |
+
Lib\Entities\SubService::query()->delete()->where( 'service_id', $this->data['id'] )->execute();
|
76 |
+
}
|
77 |
+
|
78 |
+
if ( $this->data['limit_period'] == 'off' || ! $this->data['appointments_limit'] ) {
|
79 |
+
$this->data['appointments_limit'] = null;
|
80 |
+
}
|
81 |
+
|
82 |
+
$this->data = Lib\Proxy\Shared::prepareUpdateService( $this->data );
|
83 |
+
|
84 |
+
/** @var Lib\Entities\Service $service */
|
85 |
+
$service = parent::save();
|
86 |
+
|
87 |
+
// Saving staff preferences for service
|
88 |
+
|
89 |
+
/** @var Lib\Entities\StaffPreferenceOrder[] $staff_preferences */
|
90 |
+
$staff_preferences = Lib\Entities\StaffPreferenceOrder::query()
|
91 |
+
->where( 'service_id', $service->getId() )
|
92 |
+
->indexBy( 'staff_id' )
|
93 |
+
->find();
|
94 |
+
foreach ( (array) $this->data['positions'] as $position => $staff_id ) {
|
95 |
+
if ( array_key_exists( $staff_id, $staff_preferences ) ) {
|
96 |
+
$staff_preferences[ $staff_id ]->setPosition( $position )->save();
|
97 |
+
} else {
|
98 |
+
$preference = new Lib\Entities\StaffPreferenceOrder();
|
99 |
+
$preference
|
100 |
+
->setServiceId( $service->getId() )
|
101 |
+
->setStaffId( $staff_id )
|
102 |
+
->setPosition( $position )
|
103 |
+
->save();
|
104 |
+
}
|
105 |
}
|
106 |
|
107 |
+
return $service;
|
108 |
}
|
109 |
|
110 |
}
|
backend/modules/services/resources/js/service.js
CHANGED
@@ -17,7 +17,7 @@ jQuery(function($) {
|
|
17 |
}).on('shown.bs.popover', function () {
|
18 |
// focus input
|
19 |
$new_category_name.focus();
|
20 |
-
}).on('hidden.bs.popover', function (
|
21 |
//clear input
|
22 |
$new_category_name.val('');
|
23 |
});
|
@@ -27,12 +27,12 @@ jQuery(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 |
|
@@ -41,21 +41,41 @@ jQuery(function($) {
|
|
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 |
-
$('#
|
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
|
59 |
}
|
60 |
});
|
61 |
})
|
@@ -72,30 +92,13 @@ jQuery(function($) {
|
|
72 |
})
|
73 |
|
74 |
// On blur save changes.
|
75 |
-
.on('blur', 'input',
|
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 |
-
|
99 |
}
|
100 |
})
|
101 |
|
@@ -108,7 +111,7 @@ jQuery(function($) {
|
|
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();
|
@@ -132,7 +135,7 @@ jQuery(function($) {
|
|
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 |
}
|
@@ -147,7 +150,7 @@ jQuery(function($) {
|
|
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 |
|
@@ -155,59 +158,89 @@ jQuery(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 |
-
|
162 |
-
|
163 |
-
$
|
164 |
-
$(this).
|
|
|
|
|
165 |
});
|
166 |
-
|
|
|
167 |
});
|
168 |
}
|
169 |
})
|
170 |
|
171 |
.on('change', 'input.bookly-check-all-entities, input.bookly-js-check-entity', function () {
|
172 |
-
var $
|
173 |
if ($(this).hasClass('bookly-check-all-entities')) {
|
174 |
-
$
|
175 |
} else {
|
176 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
178 |
-
|
179 |
});
|
180 |
|
181 |
// Modal window events.
|
182 |
-
var $modal = $('#
|
183 |
$modal
|
184 |
-
.on('click', '.
|
185 |
$modal.modal('hide');
|
186 |
-
if ( $('#
|
187 |
update_staff_choice = true;
|
188 |
}
|
189 |
submitServiceFrom($modal.data('input'),true);
|
190 |
})
|
191 |
-
.on('click', '.
|
192 |
-
if ( $('#
|
193 |
update_staff_choice = false;
|
194 |
}
|
195 |
submitServiceFrom($modal.data('input'),false);
|
196 |
});
|
197 |
|
198 |
function refreshList(response,service_id) {
|
199 |
-
var $list = $('#
|
200 |
$list.html(response);
|
201 |
if (response.indexOf('panel') >= 0) {
|
202 |
$no_result.hide();
|
203 |
-
|
204 |
-
onCollapseInitChildren();
|
205 |
$list.booklyHelp();
|
206 |
} else {
|
207 |
$no_result.show();
|
208 |
}
|
209 |
-
|
210 |
-
|
|
|
|
|
|
|
211 |
}
|
212 |
|
213 |
function initColorPicker($jquery_collection) {
|
@@ -219,7 +252,7 @@ jQuery(function($) {
|
|
219 |
});
|
220 |
}
|
221 |
|
222 |
-
$('#
|
223 |
if ($(this).val() > 1) {
|
224 |
booklyAlert({error: [BooklyL10n.limitations]});
|
225 |
$(this).val('1').prop('readonly',true);
|
@@ -234,34 +267,41 @@ jQuery(function($) {
|
|
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 |
-
|
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 |
-
$
|
252 |
-
|
|
|
|
|
|
|
|
|
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 |
-
$
|
258 |
-
|
259 |
-
|
|
|
|
|
|
|
|
|
|
|
260 |
var $li = $('li.extra.new[data-extra-id="' + front_id + '"]', $form);
|
261 |
$('[name^="extras"]', $li).each(function () {
|
262 |
-
|
263 |
-
|
264 |
-
|
|
|
|
|
|
|
|
|
265 |
});
|
266 |
$li.data('extra-id', real_id).removeClass('new');
|
267 |
$li.append('<input type="hidden" value="' + real_id + '" name="extras[' + real_id + '][id]">');
|
@@ -274,14 +314,30 @@ jQuery(function($) {
|
|
274 |
});
|
275 |
}
|
276 |
|
277 |
-
function
|
278 |
-
var
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
} else {
|
284 |
-
$panel.find('.bookly-
|
|
|
|
|
285 |
}
|
286 |
}
|
287 |
|
@@ -299,12 +355,12 @@ jQuery(function($) {
|
|
299 |
$.ajax({
|
300 |
type : 'POST',
|
301 |
url : ajaxurl,
|
302 |
-
data : { action: 'bookly_update_category_position', position: data }
|
303 |
});
|
304 |
}
|
305 |
});
|
306 |
|
307 |
-
function
|
308 |
if ($('.bookly-js-all-services').hasClass('active')) {
|
309 |
var $services = $('#services_list'),
|
310 |
fixHelper = function(e, ui) {
|
@@ -325,7 +381,7 @@ jQuery(function($) {
|
|
325 |
$.ajax({
|
326 |
type : 'POST',
|
327 |
url : ajaxurl,
|
328 |
-
data : { action: 'bookly_update_services_position', position: data }
|
329 |
});
|
330 |
}
|
331 |
});
|
@@ -334,21 +390,33 @@ jQuery(function($) {
|
|
334 |
}
|
335 |
}
|
336 |
|
337 |
-
function
|
338 |
$('.panel-collapse').on('show.bs.collapse.bookly', function () {
|
339 |
-
var $panel = $(this)
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
$
|
348 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
349 |
}
|
350 |
-
|
351 |
-
|
|
|
|
|
352 |
|
353 |
$('[data-toggle="popover"]').popover({
|
354 |
html: true,
|
@@ -357,155 +425,89 @@ jQuery(function($) {
|
|
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 |
-
|
361 |
-
|
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 |
-
$
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
initSubServicesLi($li);
|
377 |
-
$(this).val(0);
|
378 |
-
}
|
379 |
-
});
|
380 |
|
381 |
-
$
|
|
|
|
|
|
|
382 |
|
383 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
384 |
|
385 |
-
$panel
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
$('
|
391 |
-
|
392 |
-
|
393 |
-
|
|
|
|
|
|
|
394 |
});
|
395 |
-
|
396 |
-
|
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 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
$container.append(
|
452 |
-
template.replace(/%id%/g, id)
|
453 |
-
);
|
454 |
-
$('#title_' + id).focus();
|
455 |
-
});
|
456 |
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
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 |
-
|
476 |
-
|
477 |
-
|
478 |
-
$(
|
|
|
|
|
|
|
|
|
|
|
479 |
}
|
|
|
480 |
});
|
|
|
481 |
|
482 |
-
|
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 |
});
|
17 |
}).on('shown.bs.popover', function () {
|
18 |
// focus input
|
19 |
$new_category_name.focus();
|
20 |
+
}).on('hidden.bs.popover', function () {
|
21 |
//clear input
|
22 |
$new_category_name.val('');
|
23 |
});
|
27 |
var data = $(this).serialize();
|
28 |
|
29 |
$.post(ajaxurl, data, function(response) {
|
30 |
+
$('#bookly-category-item-list').append(response.data.html);
|
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 |
+
$new_category_popover.popover('hide');
|
35 |
});
|
|
|
36 |
return false;
|
37 |
});
|
38 |
|
41 |
$new_category_popover.popover('hide');
|
42 |
});
|
43 |
|
44 |
+
// Save category.
|
45 |
+
function saveCategory() {
|
46 |
+
var $this = $(this),
|
47 |
+
$item = $this.closest('.bookly-category-item'),
|
48 |
+
field = $this.attr('name'),
|
49 |
+
value = $this.val(),
|
50 |
+
id = $item.data('category-id'),
|
51 |
+
data = { action: 'bookly_update_category', id: id, csrf_token : BooklyL10n.csrf_token };
|
52 |
+
data[field] = value;
|
53 |
+
$.post(ajaxurl, data, function(response) {
|
54 |
+
// Hide input field.
|
55 |
+
$item.find('input').hide();
|
56 |
+
$item.find('.displayed-value').show();
|
57 |
+
// Show modified category name.
|
58 |
+
$item.find('.displayed-value').text(value);
|
59 |
+
// update edited category's name for services
|
60 |
+
$('select[name="category_id"] option[value="' + id + '"]').text(value);
|
61 |
+
});
|
62 |
+
}
|
63 |
+
|
64 |
// Categories list delegated events.
|
65 |
$('#bookly-categories-list')
|
66 |
|
67 |
// On category item click.
|
68 |
.on('click', '.bookly-category-item', function(e) {
|
69 |
if ($(e.target).is('.bookly-js-handle')) return;
|
70 |
+
$('#bookly-js-services-list').html('<div class="bookly-loading"></div>');
|
71 |
var $clicked = $(this);
|
72 |
|
73 |
+
$.get(ajaxurl, {action:'bookly_get_category_services', category_id: $clicked.data('category-id'), csrf_token : BooklyL10n.csrf_token}, function(response) {
|
74 |
if ( response.success ) {
|
75 |
$('.bookly-category-item').not($clicked).removeClass('active');
|
76 |
$clicked.addClass('active');
|
77 |
$('.bookly-category-title').text($clicked.text());
|
78 |
+
refreshList(response.data);
|
79 |
}
|
80 |
});
|
81 |
})
|
92 |
})
|
93 |
|
94 |
// On blur save changes.
|
95 |
+
.on('blur', 'input', saveCategory)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
// On press Enter save changes.
|
98 |
.on('keypress', 'input', function (e) {
|
99 |
var code = e.keyCode || e.which;
|
100 |
if (code == 13) {
|
101 |
+
saveCategory.apply(this);
|
102 |
}
|
103 |
})
|
104 |
|
111 |
// Ask user if he is sure.
|
112 |
if (confirm(BooklyL10n.are_you_sure)) {
|
113 |
var $item = $(this).closest('.bookly-category-item');
|
114 |
+
var data = { action: 'bookly_delete_category', id: $item.data('category-id'), csrf_token : BooklyL10n.csrf_token };
|
115 |
$.post(ajaxurl, data, function(response) {
|
116 |
// Remove category item from Services
|
117 |
$('select[name="category_id"] option[value="' + $item.data('category-id') + '"]').remove();
|
135 |
e.preventDefault();
|
136 |
var ladda = rangeTools.ladda(this);
|
137 |
var selected_category_id = $('#bookly-categories-list .active').data('category-id'),
|
138 |
+
data = { action: 'bookly_add_service', csrf_token : BooklyL10n.csrf_token };
|
139 |
if (selected_category_id) {
|
140 |
data['category_id'] = selected_category_id;
|
141 |
}
|
150 |
var ladda = rangeTools.ladda(this);
|
151 |
|
152 |
var $for_delete = $('.service-checker:checked'),
|
153 |
+
data = { action: 'bookly_remove_services', csrf_token : BooklyL10n.csrf_token },
|
154 |
services = [],
|
155 |
$panels = [];
|
156 |
|
158 |
var panel = $(this).parents('.bookly-js-collapse');
|
159 |
$panels.push(panel);
|
160 |
services.push(this.value);
|
161 |
+
if (panel.find('.bookly-js-service-type input[name="type"]:checked').val() == 'simple') {
|
162 |
+
$('#services_list .panel.bookly-js-collapse').each(function () {
|
163 |
+
if ($(this).find('.bookly-js-service-type input[name="type"]:checked').val() == 'package' && $(this).find('.bookly-js-package-sub-service option:selected').val() == panel.data('service-id')) {
|
164 |
+
$panels.push($(this));
|
165 |
+
}
|
166 |
+
});
|
167 |
+
}
|
168 |
});
|
169 |
data['service_ids[]'] = services;
|
170 |
+
$.post(ajaxurl, data, function(response) {
|
171 |
+
if (response.success) {
|
172 |
+
ladda.stop();
|
173 |
+
$.each($panels.reverse(), function (index) {
|
174 |
+
$(this).delay(500 * index).fadeOut(200, function () {
|
175 |
+
$(this).remove();
|
176 |
+
});
|
177 |
});
|
178 |
+
$(document.body).trigger( 'service.deleted', [ services ] );
|
179 |
+
}
|
180 |
});
|
181 |
}
|
182 |
})
|
183 |
|
184 |
.on('change', 'input.bookly-check-all-entities, input.bookly-js-check-entity', function () {
|
185 |
+
var $container = $(this).parents('.form-group');
|
186 |
if ($(this).hasClass('bookly-check-all-entities')) {
|
187 |
+
$container.find('.bookly-js-check-entity').prop('checked', $(this).prop('checked'));
|
188 |
} else {
|
189 |
+
$container.find('.bookly-check-all-entities').prop('checked', $container.find('.bookly-js-check-entity:not(:checked)').length == 0);
|
190 |
+
}
|
191 |
+
var $form = $(this).closest('.panel.bookly-js-collapse'),
|
192 |
+
service_id = $form.data('service-id'),
|
193 |
+
service_type = $form.find('.bookly-js-service-type input[name="type"]:checked').val(),
|
194 |
+
staff_index = $(this).closest('li').index() + 1;
|
195 |
+
if (service_type == 'simple' && !$(this).is(':checked')) {
|
196 |
+
$('#services_list .panel.bookly-js-collapse').each(function () {
|
197 |
+
if ($(this).find('.bookly-js-service-type input[name="type"]:checked').val() == 'package' && $(this).find('.bookly-js-package-sub-service option:selected').val() == service_id) {
|
198 |
+
$(this).find('.bookly-entity-selector li:nth-child(' + staff_index + ') input').prop('checked', false).trigger('change');
|
199 |
+
}
|
200 |
+
});
|
201 |
+
} else if (service_type == 'package' && $(this).is(':checked')) {
|
202 |
+
var sub_service_id = $form.find('.bookly-js-package-sub-service option:selected').val();
|
203 |
+
$('#services_list .panel.bookly-js-collapse').each(function () {
|
204 |
+
if ($(this).find('.bookly-js-service-type input[name="type"]:checked').val() == 'simple' && $(this).data('service-id') == sub_service_id) {
|
205 |
+
$(this).find('.bookly-entity-selector li:nth-child(' + staff_index + ') input').prop('checked', true).trigger('change');
|
206 |
+
}
|
207 |
+
});
|
208 |
}
|
209 |
+
updateSelectorButton($container);
|
210 |
});
|
211 |
|
212 |
// Modal window events.
|
213 |
+
var $modal = $('#bookly-update-service-settings');
|
214 |
$modal
|
215 |
+
.on('click', '.bookly-yes', function() {
|
216 |
$modal.modal('hide');
|
217 |
+
if ( $('#bookly-remember-my-choice').prop('checked') ) {
|
218 |
update_staff_choice = true;
|
219 |
}
|
220 |
submitServiceFrom($modal.data('input'),true);
|
221 |
})
|
222 |
+
.on('click', '.bookly-no', function() {
|
223 |
+
if ( $('#bookly-remember-my-choice').prop('checked') ) {
|
224 |
update_staff_choice = false;
|
225 |
}
|
226 |
submitServiceFrom($modal.data('input'),false);
|
227 |
});
|
228 |
|
229 |
function refreshList(response,service_id) {
|
230 |
+
var $list = $('#bookly-js-services-list');
|
231 |
$list.html(response);
|
232 |
if (response.indexOf('panel') >= 0) {
|
233 |
$no_result.hide();
|
234 |
+
onCollapseInitServiceForm();
|
|
|
235 |
$list.booklyHelp();
|
236 |
} else {
|
237 |
$no_result.show();
|
238 |
}
|
239 |
+
if (service_id) {
|
240 |
+
$('#service_' + service_id).collapse('show');
|
241 |
+
$('#service_' + service_id).find('input[name=title]').focus();
|
242 |
+
}
|
243 |
+
makeSortable();
|
244 |
}
|
245 |
|
246 |
function initColorPicker($jquery_collection) {
|
252 |
});
|
253 |
}
|
254 |
|
255 |
+
$('#services_list').on('change', '[name=capacity_min],[name=capacity_max]', function(){
|
256 |
if ($(this).val() > 1) {
|
257 |
booklyAlert({error: [BooklyL10n.limitations]});
|
258 |
$(this).val('1').prop('readonly',true);
|
267 |
|
268 |
function submitServiceFrom($form, update_staff) {
|
269 |
$form.find('input[name=update_staff]').val(update_staff ? 1 : 0);
|
270 |
+
$form.find('input[name=package_service_changed]').val($form.find('[name=package_service]').data('last_value') != $form.find('[name=package_service]').val() ? 1 : 0);
|
271 |
var ladda = rangeTools.ladda($form.find('button.ajax-service-send[type=submit]').get(0)),
|
272 |
data = $form.serializeArray();
|
273 |
+
$(document.body).trigger( 'service.submitForm', [ $form, data ] );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
274 |
$.post(ajaxurl, data, function (response) {
|
275 |
if (response.success) {
|
276 |
var $panel = $form.parents('.bookly-js-collapse'),
|
277 |
$price = $form.find('[name=price]'),
|
278 |
+
$capacity_min = $form.find('[name=capacity_min]'),
|
279 |
+
$capacity_max = $form.find('[name=capacity_max]'),
|
280 |
+
$package_service = $form.find('[name=package_service]');
|
281 |
+
$panel.find('.bookly-js-service-color span:nth-child(1)').css('background-color', response.data.colors[0] == '-1' ? 'grey' : response.data.colors[0]);
|
282 |
+
$panel.find('.bookly-js-service-color span:nth-child(2)').css('background-color', response.data.colors[1] == '-1' ? 'grey' : response.data.colors[1]);
|
283 |
+
$panel.find('.bookly-js-service-color span:nth-child(3)').css('background-color', response.data.colors[2] == '-1' ? 'grey' : response.data.colors[2]);
|
284 |
$panel.find('.bookly-js-service-title').html(response.data.title);
|
285 |
$panel.find('.bookly-js-service-duration').html(response.data.nice_duration);
|
286 |
$panel.find('.bookly-js-service-price').html(response.data.price);
|
287 |
$price.data('last_value', $price.val());
|
288 |
+
$capacity_min.data('last_value', $capacity_min.val());
|
289 |
+
$capacity_max.data('last_value', $capacity_max.val());
|
290 |
+
$package_service.data('last_value', $package_service.val());
|
291 |
+
booklyAlert(response.data.alert);
|
292 |
+
if (response.data.new_extras_list) {
|
293 |
+
ExtrasL10n.list = response.data.new_extras_list
|
294 |
+
}
|
295 |
+
$.each(response.data.new_extras_ids, function (front_id, real_id) {
|
296 |
var $li = $('li.extra.new[data-extra-id="' + front_id + '"]', $form);
|
297 |
$('[name^="extras"]', $li).each(function () {
|
298 |
+
$(this).attr('name', $(this).attr('name').replace('[' + front_id + ']', '[' + real_id + ']'));
|
299 |
+
});
|
300 |
+
$('[id*="_extras_"]', $li).each(function () {
|
301 |
+
$(this).attr('id', $(this).attr('id').replace(front_id, real_id));
|
302 |
+
});
|
303 |
+
$('label[for*="_extras_"]', $li).each(function () {
|
304 |
+
$(this).attr('for', $(this).attr('for').replace(front_id, real_id));
|
305 |
});
|
306 |
$li.data('extra-id', real_id).removeClass('new');
|
307 |
$li.append('<input type="hidden" value="' + real_id + '" name="extras[' + real_id + '][id]">');
|
314 |
});
|
315 |
}
|
316 |
|
317 |
+
function updateSelectorButton($container) {
|
318 |
+
var entity_checked = $container.find('.bookly-js-check-entity:checked').length,
|
319 |
+
$check_all = $container.find('.bookly-check-all-entities');
|
320 |
+
if (entity_checked == 0) {
|
321 |
+
$container.find('.bookly-entity-counter').text($check_all.data('nothing'));
|
322 |
+
} else if (entity_checked == 1) {
|
323 |
+
$container.find('.bookly-entity-counter').text($container.find('.bookly-js-check-entity:checked').data('title'));
|
324 |
+
} else if (entity_checked == $container.find('.bookly-js-check-entity').length) {
|
325 |
+
$container.find('.bookly-entity-counter').text($check_all.data('title'));
|
326 |
+
$check_all.prop('checked', true);
|
327 |
+
} else {
|
328 |
+
$container.find('.bookly-entity-counter').text(entity_checked + '/' + $container.find('.bookly-js-check-entity').length);
|
329 |
+
}
|
330 |
+
}
|
331 |
+
|
332 |
+
function checkCapacityError($panel) {
|
333 |
+
if (parseInt($panel.find('[name="capacity_min"]').val()) > parseInt($panel.find('[name="capacity_max"]').val())) {
|
334 |
+
$panel.find('form .bookly-js-services-error').html(BooklyL10n.capacity_error);
|
335 |
+
$panel.find('[name="capacity_min"]').closest('.form-group').addClass('has-error');
|
336 |
+
$panel.find('form .ajax-service-send').prop('disabled', true);
|
337 |
} else {
|
338 |
+
$panel.find('form .bookly-js-services-error').html('');
|
339 |
+
$panel.find('[name="capacity_min"]').closest('.form-group').removeClass('has-error');
|
340 |
+
$panel.find('form .ajax-service-send').prop('disabled', false);
|
341 |
}
|
342 |
}
|
343 |
|
355 |
$.ajax({
|
356 |
type : 'POST',
|
357 |
url : ajaxurl,
|
358 |
+
data : { action: 'bookly_update_category_position', position: data, csrf_token : BooklyL10n.csrf_token }
|
359 |
});
|
360 |
}
|
361 |
});
|
362 |
|
363 |
+
function makeSortable() {
|
364 |
if ($('.bookly-js-all-services').hasClass('active')) {
|
365 |
var $services = $('#services_list'),
|
366 |
fixHelper = function(e, ui) {
|
381 |
$.ajax({
|
382 |
type : 'POST',
|
383 |
url : ajaxurl,
|
384 |
+
data : { action: 'bookly_update_services_position', position: data, csrf_token : BooklyL10n.csrf_token }
|
385 |
});
|
386 |
}
|
387 |
});
|
390 |
}
|
391 |
}
|
392 |
|
393 |
+
function onCollapseInitServiceForm() {
|
394 |
$('.panel-collapse').on('show.bs.collapse.bookly', function () {
|
395 |
+
var $panel = $(this),
|
396 |
+
$staff_preference = $panel.find('[name=staff_preference]'),
|
397 |
+
$staff_list = $panel.find('.bookly-staff-list'),
|
398 |
+
$staff_box = $panel.find('.bookly-preference-box');
|
399 |
+
|
400 |
+
$staff_preference.on('change', function () {
|
401 |
+
/** @see Service::PREFERRED_ORDER */
|
402 |
+
if ($(this).val() == 'order' && $staff_list.html() == '') {
|
403 |
+
var $staff_ids = $staff_preference.data('default'),
|
404 |
+
$draggable = $('<div class="bookly-flex-cell"><i class="bookly-js-handle bookly-margin-right-sm bookly-icon bookly-icon-draghandle bookly-cursor-move" title="' + BooklyL10n.reorder + '"></i><input type="hidden" name="positions[]"></div>');
|
405 |
+
|
406 |
+
$staff_ids.forEach(function (staff_id) {
|
407 |
+
$staff_list.append($draggable.clone().find('input').val(staff_id).end().append(BooklyL10n.staff[staff_id]));
|
408 |
+
});
|
409 |
+
Object.keys(BooklyL10n.staff).forEach(function (staff_id) {
|
410 |
+
staff_id = parseInt(staff_id);
|
411 |
+
if ($staff_ids.indexOf(staff_id) == -1) {
|
412 |
+
$staff_list.append($draggable.clone().find('input').val(staff_id).end().append(BooklyL10n.staff[staff_id]));
|
413 |
+
}
|
414 |
+
});
|
415 |
}
|
416 |
+
$staff_box.toggle($(this).val() == 'order');
|
417 |
+
}).trigger('change');
|
418 |
+
|
419 |
+
initColorPicker($panel.find('.bookly-js-color-picker'));
|
420 |
|
421 |
$('[data-toggle="popover"]').popover({
|
422 |
html: true,
|
425 |
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>'
|
426 |
});
|
427 |
|
428 |
+
$.each($('.bookly-js-entity-selector-container',$(this)), function () {
|
429 |
+
updateSelectorButton($(this));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
430 |
});
|
431 |
|
432 |
+
$panel
|
433 |
+
.find('[name=duration]').on('change', function () {
|
434 |
+
$panel.find('[name=start_time_info]').closest('.form-group').toggle($(this).val() >= 86400);
|
435 |
+
}).trigger('change');
|
|
|
|
|
|
|
|
|
436 |
|
437 |
+
$panel
|
438 |
+
.find('.bookly-js-capacity').on('keyup change', function () {
|
439 |
+
checkCapacityError($(this).parents('.bookly-js-collapse'));
|
440 |
+
});
|
441 |
|
442 |
+
$panel
|
443 |
+
.find('.ajax-service-send').on('click', function (e) {
|
444 |
+
e.preventDefault();
|
445 |
+
var $form = $(this).parents('form'),
|
446 |
+
show_modal = false;
|
447 |
+
if(update_staff_choice === null) {
|
448 |
+
$('.bookly-question', $form).each(function () {
|
449 |
+
if ($(this).data('last_value') != this.value) {
|
450 |
+
show_modal = true;
|
451 |
+
}
|
452 |
+
});
|
453 |
+
}
|
454 |
+
if (show_modal) {
|
455 |
+
$modal.data('input', $form).modal('show');
|
456 |
+
} else {
|
457 |
+
submitServiceFrom($form, update_staff_choice);
|
458 |
+
}
|
459 |
+
});
|
460 |
|
461 |
+
$panel
|
462 |
+
.find('.js-reset').on('click', function () {
|
463 |
+
$(this).parents('form').trigger('reset');
|
464 |
+
var $color = $(this).parents('form').find('.wp-color-picker'),
|
465 |
+
$panel = $(this).parents('.bookly-js-collapse');
|
466 |
+
$staff_list.html('');
|
467 |
+
$staff_preference.trigger('change');
|
468 |
+
$color.val($color.data('last-color')).trigger('change');
|
469 |
+
$panel.find('.parent-range-start').trigger('change');
|
470 |
+
$panel.find('input[name=type]:checked').trigger('change');
|
471 |
+
$.each($('.bookly-js-entity-selector-container',$panel), function () {
|
472 |
+
updateSelectorButton($(this));
|
473 |
});
|
474 |
+
checkCapacityError($panel);
|
475 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
476 |
|
477 |
+
$panel
|
478 |
+
.find('.bookly-question').each(function () {
|
479 |
+
$(this).data('last_value', this.value);
|
480 |
+
});
|
481 |
|
482 |
+
$staff_list.sortable({
|
483 |
+
axis : 'y',
|
484 |
+
handle : '.bookly-js-handle',
|
485 |
+
update : function() {
|
486 |
+
var positions = [];
|
487 |
+
$('[name="positions[]"]', $(this)).each(function () {
|
488 |
+
positions.push(this.value);
|
489 |
+
});
|
|
|
|
|
|
|
|
|
|
|
490 |
|
491 |
+
$.ajax({
|
492 |
+
type : 'POST',
|
493 |
+
url : ajaxurl,
|
494 |
+
data : {action: 'bookly_update_service_staff_preference_orders', service_id: $(this).data('service_id'), positions: positions, csrf_token: BooklyL10n.csrf_token}
|
495 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
496 |
}
|
497 |
+
});
|
498 |
+
$panel.unbind('show.bs.collapse.bookly');
|
499 |
+
if ($('input[name=type]', $panel).length > 1) {
|
500 |
+
$('.bookly-js-service-type', $panel).show();
|
501 |
+
$('input[name=type]', $panel).on( 'change', function(){
|
502 |
+
$panel.closest('.panel').find('.bookly-js-service').hide();
|
503 |
+
$panel.closest('.panel').find('.bookly-js-service-' + this.value).show();
|
504 |
+
});
|
505 |
+
$('input[name=type]:checked', $panel).trigger('change');
|
506 |
}
|
507 |
+
$(document.body).trigger( 'service.initForm', [ $panel, $panel.closest('.panel').data('service-id') ] );
|
508 |
});
|
509 |
+
}
|
510 |
|
511 |
+
makeSortable();
|
512 |
+
onCollapseInitServiceForm();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
513 |
});
|
backend/modules/services/templates/_list.php
CHANGED
@@ -1,5 +1,11 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
?>
|
4 |
<?php if ( ! empty( $service_collection ) ) : ?>
|
5 |
<div class="panel-group" id="services_list" role="tablist" aria-multiselectable="true">
|
@@ -17,9 +23,13 @@
|
|
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:
|
21 |
-
<span class="bookly-service-color bookly-margin-right-sm bookly-js-service-
|
22 |
-
style="background-color: <?php echo esc_attr( $service['
|
|
|
|
|
|
|
|
|
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"
|
@@ -34,12 +44,20 @@
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
43 |
</span>
|
44 |
</div>
|
45 |
<div class="bookly-flex-cell bookly-vertical-middle text-right" style="width: 10%">
|
@@ -55,25 +73,35 @@
|
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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="
|
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>
|
@@ -83,35 +111,40 @@
|
|
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
|
90 |
</div>
|
91 |
</div>
|
92 |
-
<div class="col-sm-4
|
93 |
<div class="form-group">
|
94 |
-
<
|
95 |
-
|
96 |
-
|
|
|
|
|
|
|
|
|
|
|
97 |
</div>
|
98 |
</div>
|
99 |
</div>
|
100 |
|
101 |
-
<div class="
|
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
|
110 |
-
|
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' ) ?>
|
@@ -121,23 +154,59 @@
|
|
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 <=
|
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 <=
|
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>
|
@@ -147,10 +216,10 @@
|
|
147 |
</select>
|
148 |
</div>
|
149 |
</div>
|
150 |
-
<div class="col-sm-6
|
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>
|
@@ -164,7 +233,7 @@
|
|
164 |
<li>
|
165 |
<a class="checkbox" href="javascript:void(0)">
|
166 |
<label>
|
167 |
-
<input type="checkbox"
|
168 |
<?php _e( 'All staff', 'bookly' ) ?>
|
169 |
</label>
|
170 |
</a>
|
@@ -173,7 +242,7 @@
|
|
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-
|
177 |
<?php echo esc_html( $staff['full_name'] ) ?>
|
178 |
</label>
|
179 |
</a>
|
@@ -185,7 +254,36 @@
|
|
185 |
</div>
|
186 |
</div>
|
187 |
|
188 |
-
<div class="
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
<label for="info_<?php echo $service_id ?>">
|
190 |
<?php _e( 'Info', 'bookly' ) ?>
|
191 |
</label>
|
@@ -195,123 +293,16 @@
|
|
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
|
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 |
-
<div class="form-group">
|
259 |
-
<label for="title_extras_<?php echo $extra->get( 'id' ) ?>">
|
260 |
-
<?php _e( 'Title', 'bookly' ) ?>
|
261 |
-
</label>
|
262 |
-
<input name="extras[<?php echo $extra->get( 'id' ) ?>][title]" class="form-control" type="text" id="title_extras_<?php echo $extra->get( 'id' ) ?>" value="<?php echo $extra->get( 'title' ) ?>">
|
263 |
-
</div>
|
264 |
-
|
265 |
-
<div class="row">
|
266 |
-
<div class="col-sm-4">
|
267 |
-
<div class="form-group">
|
268 |
-
<label for="price_extras_<?php echo $extra->get( 'id' ) ?>">
|
269 |
-
<?php _e( 'Price', 'bookly' ) ?>
|
270 |
-
</label>
|
271 |
-
<input name="extras[<?php echo $extra->get( 'id' ) ?>][price]" class="form-control" type="number" step="1" id="price_extras_<?php echo $extra->get( 'id' ) ?>" min="0.00" value="<?php echo $extra->get( 'price' ) ?>">
|
272 |
-
</div>
|
273 |
-
</div>
|
274 |
-
|
275 |
-
<div class="col-sm-4">
|
276 |
-
<div class="form-group">
|
277 |
-
<label for="duration_extras_<?php echo $extra->get( 'id' ) ?>">
|
278 |
-
<?php _e( 'Duration', 'bookly' ) ?>
|
279 |
-
</label>
|
280 |
-
<select name="extras[<?php echo $extra->get( 'id' ) ?>][duration]" id="duration_extras_<?php echo $extra->get( 'id' ) ?>" class="form-control">
|
281 |
-
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
282 |
-
<?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 ?>
|
283 |
-
</select>
|
284 |
-
</div>
|
285 |
-
</div>
|
286 |
-
|
287 |
-
<div class="col-sm-4">
|
288 |
-
<div class="form-group">
|
289 |
-
<label for="max_quantity_extras_<?php echo $extra->get( 'id' ) ?>">
|
290 |
-
<?php _e( 'Max quantity', 'bookly' ) ?>
|
291 |
-
</label>
|
292 |
-
<input name="extras[<?php echo $extra->get( 'id' ) ?>][max_quantity]" class="form-control" type="number" step="1" id="max_quantity_extras_<?php echo $extra->get( 'id' ) ?>" min="1" value="<?php echo $extra->get( 'max_quantity' ) ?>">
|
293 |
-
</div>
|
294 |
-
</div>
|
295 |
-
</div>
|
296 |
-
|
297 |
-
<div class="form-group text-right">
|
298 |
-
<?php \BooklyLite\Lib\Utils\Common::deleteButton( null, 'extra-delete' ) ?>
|
299 |
-
</div>
|
300 |
-
</div>
|
301 |
-
</div>
|
302 |
-
</li>
|
303 |
-
<?php endforeach ?>
|
304 |
-
</ul>
|
305 |
-
</div>
|
306 |
-
</div>
|
307 |
-
<?php endif ?>
|
308 |
-
|
309 |
<div class="panel-footer">
|
310 |
<input type="hidden" name="action" value="bookly_update_service">
|
311 |
<input type="hidden" name="id" value="<?php echo esc_html( $service_id ) ?>">
|
312 |
<input type="hidden" name="update_staff" value="0">
|
313 |
-
|
314 |
-
<?php
|
|
|
|
|
315 |
</div>
|
316 |
</form>
|
317 |
</div>
|
@@ -319,4 +310,7 @@
|
|
319 |
</div>
|
320 |
<?php endforeach ?>
|
321 |
</div>
|
322 |
-
<?php endif ?>
|
|
|
|
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Common;
|
3 |
+
use BooklyLite\Lib\Utils\DateTime;
|
4 |
+
use BooklyLite\Lib\Utils\Price;
|
5 |
+
use BooklyLite\Lib\Proxy;
|
6 |
+
use BooklyLite\Lib\Entities\Service;
|
7 |
+
|
8 |
+
$time_interval = get_option( 'bookly_gen_time_slot_length' );
|
9 |
?>
|
10 |
<?php if ( ! empty( $service_collection ) ) : ?>
|
11 |
<div class="panel-group" id="services_list" role="tablist" aria-multiselectable="true">
|
23 |
<i class="bookly-js-handle bookly-icon bookly-icon-draghandle bookly-margin-right-sm bookly-cursor-move"
|
24 |
title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>"></i>
|
25 |
</div>
|
26 |
+
<div class="bookly-flex-cell bookly-vertical-middle bookly-js-service-color" style="width: 55px; padding-left: 25px;">
|
27 |
+
<span class="bookly-service-color bookly-margin-right-sm bookly-js-service bookly-js-service-simple bookly-js-service-compound bookly-js-service-package"
|
28 |
+
style="background-color: <?php echo esc_attr( $service['colors'][0] == '-1' ? 'grey' : $service['colors'][0] ) ?>"> </span>
|
29 |
+
<span class="bookly-service-color bookly-margin-right-sm bookly-js-service bookly-js-service-compound bookly-js-service-package"
|
30 |
+
style="background-color: <?php echo esc_attr( $service['colors'][1] == '-1' ? 'grey' : $service['colors'][1] ) ?>; <?php if ( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_SIMPLE ) : ?>display: none;<?php endif ?>"> </span>
|
31 |
+
<span class="bookly-service-color bookly-margin-right-sm bookly-js-service bookly-js-service-package"
|
32 |
+
style="background-color: <?php echo esc_attr( $service['colors'][2] == '-1' ? 'grey' : $service['colors'][2] ) ?>; <?php if ( $service['type'] != \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ) : ?>display: none;<?php endif ?>"> </span>
|
33 |
</div>
|
34 |
<div class="bookly-flex-cell bookly-vertical-middle">
|
35 |
<a role="button" class="panel-title collapsed bookly-js-service-title" data-toggle="collapse"
|
44 |
<div class="bookly-flexbox">
|
45 |
<div class="bookly-flex-cell bookly-vertical-middle hidden-xs" style="width: 60%">
|
46 |
<span class="bookly-js-service-duration">
|
47 |
+
<?php
|
48 |
+
switch ( $service['type'] ) {
|
49 |
+
case Service::TYPE_SIMPLE:
|
50 |
+
case Service::TYPE_PACKAGE:
|
51 |
+
echo DateTime::secondsToInterval( $service['duration'] ); break;
|
52 |
+
case Service::TYPE_COMPOUND:
|
53 |
+
echo sprintf( _n( '%d service', '%d services', $service['sub_services_count'], 'bookly' ), $service['sub_services_count'] ); break;
|
54 |
+
}
|
55 |
+
?>
|
56 |
</span>
|
57 |
</div>
|
58 |
<div class="bookly-flex-cell bookly-vertical-middle hidden-xs" style="width: 30%">
|
59 |
<span class="bookly-js-service-price">
|
60 |
+
<?php echo Price::format( $service['price'] ) ?>
|
61 |
</span>
|
62 |
</div>
|
63 |
<div class="bookly-flex-cell bookly-vertical-middle text-right" style="width: 10%">
|
73 |
<div id="service_<?php echo $service_id ?>" class="panel-collapse collapse" role="tabpanel" style="height: 0">
|
74 |
<div class="panel-body">
|
75 |
<form method="post">
|
76 |
+
<div class="form-inline bookly-margin-bottom-lg bookly-js-service-type collapse">
|
77 |
+
<div class="form-group">
|
78 |
+
<div class="radio">
|
79 |
+
<label class="bookly-margin-right-md">
|
80 |
+
<input type="radio" name="type" value="simple" data-panel-class="panel-default" <?php echo checked( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_SIMPLE ) ?>><?php _e( 'Simple', 'bookly' ) ?>
|
81 |
+
</label>
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
<?php Proxy\Shared::renderServiceFormHead( $service ) ?>
|
85 |
+
</div>
|
86 |
<div class="row">
|
87 |
+
<div class="col-md-9 col-sm-6 bookly-js-service bookly-js-service-simple bookly-js-service-compound bookly-js-service-package">
|
88 |
<div class="form-group">
|
89 |
<label for="title_<?php echo $service_id ?>"><?php _e( 'Title', 'bookly' ) ?></label>
|
90 |
<input name="title" value="<?php echo esc_attr( $service['title'] ) ?>" id="title_<?php echo $service_id ?>" class="form-control" type="text">
|
91 |
</div>
|
92 |
</div>
|
93 |
+
<div class="col-md-3 col-sm-6 bookly-js-service bookly-js-service-simple">
|
94 |
<div class="form-group">
|
95 |
<label><?php _e( 'Color', 'bookly' ) ?></label>
|
96 |
<div class="bookly-color-picker-wrapper">
|
97 |
+
<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="text">
|
98 |
</div>
|
99 |
</div>
|
100 |
</div>
|
101 |
</div>
|
102 |
+
<?php Proxy\Packages::renderServicePackage( $service, $service_collection ) ?>
|
103 |
<div class="row">
|
104 |
+
<div class="col-sm-4 bookly-js-service bookly-js-service-simple bookly-js-service-compound bookly-js-service-package">
|
105 |
<div class="form-group">
|
106 |
<label for="visibility_<?php echo $service_id ?>"><?php _e( 'Visibility', 'bookly' ) ?></label>
|
107 |
<p class="help-block"><?php _e( 'To make service invisible to your customers set the visibility to "Private".', 'bookly' ) ?></p>
|
111 |
</select>
|
112 |
</div>
|
113 |
</div>
|
114 |
+
<div class="col-sm-4 bookly-js-service bookly-js-service-simple bookly-js-service-compound bookly-js-service-package">
|
115 |
<div class="form-group">
|
116 |
<label for="price_<?php echo $service_id ?>"><?php _e( 'Price', 'bookly' ) ?></label>
|
117 |
+
<input id="price_<?php echo $service_id ?>" class="form-control bookly-question" type="number" min="0" step="1" name="price" value="<?php echo esc_attr( $service['price'] ) ?>">
|
118 |
</div>
|
119 |
</div>
|
120 |
+
<div class="col-sm-4 bookly-js-service bookly-js-service-simple">
|
121 |
<div class="form-group">
|
122 |
+
<div class="row">
|
123 |
+
<div class="col-xs-6">
|
124 |
+
<input id="capacity_min_<?php echo $service_id ?>" class="form-control bookly-question bookly-js-capacity" type="hidden" min="1" step="1" name="capacity_min" value="1">
|
125 |
+
</div>
|
126 |
+
<div class="col-xs-6">
|
127 |
+
<input id="capacity_max_<?php echo $service_id ?>" class="form-control bookly-question bookly-js-capacity" type="hidden" min="1" step="1" name="capacity_max" value="1">
|
128 |
+
</div>
|
129 |
+
</div>
|
130 |
</div>
|
131 |
</div>
|
132 |
</div>
|
133 |
|
134 |
+
<div class="bookly-js-service bookly-js-service-simple">
|
135 |
<div class="row">
|
136 |
+
<div class="col-sm-4 bookly-js-service bookly-js-service-simple">
|
137 |
<div class="form-group">
|
138 |
<label for="duration_<?php echo $service_id ?>">
|
139 |
<?php _e( 'Duration', 'bookly' ) ?>
|
140 |
</label>
|
141 |
<select id="duration_<?php echo $service_id ?>" class="form-control" name="duration">
|
142 |
+
<?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 DateTime::secondsToInterval( $service['duration'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['duration'], $j * 60 ) ?>><?php echo DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
143 |
+
<?php for ( $j = 86400; $j <= 604800; $j += 86400 ) : ?><option value="<?php echo $j ?>" <?php selected( $service['duration'], $j ) ?>><?php echo DateTime::secondsToInterval( $j ) ?></option><?php endfor ?>
|
144 |
</select>
|
145 |
</div>
|
146 |
</div>
|
147 |
+
<div class="col-sm-8 bookly-js-service bookly-js-service-simple">
|
148 |
<div class="form-group">
|
149 |
<label for="padding_left_<?php echo $service_id ?>">
|
150 |
<?php _e( 'Padding time (before and after)', 'bookly' ) ?>
|
154 |
<div class="col-xs-6">
|
155 |
<select id="padding_left_<?php echo $service_id ?>" class="form-control" name="padding_left">
|
156 |
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
157 |
+
<?php for ( $j = $time_interval; $j <= 1440; $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 DateTime::secondsToInterval( $service['padding_left'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['padding_left'], $j * 60 ) ?>><?php echo DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
158 |
</select>
|
159 |
</div>
|
160 |
<div class="col-xs-6">
|
161 |
<select id="padding_right_<?php echo $service_id ?>" class="form-control" name="padding_right">
|
162 |
<option value="0"><?php _e( 'OFF', 'bookly' ) ?></option>
|
163 |
+
<?php for ( $j = $time_interval; $j <= 1440; $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 DateTime::secondsToInterval( $service['padding_right'] ) ?></option><?php endif ?><option value="<?php echo $j * 60 ?>" <?php selected( $service['padding_right'], $j * 60 ) ?>><?php echo DateTime::secondsToInterval( $j * 60 ) ?></option><?php endfor ?>
|
164 |
</select>
|
165 |
</div>
|
166 |
</div>
|
167 |
</div>
|
168 |
</div>
|
169 |
+
<div class="col-sm-4 bookly-js-service bookly-js-service-simple">
|
170 |
+
<div class="form-group">
|
171 |
+
<label for="start_time_info_<?php echo $service_id ?>"><?php _e( 'Start and end times of the appointment', 'bookly' ) ?></label>
|
172 |
+
<p class="help-block"><?php _e( 'Allows to set the start and end times for an appointment for services with the duration of 1 day or longer. This time will be displayed in notifications to customers.', 'bookly' ) ?></p>
|
173 |
+
<div class="row">
|
174 |
+
<div class="col-xs-6">
|
175 |
+
<input id="start_time_info_<?php echo $service_id ?>" class="form-control" type="text" name="start_time_info" value="<?php echo esc_attr( $service['start_time_info'] ) ?>">
|
176 |
+
</div>
|
177 |
+
<div class="col-xs-6">
|
178 |
+
<input class="form-control" type="text" name="end_time_info" value="<?php echo esc_attr( $service['end_time_info'] ) ?>">
|
179 |
+
</div>
|
180 |
+
</div>
|
181 |
+
</div>
|
182 |
+
</div>
|
183 |
+
</div>
|
184 |
+
</div>
|
185 |
+
|
186 |
+
<div class="bookly-js-service bookly-js-service-simple">
|
187 |
+
<div class="row">
|
188 |
+
<div class="col-sm-4 bookly-js-service bookly-js-service-simple">
|
189 |
+
<div class="form-group">
|
190 |
+
<label for="staff_preference_<?php echo $service_id ?>">
|
191 |
+
<?php _e( 'Providers preference for ANY', 'bookly' ) ?>
|
192 |
+
</label>
|
193 |
+
<p class="help-block"><?php _e( 'Allows you to define the rule of staff members auto assignment when ANY option is selected', 'bookly' ) ?></p>
|
194 |
+
<select id="staff_preference_<?php echo $service_id ?>" class="form-control" name="staff_preference" data-default="[<?php echo $service['pref_staff_ids'] ?>]">
|
195 |
+
<?php foreach ( $staff_preference as $rule => $name ) : ?><option value="<?php echo $rule ?>" <?php selected( $rule == $service['staff_preference'] ) ?>><?php echo $name ?></option><?php endforeach ?>
|
196 |
+
</select>
|
197 |
+
</div>
|
198 |
+
</div>
|
199 |
+
<div class="col-sm-8 bookly-preference-box">
|
200 |
+
<div class="form-group">
|
201 |
+
<label for="staff_preferred_<?php echo $service_id ?>"><?php _e( 'Providers', 'bookly' ) ?></label><br/>
|
202 |
+
<div class="bookly-staff-list" data-service_id="<?php echo $service_id ?>"></div>
|
203 |
+
</div>
|
204 |
+
</div>
|
205 |
</div>
|
206 |
</div>
|
207 |
|
208 |
<div class="row">
|
209 |
+
<div class="col-sm-6 bookly-js-service bookly-js-service-simple bookly-js-service-compound">
|
210 |
<div class="form-group">
|
211 |
<label for="category_<?php echo $service_id ?>"><?php _e( 'Category', 'bookly' ) ?></label>
|
212 |
<select id="category_<?php echo $service_id ?>" class="form-control" name="category_id"><option value="0"><?php _e( 'Uncategorized', 'bookly' ) ?></option>
|
216 |
</select>
|
217 |
</div>
|
218 |
</div>
|
219 |
+
<div class="col-sm-6 bookly-js-service bookly-js-service-simple bookly-js-service-package">
|
220 |
<div class="form-group">
|
221 |
<label><?php _e( 'Providers', 'bookly' ) ?></label><br>
|
222 |
+
<div class="btn-group bookly-js-entity-selector-container">
|
223 |
<button class="btn btn-default btn-block dropdown-toggle bookly-flexbox" data-toggle="dropdown">
|
224 |
<div class="bookly-flex-cell">
|
225 |
<i class="dashicons dashicons-admin-users bookly-margin-right-md"></i>
|
233 |
<li>
|
234 |
<a class="checkbox" href="javascript:void(0)">
|
235 |
<label>
|
236 |
+
<input type="checkbox" class="bookly-check-all-entities" <?php checked( $all_staff_selected ) ?> data-title="<?php esc_attr_e( 'All staff', 'bookly' ) ?>" data-nothing="<?php esc_attr_e( 'No staff selected', 'bookly' ) ?>">
|
237 |
<?php _e( 'All staff', 'bookly' ) ?>
|
238 |
</label>
|
239 |
</a>
|
242 |
<li>
|
243 |
<a class="checkbox" href="javascript:void(0)">
|
244 |
<label>
|
245 |
+
<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-title="<?php echo esc_attr( $staff['full_name'] ) ?>">
|
246 |
<?php echo esc_html( $staff['full_name'] ) ?>
|
247 |
</label>
|
248 |
</a>
|
254 |
</div>
|
255 |
</div>
|
256 |
|
257 |
+
<div class="bookly-js-service bookly-js-service-simple bookly-js-service-compound">
|
258 |
+
<div class="row">
|
259 |
+
<div class="col-sm-8">
|
260 |
+
<label for="appointments_limit_<?php echo $service_id ?>">
|
261 |
+
<?php _e( 'Limit appointments per customer', 'bookly' ) ?>
|
262 |
+
</label>
|
263 |
+
<p class="help-block"><?php _e( 'Allows you to limit the frequency of service bookings per customer.', 'bookly' ) ?></p>
|
264 |
+
<div class="row">
|
265 |
+
<div class="col-sm-6">
|
266 |
+
<div class="form-group">
|
267 |
+
<input id="appointments_limit_<?php echo $service_id ?>" class="form-control" type="number" min="0" step="1" name="appointments_limit" value="<?php echo esc_attr( $service['appointments_limit'] ) ?>">
|
268 |
+
</div>
|
269 |
+
</div>
|
270 |
+
<div class="col-sm-6">
|
271 |
+
<div class="form-group">
|
272 |
+
<select id="limit_period_<?php echo $service_id ?>" class="form-control" name="limit_period">
|
273 |
+
<option value="off"><?php _e( 'OFF', 'bookly' ) ?></option>
|
274 |
+
<option value="day"<?php selected( 'day', $service['limit_period'] ) ?>><?php _e( 'per day', 'bookly' ) ?></option>
|
275 |
+
<option value="week"<?php selected( 'week', $service['limit_period'] ) ?>><?php _e( 'per week', 'bookly' ) ?></option>
|
276 |
+
<option value="month"<?php selected( 'month', $service['limit_period'] ) ?>><?php _e( 'per month', 'bookly' ) ?></option>
|
277 |
+
<option value="year"<?php selected( 'year', $service['limit_period'] ) ?>><?php _e( 'per year', 'bookly' ) ?></option>
|
278 |
+
</select>
|
279 |
+
</div>
|
280 |
+
</div>
|
281 |
+
</div>
|
282 |
+
</div>
|
283 |
+
</div>
|
284 |
+
</div>
|
285 |
+
|
286 |
+
<div class="form-group bookly-js-service bookly-js-service-simple bookly-js-service-compound bookly-js-service-package">
|
287 |
<label for="info_<?php echo $service_id ?>">
|
288 |
<?php _e( 'Info', 'bookly' ) ?>
|
289 |
</label>
|
293 |
<textarea class="form-control" id="info_<?php echo $service_id ?>" name="info" rows="3" type="text"><?php echo esc_textarea( $service['info'] ) ?></textarea>
|
294 |
</div>
|
295 |
|
296 |
+
<?php Proxy\CompoundServices::renderSubServices( $service, $service_collection ) ?>
|
297 |
+
<?php Proxy\Shared::renderServiceForm( $service ) ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
<div class="panel-footer">
|
299 |
<input type="hidden" name="action" value="bookly_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 |
+
<span class="bookly-js-services-error text-danger"></span>
|
303 |
+
<?php Common::csrf() ?>
|
304 |
+
<?php Common::submitButton( null, 'ajax-service-send' ) ?>
|
305 |
+
<?php Common::resetButton( null, 'js-reset' ) ?>
|
306 |
</div>
|
307 |
</form>
|
308 |
</div>
|
310 |
</div>
|
311 |
<?php endforeach ?>
|
312 |
</div>
|
313 |
+
<?php endif ?>
|
314 |
+
<div style="display: none">
|
315 |
+
<?php Proxy\Shared::renderAfterServiceList( $service_collection ) ?>
|
316 |
+
</div>
|
backend/modules/services/templates/index.php
CHANGED
@@ -14,7 +14,7 @@
|
|
14 |
<div class="bookly-padding-vertical-xs"><?php _e( 'All Services', 'bookly' ) ?></div>
|
15 |
</div>
|
16 |
<ul id="bookly-category-item-list">
|
17 |
-
<?php foreach ( $category_collection as $category )
|
18 |
</ul>
|
19 |
</div>
|
20 |
|
@@ -31,7 +31,8 @@
|
|
31 |
<div class="form-field form-required">
|
32 |
<label for="bookly-category-name"><?php _e( 'Name', 'bookly' ) ?></label>
|
33 |
<input class="form-control" id="bookly-category-name" type="text" name="name" />
|
34 |
-
<input type="hidden" name="action" value="
|
|
|
35 |
</div>
|
36 |
</div>
|
37 |
|
@@ -61,7 +62,7 @@
|
|
61 |
<?php _e( 'No services found. Please add services.', 'bookly' ) ?>
|
62 |
</p>
|
63 |
|
64 |
-
<div class="bookly-margin-top-xlg" id="
|
65 |
<?php include '_list.php' ?>
|
66 |
</div>
|
67 |
<div class="text-right">
|
@@ -73,7 +74,7 @@
|
|
73 |
</div>
|
74 |
</div>
|
75 |
|
76 |
-
<div id="
|
77 |
<div class="modal-dialog">
|
78 |
<div class="modal-content">
|
79 |
<div class="modal-header">
|
@@ -84,22 +85,18 @@
|
|
84 |
<p><?php _e( 'You are about to change a service setting which is also configured separately for each staff member. Do you want to update it in staff settings too?', 'bookly' ) ?></p>
|
85 |
<div class="checkbox">
|
86 |
<label>
|
87 |
-
<input id="
|
88 |
<?php _e( 'Remember my choice', 'bookly' ) ?>
|
89 |
</label>
|
90 |
</div>
|
91 |
</div>
|
92 |
<div class="modal-footer">
|
93 |
-
<button type="reset" class="btn btn-default
|
94 |
<?php _e( 'No, update just here in services', 'bookly' ) ?>
|
95 |
</button>
|
96 |
-
<button type="submit" class="btn btn-success
|
97 |
</div>
|
98 |
</div>
|
99 |
</div>
|
100 |
</div>
|
101 |
-
</div>
|
102 |
-
|
103 |
-
<div class="hidden">
|
104 |
-
<?php do_action( 'bookly_render_after_service_list', $service_collection ) ?>
|
105 |
</div>
|
14 |
<div class="bookly-padding-vertical-xs"><?php _e( 'All Services', 'bookly' ) ?></div>
|
15 |
</div>
|
16 |
<ul id="bookly-category-item-list">
|
17 |
+
<?php foreach ( $category_collection as $category ) $this->render( '_category_item', compact( 'category' ) ) ?>
|
18 |
</ul>
|
19 |
</div>
|
20 |
|
31 |
<div class="form-field form-required">
|
32 |
<label for="bookly-category-name"><?php _e( 'Name', 'bookly' ) ?></label>
|
33 |
<input class="form-control" id="bookly-category-name" type="text" name="name" />
|
34 |
+
<input type="hidden" name="action" value="bookly_add_category" />
|
35 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
36 |
</div>
|
37 |
</div>
|
38 |
|
62 |
<?php _e( 'No services found. Please add services.', 'bookly' ) ?>
|
63 |
</p>
|
64 |
|
65 |
+
<div class="bookly-margin-top-xlg" id="bookly-js-services-list">
|
66 |
<?php include '_list.php' ?>
|
67 |
</div>
|
68 |
<div class="text-right">
|
74 |
</div>
|
75 |
</div>
|
76 |
|
77 |
+
<div id="bookly-update-service-settings" class="modal fade" tabindex=-1 role="dialog">
|
78 |
<div class="modal-dialog">
|
79 |
<div class="modal-content">
|
80 |
<div class="modal-header">
|
85 |
<p><?php _e( 'You are about to change a service setting which is also configured separately for each staff member. Do you want to update it in staff settings too?', 'bookly' ) ?></p>
|
86 |
<div class="checkbox">
|
87 |
<label>
|
88 |
+
<input id="bookly-remember-my-choice" type="checkbox">
|
89 |
<?php _e( 'Remember my choice', 'bookly' ) ?>
|
90 |
</label>
|
91 |
</div>
|
92 |
</div>
|
93 |
<div class="modal-footer">
|
94 |
+
<button type="reset" class="btn btn-default bookly-no" data-dismiss="modal" aria-hidden="true">
|
95 |
<?php _e( 'No, update just here in services', 'bookly' ) ?>
|
96 |
</button>
|
97 |
+
<button type="submit" class="btn btn-success bookly-yes"><?php _e( 'Yes', 'bookly' ) ?></button>
|
98 |
</div>
|
99 |
</div>
|
100 |
</div>
|
101 |
</div>
|
|
|
|
|
|
|
|
|
102 |
</div>
|
backend/modules/settings/Components.php
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Settings;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Components
|
8 |
+
* @package BooklyLite\Backend\Modules\Support
|
9 |
+
*/
|
10 |
+
class Components extends Lib\Base\Components
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render collect stats notice and marks it as showed for every user
|
14 |
+
*/
|
15 |
+
public function renderCollectStatsNotice()
|
16 |
+
{
|
17 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() &&
|
18 |
+
get_option( 'bookly_gen_collect_stats' ) == '0' &&
|
19 |
+
! (int) get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_collect_stats_notice', true )
|
20 |
+
) {
|
21 |
+
$this->enqueueStyles( array(
|
22 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
23 |
+
) );
|
24 |
+
$this->enqueueScripts( array(
|
25 |
+
'module' => array( 'js/collect-stats-notice.js' => array( 'jquery' ), ),
|
26 |
+
) );
|
27 |
+
$this->render( '_collect_stats_notice' );
|
28 |
+
}
|
29 |
+
}
|
30 |
+
}
|
backend/modules/settings/Controller.php
CHANGED
@@ -41,93 +41,98 @@ class Controller extends Lib\Base\Controller
|
|
41 |
|
42 |
// Save the settings.
|
43 |
if ( ! empty ( $_POST ) ) {
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
update_option( '
|
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 |
-
update_option(
|
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 |
-
$form->save();
|
125 |
|
126 |
-
$
|
|
|
|
|
|
|
|
|
|
|
127 |
}
|
128 |
}
|
129 |
|
130 |
-
$holidays = $this->getHolidays();
|
131 |
$candidates = $this->getCandidatesBooklyProduct();
|
132 |
|
133 |
// Check if WooCommerce cart exists.
|
@@ -150,18 +155,23 @@ class Controller extends Lib\Base\Controller
|
|
150 |
);
|
151 |
|
152 |
wp_localize_script( 'bookly-jCal.js', 'BooklyL10n', array(
|
153 |
-
'alert'
|
154 |
-
'
|
155 |
-
'
|
156 |
-
'
|
157 |
-
'
|
158 |
-
'
|
|
|
|
|
|
|
|
|
|
|
159 |
'we_are_not_working' => __( 'We are not working on this day', 'bookly' ),
|
160 |
-
'
|
161 |
-
'limitations'
|
162 |
) );
|
163 |
$values = array(
|
164 |
-
'bookly_gc_limit_events' => array( array( '0', __( 'Disabled', 'bookly' ) ), array( 25, 25 ), array( 50, 50 ), array( 100, 100 ), array( 250, 250 ), array( 500, 500 ), array( 1000, 1000), array( 2500, 2500 ) ),
|
165 |
'bookly_gen_min_time_prior_booking' => array( array( '0', __( 'Disabled', 'bookly' ) ) ),
|
166 |
'bookly_gen_min_time_prior_cancel' => array( array( '0', __( 'Disabled', 'bookly' ) ) ),
|
167 |
);
|
@@ -172,14 +182,14 @@ class Controller extends Lib\Base\Controller
|
|
172 |
foreach ( array( 5, 10, 12, 15, 20, 30, 45, 60, 90, 120, 180, 240, 360 ) as $duration ) {
|
173 |
$values['bookly_gen_time_slot_length'][] = array( $duration, Lib\Utils\DateTime::secondsToInterval( $duration * MINUTE_IN_SECONDS ) );
|
174 |
}
|
175 |
-
foreach ( array_merge( range( 1, 12 ), range( 24, 144, 24 ), range( 168, 672, 168 ) ) as $hour ) {
|
176 |
$values['bookly_gen_min_time_prior_booking'][] = array( $hour, Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) );
|
177 |
}
|
178 |
foreach ( array_merge( array( 1 ), range( 2, 12, 2 ), range( 24, 168, 24 ) ) as $hour ) {
|
179 |
$values['bookly_gen_min_time_prior_cancel'][] = array( $hour, Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) );
|
180 |
}
|
181 |
|
182 |
-
$this->render( 'index', compact( '
|
183 |
}
|
184 |
|
185 |
/**
|
@@ -192,31 +202,59 @@ class Controller extends Lib\Base\Controller
|
|
192 |
$id = $this->getParameter( 'id', false );
|
193 |
$day = $this->getParameter( 'day', false );
|
194 |
$holiday = $this->getParameter( 'holiday' ) == 'true';
|
195 |
-
$repeat = $this->getParameter( 'repeat' )
|
196 |
|
197 |
// update or delete the event
|
198 |
if ( $id ) {
|
199 |
if ( $holiday ) {
|
200 |
-
$wpdb->update( Lib\Entities\Holiday::getTableName(), array( 'repeat_event' =>
|
201 |
-
$wpdb->update( Lib\Entities\Holiday::getTableName(), array( 'repeat_event' =>
|
202 |
} else {
|
203 |
Lib\Entities\Holiday::query()->delete()->where( 'id', $id )->where( 'parent_id', $id, 'OR' )->execute();
|
204 |
}
|
205 |
// add the new event
|
206 |
} elseif ( $holiday && $day ) {
|
207 |
-
$holiday = new Lib\Entities\Holiday(
|
208 |
-
$holiday
|
|
|
|
|
|
|
209 |
foreach ( Lib\Entities\Staff::query()->fetchArray() as $employee ) {
|
210 |
-
$staff_holiday = new Lib\Entities\Holiday(
|
211 |
-
$staff_holiday
|
|
|
|
|
|
|
|
|
|
|
212 |
}
|
213 |
}
|
214 |
|
215 |
// and return refreshed events
|
216 |
-
echo $this->getHolidays();
|
217 |
exit;
|
218 |
}
|
219 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
/**
|
221 |
* @return string
|
222 |
*/
|
@@ -237,35 +275,25 @@ class Controller extends Lib\Base\Controller
|
|
237 |
}
|
238 |
}
|
239 |
|
240 |
-
return
|
241 |
}
|
242 |
|
|
|
|
|
|
|
243 |
protected function getCandidatesBooklyProduct()
|
244 |
{
|
245 |
-
|
246 |
-
$
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
);
|
251 |
-
|
252 |
-
foreach ( $
|
253 |
-
$goods[] = array( 'id' => $
|
254 |
}
|
255 |
-
wp_reset_postdata();
|
256 |
|
257 |
return $goods;
|
258 |
}
|
259 |
-
|
260 |
-
/**
|
261 |
-
* Override parent method to add 'wp_ajax_bookly_' prefix
|
262 |
-
* so current 'execute*' methods look nicer.
|
263 |
-
*
|
264 |
-
* @param string $prefix
|
265 |
-
*/
|
266 |
-
protected function registerWpActions( $prefix = '' )
|
267 |
-
{
|
268 |
-
parent::registerWpActions( 'wp_ajax_bookly_' );
|
269 |
-
}
|
270 |
-
|
271 |
}
|
41 |
|
42 |
// Save the settings.
|
43 |
if ( ! empty ( $_POST ) ) {
|
44 |
+
if ( $this->csrfTokenValid() ) {
|
45 |
+
switch ( $this->getParameter( 'tab' ) ) {
|
46 |
+
case 'calendar': // Calendar form.
|
47 |
+
update_option( 'bookly_cal_one_participant', $this->getParameter( 'bookly_cal_one_participant' ) );
|
48 |
+
update_option( 'bookly_cal_many_participants', $this->getParameter( 'bookly_cal_many_participants' ) );
|
49 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
50 |
+
break;
|
51 |
+
case 'payments': // Payments form.
|
52 |
+
$form = new Forms\Payments();
|
53 |
+
break;
|
54 |
+
case 'business_hours': // Business hours form.
|
55 |
+
$form = new Forms\BusinessHours();
|
56 |
+
break;
|
57 |
+
case 'purchase_code': // Purchase Code form.
|
58 |
+
break;
|
59 |
+
case 'general': // General form.
|
60 |
+
$bookly_gen_time_slot_length = $this->getParameter( 'bookly_gen_time_slot_length' );
|
61 |
+
if ( in_array( $bookly_gen_time_slot_length, array( 5, 10, 12, 15, 20, 30, 45, 60, 90, 120, 180, 240, 360 ) ) ) {
|
62 |
+
update_option( 'bookly_gen_time_slot_length', $bookly_gen_time_slot_length );
|
63 |
+
}
|
64 |
+
update_option( 'bookly_gen_lite_uninstall_remove_bookly_data', (int) $this->getParameter( 'bookly_gen_lite_uninstall_remove_bookly_data' ) );
|
65 |
+
update_option( 'bookly_gen_service_duration_as_slot_length', (int) $this->getParameter( 'bookly_gen_service_duration_as_slot_length' ) );
|
66 |
+
update_option( 'bookly_gen_allow_staff_edit_profile', (int) $this->getParameter( 'bookly_gen_allow_staff_edit_profile' ) );
|
67 |
+
update_option( 'bookly_gen_default_appointment_status', $this->getParameter( 'bookly_gen_default_appointment_status' ) );
|
68 |
+
update_option( 'bookly_gen_link_assets_method', $this->getParameter( 'bookly_gen_link_assets_method' ) );
|
69 |
+
update_option( 'bookly_gen_max_days_for_booking', (int) $this->getParameter( 'bookly_gen_max_days_for_booking' ) );
|
70 |
+
update_option( 'bookly_gen_min_time_prior_booking', $this->getParameter( 'bookly_gen_min_time_prior_booking' ) );
|
71 |
+
update_option( 'bookly_gen_min_time_prior_cancel', $this->getParameter( 'bookly_gen_min_time_prior_cancel' ) );
|
72 |
+
update_option( 'bookly_gen_use_client_time_zone', (int) $this->getParameter( 'bookly_gen_use_client_time_zone' ) );
|
73 |
+
update_option( 'bookly_gen_collect_stats', $this->getParameter( 'bookly_gen_collect_stats' ) );
|
74 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
75 |
+
break;
|
76 |
+
case 'url': // URL settings form.
|
77 |
+
update_option( 'bookly_url_approve_page_url', $this->getParameter( 'bookly_url_approve_page_url' ) );
|
78 |
+
update_option( 'bookly_url_approve_denied_page_url', $this->getParameter( 'bookly_url_approve_denied_page_url' ) );
|
79 |
+
update_option( 'bookly_url_cancel_page_url', $this->getParameter( 'bookly_url_cancel_page_url' ) );
|
80 |
+
update_option( 'bookly_url_cancel_denied_page_url', $this->getParameter( 'bookly_url_cancel_denied_page_url' ) );
|
81 |
+
update_option( 'bookly_url_cancel_confirm_page_url', $this->getParameter( 'bookly_url_cancel_confirm_page_url' ) );
|
82 |
+
update_option( 'bookly_url_reject_denied_page_url', $this->getParameter( 'bookly_url_reject_denied_page_url' ) );
|
83 |
+
update_option( 'bookly_url_reject_page_url', $this->getParameter( 'bookly_url_reject_page_url' ) );
|
84 |
+
update_option( 'bookly_url_final_step_url', '' );
|
85 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
86 |
+
break;
|
87 |
+
case 'google_calendar': // Google calendar form.
|
88 |
+
update_option( 'bookly_gc_client_id', '' );
|
89 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
90 |
+
break;
|
91 |
+
case 'customers': // Customers form.
|
92 |
+
update_option( 'bookly_cst_cancel_action', $this->getParameter( 'bookly_cst_cancel_action' ) );
|
93 |
+
update_option( 'bookly_cst_combined_notifications', $this->getParameter( 'bookly_cst_combined_notifications' ) );
|
94 |
+
update_option( 'bookly_cst_create_account', $this->getParameter( 'bookly_cst_create_account' ) );
|
95 |
+
update_option( 'bookly_cst_default_country_code', $this->getParameter( 'bookly_cst_default_country_code' ) );
|
96 |
+
update_option( 'bookly_cst_new_account_role', $this->getParameter( 'bookly_cst_new_account_role' ) );
|
97 |
+
update_option( 'bookly_cst_phone_default_country', $this->getParameter( 'bookly_cst_phone_default_country' ) );
|
98 |
+
update_option( 'bookly_cst_remember_in_cookie', $this->getParameter( 'bookly_cst_remember_in_cookie' ) );
|
99 |
+
update_option( 'bookly_cst_show_update_details_dialog', $this->getParameter( 'bookly_cst_show_update_details_dialog' ) );
|
100 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
101 |
+
break;
|
102 |
+
case 'woo_commerce': // WooCommerce form.
|
103 |
+
update_option( 'bookly_wc_enabled', '0' );
|
104 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
105 |
+
break;
|
106 |
+
case 'cart': // Cart form.
|
107 |
+
update_option( 'bookly_cart_show_columns', $this->getParameter( 'bookly_cart_show_columns', array() ) );
|
108 |
+
update_option( 'bookly_cart_enabled', '0' );
|
109 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
110 |
+
if ( get_option( 'bookly_wc_enabled' ) && $this->getParameter( 'bookly_cart_enabled' ) ) {
|
111 |
+
$alert['error'][] = sprintf( __( 'To use the cart, disable integration with WooCommerce <a href="%s">here</a>.', 'bookly' ), Lib\Utils\Common::escAdminUrl( self::page_slug, array( 'tab' => 'woocommerce' ) ) );
|
112 |
+
}
|
113 |
+
break;
|
114 |
+
case 'company': // Company form.
|
115 |
+
update_option( 'bookly_co_address', $this->getParameter( 'bookly_co_address' ) );
|
116 |
+
update_option( 'bookly_co_logo_attachment_id', $this->getParameter( 'bookly_co_logo_attachment_id' ) );
|
117 |
+
update_option( 'bookly_co_name', $this->getParameter( 'bookly_co_name' ) );
|
118 |
+
update_option( 'bookly_co_phone', $this->getParameter( 'bookly_co_phone' ) );
|
119 |
+
update_option( 'bookly_co_website', $this->getParameter( 'bookly_co_website' ) );
|
120 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
121 |
+
break;
|
122 |
+
}
|
123 |
|
124 |
+
// Let Add-ons save their settings.
|
125 |
+
$alert = Lib\Proxy\Shared::saveSettings( $alert, $this->getParameter( 'tab' ), $this->getPostParameters() );
|
|
|
126 |
|
127 |
+
if ( in_array( $this->getParameter( 'tab' ), array( 'payments', 'business_hours' ) ) ) {
|
128 |
+
$form->bind( $this->getPostParameters(), $_FILES );
|
129 |
+
$form->save();
|
130 |
+
|
131 |
+
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
132 |
+
}
|
133 |
}
|
134 |
}
|
135 |
|
|
|
136 |
$candidates = $this->getCandidatesBooklyProduct();
|
137 |
|
138 |
// Check if WooCommerce cart exists.
|
155 |
);
|
156 |
|
157 |
wp_localize_script( 'bookly-jCal.js', 'BooklyL10n', array(
|
158 |
+
'alert' => $alert,
|
159 |
+
'current_tab' => $current_tab,
|
160 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
161 |
+
'default_country' => get_option( 'bookly_cst_phone_default_country' ),
|
162 |
+
'holidays' => $this->getHolidays(),
|
163 |
+
'loading_img' => plugins_url( 'bookly-responsive-appointment-booking-tool/backend/resources/images/loading.gif' ),
|
164 |
+
'start_of_week' => get_option( 'start_of_week' ),
|
165 |
+
'days' => array_values( $wp_locale->weekday_abbrev ),
|
166 |
+
'months' => array_values( $wp_locale->month ),
|
167 |
+
'close' => __( 'Close', 'bookly' ),
|
168 |
+
'repeat' => __( 'Repeat every year', 'bookly' ),
|
169 |
'we_are_not_working' => __( 'We are not working on this day', 'bookly' ),
|
170 |
+
'sample_price' => number_format_i18n( 10, 3 ),
|
171 |
+
'limitations' => __( '<b class="h4">This function is not available in the Lite version of Bookly.</b><br><br>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', 'bookly' ) . ' <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
172 |
) );
|
173 |
$values = array(
|
174 |
+
'bookly_gc_limit_events' => array( array( '0', __( 'Disabled', 'bookly' ) ), array( 25, 25 ), array( 50, 50 ), array( 100, 100 ), array( 250, 250 ), array( 500, 500 ), array( 1000, 1000 ), array( 2500, 2500 ) ),
|
175 |
'bookly_gen_min_time_prior_booking' => array( array( '0', __( 'Disabled', 'bookly' ) ) ),
|
176 |
'bookly_gen_min_time_prior_cancel' => array( array( '0', __( 'Disabled', 'bookly' ) ) ),
|
177 |
);
|
182 |
foreach ( array( 5, 10, 12, 15, 20, 30, 45, 60, 90, 120, 180, 240, 360 ) as $duration ) {
|
183 |
$values['bookly_gen_time_slot_length'][] = array( $duration, Lib\Utils\DateTime::secondsToInterval( $duration * MINUTE_IN_SECONDS ) );
|
184 |
}
|
185 |
+
foreach ( array_merge( array( 0.5 ), range( 1, 12 ), range( 24, 144, 24 ), range( 168, 672, 168 ) ) as $hour ) {
|
186 |
$values['bookly_gen_min_time_prior_booking'][] = array( $hour, Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) );
|
187 |
}
|
188 |
foreach ( array_merge( array( 1 ), range( 2, 12, 2 ), range( 24, 168, 24 ) ) as $hour ) {
|
189 |
$values['bookly_gen_min_time_prior_cancel'][] = array( $hour, Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) );
|
190 |
}
|
191 |
|
192 |
+
$this->render( 'index', compact( 'candidates', 'cart_columns', 'values' ) );
|
193 |
}
|
194 |
|
195 |
/**
|
202 |
$id = $this->getParameter( 'id', false );
|
203 |
$day = $this->getParameter( 'day', false );
|
204 |
$holiday = $this->getParameter( 'holiday' ) == 'true';
|
205 |
+
$repeat = (int) ( $this->getParameter( 'repeat' ) == 'true' );
|
206 |
|
207 |
// update or delete the event
|
208 |
if ( $id ) {
|
209 |
if ( $holiday ) {
|
210 |
+
$wpdb->update( Lib\Entities\Holiday::getTableName(), array( 'repeat_event' => $repeat ), array( 'id' => $id ), array( '%d' ) );
|
211 |
+
$wpdb->update( Lib\Entities\Holiday::getTableName(), array( 'repeat_event' => $repeat ), array( 'parent_id' => $id ), array( '%d' ) );
|
212 |
} else {
|
213 |
Lib\Entities\Holiday::query()->delete()->where( 'id', $id )->where( 'parent_id', $id, 'OR' )->execute();
|
214 |
}
|
215 |
// add the new event
|
216 |
} elseif ( $holiday && $day ) {
|
217 |
+
$holiday = new Lib\Entities\Holiday( );
|
218 |
+
$holiday
|
219 |
+
->setDate( $day )
|
220 |
+
->setRepeatEvent( $repeat )
|
221 |
+
->save();
|
222 |
foreach ( Lib\Entities\Staff::query()->fetchArray() as $employee ) {
|
223 |
+
$staff_holiday = new Lib\Entities\Holiday();
|
224 |
+
$staff_holiday
|
225 |
+
->setDate( $day)
|
226 |
+
->setRepeatEvent( $repeat )
|
227 |
+
->setStaffId( $employee['id'] )
|
228 |
+
->setParent( $holiday )
|
229 |
+
->save();
|
230 |
}
|
231 |
}
|
232 |
|
233 |
// and return refreshed events
|
234 |
+
echo json_encode( $this->getHolidays() );
|
235 |
exit;
|
236 |
}
|
237 |
|
238 |
+
/**
|
239 |
+
* Dismiss collect stats notice.
|
240 |
+
*/
|
241 |
+
public function executeDismissCollectStatsNotice()
|
242 |
+
{
|
243 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_collect_stats_notice', 1 );
|
244 |
+
update_option( 'bookly_gen_collect_stats', '0' );
|
245 |
+
|
246 |
+
wp_send_json_success();
|
247 |
+
}
|
248 |
+
|
249 |
+
public function executeAllowCollectStats()
|
250 |
+
{
|
251 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_collect_stats_notice', 1 );
|
252 |
+
update_option( 'bookly_gen_collect_stats', '1' );
|
253 |
+
|
254 |
+
wp_send_json_success();
|
255 |
+
}
|
256 |
+
|
257 |
+
|
258 |
/**
|
259 |
* @return string
|
260 |
*/
|
275 |
}
|
276 |
}
|
277 |
|
278 |
+
return $holidays;
|
279 |
}
|
280 |
|
281 |
+
/**
|
282 |
+
* @return array
|
283 |
+
*/
|
284 |
protected function getCandidatesBooklyProduct()
|
285 |
{
|
286 |
+
/** @global \wpdb $wpdb */
|
287 |
+
global $wpdb;
|
288 |
+
|
289 |
+
$goods = array( array( 'id' => 0, 'name' => __( 'Select product', 'bookly' ) ) );
|
290 |
+
$query = 'SELECT ID, post_title FROM ' . $wpdb->posts . ' WHERE post_type = \'product\' AND post_status = \'publish\' ORDER BY post_title';
|
291 |
+
$products = $wpdb->get_results( $query );
|
292 |
+
|
293 |
+
foreach ( $products as $product ) {
|
294 |
+
$goods[] = array( 'id' => $product->ID, 'name' => $product->post_title );
|
295 |
}
|
|
|
296 |
|
297 |
return $goods;
|
298 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
299 |
}
|
backend/modules/settings/forms/BusinessHours.php
CHANGED
@@ -41,11 +41,11 @@ class BusinessHours extends Lib\Base\Form
|
|
41 |
* @param bool $is_start
|
42 |
* @return string
|
43 |
*/
|
44 |
-
public function renderField( $field_name = '
|
45 |
{
|
46 |
$ts_length = Lib\Config::getTimeSlotLength();
|
47 |
-
$time_output =
|
48 |
-
$time_end =
|
49 |
$option_name = $field_name . ( $is_start ? '_start' : '_end' );
|
50 |
$class_name = $is_start ? 'select_start' : 'select_end bookly-hide-on-off';
|
51 |
$selected_value = get_option( $option_name );
|
@@ -62,7 +62,7 @@ class BusinessHours extends Lib\Base\Form
|
|
62 |
if ( $selected_seconds == $time_output ) {
|
63 |
$value_added = true;
|
64 |
} elseif ( $selected_seconds < $time_output ) {
|
65 |
-
$output
|
66 |
$value_added = true;
|
67 |
}
|
68 |
}
|
41 |
* @param bool $is_start
|
42 |
* @return string
|
43 |
*/
|
44 |
+
public function renderField( $field_name = 'bookly_bh_monday', $is_start = true )
|
45 |
{
|
46 |
$ts_length = Lib\Config::getTimeSlotLength();
|
47 |
+
$time_output = 0;
|
48 |
+
$time_end = DAY_IN_SECONDS;
|
49 |
$option_name = $field_name . ( $is_start ? '_start' : '_end' );
|
50 |
$class_name = $is_start ? 'select_start' : 'select_end bookly-hide-on-off';
|
51 |
$selected_value = get_option( $option_name );
|
62 |
if ( $selected_seconds == $time_output ) {
|
63 |
$value_added = true;
|
64 |
} elseif ( $selected_seconds < $time_output ) {
|
65 |
+
$output .= sprintf( '<option value="%s" selected="selected">%s</option>', $selected_value, Lib\Utils\DateTime::formatTime( $selected_value ) );
|
66 |
$value_added = true;
|
67 |
}
|
68 |
}
|
backend/modules/settings/forms/Payments.php
CHANGED
@@ -11,10 +11,20 @@ class Payments extends Lib\Base\Form
|
|
11 |
{
|
12 |
public function __construct()
|
13 |
{
|
14 |
-
|
|
|
|
|
|
|
|
|
15 |
'bookly_pmt_currency',
|
|
|
16 |
'bookly_pmt_local',
|
17 |
) );
|
|
|
|
|
|
|
|
|
|
|
18 |
}
|
19 |
|
20 |
public function save()
|
11 |
{
|
12 |
public function __construct()
|
13 |
{
|
14 |
+
}
|
15 |
+
|
16 |
+
public function bind( array $_post, array $files = array() )
|
17 |
+
{
|
18 |
+
$fields = Lib\Proxy\Shared::preparePaymentOptions( array(
|
19 |
'bookly_pmt_currency',
|
20 |
+
'bookly_pmt_price_format',
|
21 |
'bookly_pmt_local',
|
22 |
) );
|
23 |
+
|
24 |
+
$_post = Lib\Proxy\Shared::preparePaymentOptionsData( $_post );
|
25 |
+
|
26 |
+
$this->setFields( $fields );
|
27 |
+
parent::bind( $_post, $files );
|
28 |
}
|
29 |
|
30 |
public function save()
|
backend/modules/settings/resources/js/collect-stats-notice.js
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
var $alert = $('#bookly-collect-stats-notice');
|
3 |
+
|
4 |
+
$alert
|
5 |
+
.on('click', '.bookly-js-disallow-stats', function () {
|
6 |
+
$.post(ajaxurl, {action: 'bookly_dismiss_collect_stats_notice', csrf_token: SupportL10n.csrf_token});
|
7 |
+
$alert.alert('close');
|
8 |
+
})
|
9 |
+
.on('click', '.bookly-js-allow-stats', function () {
|
10 |
+
$.post(ajaxurl, {action: 'bookly_allow_collect_stats', csrf_token: SupportL10n.csrf_token});
|
11 |
+
$alert.alert('close');
|
12 |
+
});
|
13 |
+
});
|
backend/modules/settings/resources/js/settings.js
CHANGED
@@ -1,8 +1,9 @@
|
|
1 |
jQuery(function ($) {
|
2 |
var $form = $('#business-hours'),
|
3 |
-
$final_step_url = $('input[name=
|
4 |
$final_step_url_mode = $('#bookly_settings_final_step_url_mode'),
|
5 |
-
$help_btn = $('#bookly-help-btn')
|
|
|
6 |
;
|
7 |
|
8 |
booklyAlert(BooklyL10n.alert);
|
@@ -25,6 +26,10 @@ jQuery(function ($) {
|
|
25 |
$(this).prop('disabled',true);
|
26 |
booklyAlert({error: [BooklyL10n.limitations]});
|
27 |
});
|
|
|
|
|
|
|
|
|
28 |
$('.select_start', $form).on('change', function () {
|
29 |
var $flexbox = $(this).closest('.bookly-flexbox'),
|
30 |
$end_select = $('.select_end', $flexbox),
|
@@ -78,6 +83,20 @@ jQuery(function ($) {
|
|
78 |
$default_country_code.val($default_country.find('option:selected').data('code'));
|
79 |
});
|
80 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
81 |
// Company Tab
|
82 |
$('#bookly-company-reset').on('click', function () {
|
83 |
var $div = $('#bookly-js-logo .bookly-js-image'),
|
@@ -93,73 +112,38 @@ jQuery(function ($) {
|
|
93 |
});
|
94 |
|
95 |
// Payment Tab
|
96 |
-
$('#
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
}).change
|
113 |
-
|
114 |
-
$('#bookly_pmt_stripe').change(function () {
|
115 |
-
if (this.value != 'disabled') {
|
116 |
-
$(this).val('disabled');
|
117 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
118 |
-
$(this).find('option:gt(0)').prop('disabled', true);
|
119 |
-
}
|
120 |
-
$('.bookly-stripe').toggle(this.value == 1);
|
121 |
-
}).change();
|
122 |
-
|
123 |
-
$('#bookly_pmt_2checkout').change(function () {
|
124 |
-
if (this.value != 'disabled') {
|
125 |
-
$(this).val('disabled');
|
126 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
127 |
-
$(this).find('option:gt(0)').prop('disabled', true);
|
128 |
-
}
|
129 |
-
$('.bookly-2checkout').toggle(this.value != 'disabled');
|
130 |
-
}).change();
|
131 |
-
|
132 |
-
$('#bookly_pmt_payu_latam').change(function () {
|
133 |
-
if (this.value != 'disabled') {
|
134 |
-
$(this).val('disabled');
|
135 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
136 |
-
$(this).find('option:gt(0)').prop('disabled', true);
|
137 |
-
}
|
138 |
-
$('.bookly-payu_latam').toggle(this.value != 'disabled');
|
139 |
-
}).change();
|
140 |
-
|
141 |
-
$('#bookly_pmt_payson').change(function () {
|
142 |
-
if (this.value != 'disabled') {
|
143 |
-
$(this).val('disabled');
|
144 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
145 |
-
$(this).find('option:gt(0)').prop('disabled', true);
|
146 |
-
}
|
147 |
-
$('.bookly-payson').toggle(this.value != 'disabled');
|
148 |
-
}).change();
|
149 |
|
150 |
-
|
151 |
-
|
152 |
-
|
|
|
153 |
booklyAlert({error: [BooklyL10n.limitations]});
|
154 |
$(this).find('option:gt(0)').prop('disabled', true);
|
155 |
}
|
156 |
-
$('.bookly-
|
157 |
}).change();
|
158 |
|
159 |
$('#bookly-payments-reset').on('click', function (event) {
|
160 |
setTimeout(function () {
|
161 |
-
$('#
|
162 |
-
},
|
163 |
});
|
164 |
|
165 |
$('#bookly-customer-reset').on('click', function (event) {
|
@@ -179,6 +163,32 @@ jQuery(function ($) {
|
|
179 |
$('.bookly-nav li[data-toggle="tab"]').on('shown.bs.tab', function(e) {
|
180 |
$help_btn.attr('href', help_link + e.target.getAttribute('data-target').substring(1).replace(/_/g, '-'));
|
181 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
182 |
// Activate tab.
|
183 |
$('li[data-target="#bookly_settings_' + BooklyL10n.current_tab + '"]').tab('show');
|
184 |
|
1 |
jQuery(function ($) {
|
2 |
var $form = $('#business-hours'),
|
3 |
+
$final_step_url = $('input[name=bookly_url_final_step_url]'),
|
4 |
$final_step_url_mode = $('#bookly_settings_final_step_url_mode'),
|
5 |
+
$help_btn = $('#bookly-help-btn'),
|
6 |
+
$participants = $('#bookly_appointment_participants')
|
7 |
;
|
8 |
|
9 |
booklyAlert(BooklyL10n.alert);
|
26 |
$(this).prop('disabled',true);
|
27 |
booklyAlert({error: [BooklyL10n.limitations]});
|
28 |
});
|
29 |
+
$('#bookly_wc_product,#bookly_l10n_wc_cart_info_name,[name=bookly_l10n_wc_cart_info_value]').on('focus', function () {
|
30 |
+
$(this).prop('disabled',true);
|
31 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
32 |
+
});
|
33 |
$('.select_start', $form).on('change', function () {
|
34 |
var $flexbox = $(this).closest('.bookly-flexbox'),
|
35 |
$end_select = $('.select_end', $flexbox),
|
83 |
$default_country_code.val($default_country.find('option:selected').data('code'));
|
84 |
});
|
85 |
|
86 |
+
// Calendar tab
|
87 |
+
$participants.on('change', function () {
|
88 |
+
|
89 |
+
$('#bookly_cal_one_participant').hide();
|
90 |
+
$('#bookly_cal_many_participants').hide();
|
91 |
+
$('#' + $(this).val() ).show();
|
92 |
+
}).trigger('change');
|
93 |
+
|
94 |
+
$("#bookly_settings_calendar button[type=reset]").on( 'click', function () {
|
95 |
+
setTimeout(function () {
|
96 |
+
$participants.trigger('change');
|
97 |
+
}, 50 );
|
98 |
+
});
|
99 |
+
|
100 |
// Company Tab
|
101 |
$('#bookly-company-reset').on('click', function () {
|
102 |
var $div = $('#bookly-js-logo .bookly-js-image'),
|
112 |
});
|
113 |
|
114 |
// Payment Tab
|
115 |
+
var $currency = $('#bookly_pmt_currency'),
|
116 |
+
$formats = $('#bookly_pmt_price_format')
|
117 |
+
;
|
118 |
+
$currency.on('change', function () {
|
119 |
+
$formats.find('option').each(function () {
|
120 |
+
var decimals = this.value.match(/{price\|(\d)}/)[1],
|
121 |
+
price = BooklyL10n.sample_price
|
122 |
+
;
|
123 |
+
if (decimals < 3) {
|
124 |
+
price = price.slice(0, -(decimals == 0 ? 4 : 3 - decimals));
|
125 |
+
}
|
126 |
+
this.innerHTML = this.value
|
127 |
+
.replace('{symbol}', $currency.find('option:selected').data('symbol'))
|
128 |
+
.replace(/{price\|\d}/, price)
|
129 |
+
;
|
130 |
+
});
|
131 |
+
}).trigger('change');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
132 |
|
133 |
+
// Payment Tab
|
134 |
+
$('#bookly_paypal_enabled').change(function () {
|
135 |
+
if (this.value != '0') {
|
136 |
+
$(this).val('0');
|
137 |
booklyAlert({error: [BooklyL10n.limitations]});
|
138 |
$(this).find('option:gt(0)').prop('disabled', true);
|
139 |
}
|
140 |
+
$('.bookly-paypal').toggle(this.value != '0');
|
141 |
}).change();
|
142 |
|
143 |
$('#bookly-payments-reset').on('click', function (event) {
|
144 |
setTimeout(function () {
|
145 |
+
$('#bookly_pmt_currency,#bookly_paypal_enabled,#bookly_authorize_net_enabled,#bookly_stripe_enabled,#bookly_2checkout_enabled,#bookly_payu_latam_enabled,#bookly_payson_enabled,#bookly_mollie_enabled,#bookly_payu_latam_sandbox').change();
|
146 |
+
}, 0);
|
147 |
});
|
148 |
|
149 |
$('#bookly-customer-reset').on('click', function (event) {
|
163 |
$('.bookly-nav li[data-toggle="tab"]').on('shown.bs.tab', function(e) {
|
164 |
$help_btn.attr('href', help_link + e.target.getAttribute('data-target').substring(1).replace(/_/g, '-'));
|
165 |
});
|
166 |
+
|
167 |
+
// Holidays
|
168 |
+
var d = new Date();
|
169 |
+
$('.bookly-js-annual-calendar').jCal({
|
170 |
+
day: new Date(d.getFullYear(), 0, 1),
|
171 |
+
days: 1,
|
172 |
+
showMonths: 12,
|
173 |
+
scrollSpeed: 350,
|
174 |
+
events: BooklyL10n.holidays,
|
175 |
+
action: 'bookly_settings_holiday',
|
176 |
+
csrf_token: BooklyL10n.csrf_token,
|
177 |
+
dayOffset: parseInt(BooklyL10n.start_of_week),
|
178 |
+
loadingImg: BooklyL10n.loading_img,
|
179 |
+
dow: BooklyL10n.days,
|
180 |
+
ml: BooklyL10n.months,
|
181 |
+
we_are_not_working: BooklyL10n.we_are_not_working,
|
182 |
+
repeat: BooklyL10n.repeat,
|
183 |
+
close: BooklyL10n.close
|
184 |
+
});
|
185 |
+
|
186 |
+
$('.bookly-js-jCalBtn').on('click', function (e) {
|
187 |
+
e.preventDefault();
|
188 |
+
var trigger = $(this).data('trigger');
|
189 |
+
$('.bookly-js-annual-calendar').find($(trigger)).trigger('click');
|
190 |
+
});
|
191 |
+
|
192 |
// Activate tab.
|
193 |
$('li[data-target="#bookly_settings_' + BooklyL10n.current_tab + '"]').tab('show');
|
194 |
|
backend/modules/settings/templates/_calendarForm.php
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'calendar' ) ) ?>">
|
3 |
+
<div class="form-group"><label for="bookly_appointment_participants"><?php _e( 'Calendar', 'bookly' ) ?></label>
|
4 |
+
<p class="help-block"><?php _e( 'Set order of the fields in calendar for', 'bookly' ) ?></p>
|
5 |
+
</div>
|
6 |
+
<input id="bookly_appointment_participants" type="hidden" name="bookly_appointment_participants" value="bookly_cal_one_participant">
|
7 |
+
<div class="form-group" id="bookly_cal_one_participant">
|
8 |
+
<textarea class="form-control" rows="9" name="bookly_cal_one_participant" placeholder="<?php _e( 'Enter a value', 'bookly' ) ?>"><?php echo esc_textarea( get_option( 'bookly_cal_one_participant' ) ) ?></textarea><br/>
|
9 |
+
<?php $this->render( '_calendar_codes', array( 'participants' => 'one' ) ) ?>
|
10 |
+
</div>
|
11 |
+
<div class="form-group" id="bookly_cal_many_participants">
|
12 |
+
<textarea class="form-control" rows="9" name="bookly_cal_many_participants" placeholder="<?php _e( 'Enter a value', 'bookly' ) ?>"><?php echo esc_textarea( get_option( 'bookly_cal_many_participants' ) ) ?></textarea><br/>
|
13 |
+
<?php $this->render( '_calendar_codes', array( 'participants' => 'many' ) ) ?>
|
14 |
+
</div>
|
15 |
+
|
16 |
+
<div class="panel-footer">
|
17 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
18 |
+
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
19 |
+
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
20 |
+
</div>
|
21 |
+
</form>
|
backend/modules/settings/templates/_calendar_codes.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
$codes = array(
|
3 |
+
array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) ),
|
4 |
+
array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) ),
|
5 |
+
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) ),
|
6 |
+
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
7 |
+
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
8 |
+
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
9 |
+
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
10 |
+
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
11 |
+
array( 'code' => 'service_capacity', 'description' => __( 'capacity of service', 'bookly' ) ),
|
12 |
+
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) ),
|
13 |
+
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) ),
|
14 |
+
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) ),
|
15 |
+
array( 'code' => 'signed_up', 'description' => __( 'number of persons already in the list', 'bookly' ) ),
|
16 |
+
array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) ),
|
17 |
+
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) ),
|
18 |
+
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
19 |
+
array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) ),
|
20 |
+
);
|
21 |
+
if ( $participants == 'one' ) {
|
22 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
23 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
24 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
25 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
26 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
27 |
+
$codes[] = array( 'code' => 'payment_status', 'description' => __( 'status of payment', 'bookly' ) );
|
28 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
29 |
+
$codes[] = array( 'code' => 'status', 'description' => __( 'status of appointment', 'bookly' ) );
|
30 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
31 |
+
}
|
32 |
+
|
33 |
+
$codes = BooklyLite\Lib\Proxy\Shared::prepareCalendarAppointmentCodes( $codes, $participants );
|
34 |
+
|
35 |
+
BooklyLite\Lib\Utils\Common::codes( $codes );
|
backend/modules/settings/templates/_cartForm.php
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'cart' ) ) ?>">
|
3 |
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_cart_enabled', __( 'Cart', 'bookly' ), __( 'If cart is enabled then your clients will be able to book several appointments at once. Please note that WooCommerce integration must be disabled.', 'bookly' ) ) ?>
|
|
|
4 |
<div class="form-group">
|
5 |
<label for="bookly_cart_show_columns"><?php _e( 'Columns', 'bookly' ) ?></label><br/>
|
6 |
-
<div class="
|
7 |
<?php foreach ( (array) get_option( 'bookly_cart_show_columns' ) as $column => $attr ) : ?>
|
8 |
-
<div class="bookly-flexbox"<?php if ( $column == 'deposit' && ! \BooklyLite\Lib\Config::
|
9 |
<div class="bookly-flex-cell">
|
10 |
<i class="bookly-js-handle bookly-margin-right-sm bookly-icon bookly-icon-draghandle bookly-cursor-move" title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>"></i>
|
11 |
</div>
|
@@ -25,7 +26,8 @@
|
|
25 |
</div>
|
26 |
</div>
|
27 |
<div class="panel-footer">
|
28 |
-
<?php \BooklyLite\Lib\Utils\Common::
|
|
|
29 |
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
30 |
</div>
|
31 |
</form>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'cart' ) ) ?>">
|
3 |
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_cart_enabled', __( 'Cart', 'bookly' ), __( 'If cart is enabled then your clients will be able to book several appointments at once. Please note that WooCommerce integration must be disabled.', 'bookly' ) ) ?>
|
4 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderCartSettings() ?>
|
5 |
<div class="form-group">
|
6 |
<label for="bookly_cart_show_columns"><?php _e( 'Columns', 'bookly' ) ?></label><br/>
|
7 |
+
<div class="bookly-flags" id="bookly_cart_show_columns">
|
8 |
<?php foreach ( (array) get_option( 'bookly_cart_show_columns' ) as $column => $attr ) : ?>
|
9 |
+
<div class="bookly-flexbox"<?php if ( $column == 'deposit' && ! \BooklyLite\Lib\Config::depositPaymentsEnabled() ) : ?> style="display:none"<?php endif ?>>
|
10 |
<div class="bookly-flex-cell">
|
11 |
<i class="bookly-js-handle bookly-margin-right-sm bookly-icon bookly-icon-draghandle bookly-cursor-move" title="<?php esc_attr_e( 'Reorder', 'bookly' ) ?>"></i>
|
12 |
</div>
|
26 |
</div>
|
27 |
</div>
|
28 |
<div class="panel-footer">
|
29 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
30 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn btn-lg btn-success bookly-limitation' ) ?>
|
31 |
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
32 |
</div>
|
33 |
</form>
|
backend/modules/settings/templates/_collect_stats_notice.php
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Template to show notice about "we'r starting to collect statistics about usage"
|
4 |
+
*/
|
5 |
+
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
6 |
+
use BooklyLite\Lib\Utils\Common;
|
7 |
+
?>
|
8 |
+
<div id="bookly-tbs" class="wrap">
|
9 |
+
<div id="bookly-collect-stats-notice" class="alert alert-info bookly-tbs-body bookly-flexbox">
|
10 |
+
<div class="bookly-flex-row">
|
11 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
12 |
+
<div class="bookly-flex-cell">
|
13 |
+
<button type="button" class="close bookly-js-disallow-stats" data-dismiss="alert"></button>
|
14 |
+
<?php _e( 'Dear customer,', 'bookly' ) ?>
|
15 |
+
<br>
|
16 |
+
<?php _e( 'Bookly needs your permission to collect anonymous plugin usage stats so we could constantly improve the plugin. You can always change permissions in Bookly settings.', 'bookly' ); ?>
|
17 |
+
<br>
|
18 |
+
<br>
|
19 |
+
<?php Common::customButton( null, 'btn-success bookly-js-allow-stats', __( 'Allow (OK)', 'bookly' ) ) ?>
|
20 |
+
<?php Common::customButton( null, 'btn-default bookly-js-disallow-stats', __( 'Don’t allow', 'bookly' ) ) ?>
|
21 |
+
</div>
|
22 |
+
</div>
|
23 |
+
</div>
|
24 |
+
</div>
|
backend/modules/settings/templates/_companyForm.php
CHANGED
@@ -47,6 +47,7 @@
|
|
47 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_co_website', __( 'Website', 'bookly' ) ) ?>
|
48 |
|
49 |
<div class="panel-footer">
|
|
|
50 |
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
51 |
<?php \BooklyLite\Lib\Utils\Common::resetButton( 'bookly-company-reset' ) ?>
|
52 |
</div>
|
47 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_co_website', __( 'Website', 'bookly' ) ) ?>
|
48 |
|
49 |
<div class="panel-footer">
|
50 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
51 |
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
52 |
<?php \BooklyLite\Lib\Utils\Common::resetButton( 'bookly-company-reset' ) ?>
|
53 |
</div>
|
backend/modules/settings/templates/_customers.php
CHANGED
@@ -1,17 +1,22 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
2 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'customers' ) ) ?>">
|
3 |
-
<?php
|
4 |
-
|
5 |
$values['bookly_cst_new_account_role'] );
|
6 |
-
|
7 |
array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( 'auto', __( 'Guess country by user\'s IP address', 'bookly' ) ) ) );
|
8 |
-
|
9 |
-
|
10 |
array( array( 'delete', __( 'Delete', 'bookly' ) ), array( 'cancel', __( 'Cancel', 'bookly' ) ) ) );
|
11 |
-
|
|
|
|
|
12 |
?>
|
13 |
<div class="panel-footer">
|
14 |
-
<?php
|
15 |
-
<?php
|
|
|
16 |
</div>
|
17 |
</form>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Common;
|
3 |
+
?>
|
4 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'customers' ) ) ?>">
|
5 |
+
<?php Common::optionToggle( 'bookly_cst_create_account', __( 'Create WordPress user account for customers', 'bookly' ), __( 'If this setting is enabled then Bookly will be creating WordPress user accounts for all new customers. If the user is logged in then the new customer will be associated with the existing user account.', 'bookly' ) );
|
6 |
+
Common::optionToggle( 'bookly_cst_new_account_role', __( 'New user account role', 'bookly' ), __( 'Select what role will be assigned to newly created WordPress user accounts for customers.', 'bookly' ),
|
7 |
$values['bookly_cst_new_account_role'] );
|
8 |
+
Common::optionToggle( 'bookly_cst_phone_default_country', __( 'Phone field default country', 'bookly' ), __( 'Select default country for the phone field in the \'Details\' step of booking. You can also let Bookly determine the country based on the IP address of the client.', 'bookly' ),
|
9 |
array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( 'auto', __( 'Guess country by user\'s IP address', 'bookly' ) ) ) );
|
10 |
+
Common::optionText( 'bookly_cst_default_country_code', __( 'Default country code', 'bookly' ), __( 'Your clients must have their phone numbers in international format in order to receive text messages. However you can specify a default country code that will be used as a prefix for all phone numbers that do not start with "+" or "00". E.g. if you enter "1" as the default country code and a client enters their phone as "(600) 555-2222" the resulting phone number to send the SMS to will be "+1600555222".', 'bookly' ) );
|
11 |
+
Common::optionToggle( 'bookly_cst_cancel_action', __( 'Cancel appointment action', 'bookly' ), __( 'Select what happens when customer clicks cancel appointment link. With "Delete" the appointment will be deleted from the calendar. With "Cancel" only appointment status will be changed to "Cancelled".', 'bookly' ),
|
12 |
array( array( 'delete', __( 'Delete', 'bookly' ) ), array( 'cancel', __( 'Cancel', 'bookly' ) ) ) );
|
13 |
+
Common::optionToggle( 'bookly_cst_combined_notifications', __( 'Combined notifications', 'bookly' ), __( 'If combined notifications are enabled then your clients will receive single notification for entire booking instead of separate notification per each booked appointment (e.g. when cart is enabled). You will need to edit corresponding templates in Email and SMS Notifications.', 'bookly' ) );
|
14 |
+
Common::optionToggle( 'bookly_cst_remember_in_cookie', __( 'Remember personal information in cookies', 'bookly' ), __( 'If this setting is enabled then returning customers will have their personal information fields filled in at the Details step with the data previously saved in cookies.', 'bookly' ) );
|
15 |
+
Common::optionToggle( 'bookly_cst_show_update_details_dialog', __( 'Show confirmation dialog before updating customer\'s data', 'bookly' ), __( 'If this option is enabled and customer enters contact info different from the previous order, a warning message will appear asking to update the data.', 'bookly' ) );
|
16 |
?>
|
17 |
<div class="panel-footer">
|
18 |
+
<?php Common::csrf() ?>
|
19 |
+
<?php Common::submitButton() ?>
|
20 |
+
<?php Common::resetButton( 'bookly-customer-reset' ) ?>
|
21 |
</div>
|
22 |
</form>
|
backend/modules/settings/templates/_generalForm.php
CHANGED
@@ -1,42 +1,36 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
|
|
|
|
2 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'general' ) ) ?>">
|
3 |
<?php
|
4 |
-
|
5 |
-
|
6 |
$values['bookly_gen_time_slot_length'] );
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
\BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_gen_min_time_prior_booking', __( 'Minimum time requirement prior to booking', 'bookly' ), __( 'Set how late appointments can be booked (for example, require customers to book at least 1 hour before the appointment time).', 'bookly' ),
|
11 |
$values['bookly_gen_min_time_prior_booking'] );
|
12 |
-
|
13 |
$values['bookly_gen_min_time_prior_cancel'] );
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
?>
|
20 |
<div class="form-group">
|
21 |
-
<label for="
|
22 |
-
<
|
23 |
-
<select class="form-control" id="bookly_settings_final_step_url_mode">
|
24 |
<?php foreach ( array( __( 'Disabled', 'bookly' ) => 0, __( 'Enabled', 'bookly' ) => 1 ) as $text => $mode ) : ?>
|
25 |
-
<option value="<?php echo esc_attr( $mode ) ?>" <?php selected( get_option( '
|
26 |
<?php endforeach ?>
|
27 |
</select>
|
28 |
-
<input class="form-control"
|
29 |
-
style="margin-top: 5px; <?php echo get_option( 'bookly_gen_final_step_url' ) == '' ? 'display: none' : '' ?>"
|
30 |
-
type="text" name="bookly_gen_final_step_url"
|
31 |
-
value="<?php form_option( 'bookly_gen_final_step_url' ) ?>"
|
32 |
-
placeholder="<?php esc_attr_e( 'Enter a URL', 'bookly' ) ?>"/>
|
33 |
</div>
|
34 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_gen_allow_staff_edit_profile', __( 'Allow staff members to edit their profiles', 'bookly' ), __( 'If this option is enabled then all staff members who are associated with WordPress users will be able to edit their own profiles, services, schedule and days off.', 'bookly' ) ) ?>
|
35 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_gen_link_assets_method', __( 'Method to include Bookly JavaScript and CSS files on the page', 'bookly' ), __( 'With "Enqueue" method the JavaScript and CSS files of Bookly will be included on all pages of your website. This method should work with all themes. With "Print" method the files will be included only on the pages which contain Bookly booking form. This method may not work with all themes.', 'bookly' ),
|
36 |
-
array( array( 'enqueue', 'Enqueue' ), array( 'print', 'Print' ) ) )
|
37 |
-
?>
|
38 |
<div class="panel-footer">
|
39 |
-
<?php
|
40 |
-
<?php
|
|
|
41 |
</div>
|
42 |
</form>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Plugin;
|
3 |
+
use BooklyLite\Lib\Utils\Common;
|
4 |
+
use BooklyLite\Lib\Entities\CustomerAppointment;
|
5 |
+
?>
|
6 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'general' ) ) ?>">
|
7 |
<?php
|
8 |
+
Common::optionToggle( 'bookly_gen_lite_uninstall_remove_bookly_data', __( 'Delete all data on uninstall', 'bookly' ), __( 'If you want to replace Bookly Lite with full version of Bookly then disable this setting to prevent data from being deleted when you uninstall Bookly Lite.', 'bookly' ) );
|
9 |
+
Common::optionToggle( 'bookly_gen_time_slot_length', __( 'Time slot length', 'bookly' ), __( 'Select a time interval which will be used as a step when building all time slots in the system.', 'bookly' ),
|
10 |
$values['bookly_gen_time_slot_length'] );
|
11 |
+
Common::optionToggle( 'bookly_gen_service_duration_as_slot_length', __( 'Service duration as slot length', 'bookly' ), __( 'Enable this option to make slot length equal to service duration at the Time step of booking form.', 'bookly' ) );
|
12 |
+
Common::optionToggle( 'bookly_gen_default_appointment_status', __( 'Default appointment status', 'bookly' ), __( 'Select status for newly booked appointments.', 'bookly' ), array( array( CustomerAppointment::STATUS_PENDING, __( 'Pending', 'bookly' ) ), array( CustomerAppointment::STATUS_APPROVED, __( 'Approved', 'bookly' ) ), ) );
|
13 |
+
Common::optionToggle( 'bookly_gen_min_time_prior_booking', __( 'Minimum time requirement prior to booking', 'bookly' ), __( 'Set how late appointments can be booked (for example, require customers to book at least 1 hour before the appointment time).', 'bookly' ),
|
|
|
14 |
$values['bookly_gen_min_time_prior_booking'] );
|
15 |
+
Common::optionToggle( 'bookly_gen_min_time_prior_cancel', __( 'Minimum time requirement prior to canceling', 'bookly' ), __( 'Set how late appointments can be cancelled (for example, require customers to cancel at least 1 hour before the appointment time).', 'bookly' ),
|
16 |
$values['bookly_gen_min_time_prior_cancel'] );
|
17 |
+
Common::optionNumeric( 'bookly_gen_max_days_for_booking', __( 'Number of days available for booking', 'bookly' ), __( 'Set how far in the future the clients can book appointments.', 'bookly' ), 1, 1 );
|
18 |
+
Common::optionToggle( 'bookly_gen_use_client_time_zone', __( 'Display available time slots in client\'s time zone', 'bookly' ), __( 'The value is taken from client’s browser.', 'bookly' ) );
|
19 |
+
Common::optionToggle( 'bookly_gen_allow_staff_edit_profile', __( 'Allow staff members to edit their profiles', 'bookly' ), __( 'If this option is enabled then all staff members who are associated with WordPress users will be able to edit their own profiles, services, schedule and days off.', 'bookly' ) );
|
20 |
+
Common::optionToggle( 'bookly_gen_link_assets_method', __( 'Method to include Bookly JavaScript and CSS files on the page', 'bookly' ), __( 'With "Enqueue" method the JavaScript and CSS files of Bookly will be included on all pages of your website. This method should work with all themes. With "Print" method the files will be included only on the pages which contain Bookly booking form. This method may not work with all themes.', 'bookly' ),
|
21 |
+
array( array( 'enqueue', 'Enqueue' ), array( 'print', 'Print' ) ) )
|
22 |
?>
|
23 |
<div class="form-group">
|
24 |
+
<label for="bookly_gen_collect_stats"><?php _e( 'Help us improve Bookly by sending anonymous usage stats', 'bookly' ); ?></label>
|
25 |
+
<select class="form-control" name="bookly_gen_collect_stats" id="bookly_gen_collect_stats">
|
|
|
26 |
<?php foreach ( array( __( 'Disabled', 'bookly' ) => 0, __( 'Enabled', 'bookly' ) => 1 ) as $text => $mode ) : ?>
|
27 |
+
<option value="<?php echo esc_attr( $mode ) ?>" <?php selected( get_option( 'bookly_gen_collect_stats' ), $mode ) ?> ><?php echo $text ?></option>
|
28 |
<?php endforeach ?>
|
29 |
</select>
|
|
|
|
|
|
|
|
|
|
|
30 |
</div>
|
|
|
|
|
|
|
|
|
31 |
<div class="panel-footer">
|
32 |
+
<?php Common::csrf() ?>
|
33 |
+
<?php Common::submitButton() ?>
|
34 |
+
<?php Common::resetButton() ?>
|
35 |
</div>
|
36 |
</form>
|
backend/modules/settings/templates/_googleCalendarForm.php
CHANGED
@@ -18,9 +18,9 @@
|
|
18 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_gc_client_id', __( 'Client ID', 'bookly' ), __( 'The client ID obtained from the Developers Console', 'bookly' ) ) ?>
|
19 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_gc_client_secret', __( 'Client secret', 'bookly' ), __( 'The client secret obtained from the Developers Console', 'bookly' ) ) ?>
|
20 |
<div class="form-group">
|
21 |
-
<label for="
|
22 |
<p class="help-block"><?php _e( 'Enter this URL as a redirect URI in the Developers Console', 'bookly' ) ?></p>
|
23 |
-
<input id="
|
24 |
value="<?php echo \BooklyLite\Lib\Google::generateRedirectURI() ?>" onclick="this.select();"
|
25 |
style="cursor: pointer;"/>
|
26 |
</div>
|
@@ -29,6 +29,7 @@
|
|
29 |
$values['bookly_gc_limit_events'] ) ?>
|
30 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_gc_event_title', __( 'Template for event title', 'bookly' ), __( 'Configure what information should be placed in the title of Google Calendar event. Available codes are {service_name}, {staff_name} and {client_names}.', 'bookly' ) ) ?>
|
31 |
<div class="panel-footer">
|
|
|
32 |
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn btn-lg btn-success bookly-limitation' ) ?>
|
33 |
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
34 |
</div>
|
18 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_gc_client_id', __( 'Client ID', 'bookly' ), __( 'The client ID obtained from the Developers Console', 'bookly' ) ) ?>
|
19 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_gc_client_secret', __( 'Client secret', 'bookly' ), __( 'The client secret obtained from the Developers Console', 'bookly' ) ) ?>
|
20 |
<div class="form-group">
|
21 |
+
<label for="bookly-redirect-uri"><?php _e( 'Redirect URI', 'bookly' ) ?></label>
|
22 |
<p class="help-block"><?php _e( 'Enter this URL as a redirect URI in the Developers Console', 'bookly' ) ?></p>
|
23 |
+
<input id="bookly-redirect-uri" class="form-control" type="text" readonly
|
24 |
value="<?php echo \BooklyLite\Lib\Google::generateRedirectURI() ?>" onclick="this.select();"
|
25 |
style="cursor: pointer;"/>
|
26 |
</div>
|
29 |
$values['bookly_gc_limit_events'] ) ?>
|
30 |
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_gc_event_title', __( 'Template for event title', 'bookly' ), __( 'Configure what information should be placed in the title of Google Calendar event. Available codes are {service_name}, {staff_name} and {client_names}.', 'bookly' ) ) ?>
|
31 |
<div class="panel-footer">
|
32 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
33 |
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn btn-lg btn-success bookly-limitation' ) ?>
|
34 |
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
35 |
</div>
|
backend/modules/settings/templates/_holidaysForm.php
CHANGED
@@ -16,26 +16,4 @@
|
|
16 |
</div>
|
17 |
</div>
|
18 |
|
19 |
-
<div class="bookly-js-annual-calendar bookly-margin-top-lg jCal-wrap"></div>
|
20 |
-
|
21 |
-
<script>
|
22 |
-
jQuery(function ($) {
|
23 |
-
var d = new Date();
|
24 |
-
$('.bookly-js-annual-calendar').jCal({
|
25 |
-
day : new Date(d.getFullYear(), 0, 1),
|
26 |
-
days : 1,
|
27 |
-
showMonths : 12,
|
28 |
-
scrollSpeed: 350,
|
29 |
-
events : <?php echo $holidays ?>,
|
30 |
-
action : 'bookly_settings_holiday',
|
31 |
-
dayOffset : <?php echo (int)get_option('start_of_week') ?>,
|
32 |
-
loadingImg : <?php echo json_encode( plugins_url( 'bookly-responsive-appointment-booking-tool/backend/resources/images/loading.gif' ) ) ?>
|
33 |
-
});
|
34 |
-
|
35 |
-
$('.bookly-js-jCalBtn').on('click', function(e) {
|
36 |
-
e.preventDefault();
|
37 |
-
var trigger = $(this).data('trigger');
|
38 |
-
$('.bookly-js-annual-calendar').find($(trigger)).trigger('click');
|
39 |
-
})
|
40 |
-
});
|
41 |
-
</script>
|
16 |
</div>
|
17 |
</div>
|
18 |
|
19 |
+
<div class="bookly-js-annual-calendar bookly-margin-top-lg jCal-wrap"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/settings/templates/_hoursForm.php
CHANGED
@@ -28,6 +28,7 @@
|
|
28 |
<?php endfor ?>
|
29 |
|
30 |
<div class="panel-footer">
|
|
|
31 |
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
32 |
<?php \BooklyLite\Lib\Utils\Common::resetButton( 'bookly-hours-reset' ) ?>
|
33 |
</div>
|
28 |
<?php endfor ?>
|
29 |
|
30 |
<div class="panel-footer">
|
31 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
32 |
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
33 |
<?php \BooklyLite\Lib\Utils\Common::resetButton( 'bookly-hours-reset' ) ?>
|
34 |
</div>
|
backend/modules/settings/templates/_paymentsForm.php
CHANGED
@@ -1,19 +1,31 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
|
|
|
|
2 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'payments' ) ) ?>">
|
3 |
<div class="row">
|
4 |
-
<div class="col-lg-
|
5 |
<div class="form-group">
|
6 |
<label for="bookly_pmt_currency"><?php _e( 'Currency', 'bookly' ) ?></label>
|
7 |
<select id="bookly_pmt_currency" class="form-control" name="bookly_pmt_currency">
|
8 |
-
<?php foreach (
|
9 |
-
<option value="<?php echo $code ?>" <?php selected( get_option( 'bookly_pmt_currency' ), $code ) ?> ><?php echo $code
|
10 |
<?php endforeach ?>
|
11 |
</select>
|
12 |
</div>
|
13 |
</div>
|
14 |
-
<div class="col-lg-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
</div>
|
|
|
17 |
</div>
|
18 |
|
19 |
<div class="panel panel-default">
|
@@ -21,148 +33,41 @@
|
|
21 |
<label for="bookly_pmt_local"><?php _e( 'Service paid locally', 'bookly' ) ?></label>
|
22 |
</div>
|
23 |
<div class="panel-body">
|
24 |
-
<?php
|
25 |
-
</div>
|
26 |
-
</div>
|
27 |
-
|
28 |
-
<div class="panel panel-default">
|
29 |
-
<div class="panel-heading">
|
30 |
-
<label for="bookly_pmt_2checkout">2Checkout</label>
|
31 |
-
<img style="margin-left: 10px; float: right" src="<?php echo plugins_url( 'frontend/resources/images/2Checkout.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>"/>
|
32 |
-
</div>
|
33 |
-
<div class="panel-body">
|
34 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_2checkout', null, null, array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( 'standard_checkout', __( '2Checkout Standard Checkout', 'bookly' ) ) ) ) ?>
|
35 |
-
<div class="bookly-2checkout">
|
36 |
-
<div class="form-group">
|
37 |
-
<h4><?php _e( 'Instructions', 'bookly' ) ?></h4>
|
38 |
-
<p>
|
39 |
-
<?php _e( 'In <b>Checkout Options</b> of your 2Checkout account do the following steps:', 'bookly' ) ?>
|
40 |
-
</p>
|
41 |
-
<ol>
|
42 |
-
<li><?php _e( 'In <b>Direct Return</b> select <b>Header Redirect (Your URL)</b>.', 'bookly' ) ?></li>
|
43 |
-
<li><?php _e( 'In <b>Approved URL</b> enter the URL of your booking page.', 'bookly' ) ?></li>
|
44 |
-
</ol>
|
45 |
-
<p>
|
46 |
-
<?php _e( 'Finally provide the necessary information in the form below.', 'bookly' ) ?>
|
47 |
-
</p>
|
48 |
-
</div>
|
49 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_2checkout_api_seller_id', __( 'Account Number', 'bookly' ) ) ?>
|
50 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_2checkout_api_secret_word', __( 'Secret Word', 'bookly' ) ) ?>
|
51 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_2checkout_sandbox', __( 'Sandbox Mode', 'bookly' ), null, array( array( 0, __( 'No', 'bookly' ) ), array( 1, __( 'Yes', 'bookly' ) ) ) ) ?>
|
52 |
-
</div>
|
53 |
</div>
|
54 |
</div>
|
55 |
|
56 |
<div class="panel panel-default">
|
57 |
<div class="panel-heading">
|
58 |
-
<label for="
|
59 |
<img style="margin-left: 10px; float: right" src="<?php echo plugins_url( 'frontend/resources/images/paypal.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" />
|
60 |
</div>
|
61 |
<div class="panel-body">
|
62 |
<div class="form-group">
|
63 |
-
<?php
|
64 |
array(
|
65 |
-
array( '
|
66 |
array( 'ec', 'PayPal Express Checkout' ),
|
67 |
-
)
|
|
|
68 |
</div>
|
69 |
<div class="bookly-paypal">
|
70 |
<div class="bookly-paypal-ec">
|
71 |
-
<?php
|
72 |
-
<?php
|
73 |
-
<?php
|
74 |
-
</div>
|
75 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_paypal_sandbox', __( 'Sandbox Mode', 'bookly' ), null, array( array( 1, __( 'Yes', 'bookly' ) ), array( 0, __( 'No', 'bookly' ) ) ) ) ?>
|
76 |
-
</div>
|
77 |
-
</div>
|
78 |
-
</div>
|
79 |
-
|
80 |
-
<div class="panel panel-default">
|
81 |
-
<div class="panel-heading">
|
82 |
-
<label for="bookly_pmt_authorize_net">Authorize.Net</label>
|
83 |
-
<img style="margin-left: 10px; float: right" src="<?php echo plugins_url( 'frontend/resources/images/authorize_net.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>"/>
|
84 |
-
</div>
|
85 |
-
<div class="panel-body">
|
86 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_authorize_net', null, null, array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( 'aim', 'Authorize.Net AIM' ) ) ) ?>
|
87 |
-
<div class="authorize-net">
|
88 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_authorize_net_api_login_id', __( 'API Login ID', 'bookly' ) ) ?>
|
89 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_authorize_net_transaction_key', __( 'API Transaction Key', 'bookly' ) ) ?>
|
90 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_authorize_net_sandbox', __( 'Sandbox Mode', 'bookly' ), null, array( array( 1, __( 'Yes', 'bookly' ) ), array( 0, __( 'No', 'bookly' ) ) ) ) ?>
|
91 |
-
</div>
|
92 |
-
</div>
|
93 |
-
</div>
|
94 |
-
|
95 |
-
<div class="panel panel-default">
|
96 |
-
<div class="panel-heading">
|
97 |
-
<label for="bookly_pmt_stripe">Stripe</label>
|
98 |
-
<img class="pull-right" src="<?php echo plugins_url( 'frontend/resources/images/stripe.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>">
|
99 |
-
</div>
|
100 |
-
<div class="panel-body">
|
101 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_stripe', null, null, array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( '1', __( 'Enabled', 'bookly' ) ) ) ) ?>
|
102 |
-
<div class="bookly-stripe">
|
103 |
-
<div class="form-group">
|
104 |
-
<h4><?php _e( 'Instructions', 'bookly' ) ?></h4>
|
105 |
-
<p>
|
106 |
-
<?php _e( 'If <b>Publishable Key</b> is provided then Bookly will use <a href="https://stripe.com/docs/stripe.js" target="_blank">Stripe.js</a><br/>for collecting credit card details.', 'bookly' ) ?>
|
107 |
-
</p>
|
108 |
</div>
|
109 |
-
<?php \
|
110 |
-
<?php
|
111 |
-
</div>
|
112 |
-
</div>
|
113 |
-
</div>
|
114 |
-
|
115 |
-
<div class="panel panel-default">
|
116 |
-
<div class="panel-heading">
|
117 |
-
<label for="bookly_pmt_payu_latam">PayU Latam</label>
|
118 |
-
<img class="pull-right" src="<?php echo plugins_url( 'frontend/resources/images/payu_latam.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>"/>
|
119 |
-
</div>
|
120 |
-
<div class="panel-body">
|
121 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_payu_latam', null, null, array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( '1', __( 'Enabled', 'bookly' ) ) ) ) ?>
|
122 |
-
<div class="bookly-payu_latam">
|
123 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_payu_latam_api_key', __( 'API Key', 'bookly' ) ) ?>
|
124 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_payu_latam_api_account_id', __( 'Account ID', 'bookly' ) ) ?>
|
125 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_payu_latam_api_merchant_id', __( 'Merchant ID', 'bookly' ) ) ?>
|
126 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_payu_latam_sandbox', __( 'Sandbox Mode', 'bookly' ), null, array( array( 0, __( 'No', 'bookly' ) ), array( 1, __( 'Yes', 'bookly' ) ) ) ) ?>
|
127 |
-
</div>
|
128 |
-
</div>
|
129 |
-
</div>
|
130 |
-
|
131 |
-
<div class="panel panel-default">
|
132 |
-
<div class="panel-heading">
|
133 |
-
<label for="bookly_pmt_payson">Payson</label>
|
134 |
-
<img class="pull-right" src="<?php echo plugins_url( 'frontend/resources/images/payson.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>"/>
|
135 |
-
</div>
|
136 |
-
<div class="panel-body">
|
137 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_payson', null, null, array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( '1', __( 'Enabled', 'bookly' ) ) ) ) ?>
|
138 |
-
<div class="bookly-payson">
|
139 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_payson_api_agent_id', __( 'Agent ID', 'bookly' ) ) ?>
|
140 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_payson_api_key', __( 'API Key', 'bookly' ) ) ?>
|
141 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_payson_api_receiver_email', __( 'Receiver Email (login)', 'bookly' ) ) ?>
|
142 |
-
<?php \BooklyLite\Lib\Utils\Common::optionFlags( 'bookly_pmt_payson_funding', array( array( 'CREDITCARD', __( 'Card', 'bookly' ) ), array( 'INVOICE', __( 'Invoice', 'bookly' ) ) ), __( 'Funding', 'bookly' ) ) ?>
|
143 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_payson_fees_payer', __( 'Fees Payer', 'bookly' ), null, array( array( 'PRIMARYRECEIVER', __( 'I am', 'bookly' ) ), array( 'SENDER', __( 'Client', 'bookly' ) ) ) ) ?>
|
144 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_payson_sandbox', __( 'Sandbox Mode', 'bookly' ), null, array( array( 0, __( 'No', 'bookly' ) ), array( 1, __( 'Yes', 'bookly' ) ) ) ) ?>
|
145 |
-
</div>
|
146 |
-
</div>
|
147 |
-
</div>
|
148 |
-
|
149 |
-
<div class="panel panel-default">
|
150 |
-
<div class="panel-heading">
|
151 |
-
<label for="bookly_pmt_mollie">Mollie</label>
|
152 |
-
<img class="pull-right" src="<?php echo plugins_url( 'frontend/resources/images/mollie.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>"/>
|
153 |
-
</div>
|
154 |
-
<div class="panel-body">
|
155 |
-
<?php \BooklyLite\Lib\Utils\Common::optionToggle( 'bookly_pmt_mollie', null, null, array( array( 'disabled', __( 'Disabled', 'bookly' ) ), array( '1', __( 'Enabled', 'bookly' ) ) ) ) ?>
|
156 |
-
<div class="bookly-mollie">
|
157 |
-
<?php \BooklyLite\Lib\Utils\Common::optionText( 'bookly_pmt_mollie_api_key', __( 'API Key', 'bookly' ) ) ?>
|
158 |
</div>
|
159 |
</div>
|
160 |
</div>
|
161 |
|
162 |
-
<?php
|
163 |
|
164 |
<div class="panel-footer">
|
165 |
-
<?php
|
166 |
-
<?php
|
|
|
167 |
</div>
|
168 |
</form>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Utils\Common;
|
3 |
+
use BooklyLite\Lib\Utils\Price;
|
4 |
+
use BooklyLite\Lib\Proxy;
|
5 |
+
?>
|
6 |
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'payments' ) ) ?>">
|
7 |
<div class="row">
|
8 |
+
<div class="col-lg-4">
|
9 |
<div class="form-group">
|
10 |
<label for="bookly_pmt_currency"><?php _e( 'Currency', 'bookly' ) ?></label>
|
11 |
<select id="bookly_pmt_currency" class="form-control" name="bookly_pmt_currency">
|
12 |
+
<?php foreach ( Price::getCurrencies() as $code => $currency ) : ?>
|
13 |
+
<option value="<?php echo $code ?>" data-symbol="<?php esc_attr_e( $currency['symbol'] ) ?>" <?php selected( get_option( 'bookly_pmt_currency' ), $code ) ?> ><?php echo $code ?> (<?php esc_html_e( $currency['symbol'] ) ?>)</option>
|
14 |
<?php endforeach ?>
|
15 |
</select>
|
16 |
</div>
|
17 |
</div>
|
18 |
+
<div class="col-lg-4">
|
19 |
+
<div class="form-group">
|
20 |
+
<label for="bookly_pmt_price_format"><?php _e( 'Price format', 'bookly' ) ?></label>
|
21 |
+
<select id="bookly_pmt_price_format" class="form-control" name="bookly_pmt_price_format">
|
22 |
+
<?php foreach ( Price::getFormats() as $format ) : ?>
|
23 |
+
<option value="<?php echo $format ?>" <?php selected( get_option( 'bookly_pmt_price_format' ), $format ) ?> ></option>
|
24 |
+
<?php endforeach ?>
|
25 |
+
</select>
|
26 |
+
</div>
|
27 |
</div>
|
28 |
+
<?php Proxy\Coupons::renderSettings() ?>
|
29 |
</div>
|
30 |
|
31 |
<div class="panel panel-default">
|
33 |
<label for="bookly_pmt_local"><?php _e( 'Service paid locally', 'bookly' ) ?></label>
|
34 |
</div>
|
35 |
<div class="panel-body">
|
36 |
+
<?php Common::optionToggle( 'bookly_pmt_local' ) ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
</div>
|
38 |
</div>
|
39 |
|
40 |
<div class="panel panel-default">
|
41 |
<div class="panel-heading">
|
42 |
+
<label for="bookly_paypal_enabled">PayPal</label>
|
43 |
<img style="margin-left: 10px; float: right" src="<?php echo plugins_url( 'frontend/resources/images/paypal.png', \BooklyLite\Lib\Plugin::getMainFile() ) ?>" />
|
44 |
</div>
|
45 |
<div class="panel-body">
|
46 |
<div class="form-group">
|
47 |
+
<?php Common::optionToggle( 'bookly_paypal_enabled', null, null,
|
48 |
array(
|
49 |
+
array( '0', __( 'Disabled', 'bookly' ) ),
|
50 |
array( 'ec', 'PayPal Express Checkout' ),
|
51 |
+
)
|
52 |
+
) ?>
|
53 |
</div>
|
54 |
<div class="bookly-paypal">
|
55 |
<div class="bookly-paypal-ec">
|
56 |
+
<?php Common::optionText( 'bookly_paypal_api_username', __( 'API Username', 'bookly' ) ) ?>
|
57 |
+
<?php Common::optionText( 'bookly_paypal_api_password', __( 'API Password', 'bookly' ) ) ?>
|
58 |
+
<?php Common::optionText( 'bookly_paypal_api_signature', __( 'API Signature', 'bookly' ) ) ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
</div>
|
60 |
+
<?php Proxy\PaypalPaymentsStandard::renderSetUpOptions() ?>
|
61 |
+
<?php Common::optionToggle( 'bookly_paypal_sandbox', __( 'Sandbox Mode', 'bookly' ), null, array( array( 1, __( 'Yes', 'bookly' ) ), array( 0, __( 'No', 'bookly' ) ) ) ) ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
</div>
|
63 |
</div>
|
64 |
</div>
|
65 |
|
66 |
+
<?php BooklyLite\Lib\Proxy\Shared::renderPaymentGatewaySettings() ?>
|
67 |
|
68 |
<div class="panel-footer">
|
69 |
+
<?php Common::csrf() ?>
|
70 |
+
<?php Common::submitButton() ?>
|
71 |
+
<?php Common::resetButton( 'bookly-payments-reset' ) ?>
|
72 |
</div>
|
73 |
</form>
|
backend/modules/settings/templates/_urlForm.php
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Proxy;
|
3 |
+
use BooklyLite\Lib\Utils\Common;
|
4 |
+
?>
|
5 |
+
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'url' ) ) ?>">
|
6 |
+
<?php
|
7 |
+
Common::optionText( 'bookly_url_approve_page_url', __( 'Approve appointment URL (success)', 'bookly' ), __( 'Set the URL of a page that is shown to staff after they successfully approved the appointment.', 'bookly' ) );
|
8 |
+
Common::optionText( 'bookly_url_approve_denied_page_url', __( 'Approve appointment URL (denied)', 'bookly' ), __( 'Set the URL of a page that is shown to staff when the approval of appointment cannot be done (due to capacity, changed status, etc.).', 'bookly' ) );
|
9 |
+
Common::optionText( 'bookly_url_cancel_page_url', __( 'Cancel appointment URL (success)', 'bookly' ), __( 'Set the URL of a page that is shown to clients after they successfully cancelled their appointment.', 'bookly' ) );
|
10 |
+
Common::optionText( 'bookly_url_cancel_denied_page_url', __( 'Cancel appointment URL (denied)', 'bookly' ), __( 'Set the URL of a page that is shown to clients when the cancellation of appointment is not available anymore.', 'bookly' ) );
|
11 |
+
Common::optionText( 'bookly_url_cancel_confirm_page_url', __( 'Appointment cancellation confirmation URL', 'bookly' ), __( 'Set the URL of an appointment cancellation confirmation page that is shown to clients when they press cancellation link.', 'bookly' ) );
|
12 |
+
Common::optionText( 'bookly_url_reject_page_url', __( 'Reject appointment URL (success)', 'bookly' ), __( 'Set the URL of a page that is shown to staff after they successfully rejected the appointment.', 'bookly' ) );
|
13 |
+
Common::optionText( 'bookly_url_reject_denied_page_url', __( 'Reject appointment URL (denied)', 'bookly' ), __( 'Set the URL of a page that is shown to staff when the rejection of appointment cannot be done (due to changed status, etc.).', 'bookly' ) );
|
14 |
+
?>
|
15 |
+
<div class="form-group">
|
16 |
+
<label for="bookly_settings_final_step_url_mode"><?php _e( 'Final step URL', 'bookly' ) ?></label>
|
17 |
+
<p class="help-block"><?php _e( 'Set the URL of a page that the user will be forwarded to after successful booking. If disabled then the default Done step is displayed.', 'bookly' ) ?></p>
|
18 |
+
<select class="form-control" id="bookly_settings_final_step_url_mode">
|
19 |
+
<?php foreach ( array( __( 'Disabled', 'bookly' ) => 0, __( 'Enabled', 'bookly' ) => 1 ) as $text => $mode ) : ?>
|
20 |
+
<option value="<?php echo esc_attr( $mode ) ?>" <?php selected( get_option( 'bookly_url_final_step_url' ), $mode ) ?> ><?php echo $text ?></option>
|
21 |
+
<?php endforeach ?>
|
22 |
+
</select>
|
23 |
+
<input class="form-control"
|
24 |
+
style="margin-top: 5px; <?php echo get_option( 'bookly_url_final_step_url' ) == '' ? 'display: none' : '' ?>"
|
25 |
+
type="text" name="bookly_url_final_step_url"
|
26 |
+
value="<?php form_option( 'bookly_url_final_step_url' ) ?>"
|
27 |
+
placeholder="<?php esc_attr_e( 'Enter a URL', 'bookly' ) ?>"/>
|
28 |
+
</div>
|
29 |
+
<?php Proxy\Shared::renderUrlSettings() ?>
|
30 |
+
<div class="panel-footer">
|
31 |
+
<?php Common::csrf() ?>
|
32 |
+
<?php Common::submitButton() ?>
|
33 |
+
<?php Common::resetButton() ?>
|
34 |
+
</div>
|
35 |
+
</form>
|
backend/modules/settings/templates/_woocommerce.php
CHANGED
@@ -1,5 +1,5 @@
|
|
1 |
<?php if (!defined('ABSPATH')) exit; // Exit if accessed directly ?>
|
2 |
-
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', '
|
3 |
id="woocommerce">
|
4 |
<div class="form-group">
|
5 |
<h4><?php _e( 'Instructions', 'bookly' ) ?></h4>
|
@@ -38,6 +38,7 @@
|
|
38 |
</div>
|
39 |
|
40 |
<div class="panel-footer">
|
|
|
41 |
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn btn-lg btn-success bookly-limitation' ) ?>
|
42 |
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
43 |
</div>
|
1 |
<?php if (!defined('ABSPATH')) exit; // Exit if accessed directly ?>
|
2 |
+
<form method="post" action="<?php echo esc_url( add_query_arg( 'tab', 'woo_commerce' ) ) ?>"
|
3 |
id="woocommerce">
|
4 |
<div class="form-group">
|
5 |
<h4><?php _e( 'Instructions', 'bookly' ) ?></h4>
|
38 |
</div>
|
39 |
|
40 |
<div class="panel-footer">
|
41 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
42 |
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'btn btn-lg btn-success bookly-limitation' ) ?>
|
43 |
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
44 |
</div>
|
backend/modules/settings/templates/_woocommerce_codes.php
CHANGED
@@ -10,4 +10,4 @@ $codes = array(
|
|
10 |
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ), ),
|
11 |
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ), ),
|
12 |
);
|
13 |
-
|
10 |
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ), ),
|
11 |
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ), ),
|
12 |
);
|
13 |
+
BooklyLite\Lib\Utils\Common::codes( BooklyLite\Lib\Proxy\Shared::prepareWooCommerceShortCodes( $codes ) );
|
backend/modules/settings/templates/index.php
CHANGED
@@ -10,10 +10,15 @@
|
|
10 |
<div class="row">
|
11 |
<div id="bookly-sidebar" class="col-sm-4">
|
12 |
<ul class="bookly-nav" role="tablist">
|
13 |
-
<?php $tab = isset ( $_GET['tab'] ) ? $_GET['tab'] : 'general' ?>
|
14 |
<li class="bookly-nav-item" data-target="#bookly_settings_general" data-toggle="tab">
|
15 |
<?php _e( 'General', 'bookly' ) ?>
|
16 |
</li>
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
<li class="bookly-nav-item" data-target="#bookly_settings_company" data-toggle="tab">
|
18 |
<?php _e( 'Company', 'bookly' ) ?>
|
19 |
</li>
|
@@ -23,13 +28,13 @@
|
|
23 |
<li class="bookly-nav-item" data-target="#bookly_settings_google_calendar" data-toggle="tab">
|
24 |
<?php _e( 'Google Calendar', 'bookly' ) ?>
|
25 |
</li>
|
26 |
-
<li class="bookly-nav-item" data-target="#
|
27 |
WooCommerce
|
28 |
</li>
|
29 |
<li class="bookly-nav-item" data-target="#bookly_settings_cart" data-toggle="tab">
|
30 |
<?php _e( 'Cart', 'bookly' ) ?>
|
31 |
</li>
|
32 |
-
<?php
|
33 |
<li class="bookly-nav-item" data-target="#bookly_settings_payments" data-toggle="tab">
|
34 |
<?php _e( 'Payments', 'bookly' ) ?>
|
35 |
</li>
|
@@ -49,6 +54,12 @@
|
|
49 |
<div class="tab-pane active" id="bookly_settings_general">
|
50 |
<?php include '_generalForm.php' ?>
|
51 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
52 |
<div class="tab-pane" id="bookly_settings_company">
|
53 |
<?php include '_companyForm.php' ?>
|
54 |
</div>
|
@@ -58,13 +69,13 @@
|
|
58 |
<div class="tab-pane" id="bookly_settings_google_calendar">
|
59 |
<?php include '_googleCalendarForm.php' ?>
|
60 |
</div>
|
61 |
-
<div class="tab-pane" id="
|
62 |
<?php include '_woocommerce.php' ?>
|
63 |
</div>
|
64 |
<div class="tab-pane" id="bookly_settings_cart">
|
65 |
<?php include '_cartForm.php' ?>
|
66 |
</div>
|
67 |
-
<?php
|
68 |
<div class="tab-pane" id="bookly_settings_payments">
|
69 |
<?php include '_paymentsForm.php' ?>
|
70 |
</div>
|
10 |
<div class="row">
|
11 |
<div id="bookly-sidebar" class="col-sm-4">
|
12 |
<ul class="bookly-nav" role="tablist">
|
|
|
13 |
<li class="bookly-nav-item" data-target="#bookly_settings_general" data-toggle="tab">
|
14 |
<?php _e( 'General', 'bookly' ) ?>
|
15 |
</li>
|
16 |
+
<li class="bookly-nav-item" data-target="#bookly_settings_url" data-toggle="tab">
|
17 |
+
<?php _e( 'URL Settings', 'bookly' ) ?>
|
18 |
+
</li>
|
19 |
+
<li class="bookly-nav-item" data-target="#bookly_settings_calendar" data-toggle="tab">
|
20 |
+
<?php _e( 'Calendar', 'bookly' ) ?>
|
21 |
+
</li>
|
22 |
<li class="bookly-nav-item" data-target="#bookly_settings_company" data-toggle="tab">
|
23 |
<?php _e( 'Company', 'bookly' ) ?>
|
24 |
</li>
|
28 |
<li class="bookly-nav-item" data-target="#bookly_settings_google_calendar" data-toggle="tab">
|
29 |
<?php _e( 'Google Calendar', 'bookly' ) ?>
|
30 |
</li>
|
31 |
+
<li class="bookly-nav-item" data-target="#bookly_settings_woo_commerce" data-toggle="tab">
|
32 |
WooCommerce
|
33 |
</li>
|
34 |
<li class="bookly-nav-item" data-target="#bookly_settings_cart" data-toggle="tab">
|
35 |
<?php _e( 'Cart', 'bookly' ) ?>
|
36 |
</li>
|
37 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderSettingsMenu() ?>
|
38 |
<li class="bookly-nav-item" data-target="#bookly_settings_payments" data-toggle="tab">
|
39 |
<?php _e( 'Payments', 'bookly' ) ?>
|
40 |
</li>
|
54 |
<div class="tab-pane active" id="bookly_settings_general">
|
55 |
<?php include '_generalForm.php' ?>
|
56 |
</div>
|
57 |
+
<div class="tab-pane" id="bookly_settings_url">
|
58 |
+
<?php include '_urlForm.php' ?>
|
59 |
+
</div>
|
60 |
+
<div class="tab-pane active" id="bookly_settings_calendar">
|
61 |
+
<?php include '_calendarForm.php' ?>
|
62 |
+
</div>
|
63 |
<div class="tab-pane" id="bookly_settings_company">
|
64 |
<?php include '_companyForm.php' ?>
|
65 |
</div>
|
69 |
<div class="tab-pane" id="bookly_settings_google_calendar">
|
70 |
<?php include '_googleCalendarForm.php' ?>
|
71 |
</div>
|
72 |
+
<div class="tab-pane" id="bookly_settings_woo_commerce">
|
73 |
<?php include '_woocommerce.php' ?>
|
74 |
</div>
|
75 |
<div class="tab-pane" id="bookly_settings_cart">
|
76 |
<?php include '_cartForm.php' ?>
|
77 |
</div>
|
78 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderSettingsForm() ?>
|
79 |
<div class="tab-pane" id="bookly_settings_payments">
|
80 |
<?php include '_paymentsForm.php' ?>
|
81 |
</div>
|
backend/modules/sms/Components.php
ADDED
@@ -0,0 +1,348 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace BooklyLite\Backend\Modules\Sms;
|
3 |
+
|
4 |
+
use BooklyLite\Lib;
|
5 |
+
use BooklyLite\Lib\Entities\Notification;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Components
|
9 |
+
* @package BooklyLite\Backend\Modules\Notifications
|
10 |
+
*/
|
11 |
+
class Components extends Lib\Base\Components
|
12 |
+
{
|
13 |
+
protected $css_prefix = 'bookly-js-codes-';
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Codes for all notifications.
|
17 |
+
*
|
18 |
+
* @return array
|
19 |
+
*/
|
20 |
+
private function getCommonCodes()
|
21 |
+
{
|
22 |
+
return array(
|
23 |
+
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
24 |
+
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
25 |
+
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
26 |
+
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
27 |
+
);
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Render codes for notifications
|
32 |
+
*
|
33 |
+
* @param string $notification_type
|
34 |
+
*/
|
35 |
+
public function renderCodes( $notification_type )
|
36 |
+
{
|
37 |
+
switch ( $notification_type ) {
|
38 |
+
case Notification::TYPE_APPOINTMENT_START_TIME:
|
39 |
+
case Notification::TYPE_CUSTOMER_APPOINTMENT_CREATED:
|
40 |
+
case Notification::TYPE_LAST_CUSTOMER_APPOINTMENT:
|
41 |
+
case Notification::TYPE_CUSTOMER_APPOINTMENT_STATUS_CHANGED:
|
42 |
+
$this->renderCustomerAppointmentCodesForCN( $notification_type );
|
43 |
+
break;
|
44 |
+
case 'staff_agenda':
|
45 |
+
case Notification::TYPE_STAFF_DAY_AGENDA:
|
46 |
+
$this->renderStaffDayAgendaCodes();
|
47 |
+
break;
|
48 |
+
case 'client_birthday_greeting':
|
49 |
+
case Notification::TYPE_CUSTOMER_BIRTHDAY:
|
50 |
+
$this->renderBirthdayGreetingCodes();
|
51 |
+
break;
|
52 |
+
case 'client_new_wp_user':
|
53 |
+
$this->renderNewWpUserCodes();
|
54 |
+
break;
|
55 |
+
case 'client_pending_appointment_cart':
|
56 |
+
case 'client_approved_appointment_cart':
|
57 |
+
$this->renderCompoundCodes();
|
58 |
+
break;
|
59 |
+
case 'staff_waiting_list':
|
60 |
+
$this->renderWaitingListCodes();
|
61 |
+
break;
|
62 |
+
case 'client_pending_appointment':
|
63 |
+
case 'staff_pending_appointment':
|
64 |
+
case 'client_approved_appointment':
|
65 |
+
case 'staff_approved_appointment':
|
66 |
+
case 'client_cancelled_appointment':
|
67 |
+
case 'staff_cancelled_appointment':
|
68 |
+
case 'client_rejected_appointment':
|
69 |
+
case 'staff_rejected_appointment':
|
70 |
+
case 'client_waitlisted_appointment':
|
71 |
+
case 'staff_waitlisted_appointment':
|
72 |
+
case 'client_reminder':
|
73 |
+
case 'client_reminder_1st':
|
74 |
+
case 'client_reminder_2nd':
|
75 |
+
case 'client_reminder_3rd':
|
76 |
+
case 'client_follow_up':
|
77 |
+
$this->renderBaseCodes();
|
78 |
+
break;
|
79 |
+
case 'staff_package_purchased':
|
80 |
+
case 'client_package_purchased':
|
81 |
+
case 'staff_package_deleted':
|
82 |
+
case 'client_package_deleted':
|
83 |
+
$this->renderPackageCodes( $notification_type );
|
84 |
+
break;
|
85 |
+
case 'client_pending_recurring_appointment':
|
86 |
+
case 'staff_pending_recurring_appointment':
|
87 |
+
case 'client_approved_recurring_appointment':
|
88 |
+
case 'staff_approved_recurring_appointment':
|
89 |
+
case 'client_cancelled_recurring_appointment':
|
90 |
+
case 'staff_cancelled_recurring_appointment':
|
91 |
+
case 'client_rejected_recurring_appointment':
|
92 |
+
case 'staff_rejected_recurring_appointment':
|
93 |
+
case 'client_waitlisted_recurring_appointment':
|
94 |
+
case 'staff_waitlisted_recurring_appointment':
|
95 |
+
$this->renderRecurringCodes();
|
96 |
+
break;
|
97 |
+
}
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Render codes for custom notifications with appointment(s)
|
102 |
+
*
|
103 |
+
* @param string $notification_type
|
104 |
+
*/
|
105 |
+
private function renderCustomerAppointmentCodesForCN( $notification_type )
|
106 |
+
{
|
107 |
+
$codes = $this->getCommonCodes();
|
108 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
109 |
+
$codes[] = array( 'code' => 'appointment_end_date', 'description' => __( 'end date of appointment', 'bookly' ) );
|
110 |
+
$codes[] = array( 'code' => 'appointment_end_time', 'description' => __( 'end time of appointment', 'bookly' ) );
|
111 |
+
$codes[] = array( 'code' => 'appointment_notes', 'description' => __( 'customer notes for appointment', 'bookly' ) );
|
112 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
113 |
+
$codes[] = array( 'code' => 'approve_appointment_url', 'description' => esc_html__( 'URL of approve appointment link (to use inside <a> tag)', 'bookly' ) );
|
114 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
115 |
+
$codes[] = array( 'code' => 'cancel_appointment_confirm_url', 'description' => esc_html__( 'URL of cancel appointment link with confirmation (to use inside <a> tag)', 'bookly' ) );
|
116 |
+
$codes[] = array( 'code' => 'cancel_appointment_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) );
|
117 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
118 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
119 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
120 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
121 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
122 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
123 |
+
$codes[] = array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) );
|
124 |
+
$codes[] = array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) );
|
125 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
126 |
+
$codes[] = array( 'code' => 'reject_appointment_url', 'description' => esc_html__( 'URL of reject appointment link (to use inside <a> tag)', 'bookly' ) );
|
127 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
128 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
129 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
130 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
131 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
132 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
133 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
134 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
135 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
136 |
+
|
137 |
+
$codes = Lib\Proxy\Packages::prepareNotificationCodesList( $codes );
|
138 |
+
$codes = Lib\Proxy\RecurringAppointments::prepareNotificationCodesList( $codes );
|
139 |
+
|
140 |
+
Lib\Utils\Common::codes(
|
141 |
+
Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'customer' ),
|
142 |
+
array( 'type' => $notification_type )
|
143 |
+
);
|
144 |
+
}
|
145 |
+
|
146 |
+
/**
|
147 |
+
* Render codes for staff agenda.
|
148 |
+
*/
|
149 |
+
private function renderStaffDayAgendaCodes()
|
150 |
+
{
|
151 |
+
$codes = $this->getCommonCodes();
|
152 |
+
$codes[] = array( 'code' => 'agenda_date', 'description' => __( 'agenda date', 'bookly' ) );
|
153 |
+
$codes[] = array( 'code' => 'next_day_agenda', 'description' => __( 'staff agenda for next day', 'bookly' ) );
|
154 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
155 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
156 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
157 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
158 |
+
$codes[] = array( 'code' => 'tomorrow_date', 'description' => __( 'date of next day', 'bookly' ) );
|
159 |
+
|
160 |
+
Lib\Utils\Common::codes(
|
161 |
+
$codes,
|
162 |
+
array( 'type' => Notification::TYPE_STAFF_DAY_AGENDA )
|
163 |
+
);
|
164 |
+
}
|
165 |
+
|
166 |
+
/**
|
167 |
+
* Render codes for Greeting notifications
|
168 |
+
*/
|
169 |
+
private function renderBirthdayGreetingCodes()
|
170 |
+
{
|
171 |
+
$codes = $this->getCommonCodes();
|
172 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
173 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
174 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
175 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
176 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
177 |
+
|
178 |
+
Lib\Utils\Common::codes(
|
179 |
+
$codes,
|
180 |
+
array( 'type' => Notification::TYPE_CUSTOMER_BIRTHDAY )
|
181 |
+
);
|
182 |
+
}
|
183 |
+
|
184 |
+
/**
|
185 |
+
* Render codes for new WordPress users.
|
186 |
+
*/
|
187 |
+
private function renderNewWpUserCodes()
|
188 |
+
{
|
189 |
+
$codes = $this->getCommonCodes();
|
190 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
191 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
192 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
193 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
194 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
195 |
+
$codes[] = array( 'code' => 'new_password', 'description' => __( 'customer new password', 'bookly' ) );
|
196 |
+
$codes[] = array( 'code' => 'new_username', 'description' => __( 'customer new username', 'bookly' ) );
|
197 |
+
$codes[] = array( 'code' => 'site_address', 'description' => __( 'site address', 'bookly' ) );
|
198 |
+
|
199 |
+
Lib\Utils\Common::codes( $codes );
|
200 |
+
}
|
201 |
+
|
202 |
+
/**
|
203 |
+
* Render codes for compound (cart) notifications.
|
204 |
+
*/
|
205 |
+
private function renderCompoundCodes()
|
206 |
+
{
|
207 |
+
$codes = $this->getCommonCodes();
|
208 |
+
$codes[] = array( 'code' => 'cart_info', 'description' => __( 'cart information', 'bookly' ) );
|
209 |
+
$codes[] = array( 'code' => 'cart_info_c', 'description' => __( 'cart information with cancel', 'bookly' ) );
|
210 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
211 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
212 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
213 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
214 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
215 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
216 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
217 |
+
|
218 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareCartNotificationShortCodes( $codes ) );
|
219 |
+
}
|
220 |
+
|
221 |
+
/**
|
222 |
+
* Render base codes
|
223 |
+
*/
|
224 |
+
private function renderBaseCodes()
|
225 |
+
{
|
226 |
+
$codes = $this->getCommonCodes();
|
227 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
228 |
+
$codes[] = array( 'code' => 'appointment_end_date', 'description' => __( 'end date of appointment', 'bookly' ) );
|
229 |
+
$codes[] = array( 'code' => 'appointment_end_time', 'description' => __( 'end time of appointment', 'bookly' ) );
|
230 |
+
$codes[] = array( 'code' => 'appointment_notes', 'description' => __( 'customer notes for appointment', 'bookly' ) );
|
231 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
232 |
+
$codes[] = array( 'code' => 'approve_appointment_url', 'description' => esc_html__( 'URL of approve appointment link (to use inside <a> tag)', 'bookly' ) );
|
233 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
234 |
+
$codes[] = array( 'code' => 'cancel_appointment_confirm_url', 'description' => esc_html__( 'URL of cancel appointment link with confirmation (to use inside <a> tag)', 'bookly' ) );
|
235 |
+
$codes[] = array( 'code' => 'cancel_appointment_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) );
|
236 |
+
$codes[] = array( 'code' => 'cancellation_reason', 'description' => __( 'reason you mentioned while deleting appointment', 'bookly' ) );
|
237 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
238 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
239 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
240 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
241 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
242 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
243 |
+
$codes[] = array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) );
|
244 |
+
$codes[] = array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) );
|
245 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
246 |
+
$codes[] = array( 'code' => 'reject_appointment_url', 'description' => esc_html__( 'URL of reject appointment link (to use inside <a> tag)', 'bookly' ) );
|
247 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
248 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
249 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
250 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
251 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
252 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
253 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
254 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
255 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
256 |
+
|
257 |
+
Lib\Utils\Common::codes(
|
258 |
+
Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'customer' )
|
259 |
+
);
|
260 |
+
}
|
261 |
+
|
262 |
+
/**
|
263 |
+
* Render codes notifications about package appointments
|
264 |
+
*
|
265 |
+
* @param string $notification_type
|
266 |
+
*/
|
267 |
+
private function renderPackageCodes( $notification_type )
|
268 |
+
{
|
269 |
+
$codes = $this->getCommonCodes();
|
270 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
271 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
272 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
273 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
274 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
275 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
276 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
277 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
278 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
279 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
280 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
281 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
282 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
283 |
+
|
284 |
+
$codes = Lib\Proxy\Packages::prepareNotificationCodesList( $codes, '', $notification_type );
|
285 |
+
|
286 |
+
Lib\Utils\Common::codes( $codes );
|
287 |
+
}
|
288 |
+
|
289 |
+
/**
|
290 |
+
* Render codes notifications wor appointments in waiting list
|
291 |
+
*/
|
292 |
+
private function renderWaitingListCodes()
|
293 |
+
{
|
294 |
+
$codes = $this->getCommonCodes();
|
295 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
296 |
+
$codes[] = array( 'code' => 'appointment_end_date', 'description' => __( 'end date of appointment', 'bookly' ) );
|
297 |
+
$codes[] = array( 'code' => 'appointment_end_time', 'description' => __( 'end time of appointment', 'bookly' ) );
|
298 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
299 |
+
$codes[] = array( 'code' => 'appointment_waiting_list', 'description' => __( 'waiting list of appointment', 'bookly-waiting-list' ) );
|
300 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
301 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
302 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
303 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
304 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
305 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
306 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
307 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
308 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
309 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
310 |
+
|
311 |
+
$codes = Lib\Proxy\WaitingList::prepareNotificationCodesList( $codes );
|
312 |
+
|
313 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'appointment' ) );
|
314 |
+
}
|
315 |
+
|
316 |
+
private function renderRecurringCodes()
|
317 |
+
{
|
318 |
+
$codes = $this->getCommonCodes();
|
319 |
+
$codes[] = array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) );
|
320 |
+
$codes[] = array( 'code' => 'appointment_end_date','description' => __( 'end date of appointment', 'bookly' ) );
|
321 |
+
$codes[] = array( 'code' => 'appointment_end_time','description' => __( 'end time of appointment', 'bookly' ) );
|
322 |
+
$codes[] = array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) );
|
323 |
+
$codes[] = array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) );
|
324 |
+
$codes[] = array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) );
|
325 |
+
$codes[] = array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) );
|
326 |
+
$codes[] = array( 'code' => 'client_first_name', 'description' => __( 'first name of client', 'bookly' ) );
|
327 |
+
$codes[] = array( 'code' => 'client_last_name', 'description' => __( 'last name of client', 'bookly' ) );
|
328 |
+
$codes[] = array( 'code' => 'client_name', 'description' => __( 'full name of client', 'bookly' ) );
|
329 |
+
$codes[] = array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) );
|
330 |
+
$codes[] = array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) );
|
331 |
+
$codes[] = array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) );
|
332 |
+
$codes[] = array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) );
|
333 |
+
$codes[] = array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) );
|
334 |
+
$codes[] = array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) );
|
335 |
+
$codes[] = array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) );
|
336 |
+
$codes[] = array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) );
|
337 |
+
$codes[] = array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) );
|
338 |
+
$codes[] = array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) );
|
339 |
+
$codes[] = array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) );
|
340 |
+
$codes[] = array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) );
|
341 |
+
$codes[] = array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) );
|
342 |
+
|
343 |
+
$codes = Lib\Proxy\RecurringAppointments::prepareNotificationCodesList( $codes );
|
344 |
+
|
345 |
+
Lib\Utils\Common::codes( Lib\Proxy\Shared::prepareNotificationCodesList( $codes, 'customer' ) );
|
346 |
+
}
|
347 |
+
|
348 |
+
}
|
backend/modules/sms/Controller.php
CHANGED
@@ -34,6 +34,7 @@ class Controller extends Lib\Base\Controller
|
|
34 |
'js/datatables.min.js' => array( 'jquery' ),
|
35 |
'js/moment.min.js',
|
36 |
'js/daterangepicker.js' => array( 'jquery' ),
|
|
|
37 |
'js/alert.js' => array( 'jquery' ),
|
38 |
),
|
39 |
'frontend' => array_merge(
|
@@ -50,7 +51,7 @@ class Controller extends Lib\Base\Controller
|
|
50 |
|
51 |
$alert = array( 'success' => array(), 'error' => array() );
|
52 |
$prices = array();
|
53 |
-
$form = new \BooklyLite\Backend\Modules\Notifications\Forms\Notifications( 'sms' );
|
54 |
$sms = new Lib\SMS();
|
55 |
$cron_reminder = (array) get_option( 'bookly_cron_reminder_times' );
|
56 |
|
@@ -92,14 +93,18 @@ class Controller extends Lib\Base\Controller
|
|
92 |
}
|
93 |
if ( $this->hasParameter( 'form-notifications' ) ) {
|
94 |
update_option( 'bookly_sms_administrator_phone', $this->getParameter( 'bookly_sms_administrator_phone' ) );
|
|
|
95 |
|
96 |
$form->bind( $this->getPostParameters() );
|
97 |
$form->save();
|
98 |
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
99 |
|
100 |
-
foreach ( array( 'staff_agenda', 'client_follow_up', 'client_reminder' ) as $type ) {
|
101 |
$cron_reminder[ $type ] = $this->getParameter( $type . '_cron_hour' );
|
102 |
}
|
|
|
|
|
|
|
103 |
update_option( 'bookly_cron_reminder_times', $cron_reminder );
|
104 |
}
|
105 |
if ( $this->hasParameter( 'tab' ) ) {
|
@@ -117,6 +122,7 @@ class Controller extends Lib\Base\Controller
|
|
117 |
$alert['error'] = array_merge( $alert['error'], $sms->getErrors() );
|
118 |
wp_localize_script( 'bookly-daterangepicker.js', 'BooklyL10n',
|
119 |
array(
|
|
|
120 |
'alert' => $alert,
|
121 |
'apply' => __( 'Apply', 'bookly' ),
|
122 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
@@ -156,9 +162,12 @@ class Controller extends Lib\Base\Controller
|
|
156 |
'processing' => __( 'Processing...', 'bookly' ),
|
157 |
)
|
158 |
);
|
159 |
-
$
|
160 |
-
|
161 |
-
|
|
|
|
|
|
|
162 |
}
|
163 |
|
164 |
public function executeGetPurchasesList()
|
@@ -234,18 +243,20 @@ class Controller extends Lib\Base\Controller
|
|
234 |
public function executeSendTestSms()
|
235 |
{
|
236 |
$sms = new Lib\SMS();
|
237 |
-
|
238 |
-
|
239 |
-
$
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
} else {
|
247 |
-
|
248 |
}
|
|
|
|
|
249 |
}
|
250 |
|
251 |
public function executeForgotPassword()
|
@@ -323,14 +334,27 @@ class Controller extends Lib\Base\Controller
|
|
323 |
}
|
324 |
|
325 |
/**
|
326 |
-
*
|
327 |
-
* so current 'execute*' methods look nicer.
|
328 |
-
*
|
329 |
-
* @param string $prefix
|
330 |
*/
|
331 |
-
|
332 |
{
|
333 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
334 |
}
|
335 |
|
336 |
}
|
34 |
'js/datatables.min.js' => array( 'jquery' ),
|
35 |
'js/moment.min.js',
|
36 |
'js/daterangepicker.js' => array( 'jquery' ),
|
37 |
+
'js/help.js' => array( 'jquery' ),
|
38 |
'js/alert.js' => array( 'jquery' ),
|
39 |
),
|
40 |
'frontend' => array_merge(
|
51 |
|
52 |
$alert = array( 'success' => array(), 'error' => array() );
|
53 |
$prices = array();
|
54 |
+
$form = new \BooklyLite\Backend\Modules\Notifications\Forms\Notifications( 'sms', Components::getInstance() );
|
55 |
$sms = new Lib\SMS();
|
56 |
$cron_reminder = (array) get_option( 'bookly_cron_reminder_times' );
|
57 |
|
93 |
}
|
94 |
if ( $this->hasParameter( 'form-notifications' ) ) {
|
95 |
update_option( 'bookly_sms_administrator_phone', $this->getParameter( 'bookly_sms_administrator_phone' ) );
|
96 |
+
update_option( 'bookly_ntf_processing_interval', (int) $this->getParameter( 'bookly_ntf_processing_interval' ) );
|
97 |
|
98 |
$form->bind( $this->getPostParameters() );
|
99 |
$form->save();
|
100 |
$alert['success'][] = __( 'Settings saved.', 'bookly' );
|
101 |
|
102 |
+
foreach ( array( 'staff_agenda', 'client_follow_up', 'client_reminder', 'client_birthday_greeting' ) as $type ) {
|
103 |
$cron_reminder[ $type ] = $this->getParameter( $type . '_cron_hour' );
|
104 |
}
|
105 |
+
foreach ( array( 'client_reminder_1st', 'client_reminder_2nd', 'client_reminder_3rd', ) as $type ) {
|
106 |
+
$cron_reminder[ $type ] = $this->getParameter( $type . '_cron_before_hour' );
|
107 |
+
}
|
108 |
update_option( 'bookly_cron_reminder_times', $cron_reminder );
|
109 |
}
|
110 |
if ( $this->hasParameter( 'tab' ) ) {
|
122 |
$alert['error'] = array_merge( $alert['error'], $sms->getErrors() );
|
123 |
wp_localize_script( 'bookly-daterangepicker.js', 'BooklyL10n',
|
124 |
array(
|
125 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
126 |
'alert' => $alert,
|
127 |
'apply' => __( 'Apply', 'bookly' ),
|
128 |
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
162 |
'processing' => __( 'Processing...', 'bookly' ),
|
163 |
)
|
164 |
);
|
165 |
+
$cron_uri = plugins_url( 'lib/utils/send_notifications_cron.php', Lib\Plugin::getMainFile() );
|
166 |
+
$statuses = Lib\Entities\CustomerAppointment::getStatuses();
|
167 |
+
foreach ( range( 1, 23 ) as $hours ) {
|
168 |
+
$bookly_ntf_processing_interval_values[] = array( $hours, Lib\Utils\DateTime::secondsToInterval( $hours * HOUR_IN_SECONDS ) );
|
169 |
+
}
|
170 |
+
$this->render( 'index', compact( 'form', 'sms', 'is_logged_in', 'prices', 'cron_uri', 'cron_reminder', 'statuses', 'bookly_ntf_processing_interval_values' ) );
|
171 |
}
|
172 |
|
173 |
public function executeGetPurchasesList()
|
243 |
public function executeSendTestSms()
|
244 |
{
|
245 |
$sms = new Lib\SMS();
|
246 |
+
|
247 |
+
$response = array( 'success' => $sms->sendSms(
|
248 |
+
$this->getParameter( 'phone_number' ),
|
249 |
+
'Bookly test SMS.',
|
250 |
+
Lib\Entities\Notification::$type_ids['test_message']
|
251 |
+
) );
|
252 |
+
|
253 |
+
if ( $response['success'] ) {
|
254 |
+
$response['message'] = __( 'SMS has been sent successfully.', 'bookly' );
|
255 |
} else {
|
256 |
+
$response['message'] = implode( ' ', $sms->getErrors() );
|
257 |
}
|
258 |
+
|
259 |
+
wp_send_json( $response );
|
260 |
}
|
261 |
|
262 |
public function executeForgotPassword()
|
334 |
}
|
335 |
|
336 |
/**
|
337 |
+
* Create new custom sms notification
|
|
|
|
|
|
|
338 |
*/
|
339 |
+
public function executeCreateCustomSms()
|
340 |
{
|
341 |
+
$notification = new Lib\Entities\Notification();
|
342 |
+
$notification
|
343 |
+
->setType( Lib\Entities\Notification::TYPE_APPOINTMENT_START_TIME )
|
344 |
+
->setToCustomer( 1 )
|
345 |
+
->setToStaff( 1 )
|
346 |
+
->setSettings( json_encode( Lib\DataHolders\Notification\Settings::getDefault() ) )
|
347 |
+
->setGateway( 'sms' )
|
348 |
+
->save();
|
349 |
+
|
350 |
+
$notification = $notification->getFields();
|
351 |
+
$id = $notification['id'];
|
352 |
+
|
353 |
+
$form = new \BooklyLite\Backend\Modules\Notifications\Forms\Notifications( 'sms', Components::getInstance() );
|
354 |
+
$statuses = Lib\Entities\CustomerAppointment::getStatuses();
|
355 |
+
|
356 |
+
$html = $this->render( '_custom_notification', compact( 'form', 'notification', 'statuses' ), false );
|
357 |
+
wp_send_json_success( compact( 'html', 'id' ) );
|
358 |
}
|
359 |
|
360 |
}
|
backend/modules/sms/resources/js/sms.js
CHANGED
@@ -1,8 +1,9 @@
|
|
1 |
jQuery(function($) {
|
2 |
|
3 |
-
var $form_login = $('.
|
4 |
-
$form_forgot = $('.
|
5 |
-
$form_register = $('.
|
|
|
6 |
|
7 |
booklyAlert(BooklyL10n.alert);
|
8 |
|
@@ -13,7 +14,7 @@ jQuery(function($) {
|
|
13 |
$form_forgot.hide();
|
14 |
});
|
15 |
|
16 |
-
$('.
|
17 |
e.preventDefault();
|
18 |
$form_login.show();
|
19 |
$form_register.hide();
|
@@ -35,7 +36,7 @@ jQuery(function($) {
|
|
35 |
var $pwd = $form.find('input[name="password"]');
|
36 |
var $username = $form.find('input[name="username"]');
|
37 |
var $pwd_repeat = $form.find('input[name="password_repeat"]');
|
38 |
-
var data = { action: 'bookly_forgot_password', step: $btn.data('step'), 'username': $username.val() };
|
39 |
switch ($(this).data('step')) {
|
40 |
case 0:
|
41 |
forgot_helper( data, function() {
|
@@ -59,7 +60,7 @@ jQuery(function($) {
|
|
59 |
data.password_repeat = $pwd_repeat.val();
|
60 |
if (data.password == data.password_repeat && data.password != '') {
|
61 |
forgot_helper(data, function() {
|
62 |
-
$('.
|
63 |
$btn.data('step', 0);
|
64 |
$username.parent().removeClass('hidden');
|
65 |
$pwd.parent().addClass('hidden');
|
@@ -98,7 +99,7 @@ jQuery(function($) {
|
|
98 |
$('.bookly-admin-notify').on('change', function () {
|
99 |
var $checkbox = $(this);
|
100 |
$checkbox.hide().prev('img').show();
|
101 |
-
$.get(ajaxurl, {action: 'bookly_admin_notify', option_name: $checkbox.attr('name'), value: $checkbox.is(':checked') ? 1 : 0 }, function () {}, 'json').always(function () {
|
102 |
$checkbox.show().prev('img').hide();
|
103 |
});
|
104 |
});
|
@@ -138,14 +139,70 @@ jQuery(function($) {
|
|
138 |
/**
|
139 |
* Notifications Tab.
|
140 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
var $phone_input = $('#admin_phone');
|
142 |
if (BooklyL10n.intlTelInput.enabled) {
|
143 |
$phone_input.intlTelInput({
|
144 |
preferredCountries: [BooklyL10n.intlTelInput.country],
|
145 |
-
|
146 |
geoIpLookup: function (callback) {
|
147 |
-
$.get(
|
148 |
-
}, 'json').always(function (resp) {
|
149 |
var countryCode = (resp && resp.country) ? resp.country : '';
|
150 |
callback(countryCode);
|
151 |
});
|
@@ -153,7 +210,7 @@ jQuery(function($) {
|
|
153 |
utilsScript: BooklyL10n.intlTelInput.utils
|
154 |
});
|
155 |
}
|
156 |
-
$('#js-submit-notifications').on('click', function (e) {
|
157 |
e.preventDefault();
|
158 |
var ladda = Ladda.create(this);
|
159 |
ladda.start();
|
@@ -165,7 +222,7 @@ jQuery(function($) {
|
|
165 |
e.preventDefault();
|
166 |
$.ajax({
|
167 |
url : ajaxurl,
|
168 |
-
data : { action: 'bookly_send_test_sms', phone_number: BooklyL10n.intlTelInput.enabled ? $phone_input.intlTelInput('getNumber') : $phone_input.val() },
|
169 |
dataType : 'json',
|
170 |
xhrFields : { withCredentials: true },
|
171 |
crossDomain : 'withCredentials' in new XMLHttpRequest(),
|
@@ -189,7 +246,7 @@ jQuery(function($) {
|
|
189 |
$recharge_init.on('click', function () {
|
190 |
var ladda = Ladda.create(this);
|
191 |
ladda.start();
|
192 |
-
$.get(ajaxurl, {action: 'bookly_init_auto_recharge', amount: $recharge_amount.val()}, function () {
|
193 |
}, 'json').always(function (response) {
|
194 |
if (response.success) {
|
195 |
window.location.replace(response.data.paypal_preapproval);
|
@@ -202,7 +259,7 @@ jQuery(function($) {
|
|
202 |
$recharge_decline.on('click', function () {
|
203 |
var ladda = Ladda.create(this);
|
204 |
ladda.start();
|
205 |
-
$.get(ajaxurl, {action: 'bookly_decline_auto_recharge'}, function () {}, 'json')
|
206 |
.always(function (response) {
|
207 |
ladda.stop();
|
208 |
if (response.success) {
|
@@ -277,6 +334,7 @@ jQuery(function($) {
|
|
277 |
data: function (d) {
|
278 |
return {
|
279 |
action: 'bookly_get_purchases_list',
|
|
|
280 |
range: $date_range.data('date')
|
281 |
};
|
282 |
},
|
@@ -331,6 +389,7 @@ jQuery(function($) {
|
|
331 |
data: function (d) {
|
332 |
return {
|
333 |
action: 'bookly_get_sms_list',
|
|
|
334 |
range: $date_range.data('date')
|
335 |
};
|
336 |
},
|
@@ -358,10 +417,10 @@ jQuery(function($) {
|
|
358 |
/**
|
359 |
* Prices Tab.
|
360 |
*/
|
361 |
-
$("[data-target='#
|
362 |
fillPriceTable();
|
363 |
});
|
364 |
-
if ($('form.
|
365 |
fillPriceTable();
|
366 |
}
|
367 |
|
@@ -375,7 +434,7 @@ jQuery(function($) {
|
|
375 |
responsive: true,
|
376 |
ajax: {
|
377 |
url : ajaxurl,
|
378 |
-
data: { action: 'bookly_get_price_list' },
|
379 |
dataSrc: 'list'
|
380 |
},
|
381 |
columns: [
|
@@ -427,7 +486,7 @@ jQuery(function($) {
|
|
427 |
responsive: true,
|
428 |
ajax: {
|
429 |
url: ajaxurl,
|
430 |
-
data: { action: 'bookly_get_sender_ids_list' },
|
431 |
dataSrc: function (json) {
|
432 |
if (json.pending) {
|
433 |
$sender_id.val(json.pending);
|
@@ -456,7 +515,7 @@ jQuery(function($) {
|
|
456 |
ladda.start();
|
457 |
$.ajax({
|
458 |
url : ajaxurl,
|
459 |
-
data : {action: 'bookly_request_sender_id', 'sender_id': $sender_id.val()},
|
460 |
dataType : 'json',
|
461 |
xhrFields: {withCredentials: true},
|
462 |
success: function (response) {
|
@@ -480,7 +539,7 @@ jQuery(function($) {
|
|
480 |
if (confirm(BooklyL10n.are_you_sure)) {
|
481 |
$.ajax({
|
482 |
url: ajaxurl,
|
483 |
-
data: {action: 'bookly_reset_sender_id'},
|
484 |
dataType: 'json',
|
485 |
xhrFields: {withCredentials: true},
|
486 |
success: function (response) {
|
@@ -507,7 +566,7 @@ jQuery(function($) {
|
|
507 |
$.ajax({
|
508 |
method : 'POST',
|
509 |
url : ajaxurl,
|
510 |
-
data: {action: 'bookly_cancel_sender_id'},
|
511 |
dataType : 'json',
|
512 |
success : function (response) {
|
513 |
if (response.success) {
|
@@ -529,6 +588,33 @@ jQuery(function($) {
|
|
529 |
$(this).on('click', function () { dt.ajax.reload(); });
|
530 |
});
|
531 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
532 |
$('#bookly-open-tab-sender-id').on('click', function (e) {
|
533 |
e.preventDefault();
|
534 |
$('#sms_tabs li[data-target="#sender_id"]').trigger('click');
|
1 |
jQuery(function($) {
|
2 |
|
3 |
+
var $form_login = $('.bookly-login-form'),
|
4 |
+
$form_forgot = $('.bookly-forgot-form'),
|
5 |
+
$form_register = $('.bookly-register-form'),
|
6 |
+
$custom_notifications = $('#bookly-js-custom-notifications');
|
7 |
|
8 |
booklyAlert(BooklyL10n.alert);
|
9 |
|
14 |
$form_forgot.hide();
|
15 |
});
|
16 |
|
17 |
+
$('.bookly-show-login-form').on('click', function (e) {
|
18 |
e.preventDefault();
|
19 |
$form_login.show();
|
20 |
$form_register.hide();
|
36 |
var $pwd = $form.find('input[name="password"]');
|
37 |
var $username = $form.find('input[name="username"]');
|
38 |
var $pwd_repeat = $form.find('input[name="password_repeat"]');
|
39 |
+
var data = { action: 'bookly_forgot_password', step: $btn.data('step'), 'username': $username.val(), csrf_token : BooklyL10n.csrf_token };
|
40 |
switch ($(this).data('step')) {
|
41 |
case 0:
|
42 |
forgot_helper( data, function() {
|
60 |
data.password_repeat = $pwd_repeat.val();
|
61 |
if (data.password == data.password_repeat && data.password != '') {
|
62 |
forgot_helper(data, function() {
|
63 |
+
$('.bookly-show-login-form').trigger('click');
|
64 |
$btn.data('step', 0);
|
65 |
$username.parent().removeClass('hidden');
|
66 |
$pwd.parent().addClass('hidden');
|
99 |
$('.bookly-admin-notify').on('change', function () {
|
100 |
var $checkbox = $(this);
|
101 |
$checkbox.hide().prev('img').show();
|
102 |
+
$.get(ajaxurl, {action: 'bookly_admin_notify', csrf_token : BooklyL10n.csrf_token, option_name: $checkbox.attr('name'), value: $checkbox.is(':checked') ? 1 : 0 }, function () {}, 'json').always(function () {
|
103 |
$checkbox.show().prev('img').hide();
|
104 |
});
|
105 |
});
|
139 |
/**
|
140 |
* Notifications Tab.
|
141 |
*/
|
142 |
+
$custom_notifications
|
143 |
+
.on('change', "select[name$='[type]']", function () {
|
144 |
+
var $panel = $(this).closest('.panel'),
|
145 |
+
$settings = $panel.find('.bookly-js-settings'),
|
146 |
+
value = $(this).find(':selected').val(),
|
147 |
+
set = $(this).find(':selected').data('set'),
|
148 |
+
to = $(this).find(':selected').data('to');
|
149 |
+
|
150 |
+
$panel.find('table.bookly-codes').each(function () {
|
151 |
+
$(this).toggle($(this).hasClass('bookly-js-codes-' + value));
|
152 |
+
});
|
153 |
+
|
154 |
+
$.each(['customer', 'staff', 'admin'], function (index, value) {
|
155 |
+
$panel.find("[name$='[to_" + value + "]']").closest('.checkbox-inline').toggle(to.indexOf(value) != -1);
|
156 |
+
});
|
157 |
+
|
158 |
+
$settings.each(function () {
|
159 |
+
$(this).toggle($(this).hasClass('bookly-js-' + set));
|
160 |
+
});
|
161 |
+
|
162 |
+
switch (set) {
|
163 |
+
case 'after_event':
|
164 |
+
var $set = $panel.find('.bookly-js-' + set);
|
165 |
+
$set.find('.bookly-js-to').toggle(value == 'ca_status_changed');
|
166 |
+
$set.find('.bookly-js-with').toggle(value != 'ca_status_changed');
|
167 |
+
break;
|
168 |
+
}
|
169 |
+
})
|
170 |
+
.on('click', '.bookly-js-delete', function () {
|
171 |
+
if (confirm(BooklyL10n.are_you_sure)) {
|
172 |
+
var $button = $(this),
|
173 |
+
id = $button.data('notification_id');
|
174 |
+
$.ajax({
|
175 |
+
url: ajaxurl,
|
176 |
+
type: 'POST',
|
177 |
+
data: {
|
178 |
+
action: 'bookly_delete_custom_notification',
|
179 |
+
id: id,
|
180 |
+
csrf_token: BooklyL10n.csrf_token
|
181 |
+
},
|
182 |
+
dataType: 'json',
|
183 |
+
success: function (response) {
|
184 |
+
if (response.success) {
|
185 |
+
$button.closest('.panel').remove();
|
186 |
+
}
|
187 |
+
}
|
188 |
+
});
|
189 |
+
}
|
190 |
+
})
|
191 |
+
.find("select[name$='[type]']").trigger('change');
|
192 |
+
|
193 |
+
$('#notifications button[type=reset]').on('click', function () {
|
194 |
+
setTimeout(function () {
|
195 |
+
$("select[name$='[type]']", $custom_notifications).trigger('change');
|
196 |
+
}, 0);
|
197 |
+
});
|
198 |
+
|
199 |
var $phone_input = $('#admin_phone');
|
200 |
if (BooklyL10n.intlTelInput.enabled) {
|
201 |
$phone_input.intlTelInput({
|
202 |
preferredCountries: [BooklyL10n.intlTelInput.country],
|
203 |
+
initialCountry: BooklyL10n.intlTelInput.country,
|
204 |
geoIpLookup: function (callback) {
|
205 |
+
$.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
|
|
206 |
var countryCode = (resp && resp.country) ? resp.country : '';
|
207 |
callback(countryCode);
|
208 |
});
|
210 |
utilsScript: BooklyL10n.intlTelInput.utils
|
211 |
});
|
212 |
}
|
213 |
+
$('#bookly-js-submit-notifications').on('click', function (e) {
|
214 |
e.preventDefault();
|
215 |
var ladda = Ladda.create(this);
|
216 |
ladda.start();
|
222 |
e.preventDefault();
|
223 |
$.ajax({
|
224 |
url : ajaxurl,
|
225 |
+
data : { action: 'bookly_send_test_sms', csrf_token : BooklyL10n.csrf_token, phone_number: BooklyL10n.intlTelInput.enabled ? $phone_input.intlTelInput('getNumber') : $phone_input.val() },
|
226 |
dataType : 'json',
|
227 |
xhrFields : { withCredentials: true },
|
228 |
crossDomain : 'withCredentials' in new XMLHttpRequest(),
|
246 |
$recharge_init.on('click', function () {
|
247 |
var ladda = Ladda.create(this);
|
248 |
ladda.start();
|
249 |
+
$.get(ajaxurl, {action: 'bookly_init_auto_recharge', csrf_token : BooklyL10n.csrf_token, amount: $recharge_amount.val()}, function () {
|
250 |
}, 'json').always(function (response) {
|
251 |
if (response.success) {
|
252 |
window.location.replace(response.data.paypal_preapproval);
|
259 |
$recharge_decline.on('click', function () {
|
260 |
var ladda = Ladda.create(this);
|
261 |
ladda.start();
|
262 |
+
$.get(ajaxurl, {action: 'bookly_decline_auto_recharge', csrf_token : BooklyL10n.csrf_token}, function () {}, 'json')
|
263 |
.always(function (response) {
|
264 |
ladda.stop();
|
265 |
if (response.success) {
|
334 |
data: function (d) {
|
335 |
return {
|
336 |
action: 'bookly_get_purchases_list',
|
337 |
+
csrf_token: BooklyL10n.csrf_token,
|
338 |
range: $date_range.data('date')
|
339 |
};
|
340 |
},
|
389 |
data: function (d) {
|
390 |
return {
|
391 |
action: 'bookly_get_sms_list',
|
392 |
+
csrf_token: BooklyL10n.csrf_token,
|
393 |
range: $date_range.data('date')
|
394 |
};
|
395 |
},
|
417 |
/**
|
418 |
* Prices Tab.
|
419 |
*/
|
420 |
+
$("[data-target='#price_list']").one('click', function() {
|
421 |
fillPriceTable();
|
422 |
});
|
423 |
+
if ($('form.bookly-login-form').length){
|
424 |
fillPriceTable();
|
425 |
}
|
426 |
|
434 |
responsive: true,
|
435 |
ajax: {
|
436 |
url : ajaxurl,
|
437 |
+
data: { action: 'bookly_get_price_list', csrf_token : BooklyL10n.csrf_token },
|
438 |
dataSrc: 'list'
|
439 |
},
|
440 |
columns: [
|
486 |
responsive: true,
|
487 |
ajax: {
|
488 |
url: ajaxurl,
|
489 |
+
data: { action: 'bookly_get_sender_ids_list', csrf_token : BooklyL10n.csrf_token },
|
490 |
dataSrc: function (json) {
|
491 |
if (json.pending) {
|
492 |
$sender_id.val(json.pending);
|
515 |
ladda.start();
|
516 |
$.ajax({
|
517 |
url : ajaxurl,
|
518 |
+
data : {action: 'bookly_request_sender_id', csrf_token : BooklyL10n.csrf_token, 'sender_id': $sender_id.val()},
|
519 |
dataType : 'json',
|
520 |
xhrFields: {withCredentials: true},
|
521 |
success: function (response) {
|
539 |
if (confirm(BooklyL10n.are_you_sure)) {
|
540 |
$.ajax({
|
541 |
url: ajaxurl,
|
542 |
+
data: {action: 'bookly_reset_sender_id', csrf_token : BooklyL10n.csrf_token},
|
543 |
dataType: 'json',
|
544 |
xhrFields: {withCredentials: true},
|
545 |
success: function (response) {
|
566 |
$.ajax({
|
567 |
method : 'POST',
|
568 |
url : ajaxurl,
|
569 |
+
data: {action: 'bookly_cancel_sender_id', csrf_token : BooklyL10n.csrf_token},
|
570 |
dataType : 'json',
|
571 |
success : function (response) {
|
572 |
if (response.success) {
|
588 |
$(this).on('click', function () { dt.ajax.reload(); });
|
589 |
});
|
590 |
|
591 |
+
$("#bookly-js-new-notification").on('click', function () {
|
592 |
+
var ladda = Ladda.create(this);
|
593 |
+
ladda.start();
|
594 |
+
$.ajax({
|
595 |
+
url : ajaxurl,
|
596 |
+
type: 'POST',
|
597 |
+
data: {
|
598 |
+
action : 'bookly_create_custom_sms',
|
599 |
+
csrf_token: BooklyL10n.csrf_token
|
600 |
+
},
|
601 |
+
dataType: 'json',
|
602 |
+
success: function (response) {
|
603 |
+
if (response.success) {
|
604 |
+
$custom_notifications.append(response.data.html);
|
605 |
+
var $subject = $custom_notifications.find('#notification_' + response.data.id + '_subject'),
|
606 |
+
$panel = $subject.closest('.panel-collapse');
|
607 |
+
$panel.collapse('show');
|
608 |
+
$panel.find("select[name$='[type]']").trigger('change');
|
609 |
+
$subject.focus();
|
610 |
+
}
|
611 |
+
},
|
612 |
+
complete: function () {
|
613 |
+
ladda.stop();
|
614 |
+
}
|
615 |
+
});
|
616 |
+
});
|
617 |
+
|
618 |
$('#bookly-open-tab-sender-id').on('click', function (e) {
|
619 |
e.preventDefault();
|
620 |
$('#sms_tabs li[data-target="#sender_id"]').trigger('click');
|
backend/modules/sms/templates/_codes.php
DELETED
@@ -1,29 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'appointment_date', 'description' => __( 'date of appointment', 'bookly' ) ),
|
4 |
-
array( 'code' => 'appointment_time', 'description' => __( 'time of appointment', 'bookly' ) ),
|
5 |
-
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ) ),
|
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_url', 'description' => esc_html__( 'URL of cancel appointment link (to use inside <a> tag)', 'bookly' ) ),
|
8 |
-
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
9 |
-
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
10 |
-
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
11 |
-
array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) ),
|
12 |
-
array( 'code' => 'company_name', 'description' => __( 'name of company', 'bookly' ) ),
|
13 |
-
array( 'code' => 'company_address', 'description' => __( 'address of company', 'bookly' ) ),
|
14 |
-
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
15 |
-
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
16 |
-
array( 'code' => 'custom_fields', 'description' => __( 'combined values of all custom fields', 'bookly' ) ),
|
17 |
-
array( 'code' => 'google_calendar_url', 'description' => esc_html__( 'URL for adding event to client\'s Google Calendar (to use inside <a> tag)', 'bookly' ) ),
|
18 |
-
array( 'code' => 'number_of_persons', 'description' => __( 'number of persons', 'bookly' ) ),
|
19 |
-
array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) ),
|
20 |
-
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) ),
|
21 |
-
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) ),
|
22 |
-
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) ),
|
23 |
-
array( 'code' => 'staff_email', 'description' => __( 'email of staff', 'bookly' ) ),
|
24 |
-
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
25 |
-
array( 'code' => 'staff_phone', 'description' => __( 'phone of staff', 'bookly' ) ),
|
26 |
-
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) ),
|
27 |
-
array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) ),
|
28 |
-
);
|
29 |
-
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( 'bookly_prepare_notification_short_codes', $codes ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/sms/templates/_codes_cart.php
DELETED
@@ -1,15 +0,0 @@
|
|
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_address', 'description' => __( 'address of company', 'bookly' ) ),
|
10 |
-
array( 'code' => 'company_phone', 'description' => __( 'company phone', 'bookly' ) ),
|
11 |
-
array( 'code' => 'company_website', 'description' => __( 'company web-site address', 'bookly' ) ),
|
12 |
-
array( 'code' => 'payment_type', 'description' => __( 'payment type', 'bookly' ) ),
|
13 |
-
array( 'code' => 'total_price', 'description' => __( 'total price of booking (sum of all cart items after applying coupon)', 'bookly' ) ),
|
14 |
-
);
|
15 |
-
\BooklyLite\Lib\Utils\Common::Codes( apply_filters( 'bookly_prepare_cart_notification_short_codes', $codes ) );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/sms/templates/_codes_client_new_wp_user.php
DELETED
@@ -1,14 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'client_email', 'description' => __( 'email of client', 'bookly' ) ),
|
4 |
-
array( 'code' => 'client_name', 'description' => __( 'name of client', 'bookly' ) ),
|
5 |
-
array( 'code' => 'client_phone', 'description' => __( 'phone of client', 'bookly' ) ),
|
6 |
-
array( 'code' => 'company_name', 'description' => __( 'name of your company', 'bookly' ) ),
|
7 |
-
array( 'code' => 'company_address', 'description' => __( 'address of your company', 'bookly' ) ),
|
8 |
-
array( 'code' => 'company_phone', 'description' => __( 'your company phone', 'bookly' ) ),
|
9 |
-
array( 'code' => 'company_website', 'description' => __( 'this web-site address', 'bookly' ) ),
|
10 |
-
array( 'code' => 'new_username', 'description' => __( 'customer new username', 'bookly' ) ),
|
11 |
-
array( 'code' => 'new_password', 'description' => __( 'customer new password', 'bookly' ) ),
|
12 |
-
array( 'code' => 'site_address', 'description' => __( 'site address', 'bookly' ) ),
|
13 |
-
);
|
14 |
-
\BooklyLite\Lib\Utils\Common::Codes( $codes );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/sms/templates/_codes_staff_agenda.php
DELETED
@@ -1,7 +0,0 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
$codes = array(
|
3 |
-
array( 'code' => 'tomorrow_date', 'description' => __( 'date of next day', 'bookly' ) ),
|
4 |
-
array( 'code' => 'next_day_agenda', 'description' => __( 'staff agenda for next day', 'bookly' ) ),
|
5 |
-
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
6 |
-
);
|
7 |
-
\BooklyLite\Lib\Utils\Common::Codes( $codes );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/sms/templates/_custom_notification.php
ADDED
@@ -0,0 +1,263 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var BooklyLite\Backend\Modules\Notifications\Forms\Notifications $form */
|
3 |
+
use BooklyLite\Lib\Entities\CustomerAppointment;
|
4 |
+
use BooklyLite\Lib\DataHolders\Notification\Settings;
|
5 |
+
use BooklyLite\Lib\Entities\Notification;
|
6 |
+
|
7 |
+
$id = $notification['id'];
|
8 |
+
$notification_settings = (array) json_decode( $notification['settings'], true );
|
9 |
+
?>
|
10 |
+
<div class="panel panel-default bookly-js-collapse">
|
11 |
+
<div class="panel-heading" role="tab">
|
12 |
+
<div class="checkbox bookly-margin-remove">
|
13 |
+
<label>
|
14 |
+
<input name="notification[<?php echo $id ?>][active]" value="0" type="checkbox" checked="checked" class="hidden">
|
15 |
+
<input id="<?php echo $id ?>_active" name="notification[<?php echo $id ?>][active]" value="1" type="checkbox" <?php checked( $notification['active'] ) ?>>
|
16 |
+
<a href="#collapse_<?php echo $id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#bookly-js-custom-notifications">
|
17 |
+
<?php echo $notification['subject'] ?: __( 'Custom notification', 'bookly' ) ?>
|
18 |
+
</a>
|
19 |
+
</label>
|
20 |
+
<button type="button" class="pull-right btn btn-link bookly-js-delete" style="margin-top: -5px" data-notification_id="<?php echo $id ?>" title="<?php esc_attr_e( 'Delete', 'bookly' ) ?>">
|
21 |
+
<span class="ladda-label"><i class="glyphicon glyphicon-trash text-danger"></i></span>
|
22 |
+
</button>
|
23 |
+
</div>
|
24 |
+
</div>
|
25 |
+
<div id="collapse_<?php echo $id ?>" class="panel-collapse collapse">
|
26 |
+
<div class="panel-body">
|
27 |
+
<div class="row">
|
28 |
+
<div class="col-md-3">
|
29 |
+
<div class="form-group">
|
30 |
+
<label for="notification_<?php echo $id ?>_type"><?php _e( 'Type', 'bookly' ) ?></label>
|
31 |
+
<select class="form-control" name="notification[<?php echo $id ?>][type]" id="notification_<?php echo $id ?>_type">
|
32 |
+
<optgroup label="<?php esc_attr_e( 'Event notification', 'bookly' ) ?>">
|
33 |
+
<option value="<?php echo Notification::TYPE_CUSTOMER_APPOINTMENT_STATUS_CHANGED ?>" data-set="<?php echo Settings::SET_AFTER_EVENT ?>" <?php selected( $notification['type'], Notification::TYPE_CUSTOMER_APPOINTMENT_STATUS_CHANGED ) ?> data-to='["customer","staff","admin"]'><?php _e( 'Status changed', 'bookly' ) ?></option>
|
34 |
+
<option value="<?php echo Notification::TYPE_CUSTOMER_APPOINTMENT_CREATED ?>" data-set="<?php echo Settings::SET_AFTER_EVENT ?>" <?php selected( $notification['type'], Notification::TYPE_CUSTOMER_APPOINTMENT_CREATED ) ?> data-to='["customer","staff","admin"]'><?php _e( 'New booking', 'bookly' ) ?></option>
|
35 |
+
</optgroup>
|
36 |
+
<optgroup label="<?php esc_attr_e( 'Reminder notification', 'bookly' ) ?>">
|
37 |
+
<option value="<?php echo Notification::TYPE_APPOINTMENT_START_TIME ?>" data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME ?>" <?php selected( $notification['type'], Notification::TYPE_APPOINTMENT_START_TIME ) ?> data-to='["customer","staff","admin"]'><?php _e( 'Appointment date and time', 'bookly' ) ?></option>
|
38 |
+
<option value="<?php echo Notification::TYPE_CUSTOMER_BIRTHDAY ?>" data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE ?>" <?php selected( $notification['type'], Notification::TYPE_CUSTOMER_BIRTHDAY ) ?> data-to='["customer"]'><?php _e( 'Customer\'s birthday', 'bookly' ) ?></option>
|
39 |
+
<option value="<?php echo Notification::TYPE_LAST_CUSTOMER_APPOINTMENT ?>" data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME ?>" <?php selected( $notification['type'], Notification::TYPE_LAST_CUSTOMER_APPOINTMENT ) ?> data-to='["customer","staff","admin"]'><?php _e( 'Last client\'s appointment', 'bookly' ) ?></option>
|
40 |
+
<option value="<?php echo Notification::TYPE_STAFF_DAY_AGENDA ?>" data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE_BEFORE ?>" <?php selected( $notification['type'], Notification::TYPE_STAFF_DAY_AGENDA ) ?> data-to='["staff","admin"]'><?php _e( 'Full day agenda', 'bookly' ) ?></option>
|
41 |
+
</optgroup>
|
42 |
+
</select>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
<div>
|
46 |
+
<?php
|
47 |
+
$set = Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME;
|
48 |
+
$settings = @$notification_settings[ $set ];
|
49 |
+
?>
|
50 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
51 |
+
<?php $name = 'notification[' . $id . '][settings][' . $set . ']' ?>
|
52 |
+
<div class="col-md-3">
|
53 |
+
<div class="form-group">
|
54 |
+
<label for="notification_<?php echo $id ?>_status_1"><?php _e( 'With status', 'bookly' ) ?></label>
|
55 |
+
<select class="form-control" name="<?php echo $name ?>[status]" id="notification_<?php echo $id ?>_status_1">
|
56 |
+
<option value="any"><?php _e( 'Any', 'bookly' ) ?></option>
|
57 |
+
<?php foreach ( $statuses as $status ) : ?>
|
58 |
+
<option value="<?php echo $status ?>" <?php selected( $settings['status'] == $status ) ?>><?php echo CustomerAppointment::statusToString( $status ) ?></option>
|
59 |
+
<?php endforeach ?>
|
60 |
+
</select>
|
61 |
+
</div>
|
62 |
+
</div>
|
63 |
+
<div class="col-md-6">
|
64 |
+
<label for="notification_<?php echo $id ?>_send_1"><?php _e( 'Send', 'bookly' ) ?></label>
|
65 |
+
<div class="form-inline bookly-margin-bottom-sm">
|
66 |
+
<div class="form-group">
|
67 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="1" checked id="notification_<?php echo $id ?>_send_1"></label>
|
68 |
+
<select class="form-control" name="<?php echo $name ?>[offset_hours]">
|
69 |
+
<?php foreach ( array_merge( range( 1, 24 ), range( 48, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
70 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?></option>
|
71 |
+
<?php endforeach ?>
|
72 |
+
<option value="43200" <?php selected( @$settings['offset_hours'], 43200 ) ?>>30 <?php _e( 'days', 'bookly' ) ?></option>
|
73 |
+
</select>
|
74 |
+
<select class="form-control" name="<?php echo $name ?>[perform]">
|
75 |
+
<option value="before"><?php _e( 'before', 'bookly' ) ?></option>
|
76 |
+
<option value="after"<?php selected( @$settings['perform'] == 'after' ) ?>> <?php _e( 'after', 'bookly' ) ?></option>
|
77 |
+
</select>
|
78 |
+
</div>
|
79 |
+
</div>
|
80 |
+
|
81 |
+
<div class="form-inline">
|
82 |
+
<div class="form-group">
|
83 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="2" <?php checked( @$settings['option'] == 2 ) ?>></label>
|
84 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]">
|
85 |
+
<?php foreach ( array_merge( array( -672, -504 ), range( -336, -24, 24 ) ) as $hour ) : ?>
|
86 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( abs( $hour ) * HOUR_IN_SECONDS ) ?> <?php _e( 'before', 'bookly' ) ?></option>
|
87 |
+
<?php endforeach ?>
|
88 |
+
<option value="0" <?php selected( @$settings['offset_bidirectional_hours'], 0 ) ?>><?php _e( 'on the same day', 'bookly' ) ?></option>
|
89 |
+
<?php foreach ( array_merge( range( 24, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
90 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php _e( 'after', 'bookly' ) ?></option>
|
91 |
+
<?php endforeach ?>
|
92 |
+
</select>
|
93 |
+
<?php _e( 'at', 'bookly' ) ?>
|
94 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
95 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
96 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
97 |
+
<?php endforeach ?>
|
98 |
+
</select>
|
99 |
+
|
100 |
+
</div>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
</div>
|
104 |
+
|
105 |
+
<?php
|
106 |
+
$set = Settings::SET_EXISTING_EVENT_WITH_DATE;
|
107 |
+
$settings = @$notification_settings[ $set ];
|
108 |
+
?>
|
109 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
110 |
+
<?php $name = 'notification[' . $id . '][settings][' . $set . ']' ?>
|
111 |
+
<div class="col-md-6">
|
112 |
+
<label for="notification_<?php echo $id ?>_send_2"><?php _e( 'Send', 'bookly' ) ?></label>
|
113 |
+
<div class="form-inline">
|
114 |
+
<div class="form-group">
|
115 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]">
|
116 |
+
<?php foreach ( array_merge( array( -672, -504 ), range( -336, -24, 24 ) ) as $hour ) : ?>
|
117 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( abs( $hour ) * HOUR_IN_SECONDS ) ?> <?php _e( 'before', 'bookly' ) ?></option>
|
118 |
+
<?php endforeach ?>
|
119 |
+
<option value="0" <?php selected( @$settings['offset_bidirectional_hours'], 0 ) ?>><?php _e( 'on the same day', 'bookly' ) ?></option>
|
120 |
+
<?php foreach ( array_merge( range( 24, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
121 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php _e( 'after', 'bookly' ) ?></option>
|
122 |
+
<?php endforeach ?>
|
123 |
+
</select>
|
124 |
+
<?php _e( 'at', 'bookly' ) ?>
|
125 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
126 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
127 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
128 |
+
<?php endforeach ?>
|
129 |
+
</select>
|
130 |
+
</div>
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
</div>
|
134 |
+
|
135 |
+
<?php
|
136 |
+
$set = Settings::SET_EXISTING_EVENT_WITH_DATE_BEFORE;
|
137 |
+
$settings = @$notification_settings[ $set ];
|
138 |
+
?>
|
139 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
140 |
+
<?php $name = 'notification[' . $id . '][settings][' . $set . ']' ?>
|
141 |
+
<div class="col-md-6">
|
142 |
+
<label for="notification_<?php echo $id ?>_send_2"><?php _e( 'Send', 'bookly' ) ?></label>
|
143 |
+
<div class="form-inline">
|
144 |
+
<div class="form-group">
|
145 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]">
|
146 |
+
<?php foreach ( array_merge( array( -672, -504 ), range( -336, -24, 24 ) ) as $hour ) : ?>
|
147 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( abs( $hour ) * HOUR_IN_SECONDS ) ?> <?php _e( 'before', 'bookly' ) ?></option>
|
148 |
+
<?php endforeach ?>
|
149 |
+
<option value="0" <?php selected( @$settings['offset_bidirectional_hours'], 0 ) ?>><?php _e( 'on the same day', 'bookly' ) ?></option>
|
150 |
+
</select>
|
151 |
+
<?php _e( 'at', 'bookly' ) ?>
|
152 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
153 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
154 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
155 |
+
<?php endforeach ?>
|
156 |
+
</select>
|
157 |
+
</div>
|
158 |
+
</div>
|
159 |
+
</div>
|
160 |
+
</div>
|
161 |
+
</div>
|
162 |
+
|
163 |
+
<?php
|
164 |
+
$set = Settings::SET_AFTER_EVENT;
|
165 |
+
$settings = @$notification_settings[ $set ];
|
166 |
+
?>
|
167 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
168 |
+
<?php $name = 'notification[' . $id . '][settings][' . $set . ']' ?>
|
169 |
+
<div class="col-md-3">
|
170 |
+
<div class="form-group">
|
171 |
+
<label for="notification_<?php echo $id ?>_status_1" class="bookly-js-with"><?php _e( 'With status', 'bookly' ) ?></label>
|
172 |
+
<label for="notification_<?php echo $id ?>_status_1" class="bookly-js-to"><?php _e( 'To', 'bookly' ) ?></label>
|
173 |
+
<select class="form-control" name="<?php echo $name ?>[status]" id="notification_<?php echo $id ?>_status_1">
|
174 |
+
<option value="any"><?php _e( 'Any', 'bookly' ) ?></option>
|
175 |
+
<?php foreach ( $statuses as $status ) : ?>
|
176 |
+
<option value="<?php echo $status ?>" <?php selected( $settings['status'] == $status ) ?>><?php echo CustomerAppointment::statusToString( $status ) ?></option>
|
177 |
+
<?php endforeach ?>
|
178 |
+
</select>
|
179 |
+
</div>
|
180 |
+
</div>
|
181 |
+
<div class="col-md-6">
|
182 |
+
<label for="notification_<?php echo $id ?>_send_1"><?php _e( 'Send', 'bookly' ) ?></label>
|
183 |
+
<div class="form-inline bookly-margin-bottom-sm">
|
184 |
+
<div class="form-group">
|
185 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="1" checked></label> <?php _e( 'Instantly', 'bookly' ) ?>
|
186 |
+
</div>
|
187 |
+
</div>
|
188 |
+
|
189 |
+
<div class="form-inline bookly-margin-bottom-sm">
|
190 |
+
<div class="form-group">
|
191 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="2" <?php checked( @$settings['option'] == 2 ) ?>></label>
|
192 |
+
<select class="form-control" name="<?php echo $name ?>[offset_hours]">
|
193 |
+
<?php foreach ( array_merge( range( 1, 24 ), range( 48, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
194 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php _e( 'after', 'bookly' ) ?></option>
|
195 |
+
<?php endforeach ?>
|
196 |
+
</select>
|
197 |
+
<input type="hidden" name="<?php echo $name ?>[perform]" value="after">
|
198 |
+
</div>
|
199 |
+
</div>
|
200 |
+
|
201 |
+
<div class="form-inline">
|
202 |
+
<div class="form-group">
|
203 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="3" <?php checked( @$settings['option'] == 3 ) ?>></label>
|
204 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]">
|
205 |
+
<option value="0"><?php _e( 'on the same day', 'bookly' ) ?></option>
|
206 |
+
<?php foreach ( array_merge( range( 24, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
207 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php _e( 'after', 'bookly' ) ?></option>
|
208 |
+
<?php endforeach ?>
|
209 |
+
</select>
|
210 |
+
<?php _e( 'at', 'bookly' ) ?>
|
211 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
212 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
213 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \BooklyLite\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
214 |
+
<?php endforeach ?>
|
215 |
+
</select>
|
216 |
+
|
217 |
+
</div>
|
218 |
+
</div>
|
219 |
+
</div>
|
220 |
+
</div>
|
221 |
+
</div>
|
222 |
+
|
223 |
+
<div class="row">
|
224 |
+
<div class="col-md-6">
|
225 |
+
<div class="form-group">
|
226 |
+
<label for="notification_<?php echo $id ?>_subject"><?php _e( 'Notification name', 'bookly' ) ?></label>
|
227 |
+
<input type="text" class="form-control" id="notification_<?php echo $id ?>_subject" name="notification[<?php echo $id ?>][subject]" value="<?php echo esc_attr( $notification['subject'] ) ?>" />
|
228 |
+
</div>
|
229 |
+
</div>
|
230 |
+
</div>
|
231 |
+
|
232 |
+
<div class="row">
|
233 |
+
<div class="col-md-4">
|
234 |
+
<div class="form-group">
|
235 |
+
<label><?php _e( 'Recipient', 'bookly' ) ?></label>
|
236 |
+
<br>
|
237 |
+
<label class="checkbox-inline">
|
238 |
+
<input type="hidden" name="notification[<?php echo $id ?>][to_customer]" value="0">
|
239 |
+
<input type="checkbox" name="notification[<?php echo $id ?>][to_customer]" value="1" <?php checked( $notification['to_customer'] ) ?>> <?php _e( 'Client', 'bookly' ) ?>
|
240 |
+
</label>
|
241 |
+
<label class="checkbox-inline">
|
242 |
+
<input type="hidden" name="notification[<?php echo $id ?>][to_staff]" value="0">
|
243 |
+
<input type="checkbox" name="notification[<?php echo $id ?>][to_staff]" value="1" <?php checked( $notification['to_staff'] ) ?>> <?php _e( 'Staff', 'bookly' ) ?>
|
244 |
+
</label>
|
245 |
+
<label class="checkbox-inline">
|
246 |
+
<input type="hidden" name="notification[<?php echo $id ?>][to_admin]" value="0">
|
247 |
+
<input type="checkbox" name="notification[<?php echo $id ?>][to_admin]" value="1" <?php checked( $notification['to_admin'] ) ?>> <?php _e( 'Administrators', 'bookly' ) ?>
|
248 |
+
</label>
|
249 |
+
</div>
|
250 |
+
</div>
|
251 |
+
</div>
|
252 |
+
|
253 |
+
<?php $form->renderEditor( $id ) ?>
|
254 |
+
|
255 |
+
<div class="form-group">
|
256 |
+
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
257 |
+
<?php foreach ( Notification::getCustomNotificationTypes() as $notification_type ) :
|
258 |
+
$form->renderCodes( $notification_type );
|
259 |
+
endforeach ?>
|
260 |
+
</div>
|
261 |
+
</div>
|
262 |
+
</div>
|
263 |
+
</div>
|
backend/modules/sms/templates/_notifications.php
CHANGED
@@ -1,7 +1,8 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
|
4 |
-
|
|
|
5 |
?>
|
6 |
<form action="<?php echo esc_url( remove_query_arg( array( 'paypal_result', 'auto-recharge', 'tab' ) ) ) ?>" method="post">
|
7 |
<input type="hidden" name="form-notifications">
|
@@ -17,40 +18,37 @@
|
|
17 |
</div>
|
18 |
</div>
|
19 |
</div>
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
<div class="panel-group bookly-margin-vertical-xlg" id="
|
24 |
-
<?php foreach ( $form->
|
|
|
|
|
25 |
<div class="panel panel-default bookly-js-collapse">
|
26 |
<div class="panel-heading" role="tab">
|
27 |
<div class="checkbox bookly-margin-remove">
|
28 |
<label>
|
29 |
-
<input name="<?php echo $
|
30 |
-
<input id="<?php echo $
|
31 |
-
<a class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#
|
32 |
-
<?php echo
|
33 |
</a>
|
34 |
</label>
|
35 |
</div>
|
36 |
</div>
|
37 |
-
<div id="collapse_<?php echo $
|
38 |
<div class="panel-body">
|
39 |
|
40 |
-
<?php $form->renderSendingTime( $
|
41 |
-
<?php $form->renderEditor( $
|
42 |
-
<?php $form->renderCopy( $
|
43 |
|
44 |
<div class="form-group">
|
45 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
46 |
-
<?php
|
47 |
-
case 'staff_agenda': include '_codes_staff_agenda.php'; break;
|
48 |
-
case 'client_new_wp_user': include '_codes_client_new_wp_user.php'; break;
|
49 |
-
default: include '_codes.php';
|
50 |
-
endswitch ?>
|
51 |
</div>
|
52 |
</div>
|
53 |
-
|
54 |
</div>
|
55 |
</div>
|
56 |
<?php endforeach ?>
|
@@ -58,29 +56,31 @@
|
|
58 |
|
59 |
<?php if ( $form->types['combined'] ) : ?>
|
60 |
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Combined', 'bookly' ) ?></h4>
|
61 |
-
<div class="panel-group bookly-margin-vertical-xlg" id="
|
62 |
-
<?php foreach ( $form->
|
|
|
|
|
63 |
<div class="panel panel-default bookly-js-collapse">
|
64 |
<div class="panel-heading" role="tab">
|
65 |
<div class="checkbox bookly-margin-remove">
|
66 |
<label>
|
67 |
-
<input name="<?php echo $
|
68 |
-
<input id="<?php echo $
|
69 |
-
<a class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#
|
70 |
-
<?php echo
|
71 |
</a>
|
72 |
</label>
|
73 |
</div>
|
74 |
</div>
|
75 |
-
<div id="collapse_<?php echo $
|
76 |
<div class="panel-body">
|
77 |
-
|
78 |
-
<?php $form->renderEditor( $
|
79 |
-
<?php $form->renderCopy( $
|
80 |
|
81 |
<div class="form-group">
|
82 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
83 |
-
<?php
|
84 |
</div>
|
85 |
</div>
|
86 |
</div>
|
@@ -89,19 +89,45 @@
|
|
89 |
</div>
|
90 |
<?php endif ?>
|
91 |
|
92 |
-
<?php
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
<div class="alert alert-info">
|
95 |
-
|
96 |
-
<
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
101 |
</div>
|
102 |
|
103 |
<div class="panel-footer">
|
104 |
-
<?php
|
105 |
-
<?php
|
106 |
</div>
|
107 |
</form>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Lib\Entities\Notification;
|
3 |
+
use BooklyLite\Lib\Proxy;
|
4 |
+
use BooklyLite\Lib\Utils\Common;
|
5 |
+
/** @var BooklyLite\Backend\Modules\Notifications\Forms\Notifications $form */
|
6 |
?>
|
7 |
<form action="<?php echo esc_url( remove_query_arg( array( 'paypal_result', 'auto-recharge', 'tab' ) ) ) ?>" method="post">
|
8 |
<input type="hidden" name="form-notifications">
|
18 |
</div>
|
19 |
</div>
|
20 |
</div>
|
21 |
+
|
22 |
+
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Single', 'bookly' ) ?></h4>
|
23 |
+
|
24 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="bookly-js-single-notifications" role="tablist" aria-multiselectable="true">
|
25 |
+
<?php foreach ( $form->getNotifications( 'single' ) as $notification ) :
|
26 |
+
$id = $notification['id'];
|
27 |
+
?>
|
28 |
<div class="panel panel-default bookly-js-collapse">
|
29 |
<div class="panel-heading" role="tab">
|
30 |
<div class="checkbox bookly-margin-remove">
|
31 |
<label>
|
32 |
+
<input name="notification[<?php echo $id ?>][active]" value="0" type="checkbox" checked="checked" class="hidden">
|
33 |
+
<input id="<?php echo $id ?>_active" name="notification[<?php echo $id ?>][active]" value="1" type="checkbox" <?php checked( $notification['active'] ) ?>>
|
34 |
+
<a href="#collapse_<?php echo $id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#bookly-js-single-notifications">
|
35 |
+
<?php echo Notification::getName( $notification['type'] ) ?>
|
36 |
</a>
|
37 |
</label>
|
38 |
</div>
|
39 |
</div>
|
40 |
+
<div id="collapse_<?php echo $id ?>" class="panel-collapse collapse">
|
41 |
<div class="panel-body">
|
42 |
|
43 |
+
<?php $form->renderSendingTime( $notification ) ?>
|
44 |
+
<?php $form->renderEditor( $id ) ?>
|
45 |
+
<?php $form->renderCopy( $notification ) ?>
|
46 |
|
47 |
<div class="form-group">
|
48 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
49 |
+
<?php $form->renderCodes( $notification['type'] ) ?>
|
|
|
|
|
|
|
|
|
50 |
</div>
|
51 |
</div>
|
|
|
52 |
</div>
|
53 |
</div>
|
54 |
<?php endforeach ?>
|
56 |
|
57 |
<?php if ( $form->types['combined'] ) : ?>
|
58 |
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Combined', 'bookly' ) ?></h4>
|
59 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="bookly-js-combined-notifications" role="tablist" aria-multiselectable="true">
|
60 |
+
<?php foreach ( $form->getNotifications( 'combined' ) as $notification ) :
|
61 |
+
$id = $notification['id'];
|
62 |
+
?>
|
63 |
<div class="panel panel-default bookly-js-collapse">
|
64 |
<div class="panel-heading" role="tab">
|
65 |
<div class="checkbox bookly-margin-remove">
|
66 |
<label>
|
67 |
+
<input name="notification[<?php echo $id ?>][active]" value="0" type="checkbox" checked="checked" class="hidden">
|
68 |
+
<input id="<?php echo $id ?>_active" name="notification[<?php echo $id ?>][active]" value="1" type="checkbox" <?php checked( $notification['active'] ) ?>>
|
69 |
+
<a href="#collapse_<?php echo $id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#bookly-js-combined-notifications">
|
70 |
+
<?php echo Notification::getName( $notification['type'] ) ?>
|
71 |
</a>
|
72 |
</label>
|
73 |
</div>
|
74 |
</div>
|
75 |
+
<div id="collapse_<?php echo $id ?>" class="panel-collapse collapse">
|
76 |
<div class="panel-body">
|
77 |
+
|
78 |
+
<?php $form->renderEditor( $id ) ?>
|
79 |
+
<?php $form->renderCopy( $notification ) ?>
|
80 |
|
81 |
<div class="form-group">
|
82 |
<label><?php _e( 'Codes', 'bookly' ) ?></label>
|
83 |
+
<?php $form->renderCodes( $notification['type'] ) ?>
|
84 |
</div>
|
85 |
</div>
|
86 |
</div>
|
89 |
</div>
|
90 |
<?php endif ?>
|
91 |
|
92 |
+
<?php Proxy\Shared::renderSmsNotifications( $form ) ?>
|
93 |
+
|
94 |
+
<h4 class="bookly-block-head bookly-color-gray"><?php _e( 'Custom', 'bookly' ) ?></h4>
|
95 |
+
<div class="panel-group bookly-margin-vertical-xlg" id="bookly-js-custom-notifications">
|
96 |
+
<?php foreach ( $form->getNotifications( 'custom' ) as $notification ) :
|
97 |
+
$this->render( '_custom_notification', compact( 'form', 'notification', 'statuses' ) );
|
98 |
+
endforeach ?>
|
99 |
+
</div>
|
100 |
+
|
101 |
+
<div class="row">
|
102 |
+
<div class="col-sm-12">
|
103 |
+
<div class="form-group">
|
104 |
+
<button id="bookly-js-new-notification" type="button" class="btn btn-xlg btn-block btn-success-outline">
|
105 |
+
<span class="ladda-label"><i class="dashicons dashicons-plus-alt"></i>
|
106 |
+
<?php _e( 'New Notification', 'bookly' ) ?>
|
107 |
+
</span>
|
108 |
+
</button>
|
109 |
+
</div>
|
110 |
+
</div>
|
111 |
+
</div>
|
112 |
|
113 |
<div class="alert alert-info">
|
114 |
+
<div class="row">
|
115 |
+
<div class="col-md-10">
|
116 |
+
<?php if ( is_multisite() ) : ?>
|
117 |
+
<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>
|
118 |
+
<?php else : ?>
|
119 |
+
<p><?php _e( 'To send scheduled notifications please execute the following command hourly with your cron:', 'bookly' ) ?></p><br/>
|
120 |
+
<code class="bookly-text-wrap">wget -q -O - <?php echo $cron_uri ?></code>
|
121 |
+
<?php endif ?>
|
122 |
+
</div>
|
123 |
+
<div class="col-md-2">
|
124 |
+
<?php Common::optionToggle( 'bookly_ntf_processing_interval', __( 'Notification period', 'bookly' ), __( 'Set period of time when system will attempt to deliver notification to user. Notification will be discarded after period expiration.', 'bookly' ), $bookly_ntf_processing_interval_values ) ?>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
</div>
|
128 |
|
129 |
<div class="panel-footer">
|
130 |
+
<?php Common::submitButton( 'bookly-js-submit-notifications' ) ?>
|
131 |
+
<?php Common::resetButton() ?>
|
132 |
</div>
|
133 |
</form>
|
backend/modules/sms/templates/index.php
CHANGED
@@ -55,7 +55,7 @@
|
|
55 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#auto_recharge"><?php _e( 'Auto-Recharge', 'bookly' ) ?></li>
|
56 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#purchases"><?php _e( 'Purchases', 'bookly' ) ?></li>
|
57 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#sms_details"><?php _e( 'SMS Details', 'bookly' ) ?></li>
|
58 |
-
<li class="bookly-nav-item" data-toggle="tab" data-target="#
|
59 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#sender_id"><?php _e( 'Sender ID', 'bookly' ) ?></li>
|
60 |
</ul>
|
61 |
<?php endif ?>
|
@@ -67,7 +67,7 @@
|
|
67 |
<div class="tab-pane" id="auto_recharge"><?php include '_auto_recharge.php' ?></div>
|
68 |
<div class="tab-pane" id="purchases"><?php include '_purchases.php' ?></div>
|
69 |
<div class="tab-pane" id="sms_details"><?php include '_sms_details.php' ?></div>
|
70 |
-
<div class="tab-pane" id="
|
71 |
<div class="tab-pane" id="sender_id"><?php include '_sender_id.php' ?></div>
|
72 |
</div>
|
73 |
<?php else : ?>
|
@@ -79,16 +79,16 @@
|
|
79 |
<div class="row">
|
80 |
<div class="col-md-4">
|
81 |
<div class="well">
|
82 |
-
<form method="post" class="
|
83 |
<fieldset>
|
84 |
<legend><?php _e( 'Login', 'bookly' ) ?></legend>
|
85 |
<div class="form-group">
|
86 |
-
<label for="
|
87 |
-
<input id="
|
88 |
</div>
|
89 |
<div class="form-group">
|
90 |
-
<label for="
|
91 |
-
<input id="
|
92 |
</div>
|
93 |
<div class="form-group">
|
94 |
<button type="submit" name="form-login" class="btn btn-success pull-right"><?php _e( 'Log In', 'bookly' ) ?></button>
|
@@ -98,38 +98,38 @@
|
|
98 |
</fieldset>
|
99 |
</form>
|
100 |
|
101 |
-
<form method="post" class="
|
102 |
<fieldset>
|
103 |
<legend><?php _e( 'Registration', 'bookly' ) ?></legend>
|
104 |
<div class="form-group">
|
105 |
-
<label for="
|
106 |
-
<input id="
|
107 |
</div>
|
108 |
<div class="form-group">
|
109 |
-
<label for="
|
110 |
-
<input id="
|
111 |
</div>
|
112 |
<div class="form-group">
|
113 |
-
<label for="
|
114 |
-
<input id="
|
115 |
</div>
|
116 |
<div class="form-group">
|
117 |
<div class="checkbox">
|
118 |
-
<label for="
|
119 |
-
<input id="
|
120 |
-
<?php _e( 'Accept <a href="
|
121 |
</label>
|
122 |
</div>
|
123 |
</div>
|
124 |
|
125 |
<div class="form-group">
|
126 |
<button type="submit" name="form-registration" class="btn btn-success pull-right"><?php _e( 'Register', 'bookly' ) ?></button>
|
127 |
-
<a href="#" class="
|
128 |
</div>
|
129 |
</fieldset>
|
130 |
</form>
|
131 |
|
132 |
-
<form method="post" class="
|
133 |
<fieldset>
|
134 |
<legend><?php _e( 'Forgot password', 'bookly' ) ?></legend>
|
135 |
<div class="form-group">
|
@@ -146,7 +146,7 @@
|
|
146 |
</div>
|
147 |
<div class="form-group">
|
148 |
<button class="btn btn-success pull-right form-forgot-next" data-step="0"><?php _e( 'Next', 'bookly' ) ?></button>
|
149 |
-
<a href="#" class="
|
150 |
</div>
|
151 |
</fieldset>
|
152 |
</form>
|
@@ -184,6 +184,7 @@
|
|
184 |
</div>
|
185 |
</div>
|
186 |
<div class="modal-footer">
|
|
|
187 |
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'ajax-send-change-password', 'btn-sm' ) ?>
|
188 |
</div>
|
189 |
<input type="hidden" name="action" value="bookly_change_password">
|
@@ -193,8 +194,7 @@
|
|
193 |
</div>
|
194 |
|
195 |
<?php else : ?>
|
196 |
-
|
197 |
-
<div class="modal fade" id="ab-tos" tabindex=-1 role="dialog">
|
198 |
<div class="modal-dialog">
|
199 |
<div class="modal-content">
|
200 |
<div class="modal-header">
|
@@ -202,52 +202,11 @@
|
|
202 |
<div class="modal-title h2"><?php _e( 'Terms & Conditions', 'bookly' ) ?></div>
|
203 |
</div>
|
204 |
<div class="modal-body">
|
205 |
-
<
|
206 |
-
<p>Save as expressly set out herein, all conditions or warranties which may be implied or incorporated into this contract by law or otherwise are hereby expressly excluded to the extent permitted by law. In no circumstances whatsoever will Bookly SMS be liable for economic, indirect or consequential loss.</p>
|
207 |
-
<p>Save where the Service is terminated by Bookly SMS without cause, the Customer shall not be entitled to a refund of subscriptions paid.</p>
|
208 |
-
<h3>Term, Suspension and Termination of Service</h3>
|
209 |
-
<p>This contract shall be for a term of 3 months from the date of adding money to balance by the Customer or the contract is terminated in accordance with the terms hereof.</p>
|
210 |
-
<p>Bookly SMS may elect to suspend or terminate the Service immediately and without prior notice, on breach of any of the terms and conditions of this contract, including without limitation late or non-payment of sums due.</p>
|
211 |
-
<p>From time to time certain mobile gateways, servers, or the whole or part of the Service may be closed down for routine repair, upgrade or maintenance work. Bookly SMS shall give as much notice as in the circumstances is reasonable and shall endeavor to carry out such works during the scheduled maintenance periods as published from time to time.</p>
|
212 |
-
<h3>Improper Use and Liabilities</h3>
|
213 |
-
<h4>Use by the Customer</h4>
|
214 |
-
<p>The Customer acknowledges that it may only use the Service for lawful purposes. The Customer warrants that:</p>
|
215 |
-
<ul>
|
216 |
-
<li>it shall not (or authorise or permit any other party to) use the Service to receive or transmit material which is in violation of any law, regulation or the Bookly SMS Acceptable Use Policy, or which is obscene, threatening, menacing, offensive, defamatory, in breach of confidence, in breach of any intellectual property right (including copyright), or otherwise unlawful;</li>
|
217 |
-
<li>it shall not knowingly or recklessly transmit any electronic material (including viruses) through the Service which shall cause or is likely to cause detriment or harm, in any degree, to computer systems owned by Bookly SMS, other customers of the Service, or any other Service users;</li>
|
218 |
-
<li>it shall not use any source address that is not allocated for its use by Bookly SMS;</li>
|
219 |
-
<li>it as the registered user of the account will keep all allocated username(s) and password(s) secure and not let them become public knowledge and that the password(s) will not be stored anywhere on a computer in plain text;</li>
|
220 |
-
<li>if any password for the Service becomes known to any other unauthorised user it will inform Bookly SMS immediately;</li>
|
221 |
-
<li>all information they provide, including during service application, will be accurate and correct;</li>
|
222 |
-
<li>any breach of these obligations shall entitle Bookly SMS to immediately terminate the Service to the Customer without notice.</li>
|
223 |
-
</ul>
|
224 |
-
<p>The Customer hereby agrees to fully indemnify and to hold Bookly SMS harmless from and against any claim brought by a third party resulting from the use of the Service by the Customer and in respect of all losses, costs, actions, proceedings, claims, damages, expenses (including reasonable legal costs and expenses), or liabilities, whatsoever suffered or incurred directly by Bookly SMS in consequence of the Customer's breach or non-observance of these terms and conditions.</p>
|
225 |
-
<p>The Customer shall defend and pay all costs, damages, awards, fees (including any reasonable legal fees) and judgments awarded against Bookly SMS arising from the above claims and shall provide Bookly SMS with notice of such claims, full authority to defend, compromise or settle such claims and reasonable assistance necessary to defend such claims, at the Customer's sole expense.</p>
|
226 |
-
<p>The Customer shall be liable to pay all and any additional charges in connection with the use of the Service including those levied by its telephone service provider(s).</p>
|
227 |
-
<h4>Use by others</h4>
|
228 |
-
<p>The Customer acknowledges that Bookly SMS is unable to exercise control over the content of information passing over the Service, and Bookly SMS hereby excludes all liability of any kind for the transmission or reception of infringing information of whatever nature.</p>
|
229 |
-
<h3>Prices</h3>
|
230 |
-
<p>All prices are subject to change without notice. The prices shown in this online price list supersede all previous prices. However, we cannot control price increases by our suppliers. We also reserve the right to correct misprints.</p>
|
231 |
-
<h3>Taxes</h3>
|
232 |
-
<p>Fees and all other amounts mentioned in this Agreement do not include any taxes, all of which will be paid by Customer (except for Bookly SMS income taxes). In the event that Bookly SMS is required by applicable law to pay or remit such Taxes, Customer will reimburse MessageMedia for such amounts.</p>
|
233 |
-
<h3>Password</h3>
|
234 |
-
<p>Bookly SMS reserves the right to change the Customer's allocated password(s) at any time at its sole discretion.</p>
|
235 |
-
<h3>Data Protection</h3>
|
236 |
-
<p>You agree that we may put your name and other information obtained about you from your subscription and the sales process into a computerised directory for internal use only, until we receive specific written instructions from you. Note that no personal details will be passed from us onto other companies, organisations or individuals not connected with servicing your subscription.</p>
|
237 |
-
<h3>Trial Accounts</h3>
|
238 |
-
<p>Trial (or evaluation) account Customers acknowledge that access to the Service may be restricted at the sole discretion of Bookly SMS in the interests of fully subscribed customers.</p>
|
239 |
-
<h3>Refunds</h3>
|
240 |
-
<p>Refunds will be given at the discretion of the Company Management.</p>
|
241 |
-
<h3>General</h3>
|
242 |
-
<p>Bookly SMS reserves the right to vary these terms and conditions from time to time. Such changes shall be notified to the Customer by posting on the Bookly SMS Web site. Changes in this manner shall be deemed to have been accepted if the Customer continues to use the Service after a period of two weeks from the date of posting on the Web site.</p>
|
243 |
-
<p>Bookly SMS shall not be liable in respect of any breach of this contract due to any cause beyond its reasonable control including but not limited to, inclement weather, hardware failures, network outages, act or omission of Government or public telephone operators or other competent authority or other party for whom Bookly SMS is not responsible.</p>
|
244 |
-
<p>The Customer acknowledges that it has read and accepts the terms of this contract. Use of the service by the Customer shall be deemed acceptance of the terms of this contract.</p>
|
245 |
-
<p>This contract shall be governed by and construed in accordance with the laws of Belize and the Customer hereby submits to the exclusive jurisdiction of the courts of Belize.</p>
|
246 |
</div>
|
247 |
</div>
|
248 |
</div>
|
249 |
</div>
|
250 |
-
|
251 |
<?php endif ?>
|
252 |
</div>
|
253 |
</div>
|
55 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#auto_recharge"><?php _e( 'Auto-Recharge', 'bookly' ) ?></li>
|
56 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#purchases"><?php _e( 'Purchases', 'bookly' ) ?></li>
|
57 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#sms_details"><?php _e( 'SMS Details', 'bookly' ) ?></li>
|
58 |
+
<li class="bookly-nav-item" data-toggle="tab" data-target="#price_list"><?php _e( 'Price list', 'bookly' ) ?></li>
|
59 |
<li class="bookly-nav-item" data-toggle="tab" data-target="#sender_id"><?php _e( 'Sender ID', 'bookly' ) ?></li>
|
60 |
</ul>
|
61 |
<?php endif ?>
|
67 |
<div class="tab-pane" id="auto_recharge"><?php include '_auto_recharge.php' ?></div>
|
68 |
<div class="tab-pane" id="purchases"><?php include '_purchases.php' ?></div>
|
69 |
<div class="tab-pane" id="sms_details"><?php include '_sms_details.php' ?></div>
|
70 |
+
<div class="tab-pane" id="price_list"><?php include '_price.php' ?></div>
|
71 |
<div class="tab-pane" id="sender_id"><?php include '_sender_id.php' ?></div>
|
72 |
</div>
|
73 |
<?php else : ?>
|
79 |
<div class="row">
|
80 |
<div class="col-md-4">
|
81 |
<div class="well">
|
82 |
+
<form method="post" class="bookly-login-form" action="<?php echo esc_url( remove_query_arg( array( 'paypal_result', 'auto-recharge', 'tab' ) ) ) ?>">
|
83 |
<fieldset>
|
84 |
<legend><?php _e( 'Login', 'bookly' ) ?></legend>
|
85 |
<div class="form-group">
|
86 |
+
<label for="bookly-username"><?php _e( 'Email', 'bookly' ) ?></label>
|
87 |
+
<input id="bookly-username" class="form-control" type="text" required="required" value="" name="username">
|
88 |
</div>
|
89 |
<div class="form-group">
|
90 |
+
<label for="bookly-password"><?php _e( 'Password', 'bookly' ) ?></label>
|
91 |
+
<input id="bookly-password" class="form-control" type="password" required="required" name="password">
|
92 |
</div>
|
93 |
<div class="form-group">
|
94 |
<button type="submit" name="form-login" class="btn btn-success pull-right"><?php _e( 'Log In', 'bookly' ) ?></button>
|
98 |
</fieldset>
|
99 |
</form>
|
100 |
|
101 |
+
<form method="post" class="bookly-register-form" style="display: none;">
|
102 |
<fieldset>
|
103 |
<legend><?php _e( 'Registration', 'bookly' ) ?></legend>
|
104 |
<div class="form-group">
|
105 |
+
<label for="bookly-r-username"><?php _e( 'Email', 'bookly' ) ?></label>
|
106 |
+
<input id="bookly-r-username" name="username" class="form-control" required="required" value="" type="text">
|
107 |
</div>
|
108 |
<div class="form-group">
|
109 |
+
<label for="bookly-r-password"><?php _e( 'Password', 'bookly' ) ?></label>
|
110 |
+
<input id="bookly-r-password" name="password" class="form-control" required="required" value="" type="password">
|
111 |
</div>
|
112 |
<div class="form-group">
|
113 |
+
<label for="bookly-r-repeat-password"><?php _e( 'Repeat password', 'bookly' ) ?></label>
|
114 |
+
<input id="bookly-r-repeat-password" name="password_repeat" class="form-control" required="required" value="" type="password">
|
115 |
</div>
|
116 |
<div class="form-group">
|
117 |
<div class="checkbox">
|
118 |
+
<label for="bookly-r-tos">
|
119 |
+
<input id="bookly-r-tos" name="accept_tos" required="required" value="1" type="checkbox">
|
120 |
+
<?php _e( 'Accept <a href="#" data-toggle="modal" data-target="#bookly-tos">Terms & Conditions</a>', 'bookly' ) ?>
|
121 |
</label>
|
122 |
</div>
|
123 |
</div>
|
124 |
|
125 |
<div class="form-group">
|
126 |
<button type="submit" name="form-registration" class="btn btn-success pull-right"><?php _e( 'Register', 'bookly' ) ?></button>
|
127 |
+
<a href="#" class="bookly-show-login-form"><?php _e( 'Log In', 'bookly' ) ?></a>
|
128 |
</div>
|
129 |
</fieldset>
|
130 |
</form>
|
131 |
|
132 |
+
<form method="post" class="bookly-forgot-form" style="display: none;">
|
133 |
<fieldset>
|
134 |
<legend><?php _e( 'Forgot password', 'bookly' ) ?></legend>
|
135 |
<div class="form-group">
|
146 |
</div>
|
147 |
<div class="form-group">
|
148 |
<button class="btn btn-success pull-right form-forgot-next" data-step="0"><?php _e( 'Next', 'bookly' ) ?></button>
|
149 |
+
<a href="#" class="bookly-show-login-form"><?php _e( 'Log In', 'bookly' ) ?></a>
|
150 |
</div>
|
151 |
</fieldset>
|
152 |
</form>
|
184 |
</div>
|
185 |
</div>
|
186 |
<div class="modal-footer">
|
187 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
188 |
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'ajax-send-change-password', 'btn-sm' ) ?>
|
189 |
</div>
|
190 |
<input type="hidden" name="action" value="bookly_change_password">
|
194 |
</div>
|
195 |
|
196 |
<?php else : ?>
|
197 |
+
<div class="modal fade" id="bookly-tos" tabindex=-1 role="dialog">
|
|
|
198 |
<div class="modal-dialog">
|
199 |
<div class="modal-content">
|
200 |
<div class="modal-header">
|
202 |
<div class="modal-title h2"><?php _e( 'Terms & Conditions', 'bookly' ) ?></div>
|
203 |
</div>
|
204 |
<div class="modal-body">
|
205 |
+
<iframe src="https://booking-wp-plugin.com/sms-terms.html" width="100%" height="600px"></iframe>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
</div>
|
207 |
</div>
|
208 |
</div>
|
209 |
</div>
|
|
|
210 |
<?php endif ?>
|
211 |
</div>
|
212 |
</div>
|
backend/modules/staff/Controller.php
CHANGED
@@ -19,9 +19,6 @@ class Controller extends Lib\Base\Controller
|
|
19 |
|
20 |
public function index()
|
21 |
{
|
22 |
-
/** @var \WP_Locale $wp_locale */
|
23 |
-
global $wp_locale;
|
24 |
-
|
25 |
wp_enqueue_media();
|
26 |
$this->enqueueStyles( array(
|
27 |
'frontend' => array_merge(
|
@@ -49,28 +46,31 @@ class Controller extends Lib\Base\Controller
|
|
49 |
? array()
|
50 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
51 |
),
|
52 |
-
'module' => array(
|
|
|
|
|
|
|
|
|
|
|
|
|
53 |
) );
|
54 |
|
55 |
wp_localize_script( 'bookly-staff.js', 'BooklyL10n', array(
|
56 |
-
'are_you_sure'
|
57 |
-
'
|
58 |
-
'
|
59 |
-
'
|
60 |
-
'
|
61 |
-
'saved' => __( 'Settings saved.', 'bookly' ),
|
62 |
-
'selector' => array( 'all_selected' => __( 'All locations', 'bookly' ), 'nothing_selected' => __( 'No locations selected', 'bookly' ), ),
|
63 |
-
'intlTelInput' => array(
|
64 |
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
65 |
'utils' => plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
66 |
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
67 |
),
|
68 |
-
'
|
69 |
-
'limitations'
|
70 |
) );
|
71 |
|
72 |
// Allow add-ons to enqueue their assets.
|
73 |
-
|
74 |
|
75 |
$active_staff_id = 1;
|
76 |
$staff_members = Lib\Entities\Staff::query()->where( 'id', $active_staff_id )->fetchArray();
|
@@ -83,7 +83,7 @@ class Controller extends Lib\Base\Controller
|
|
83 |
if ( $success_auth ) {
|
84 |
$staff = new Lib\Entities\Staff();
|
85 |
$staff->load( 1 );
|
86 |
-
$staff->
|
87 |
$staff->save();
|
88 |
|
89 |
exit ( '<script>location.href="' . Lib\Google::generateRedirectURI() . '&staff_id=1";</script>' );
|
@@ -107,9 +107,8 @@ class Controller extends Lib\Base\Controller
|
|
107 |
{
|
108 |
$staff = new Lib\Entities\Staff();
|
109 |
if ( $staff ) {
|
110 |
-
$this->render( '_list_item', array( 'staff' => $staff->getFields() ) );
|
111 |
}
|
112 |
-
exit;
|
113 |
}
|
114 |
|
115 |
public function executeUpdateStaffPosition()
|
@@ -118,12 +117,12 @@ class Controller extends Lib\Base\Controller
|
|
118 |
foreach ( $staff_sorts as $position => $staff_id ) {
|
119 |
$staff_sort = new Lib\Entities\Staff();
|
120 |
$staff_sort->load( $staff_id );
|
121 |
-
$staff_sort->
|
122 |
$staff_sort->save();
|
123 |
}
|
124 |
}
|
125 |
|
126 |
-
public function
|
127 |
{
|
128 |
$form = new Forms\StaffServices();
|
129 |
$staff_id = 1;
|
@@ -132,18 +131,18 @@ class Controller extends Lib\Base\Controller
|
|
132 |
$services_data = $form->getServicesData();
|
133 |
$uncategorized_services = $form->getUncategorizedServices();
|
134 |
|
135 |
-
$this->render( 'services', compact( 'categories', 'services_data', 'uncategorized_services', 'staff_id' ) );
|
136 |
-
|
137 |
}
|
138 |
|
139 |
-
public function
|
140 |
{
|
141 |
$staff_id = 1;
|
142 |
-
$staff
|
143 |
$staff->load( $staff_id );
|
144 |
$schedule_items = $staff->getScheduleItems();
|
145 |
-
$this->render( 'schedule', compact( 'schedule_items', 'staff_id' ) );
|
146 |
-
|
147 |
}
|
148 |
|
149 |
public function executeStaffScheduleUpdate()
|
@@ -151,7 +150,6 @@ class Controller extends Lib\Base\Controller
|
|
151 |
$form = new Forms\StaffSchedule();
|
152 |
$form->bind( $this->getPostParameters() );
|
153 |
$form->save();
|
154 |
-
|
155 |
wp_send_json_success();
|
156 |
}
|
157 |
|
@@ -161,12 +159,12 @@ class Controller extends Lib\Base\Controller
|
|
161 |
*/
|
162 |
public function executeResetBreaks()
|
163 |
{
|
164 |
-
$breaks
|
|
|
165 |
|
166 |
// Remove all breaks for staff member.
|
167 |
$break = new Lib\Entities\ScheduleItemBreak();
|
168 |
$break->removeBreaksByStaffId( 1 );
|
169 |
-
$html_breaks = array();
|
170 |
|
171 |
// Restore previous breaks.
|
172 |
if ( isset( $breaks['breaks'] ) && is_array( $breaks['breaks'] ) ) {
|
@@ -183,11 +181,11 @@ class Controller extends Lib\Base\Controller
|
|
183 |
// Make array with breaks (html) for each day.
|
184 |
foreach ( $staff->getScheduleItems() as $item ) {
|
185 |
/** @var Lib\Entities\StaffScheduleItem $item */
|
186 |
-
$html_breaks[ $item->
|
187 |
-
'day_is_not_available' => null === $item->
|
188 |
-
'item'
|
189 |
-
'break_start'
|
190 |
-
'break_end'
|
191 |
), false );
|
192 |
}
|
193 |
|
@@ -205,15 +203,14 @@ class Controller extends Lib\Base\Controller
|
|
205 |
wp_send_json_error( array( 'message' => __( 'The start time must be less than the end one', 'bookly' ), ) );
|
206 |
}
|
207 |
|
208 |
-
$
|
209 |
-
$
|
210 |
|
211 |
-
$bound = array( $staffScheduleItem->get( 'start_time' ), $staffScheduleItem->get( 'end_time' ) );
|
212 |
$break_id = $this->getParameter( 'break_id', 0 );
|
213 |
|
214 |
$in_working_time = $working_start <= $start_time && $start_time <= $working_end
|
215 |
&& $working_start <= $end_time && $end_time <= $working_end;
|
216 |
-
if (
|
217 |
wp_send_json_error( array( 'message' => __( 'The requested interval is not available', 'bookly' ), ) );
|
218 |
}
|
219 |
|
@@ -224,23 +221,23 @@ class Controller extends Lib\Base\Controller
|
|
224 |
if ( $break_id ) {
|
225 |
$break = new Lib\Entities\ScheduleItemBreak();
|
226 |
$break->load( $break_id );
|
227 |
-
$break->
|
228 |
-
|
229 |
-
|
230 |
|
231 |
wp_send_json_success( array( 'interval' => $formatted_interval, ) );
|
232 |
} else {
|
233 |
$form = new Forms\StaffScheduleItemBreak();
|
234 |
$form->bind( $this->getPostParameters() );
|
235 |
|
236 |
-
$
|
237 |
-
if ( $
|
238 |
-
$breakStart = new TimeChoice( array( 'use_empty' => false, 'type' => '
|
239 |
-
$breakEnd = new TimeChoice( array( 'use_empty' => false, 'type' => '
|
240 |
wp_send_json( array(
|
241 |
'success' => true,
|
242 |
'item_content' => $this->render( '_break', array(
|
243 |
-
'staff_schedule_item_break_id' => $
|
244 |
'formatted_interval' => $formatted_interval,
|
245 |
'break_start_choices' => $breakStart->render( '', $start_time, array( 'class' => 'break-start form-control' ) ),
|
246 |
'break_end_choices' => $breakEnd->render( '', $end_time, array( 'class' => 'break-end form-control' ) ),
|
@@ -255,7 +252,7 @@ class Controller extends Lib\Base\Controller
|
|
255 |
public function executeDeleteStaffScheduleBreak()
|
256 |
{
|
257 |
$break = new Lib\Entities\ScheduleItemBreak();
|
258 |
-
$break->
|
259 |
$break->delete();
|
260 |
|
261 |
wp_send_json_success();
|
@@ -266,20 +263,26 @@ class Controller extends Lib\Base\Controller
|
|
266 |
$form = new Forms\StaffServices();
|
267 |
$form->bind( $this->getPostParameters() );
|
268 |
$form->save();
|
269 |
-
|
270 |
wp_send_json_success();
|
271 |
}
|
272 |
|
273 |
public function executeEditStaff()
|
274 |
{
|
275 |
-
$calendar_list = array();
|
276 |
-
$authUrl = null;
|
277 |
$alert = array( 'error' => array() );
|
278 |
-
$form = new Forms\StaffMemberEdit();
|
279 |
$staff = new Lib\Entities\Staff();
|
280 |
$staff->load( 1 );
|
281 |
|
282 |
-
if ( $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
283 |
if ( get_option( 'bookly_gc_client_id' ) == '' ) {
|
284 |
$authUrl = false;
|
285 |
} else {
|
@@ -289,7 +292,7 @@ class Controller extends Lib\Base\Controller
|
|
289 |
} else {
|
290 |
$google = new Lib\Google();
|
291 |
if ( $google->loadByStaff( $staff ) ) {
|
292 |
-
$
|
293 |
} else {
|
294 |
foreach ( $google->getErrors() as $error ) {
|
295 |
$alert['error'][] = $error;
|
@@ -297,21 +300,18 @@ class Controller extends Lib\Base\Controller
|
|
297 |
}
|
298 |
}
|
299 |
|
300 |
-
|
301 |
-
foreach ( (array) json_decode( $gc_errors, true ) as $error ) {
|
302 |
-
$alert['error'][] = $error;
|
303 |
-
}
|
304 |
-
Lib\Session::destroy( 'staff_google_auth_error' );
|
305 |
-
}
|
306 |
-
|
307 |
-
$users_for_staff = Lib\Utils\Common::isCurrentUserAdmin() ? $form->getUsersForStaff( $staff->get( 'id' ) ) : array();
|
308 |
|
309 |
wp_send_json_success( array(
|
310 |
-
'html'
|
|
|
|
|
|
|
311 |
'alert' => $alert,
|
312 |
) );
|
313 |
}
|
314 |
|
|
|
315 |
/**
|
316 |
* Update staff from POST request.
|
317 |
*/
|
@@ -323,7 +323,7 @@ class Controller extends Lib\Base\Controller
|
|
323 |
if ( get_option( 'bookly_gen_allow_staff_edit_profile' ) ) {
|
324 |
$staff = new Lib\Entities\Staff();
|
325 |
$staff->load( $this->getParameter( 'id' ) );
|
326 |
-
if ( $staff->
|
327 |
unset ( $_POST['wp_user_id'] );
|
328 |
break;
|
329 |
}
|
@@ -332,11 +332,12 @@ class Controller extends Lib\Base\Controller
|
|
332 |
wp_die( 'Bookly: ' . __( 'You do not have sufficient permissions to access this page.' ) );
|
333 |
} while ( 0 );
|
334 |
}
|
335 |
-
$form
|
|
|
336 |
$form->bind( $this->getPostParameters(), $_FILES );
|
337 |
$employee = $form->save();
|
338 |
|
339 |
-
|
340 |
|
341 |
if ( $employee === false && array_key_exists( 'google_calendar_error', $form->getErrors() ) ) {
|
342 |
$errors = $form->getErrors();
|
@@ -344,7 +345,7 @@ class Controller extends Lib\Base\Controller
|
|
344 |
} else {
|
345 |
$wp_users = array();
|
346 |
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
347 |
-
$form
|
348 |
$wp_users = $form->getUsersForStaff();
|
349 |
}
|
350 |
|
@@ -368,17 +369,28 @@ class Controller extends Lib\Base\Controller
|
|
368 |
{
|
369 |
$staff = new Lib\Entities\Staff();
|
370 |
$staff->load( 1 );
|
371 |
-
$staff->
|
372 |
$staff->save();
|
|
|
373 |
wp_send_json_success();
|
374 |
}
|
375 |
|
376 |
public function executeStaffHolidays()
|
377 |
{
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
382 |
}
|
383 |
|
384 |
public function executeStaffHolidaysUpdate()
|
@@ -400,11 +412,10 @@ class Controller extends Lib\Base\Controller
|
|
400 |
}
|
401 |
// Add the new event.
|
402 |
} elseif ( $holiday && $day ) {
|
403 |
-
$wpdb->insert( Lib\Entities\Holiday::getTableName(), array( 'date' => $day, 'repeat_event' => (int) $repeat, 'staff_id' =>
|
404 |
}
|
405 |
-
|
406 |
// And return refreshed events.
|
407 |
-
echo $this->getHolidays( $staff_id );
|
408 |
}
|
409 |
exit;
|
410 |
}
|
@@ -427,7 +438,7 @@ class Controller extends Lib\Base\Controller
|
|
427 |
}
|
428 |
}
|
429 |
|
430 |
-
return
|
431 |
}
|
432 |
|
433 |
/**
|
@@ -439,43 +450,44 @@ class Controller extends Lib\Base\Controller
|
|
439 |
protected function hasAccess( $action )
|
440 |
{
|
441 |
if ( parent::hasAccess( $action ) ) {
|
442 |
-
|
443 |
if ( ! Lib\Utils\Common::isCurrentUserAdmin() ) {
|
444 |
$staff = new Lib\Entities\Staff();
|
445 |
|
446 |
switch ( $action ) {
|
447 |
case 'executeEditStaff':
|
448 |
case 'executeDeleteStaffAvatar':
|
449 |
-
case 'executeStaffServices':
|
450 |
case 'executeStaffSchedule':
|
451 |
case 'executeStaffHolidays':
|
452 |
case 'executeUpdateStaff':
|
|
|
453 |
$staff->load( $this->getParameter( 'id' ) );
|
454 |
break;
|
|
|
|
|
455 |
case 'executeStaffServicesUpdate':
|
456 |
case 'executeStaffHolidaysUpdate':
|
457 |
$staff->load( $this->getParameter( 'staff_id' ) );
|
458 |
break;
|
459 |
case 'executeStaffScheduleHandleBreak':
|
460 |
-
$
|
461 |
-
$
|
462 |
-
$staff->load( $
|
463 |
break;
|
464 |
case 'executeDeleteStaffScheduleBreak':
|
465 |
$break = new Lib\Entities\ScheduleItemBreak();
|
466 |
$break->load( $this->getParameter( 'id' ) );
|
467 |
-
$
|
468 |
-
$
|
469 |
-
$staff->load( $
|
470 |
break;
|
471 |
case 'executeStaffScheduleUpdate':
|
472 |
if ( $this->hasParameter( 'days' ) ) {
|
473 |
foreach ( $this->getParameter( 'days' ) as $id => $day_index ) {
|
474 |
-
$
|
475 |
-
$
|
476 |
$staff = new Lib\Entities\Staff();
|
477 |
-
$staff->load( $
|
478 |
-
if ( $staff->
|
479 |
return false;
|
480 |
}
|
481 |
}
|
@@ -485,7 +497,7 @@ class Controller extends Lib\Base\Controller
|
|
485 |
return false;
|
486 |
}
|
487 |
|
488 |
-
return $staff->
|
489 |
}
|
490 |
|
491 |
return true;
|
@@ -493,16 +505,4 @@ class Controller extends Lib\Base\Controller
|
|
493 |
|
494 |
return false;
|
495 |
}
|
496 |
-
|
497 |
-
/**
|
498 |
-
* Override parent method to add 'wp_ajax_bookly_' prefix
|
499 |
-
* so current 'execute*' methods look nicer.
|
500 |
-
*
|
501 |
-
* @param string $prefix
|
502 |
-
*/
|
503 |
-
protected function registerWpActions( $prefix = '' )
|
504 |
-
{
|
505 |
-
parent::registerWpActions( 'wp_ajax_bookly_' );
|
506 |
-
}
|
507 |
-
|
508 |
}
|
19 |
|
20 |
public function index()
|
21 |
{
|
|
|
|
|
|
|
22 |
wp_enqueue_media();
|
23 |
$this->enqueueStyles( array(
|
24 |
'frontend' => array_merge(
|
46 |
? array()
|
47 |
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
48 |
),
|
49 |
+
'module' => array(
|
50 |
+
'js/staff-details.js' => array( 'bookly-alert.js', ),
|
51 |
+
'js/staff-services.js' => array( 'bookly-staff-details.js' ),
|
52 |
+
'js/staff-schedule.js' => array( 'bookly-staff-services.js' ),
|
53 |
+
'js/staff-days-off.js' => array( 'bookly-staff-schedule.js' ),
|
54 |
+
'js/staff.js' => array( 'jquery-ui-sortable', 'jquery-ui-datepicker', 'bookly-range_tools.js', 'bookly-staff-days-off.js' ),
|
55 |
+
),
|
56 |
) );
|
57 |
|
58 |
wp_localize_script( 'bookly-staff.js', 'BooklyL10n', array(
|
59 |
+
'are_you_sure' => __( 'Are you sure?', 'bookly' ),
|
60 |
+
'saved' => __( 'Settings saved.', 'bookly' ),
|
61 |
+
'capacity_error' => __( 'Min capacity should not be greater than max capacity.', 'bookly' ),
|
62 |
+
'selector' => array( 'all_selected' => __( 'All locations', 'bookly' ), 'nothing_selected' => __( 'No locations selected', 'bookly' ), ),
|
63 |
+
'intlTelInput' => array(
|
|
|
|
|
|
|
64 |
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
65 |
'utils' => plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
66 |
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
67 |
),
|
68 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
69 |
+
'limitations' => __( '<b class="h4">This function is not available in the Lite version of Bookly.</b><br><br>To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Standard version of Bookly.<br>For more information visit', 'bookly' ) . ' <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://booking-wp-plugin.com</a>',
|
70 |
) );
|
71 |
|
72 |
// Allow add-ons to enqueue their assets.
|
73 |
+
Lib\Proxy\Shared::enqueueAssetsForStaffProfile();
|
74 |
|
75 |
$active_staff_id = 1;
|
76 |
$staff_members = Lib\Entities\Staff::query()->where( 'id', $active_staff_id )->fetchArray();
|
83 |
if ( $success_auth ) {
|
84 |
$staff = new Lib\Entities\Staff();
|
85 |
$staff->load( 1 );
|
86 |
+
$staff->setGoogleData( $google->getAccessToken() );
|
87 |
$staff->save();
|
88 |
|
89 |
exit ( '<script>location.href="' . Lib\Google::generateRedirectURI() . '&staff_id=1";</script>' );
|
107 |
{
|
108 |
$staff = new Lib\Entities\Staff();
|
109 |
if ( $staff ) {
|
110 |
+
wp_send_json_success( array( 'html' => $this->render( '_list_item', array( 'staff' => $staff->getFields() ), false ) ) );
|
111 |
}
|
|
|
112 |
}
|
113 |
|
114 |
public function executeUpdateStaffPosition()
|
117 |
foreach ( $staff_sorts as $position => $staff_id ) {
|
118 |
$staff_sort = new Lib\Entities\Staff();
|
119 |
$staff_sort->load( $staff_id );
|
120 |
+
$staff_sort->setPosition( $position );
|
121 |
$staff_sort->save();
|
122 |
}
|
123 |
}
|
124 |
|
125 |
+
public function executeGetStaffServices()
|
126 |
{
|
127 |
$form = new Forms\StaffServices();
|
128 |
$staff_id = 1;
|
131 |
$services_data = $form->getServicesData();
|
132 |
$uncategorized_services = $form->getUncategorizedServices();
|
133 |
|
134 |
+
$html = $this->render( 'services', compact( 'categories', 'services_data', 'uncategorized_services', 'staff_id' ), false );
|
135 |
+
wp_send_json_success( compact( 'html' ) );
|
136 |
}
|
137 |
|
138 |
+
public function executeGetStaffSchedule()
|
139 |
{
|
140 |
$staff_id = 1;
|
141 |
+
$staff = new Lib\Entities\Staff();
|
142 |
$staff->load( $staff_id );
|
143 |
$schedule_items = $staff->getScheduleItems();
|
144 |
+
$html = $this->render( 'schedule', compact( 'schedule_items', 'staff_id' ), false );
|
145 |
+
wp_send_json_success( compact( 'html' ) );
|
146 |
}
|
147 |
|
148 |
public function executeStaffScheduleUpdate()
|
150 |
$form = new Forms\StaffSchedule();
|
151 |
$form->bind( $this->getPostParameters() );
|
152 |
$form->save();
|
|
|
153 |
wp_send_json_success();
|
154 |
}
|
155 |
|
159 |
*/
|
160 |
public function executeResetBreaks()
|
161 |
{
|
162 |
+
$breaks = $this->getParameter( 'breaks' );
|
163 |
+
$html_breaks = array();
|
164 |
|
165 |
// Remove all breaks for staff member.
|
166 |
$break = new Lib\Entities\ScheduleItemBreak();
|
167 |
$break->removeBreaksByStaffId( 1 );
|
|
|
168 |
|
169 |
// Restore previous breaks.
|
170 |
if ( isset( $breaks['breaks'] ) && is_array( $breaks['breaks'] ) ) {
|
181 |
// Make array with breaks (html) for each day.
|
182 |
foreach ( $staff->getScheduleItems() as $item ) {
|
183 |
/** @var Lib\Entities\StaffScheduleItem $item */
|
184 |
+
$html_breaks[ $item->getId() ] = $this->render( '_breaks', array(
|
185 |
+
'day_is_not_available' => null === $item->getStartTime(),
|
186 |
+
'item' => $item,
|
187 |
+
'break_start' => new TimeChoice( array( 'use_empty' => false, 'type' => 'break_from' ) ),
|
188 |
+
'break_end' => new TimeChoice( array( 'use_empty' => false, 'type' => 'to' ) ),
|
189 |
), false );
|
190 |
}
|
191 |
|
203 |
wp_send_json_error( array( 'message' => __( 'The start time must be less than the end one', 'bookly' ), ) );
|
204 |
}
|
205 |
|
206 |
+
$res_schedule = new Lib\Entities\StaffScheduleItem();
|
207 |
+
$res_schedule->load( $this->getParameter( 'staff_schedule_item_id' ) );
|
208 |
|
|
|
209 |
$break_id = $this->getParameter( 'break_id', 0 );
|
210 |
|
211 |
$in_working_time = $working_start <= $start_time && $start_time <= $working_end
|
212 |
&& $working_start <= $end_time && $end_time <= $working_end;
|
213 |
+
if ( ! $in_working_time || ! $res_schedule->isBreakIntervalAvailable( $start_time, $end_time, $break_id ) ) {
|
214 |
wp_send_json_error( array( 'message' => __( 'The requested interval is not available', 'bookly' ), ) );
|
215 |
}
|
216 |
|
221 |
if ( $break_id ) {
|
222 |
$break = new Lib\Entities\ScheduleItemBreak();
|
223 |
$break->load( $break_id );
|
224 |
+
$break->setStartTime( $start_time )
|
225 |
+
->setEndTime( $end_time )
|
226 |
+
->save();
|
227 |
|
228 |
wp_send_json_success( array( 'interval' => $formatted_interval, ) );
|
229 |
} else {
|
230 |
$form = new Forms\StaffScheduleItemBreak();
|
231 |
$form->bind( $this->getPostParameters() );
|
232 |
|
233 |
+
$res_schedule_break = $form->save();
|
234 |
+
if ( $res_schedule_break ) {
|
235 |
+
$breakStart = new TimeChoice( array( 'use_empty' => false, 'type' => 'break_from' ) );
|
236 |
+
$breakEnd = new TimeChoice( array( 'use_empty' => false, 'type' => 'to' ) );
|
237 |
wp_send_json( array(
|
238 |
'success' => true,
|
239 |
'item_content' => $this->render( '_break', array(
|
240 |
+
'staff_schedule_item_break_id' => $res_schedule_break->getId(),
|
241 |
'formatted_interval' => $formatted_interval,
|
242 |
'break_start_choices' => $breakStart->render( '', $start_time, array( 'class' => 'break-start form-control' ) ),
|
243 |
'break_end_choices' => $breakEnd->render( '', $end_time, array( 'class' => 'break-end form-control' ) ),
|
252 |
public function executeDeleteStaffScheduleBreak()
|
253 |
{
|
254 |
$break = new Lib\Entities\ScheduleItemBreak();
|
255 |
+
$break->setId( $this->getParameter( 'id', 0 ) );
|
256 |
$break->delete();
|
257 |
|
258 |
wp_send_json_success();
|
263 |
$form = new Forms\StaffServices();
|
264 |
$form->bind( $this->getPostParameters() );
|
265 |
$form->save();
|
|
|
266 |
wp_send_json_success();
|
267 |
}
|
268 |
|
269 |
public function executeEditStaff()
|
270 |
{
|
|
|
|
|
271 |
$alert = array( 'error' => array() );
|
|
|
272 |
$staff = new Lib\Entities\Staff();
|
273 |
$staff->load( 1 );
|
274 |
|
275 |
+
if ( $gc_errors = Lib\Session::get( 'staff_google_auth_error' ) ) {
|
276 |
+
foreach ( (array) json_decode( $gc_errors, true ) as $error ) {
|
277 |
+
$alert['error'][] = $error;
|
278 |
+
}
|
279 |
+
Lib\Session::destroy( 'staff_google_auth_error' );
|
280 |
+
}
|
281 |
+
|
282 |
+
$google_calendars = array();
|
283 |
+
$authUrl = null;
|
284 |
+
$form = new Forms\StaffMemberEdit();
|
285 |
+
if ( $staff->getGoogleData() == '' ) {
|
286 |
if ( get_option( 'bookly_gc_client_id' ) == '' ) {
|
287 |
$authUrl = false;
|
288 |
} else {
|
292 |
} else {
|
293 |
$google = new Lib\Google();
|
294 |
if ( $google->loadByStaff( $staff ) ) {
|
295 |
+
$google_calendars = $google->getCalendarList();
|
296 |
} else {
|
297 |
foreach ( $google->getErrors() as $error ) {
|
298 |
$alert['error'][] = $error;
|
300 |
}
|
301 |
}
|
302 |
|
303 |
+
$users_for_staff = Lib\Utils\Common::isCurrentUserAdmin() ? $form->getUsersForStaff( $staff->getId() ) : array();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
304 |
|
305 |
wp_send_json_success( array(
|
306 |
+
'html' => array(
|
307 |
+
'edit' => $this->render( 'edit', compact( 'staff' ), false ),
|
308 |
+
'details' => $this->render( '_details', compact( 'staff', 'authUrl', 'google_calendars', 'users_for_staff' ), false )
|
309 |
+
),
|
310 |
'alert' => $alert,
|
311 |
) );
|
312 |
}
|
313 |
|
314 |
+
|
315 |
/**
|
316 |
* Update staff from POST request.
|
317 |
*/
|
323 |
if ( get_option( 'bookly_gen_allow_staff_edit_profile' ) ) {
|
324 |
$staff = new Lib\Entities\Staff();
|
325 |
$staff->load( $this->getParameter( 'id' ) );
|
326 |
+
if ( $staff->getWpUserId() == get_current_user_id() ) {
|
327 |
unset ( $_POST['wp_user_id'] );
|
328 |
break;
|
329 |
}
|
332 |
wp_die( 'Bookly: ' . __( 'You do not have sufficient permissions to access this page.' ) );
|
333 |
} while ( 0 );
|
334 |
}
|
335 |
+
$form = new Forms\StaffMemberEdit();
|
336 |
+
|
337 |
$form->bind( $this->getPostParameters(), $_FILES );
|
338 |
$employee = $form->save();
|
339 |
|
340 |
+
Lib\Proxy\Shared::updateStaff( $this->getPostParameters() );
|
341 |
|
342 |
if ( $employee === false && array_key_exists( 'google_calendar_error', $form->getErrors() ) ) {
|
343 |
$errors = $form->getErrors();
|
345 |
} else {
|
346 |
$wp_users = array();
|
347 |
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
348 |
+
$form = new Forms\StaffMember();
|
349 |
$wp_users = $form->getUsersForStaff();
|
350 |
}
|
351 |
|
369 |
{
|
370 |
$staff = new Lib\Entities\Staff();
|
371 |
$staff->load( 1 );
|
372 |
+
$staff->setAttachmentId( null );
|
373 |
$staff->save();
|
374 |
+
|
375 |
wp_send_json_success();
|
376 |
}
|
377 |
|
378 |
public function executeStaffHolidays()
|
379 |
{
|
380 |
+
/** @var \WP_Locale $wp_locale */
|
381 |
+
global $wp_locale;
|
382 |
+
|
383 |
+
$staff_id = 1;
|
384 |
+
$holidays = $this->getHolidays( $staff_id );
|
385 |
+
$loading_img = plugins_url( 'bookly-responsive-appointment-booking-tool/backend/resources/images/loading.gif' );
|
386 |
+
$start_of_week = (int) get_option( 'start_of_week' );
|
387 |
+
$days = array_values( $wp_locale->weekday_abbrev );
|
388 |
+
$months = array_values( $wp_locale->month );
|
389 |
+
$close = __( 'Close', 'bookly' );
|
390 |
+
$repeat = __( 'Repeat every year', 'bookly' );
|
391 |
+
$we_are_not_working = __( 'We are not working on this day', 'bookly' );
|
392 |
+
$html = $this->render( 'holidays', array(), false );
|
393 |
+
wp_send_json_success( compact( 'html', 'holidays', 'days', 'months', 'start_of_week', 'loading_img', 'we_are_not_working', 'repeat', 'close' ) );
|
394 |
}
|
395 |
|
396 |
public function executeStaffHolidaysUpdate()
|
412 |
}
|
413 |
// Add the new event.
|
414 |
} elseif ( $holiday && $day ) {
|
415 |
+
$wpdb->insert( Lib\Entities\Holiday::getTableName(), array( 'date' => $day, 'repeat_event' => (int) $repeat, 'staff_id' => 1 ), array( '%s', '%d', '%d' ) );
|
416 |
}
|
|
|
417 |
// And return refreshed events.
|
418 |
+
echo json_encode( $this->getHolidays( $staff_id ) );
|
419 |
}
|
420 |
exit;
|
421 |
}
|
438 |
}
|
439 |
}
|
440 |
|
441 |
+
return $holidays;
|
442 |
}
|
443 |
|
444 |
/**
|
450 |
protected function hasAccess( $action )
|
451 |
{
|
452 |
if ( parent::hasAccess( $action ) ) {
|
|
|
453 |
if ( ! Lib\Utils\Common::isCurrentUserAdmin() ) {
|
454 |
$staff = new Lib\Entities\Staff();
|
455 |
|
456 |
switch ( $action ) {
|
457 |
case 'executeEditStaff':
|
458 |
case 'executeDeleteStaffAvatar':
|
|
|
459 |
case 'executeStaffSchedule':
|
460 |
case 'executeStaffHolidays':
|
461 |
case 'executeUpdateStaff':
|
462 |
+
case 'executeGetStaffDetails':
|
463 |
$staff->load( $this->getParameter( 'id' ) );
|
464 |
break;
|
465 |
+
case 'executeGetStaffServices':
|
466 |
+
case 'executeGetStaffSchedule':
|
467 |
case 'executeStaffServicesUpdate':
|
468 |
case 'executeStaffHolidaysUpdate':
|
469 |
$staff->load( $this->getParameter( 'staff_id' ) );
|
470 |
break;
|
471 |
case 'executeStaffScheduleHandleBreak':
|
472 |
+
$res_schedule = new Lib\Entities\StaffScheduleItem();
|
473 |
+
$res_schedule->load( $this->getParameter( 'staff_schedule_item_id' ) );
|
474 |
+
$staff->load( $res_schedule->getStaffId() );
|
475 |
break;
|
476 |
case 'executeDeleteStaffScheduleBreak':
|
477 |
$break = new Lib\Entities\ScheduleItemBreak();
|
478 |
$break->load( $this->getParameter( 'id' ) );
|
479 |
+
$res_schedule = new Lib\Entities\StaffScheduleItem();
|
480 |
+
$res_schedule->load( $break->getStaffScheduleItemId() );
|
481 |
+
$staff->load( $res_schedule->getStaffId() );
|
482 |
break;
|
483 |
case 'executeStaffScheduleUpdate':
|
484 |
if ( $this->hasParameter( 'days' ) ) {
|
485 |
foreach ( $this->getParameter( 'days' ) as $id => $day_index ) {
|
486 |
+
$res_schedule = new Lib\Entities\StaffScheduleItem();
|
487 |
+
$res_schedule->load( $id );
|
488 |
$staff = new Lib\Entities\Staff();
|
489 |
+
$staff->load( $res_schedule->getStaffId() );
|
490 |
+
if ( $staff->getWpUserId() != get_current_user_id() ) {
|
491 |
return false;
|
492 |
}
|
493 |
}
|
497 |
return false;
|
498 |
}
|
499 |
|
500 |
+
return $staff->getWpUserId() == get_current_user_id();
|
501 |
}
|
502 |
|
503 |
return true;
|
505 |
|
506 |
return false;
|
507 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
508 |
}
|
backend/modules/staff/forms/StaffSchedule.php
CHANGED
@@ -20,17 +20,19 @@ class StaffSchedule extends Lib\Base\Form
|
|
20 |
{
|
21 |
if ( isset( $this->data['days'] ) ) {
|
22 |
foreach ( $this->data['days'] as $id => $day_index ) {
|
23 |
-
$
|
24 |
-
$
|
25 |
-
$
|
26 |
if ( $this->data['start_time'][ $day_index ] ) {
|
27 |
-
$
|
28 |
-
|
|
|
29 |
} else {
|
30 |
-
$
|
31 |
-
|
|
|
32 |
}
|
33 |
-
$
|
34 |
}
|
35 |
}
|
36 |
}
|
20 |
{
|
21 |
if ( isset( $this->data['days'] ) ) {
|
22 |
foreach ( $this->data['days'] as $id => $day_index ) {
|
23 |
+
$res_schedule = new Lib\Entities\StaffScheduleItem();
|
24 |
+
$res_schedule->load( $id );
|
25 |
+
$res_schedule->setDayIndex( $day_index );
|
26 |
if ( $this->data['start_time'][ $day_index ] ) {
|
27 |
+
$res_schedule
|
28 |
+
->setStartTime( $this->data['start_time'][ $day_index ] )
|
29 |
+
->setEndTime( $this->data['end_time'][ $day_index ] );
|
30 |
} else {
|
31 |
+
$res_schedule
|
32 |
+
->setStartTime( null )
|
33 |
+
->setEndTime( null );
|
34 |
}
|
35 |
+
$res_schedule->save();
|
36 |
}
|
37 |
}
|
38 |
}
|
backend/modules/staff/forms/StaffServices.php
CHANGED
@@ -28,7 +28,7 @@ class StaffServices extends Lib\Base\Form
|
|
28 |
|
29 |
public function configure()
|
30 |
{
|
31 |
-
$this->setFields( array( 'price', 'deposit', 'service', 'staff_id', '
|
32 |
}
|
33 |
|
34 |
public function load( $staff_id )
|
@@ -37,21 +37,26 @@ class StaffServices extends Lib\Base\Form
|
|
37 |
->select( 'c.name AS category_name, s.*' )
|
38 |
->innerJoin( 'Service', 's', 's.category_id = c.id' )
|
39 |
->sortBy( 'c.position, s.position' )
|
40 |
-
->
|
41 |
->fetchArray();
|
42 |
if ( !$data ) {
|
43 |
$data = array();
|
44 |
}
|
45 |
|
46 |
-
$this->uncategorized_services = Lib\Entities\Service::query( 's' )
|
|
|
|
|
|
|
|
|
|
|
47 |
|
48 |
$staff_services = Lib\Entities\StaffService::query( 'ss' )
|
49 |
-
->select( 'ss.service_id, ss.price, ss.deposit
|
50 |
->where( 'ss.staff_id', 1 )
|
51 |
->fetchArray();
|
52 |
if ( $staff_services ) {
|
53 |
foreach ( $staff_services as $staff_service ) {
|
54 |
-
$this->services_data[ $staff_service['service_id'] ] = array( 'price' => $staff_service['price'], 'deposit' => $staff_service['deposit'], '
|
55 |
}
|
56 |
}
|
57 |
|
@@ -70,22 +75,27 @@ class StaffServices extends Lib\Base\Form
|
|
70 |
|
71 |
public function save()
|
72 |
{
|
73 |
-
|
74 |
-
if (
|
75 |
-
|
76 |
-
|
77 |
-
$
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
|
|
|
|
|
|
|
|
|
|
83 |
}
|
84 |
}
|
85 |
}
|
86 |
|
87 |
/**
|
88 |
-
* @return Lib\Entities\Category[]
|
89 |
*/
|
90 |
public function getCategories()
|
91 |
{
|
28 |
|
29 |
public function configure()
|
30 |
{
|
31 |
+
$this->setFields( array( 'price', 'deposit', 'service', 'staff_id', 'capacity_min', 'capacity_max' ) );
|
32 |
}
|
33 |
|
34 |
public function load( $staff_id )
|
37 |
->select( 'c.name AS category_name, s.*' )
|
38 |
->innerJoin( 'Service', 's', 's.category_id = c.id' )
|
39 |
->sortBy( 'c.position, s.position' )
|
40 |
+
->whereIn( 's.type', array( Lib\Entities\Service::TYPE_SIMPLE, Lib\Entities\Service::TYPE_PACKAGE ) )
|
41 |
->fetchArray();
|
42 |
if ( !$data ) {
|
43 |
$data = array();
|
44 |
}
|
45 |
|
46 |
+
$this->uncategorized_services = Lib\Entities\Service::query( 's' )
|
47 |
+
->select( 's.*, ss.sub_service_id' )
|
48 |
+
->leftJoin( 'SubService', 'ss', 's.id = ss.service_id' )
|
49 |
+
->where( 's.category_id', null )
|
50 |
+
->whereIn( 's.type', array( Lib\Entities\Service::TYPE_SIMPLE, Lib\Entities\Service::TYPE_PACKAGE ) )
|
51 |
+
->fetchArray();
|
52 |
|
53 |
$staff_services = Lib\Entities\StaffService::query( 'ss' )
|
54 |
+
->select( 'ss.service_id, ss.price, ss.deposit' )
|
55 |
->where( 'ss.staff_id', 1 )
|
56 |
->fetchArray();
|
57 |
if ( $staff_services ) {
|
58 |
foreach ( $staff_services as $staff_service ) {
|
59 |
+
$this->services_data[ $staff_service['service_id'] ] = array( 'price' => $staff_service['price'], 'deposit' => $staff_service['deposit'], 'capacity_min' => 1, 'capacity_max' => 1 );
|
60 |
}
|
61 |
}
|
62 |
|
75 |
|
76 |
public function save()
|
77 |
{
|
78 |
+
$staff_id = $this->data['staff_id'];
|
79 |
+
if ( $staff_id ) {
|
80 |
+
Lib\Entities\StaffService::query()->delete()->where( 'staff_id', $staff_id )->execute();
|
81 |
+
if ( isset ( $this->data['service'] ) ) {
|
82 |
+
foreach ( $this->data['service'] as $service_id ) {
|
83 |
+
$staff_service = new Lib\Entities\StaffService();
|
84 |
+
$staff_service
|
85 |
+
->setCapacityMin( 1 )
|
86 |
+
->setCapacityMax( 1 )
|
87 |
+
->setDeposit( isset ( $this->data['deposit'] ) ? $this->data['deposit'][ $service_id ] : '100%' )
|
88 |
+
->setPrice( $this->data['price'][ $service_id ] )
|
89 |
+
->setServiceId( $service_id )
|
90 |
+
->setStaffId( 1 )
|
91 |
+
->save();
|
92 |
+
}
|
93 |
}
|
94 |
}
|
95 |
}
|
96 |
|
97 |
/**
|
98 |
+
* @return Lib\Entities\Category[]
|
99 |
*/
|
100 |
public function getCategories()
|
101 |
{
|
backend/modules/staff/forms/widgets/TimeChoice.php
CHANGED
@@ -34,16 +34,15 @@ class TimeChoice
|
|
34 |
}
|
35 |
|
36 |
$ts_length = Lib\Config::getTimeSlotLength();
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
} else {
|
41 |
-
$time_start = Lib\Entities\StaffScheduleItem::WORKING_START_TIME;
|
42 |
-
$time_end = Lib\Entities\StaffScheduleItem::WORKING_END_TIME;
|
43 |
-
}
|
44 |
if ( $options['type'] == 'from' ) {
|
45 |
$time_end -= $ts_length; // Exclude last slot.
|
46 |
-
}
|
|
|
|
|
|
|
47 |
$time_end *= 2; // Create slots for 2 days.
|
48 |
}
|
49 |
|
34 |
}
|
35 |
|
36 |
$ts_length = Lib\Config::getTimeSlotLength();
|
37 |
+
$time_start = 0;
|
38 |
+
$time_end = DAY_IN_SECONDS;
|
39 |
+
|
|
|
|
|
|
|
|
|
40 |
if ( $options['type'] == 'from' ) {
|
41 |
$time_end -= $ts_length; // Exclude last slot.
|
42 |
+
} else if ( $options['type'] == 'break_from' ) {
|
43 |
+
$time_end *= 2; // Create slots for 2 days.
|
44 |
+
$time_end -= $ts_length; // Exclude last slot.
|
45 |
+
} else if ( $options['type'] == 'to' ) {
|
46 |
$time_end *= 2; // Create slots for 2 days.
|
47 |
}
|
48 |
|
backend/modules/staff/resources/js/staff-days-off.js
ADDED
@@ -0,0 +1,52 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
var DaysOff = function($container, options) {
|
4 |
+
var obj = this;
|
5 |
+
jQuery.extend(obj.options, options);
|
6 |
+
|
7 |
+
if (!$container.children().length) {
|
8 |
+
$container.html('<div class="bookly-loading"></div>');
|
9 |
+
$.ajax({
|
10 |
+
url : ajaxurl,
|
11 |
+
data : {action: 'bookly_staff_holidays', id: obj.options.staff_id, csrf_token : obj.options.csrf_token},
|
12 |
+
xhrFields : { withCredentials: true },
|
13 |
+
crossDomain : 'withCredentials' in new XMLHttpRequest(),
|
14 |
+
success : function (response) {
|
15 |
+
$container.html(response.data.html);
|
16 |
+
var d = new Date();
|
17 |
+
$('.bookly-js-holidays').jCal({
|
18 |
+
day: new Date(d.getFullYear(), 0, 1),
|
19 |
+
days: 1,
|
20 |
+
showMonths: 12,
|
21 |
+
scrollSpeed: 350,
|
22 |
+
events: response.data.holidays,
|
23 |
+
action: 'bookly_staff_holidays_update',
|
24 |
+
csrf_token: obj.options.csrf_token,
|
25 |
+
staff_id: obj.options.staff_id,
|
26 |
+
dayOffset: response.data.start_of_week,
|
27 |
+
loadingImg: response.data.loading_img,
|
28 |
+
dow: response.data.days,
|
29 |
+
ml: response.data.months,
|
30 |
+
we_are_not_working: response.data.we_are_not_working,
|
31 |
+
repeat: response.data.repeat,
|
32 |
+
close: response.data.close
|
33 |
+
});
|
34 |
+
|
35 |
+
$('.bookly-js-jCalBtn', $container).on('click', function (e) {
|
36 |
+
e.preventDefault();
|
37 |
+
var trigger = $(this).data('trigger');
|
38 |
+
$('.bookly-js-holidays',$container).find($(trigger)).trigger('click');
|
39 |
+
})
|
40 |
+
}
|
41 |
+
});
|
42 |
+
}
|
43 |
+
};
|
44 |
+
|
45 |
+
DaysOff.prototype.options = {
|
46 |
+
staff_id : -1,
|
47 |
+
csrf_token: '',
|
48 |
+
l10n: {}
|
49 |
+
};
|
50 |
+
|
51 |
+
window.BooklyStaffDaysOff = DaysOff;
|
52 |
+
});
|
backend/modules/staff/resources/js/staff-details.js
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
var Details = function($container, options) {
|
4 |
+
var obj = this;
|
5 |
+
jQuery.extend(obj.options, options);
|
6 |
+
|
7 |
+
if (Object.keys(obj.options.get_details).length === 0) {
|
8 |
+
// backend united edit & details in one request.
|
9 |
+
initDetails($container);
|
10 |
+
} else {
|
11 |
+
// get details content.
|
12 |
+
$container.html('<div class="bookly-loading"></div>');
|
13 |
+
$.ajax({
|
14 |
+
url : ajaxurl,
|
15 |
+
data : obj.options.get_details,
|
16 |
+
dataType : 'json',
|
17 |
+
xhrFields : { withCredentials: true },
|
18 |
+
crossDomain : 'withCredentials' in new XMLHttpRequest(),
|
19 |
+
success : function (response) {
|
20 |
+
$container.html(response.data.html);
|
21 |
+
initDetails($container);
|
22 |
+
}
|
23 |
+
});
|
24 |
+
}
|
25 |
+
|
26 |
+
function initDetails($container) {
|
27 |
+
var $staff_full_name = $('#bookly-full-name', $container),
|
28 |
+
$staff_wp_user = $('#bookly-wp-user', $container),
|
29 |
+
$staff_email = $('#bookly-email', $container),
|
30 |
+
$staff_phone = $('#bookly-phone', $container),
|
31 |
+
$location_row = $('.locations-row', $container)
|
32 |
+
;
|
33 |
+
|
34 |
+
if (obj.options.intlTelInput.enabled) {
|
35 |
+
$staff_phone.intlTelInput({
|
36 |
+
preferredCountries: [obj.options.intlTelInput.country],
|
37 |
+
initialCountry: obj.options.intlTelInput.country,
|
38 |
+
geoIpLookup: function (callback) {
|
39 |
+
$.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
40 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
41 |
+
callback(countryCode);
|
42 |
+
});
|
43 |
+
},
|
44 |
+
utilsScript: obj.options.intlTelInput.utils
|
45 |
+
});
|
46 |
+
}
|
47 |
+
|
48 |
+
$staff_wp_user.on('change', function () {
|
49 |
+
if (this.value) {
|
50 |
+
$staff_full_name.val($staff_wp_user.find(':selected').text());
|
51 |
+
$staff_email.val($staff_wp_user.find(':selected').data('email'));
|
52 |
+
}
|
53 |
+
});
|
54 |
+
|
55 |
+
$('input.bookly-js-all-locations, input.bookly-location', $container).on('change', function () {
|
56 |
+
if ($(this).hasClass('bookly-js-all-locations')) {
|
57 |
+
$location_row.find('.bookly-location').prop('checked', $(this).prop('checked'));
|
58 |
+
} else {
|
59 |
+
$location_row.find('.bookly-js-all-locations').prop('checked', $location_row.find('.bookly-location:not(:checked)').length == 0);
|
60 |
+
}
|
61 |
+
updateLocationsButton();
|
62 |
+
});
|
63 |
+
|
64 |
+
$('button:reset', $container).on('click', function () {
|
65 |
+
setTimeout(updateLocationsButton, 0);
|
66 |
+
});
|
67 |
+
|
68 |
+
function updateLocationsButton() {
|
69 |
+
var locations_checked = $location_row.find('.bookly-location:checked').length;
|
70 |
+
if (locations_checked == 0) {
|
71 |
+
$location_row.find('.bookly-locations-count').text(obj.options.l10n.selector.nothing_selected);
|
72 |
+
} else if (locations_checked == 1) {
|
73 |
+
$location_row.find('.bookly-locations-count').text($location_row.find('.bookly-location:checked').data('location_name'));
|
74 |
+
} else {
|
75 |
+
if (locations_checked == $location_row.find('.bookly-location').length) {
|
76 |
+
$location_row.find('.bookly-locations-count').text(obj.options.l10n.selector.all_selected);
|
77 |
+
} else {
|
78 |
+
$location_row.find('.bookly-locations-count').text(locations_checked + '/' + $location_row.find('.bookly-location').length);
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
|
83 |
+
updateLocationsButton();
|
84 |
+
|
85 |
+
// Save staff member details.
|
86 |
+
$('#bookly-details-save', $container).on('click',function(e){
|
87 |
+
e.preventDefault();
|
88 |
+
var $form = $(this).closest('form'),
|
89 |
+
data = $form.serializeArray(),
|
90 |
+
ladda = Ladda.create(this),
|
91 |
+
$staff_phone = $('#bookly-phone',$form),
|
92 |
+
phone;
|
93 |
+
try {
|
94 |
+
phone = BooklyL10n.intlTelInput.enabled ? $staff_phone.intlTelInput('getNumber') : $staff_phone.val();
|
95 |
+
if (phone == '') {
|
96 |
+
phone = $staff_phone.val();
|
97 |
+
}
|
98 |
+
} catch (error) { // In case when intlTelInput can't return phone number.
|
99 |
+
phone = $staff_phone.val();
|
100 |
+
}
|
101 |
+
data.push({name: 'action', value: 'bookly_update_staff'});
|
102 |
+
data.push({name: 'phone', value: phone});
|
103 |
+
ladda.start();
|
104 |
+
|
105 |
+
$.ajax({
|
106 |
+
type: 'POST',
|
107 |
+
url: ajaxurl,
|
108 |
+
data: data,
|
109 |
+
dataType: 'json',
|
110 |
+
xhrFields: {withCredentials: true},
|
111 |
+
crossDomain: 'withCredentials' in new XMLHttpRequest(),
|
112 |
+
success: function (response) {
|
113 |
+
if (response.success) {
|
114 |
+
obj.options.booklyAlert({success: [obj.options.l10n.saved]});
|
115 |
+
$('[bookly-js-staff-name-' + obj.options.get_details.id + ']').text($('#bookly-full-name', $form).val());
|
116 |
+
if (typeof obj.options.renderWpUsers === 'function') {
|
117 |
+
obj.options.renderWpUsers(response.data.wp_users);
|
118 |
+
}
|
119 |
+
} else {
|
120 |
+
obj.options.booklyAlert({error: [response.data.error]});
|
121 |
+
}
|
122 |
+
ladda.stop();
|
123 |
+
}
|
124 |
+
});
|
125 |
+
});
|
126 |
+
}
|
127 |
+
|
128 |
+
};
|
129 |
+
|
130 |
+
Details.prototype.options = {
|
131 |
+
intlTelInput: {},
|
132 |
+
get_details : {
|
133 |
+
action: 'bookly_get_staff_details',
|
134 |
+
id : -1,
|
135 |
+
csrf_token: ''
|
136 |
+
},
|
137 |
+
l10n : {},
|
138 |
+
booklyAlert : window.booklyAlert
|
139 |
+
};
|
140 |
+
|
141 |
+
window.BooklyStaffDetails = Details;
|
142 |
+
});
|
backend/modules/staff/resources/js/staff-schedule.js
ADDED
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
var Schedule = function ($container, options) {
|
3 |
+
var obj = this;
|
4 |
+
jQuery.extend(obj.options, options);
|
5 |
+
|
6 |
+
// Loads schedule list
|
7 |
+
if (!$container.children().length) {
|
8 |
+
$container.html('<div class="bookly-loading"></div>');
|
9 |
+
$.ajax({
|
10 |
+
type: 'POST',
|
11 |
+
url: ajaxurl,
|
12 |
+
data: obj.options.get_staff_schedule,
|
13 |
+
dataType: 'json',
|
14 |
+
xhrFields: {withCredentials: true},
|
15 |
+
crossDomain: 'withCredentials' in new XMLHttpRequest(),
|
16 |
+
success: function (response) {
|
17 |
+
// fill in the container
|
18 |
+
$container.html(response.data.html);
|
19 |
+
|
20 |
+
|
21 |
+
// init 'add break' functionality
|
22 |
+
$('.bookly-js-toggle-popover:not(.break-interval)', $container).popover({
|
23 |
+
html: true,
|
24 |
+
placement: 'bottom',
|
25 |
+
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
26 |
+
trigger: 'manual',
|
27 |
+
content: function () {
|
28 |
+
return $($(this).data('popover-content')).html()
|
29 |
+
}
|
30 |
+
}).on('click', function () {
|
31 |
+
$(this).popover('toggle');
|
32 |
+
|
33 |
+
var $popover = $(this).next('.popover'),
|
34 |
+
working_start = $popover.closest('.row').find('.working-schedule-start').val(),
|
35 |
+
$break_start = $popover.find('.break-start'),
|
36 |
+
$break_end = $popover.find('.break-end'),
|
37 |
+
working_start_time = working_start.split(':'),
|
38 |
+
working_start_hours = parseInt(working_start_time[0], 10),
|
39 |
+
break_start_hours = working_start_hours + 1;
|
40 |
+
if (break_start_hours < 10) {
|
41 |
+
break_start_hours = '0' + break_start_hours;
|
42 |
+
}
|
43 |
+
var break_end_hours = working_start_hours + 2;
|
44 |
+
if (break_end_hours < 10) {
|
45 |
+
break_end_hours = '0' + break_end_hours;
|
46 |
+
}
|
47 |
+
var break_end_hours_str = break_end_hours + ':' + working_start_time[1] + ':' + working_start_time[2],
|
48 |
+
break_start_hours_str = break_start_hours + ':' + working_start_time[1] + ':' + working_start_time[2];
|
49 |
+
|
50 |
+
$break_start.val(break_start_hours_str);
|
51 |
+
$break_end.val(break_end_hours_str);
|
52 |
+
|
53 |
+
hideInaccessibleBreaks($break_start, $break_end);
|
54 |
+
|
55 |
+
$popover.find('.bookly-popover-close').on('click', function () {
|
56 |
+
$popover.popover('hide');
|
57 |
+
});
|
58 |
+
});
|
59 |
+
|
60 |
+
$container
|
61 |
+
// Save Schedule
|
62 |
+
.on('click', '#bookly-schedule-save', function (e) {
|
63 |
+
e.preventDefault();
|
64 |
+
var ladda = Ladda.create(this);
|
65 |
+
ladda.start();
|
66 |
+
var data = {};
|
67 |
+
$('select.working-schedule-start, select.working-schedule-end, input:hidden', $container).each(function () {
|
68 |
+
data[this.name] = this.value;
|
69 |
+
});
|
70 |
+
$.post(ajaxurl, $.param(data), function () {
|
71 |
+
ladda.stop();
|
72 |
+
obj.options.booklyAlert({success: [obj.options.l10n.saved]});
|
73 |
+
});
|
74 |
+
})
|
75 |
+
// Resets initial schedule values
|
76 |
+
.on('click', '#bookly-schedule-reset', function (e) {
|
77 |
+
e.preventDefault();
|
78 |
+
var ladda = Ladda.create(this);
|
79 |
+
ladda.start();
|
80 |
+
|
81 |
+
$('.working-schedule-start', $container).each(function () {
|
82 |
+
$(this).val($(this).data('default_value'));
|
83 |
+
$(this).trigger('change');
|
84 |
+
});
|
85 |
+
|
86 |
+
$('.working-schedule-end', $container).each(function () {
|
87 |
+
$(this).val($(this).data('default_value'));
|
88 |
+
});
|
89 |
+
|
90 |
+
// reset breaks
|
91 |
+
$.ajax({
|
92 |
+
url: ajaxurl,
|
93 |
+
type: 'POST',
|
94 |
+
data: {action: 'bookly_reset_breaks', breaks: $(this).data('default-breaks'), csrf_token: obj.options.l10n.csrf_token},
|
95 |
+
dataType: 'json',
|
96 |
+
success: function (response) {
|
97 |
+
for (var k in response) {
|
98 |
+
var $content = $(response[k]);
|
99 |
+
$('[data-staff_schedule_item_id=' + k + '] .breaks', $container).html($content);
|
100 |
+
$content.find('.bookly-intervals-wrapper .delete-break').on('click', function () {
|
101 |
+
deleteBreak.call(this);
|
102 |
+
});
|
103 |
+
}
|
104 |
+
},
|
105 |
+
complete: function () {
|
106 |
+
ladda.stop();
|
107 |
+
}
|
108 |
+
});
|
109 |
+
})
|
110 |
+
|
111 |
+
.on('click', '.break-interval', function () {
|
112 |
+
var $button = $(this);
|
113 |
+
$('.popover').popover('hide');
|
114 |
+
var break_id = $button.closest('.bookly-intervals-wrapper').data('break_id');
|
115 |
+
$(this).popover({
|
116 |
+
html: true,
|
117 |
+
placement: 'bottom',
|
118 |
+
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
119 |
+
content: function () {
|
120 |
+
return $('.bookly-js-content-break-' + break_id).html();
|
121 |
+
},
|
122 |
+
trigger: 'manual'
|
123 |
+
});
|
124 |
+
|
125 |
+
$(this).popover('toggle');
|
126 |
+
|
127 |
+
var $popover = $(this).next('.popover'),
|
128 |
+
$break_start = $popover.find('.break-start'),
|
129 |
+
$break_end = $popover.find('.break-end');
|
130 |
+
|
131 |
+
if ($button.hasClass('break-interval')) {
|
132 |
+
var interval = $button.html().trim().split(' - ');
|
133 |
+
rangeTools.setVal($break_start, interval[0]);
|
134 |
+
rangeTools.setVal($break_end, interval[1]);
|
135 |
+
}
|
136 |
+
|
137 |
+
hideInaccessibleBreaks($break_start, $break_end, true);
|
138 |
+
|
139 |
+
$popover.find('.bookly-popover-close').on('click', function () {
|
140 |
+
$popover.popover('hide');
|
141 |
+
});
|
142 |
+
})
|
143 |
+
|
144 |
+
.on('click', '.bookly-js-save-break', function (e) {
|
145 |
+
var $table = $(this).closest('.bookly-js-schedule-form'),
|
146 |
+
$row = $table.parents('.staff-schedule-item-row').first(),
|
147 |
+
$data = {
|
148 |
+
action: 'bookly_staff_schedule_handle_break',
|
149 |
+
staff_schedule_item_id: $row.data('staff_schedule_item_id'),
|
150 |
+
start_time: $table.find('.break-start > option:selected').val(),
|
151 |
+
end_time: $table.find('.break-end > option:selected').val(),
|
152 |
+
working_end: $row.find('.working-schedule-end > option:selected').val(),
|
153 |
+
working_start: $row.find('.working-schedule-start > option:selected').val(),
|
154 |
+
csrf_token: obj.options.l10n.csrf_token
|
155 |
+
},
|
156 |
+
$break_interval_wrapper = $table.parents('.bookly-intervals-wrapper').first(),
|
157 |
+
ladda = Ladda.create(e.currentTarget);
|
158 |
+
ladda.start();
|
159 |
+
|
160 |
+
if ($break_interval_wrapper.data('break_id')) {
|
161 |
+
$data['break_id'] = $break_interval_wrapper.data('break_id');
|
162 |
+
}
|
163 |
+
$.ajax({
|
164 |
+
url: ajaxurl,
|
165 |
+
type: 'POST',
|
166 |
+
data: $data,
|
167 |
+
dataType: 'json',
|
168 |
+
success: function (response) {
|
169 |
+
if (response.success) {
|
170 |
+
if (response['item_content']) {
|
171 |
+
var $new_break_interval_item = $(response['item_content']);
|
172 |
+
$new_break_interval_item
|
173 |
+
.hide()
|
174 |
+
.appendTo($row.find('.breaks-list-content'))
|
175 |
+
.fadeIn('slow');
|
176 |
+
} else if (response.data.interval) {
|
177 |
+
$break_interval_wrapper
|
178 |
+
.find('.break-interval')
|
179 |
+
.text(response.data.interval);
|
180 |
+
}
|
181 |
+
$('.popover').popover('hide');
|
182 |
+
} else {
|
183 |
+
obj.options.booklyAlert({error: [response.data.message]});
|
184 |
+
}
|
185 |
+
},
|
186 |
+
complete: function () {
|
187 |
+
ladda.stop();
|
188 |
+
}
|
189 |
+
});
|
190 |
+
|
191 |
+
return false;
|
192 |
+
})
|
193 |
+
|
194 |
+
.on('click', '.bookly-intervals-wrapper .delete-break', function () {
|
195 |
+
deleteBreak.call(this);
|
196 |
+
})
|
197 |
+
|
198 |
+
.on('change', '.break-start', function () {
|
199 |
+
var $start = $(this);
|
200 |
+
var $end = $start.parents('.bookly-flexbox').find('.break-end');
|
201 |
+
hideInaccessibleBreaks($start, $end);
|
202 |
+
})
|
203 |
+
|
204 |
+
.on('change', '.working-schedule-start', function () {
|
205 |
+
var $this = $(this),
|
206 |
+
$end_select = $this.closest('.bookly-flexbox').find('.working-schedule-end'),
|
207 |
+
start_time = $this.val();
|
208 |
+
|
209 |
+
// Hide end time options to keep them within 24 hours after start time.
|
210 |
+
var parts = start_time.split(':');
|
211 |
+
parts[0] = parseInt(parts[0]) + 24;
|
212 |
+
var end_time = parts.join(':');
|
213 |
+
var frag = document.createDocumentFragment();
|
214 |
+
var old_value = $end_select.val();
|
215 |
+
var new_value = null;
|
216 |
+
$('option', $end_select).each(function () {
|
217 |
+
if (this.value <= start_time || this.value > end_time) {
|
218 |
+
var span = document.createElement('span');
|
219 |
+
span.style.display = 'none';
|
220 |
+
span.appendChild(this.cloneNode(true));
|
221 |
+
frag.appendChild(span);
|
222 |
+
} else {
|
223 |
+
frag.appendChild(this.cloneNode(true));
|
224 |
+
if (new_value === null || old_value == this.value) {
|
225 |
+
new_value = this.value;
|
226 |
+
}
|
227 |
+
}
|
228 |
+
});
|
229 |
+
$end_select.empty().append(frag).val(new_value);
|
230 |
+
|
231 |
+
// when the working day is disabled (working start time is set to 'OFF')
|
232 |
+
// hide all the elements inside the row
|
233 |
+
if (!$this.val()) {
|
234 |
+
$this.closest('.row').find('.bookly-hide-on-off').hide();
|
235 |
+
} else {
|
236 |
+
$this.closest('.row').find('.bookly-hide-on-off').show();
|
237 |
+
}
|
238 |
+
});
|
239 |
+
$('.working-schedule-start', $container).trigger('change');
|
240 |
+
$('.break-start', $container).trigger('change');
|
241 |
+
}
|
242 |
+
});
|
243 |
+
}
|
244 |
+
|
245 |
+
function hideInaccessibleBreaks($start, $end, force_keep_values) {
|
246 |
+
var $row = $start.closest('.row'),
|
247 |
+
$working_start = $row.find('.working-schedule-start'),
|
248 |
+
$working_end = $row.find('.working-schedule-end'),
|
249 |
+
frag1 = document.createDocumentFragment(),
|
250 |
+
frag2 = document.createDocumentFragment(),
|
251 |
+
old_value = $start.val(),
|
252 |
+
new_value = null;
|
253 |
+
|
254 |
+
$('option', $start).each(function () {
|
255 |
+
if ((this.value < $working_start.val() || this.value >= $working_end.val()) && (!force_keep_values || this.value != old_value)) {
|
256 |
+
var span = document.createElement('span');
|
257 |
+
span.style.display = 'none';
|
258 |
+
span.appendChild(this.cloneNode(true));
|
259 |
+
frag1.appendChild(span);
|
260 |
+
} else {
|
261 |
+
frag1.appendChild(this.cloneNode(true));
|
262 |
+
if (new_value === null || old_value == this.value) {
|
263 |
+
new_value = this.value;
|
264 |
+
}
|
265 |
+
}
|
266 |
+
});
|
267 |
+
$start.empty().append(frag1).val(new_value);
|
268 |
+
|
269 |
+
// Hide end time options with value less than in the start time.
|
270 |
+
old_value = $end.val();
|
271 |
+
new_value = null;
|
272 |
+
$('option', $end).each(function () {
|
273 |
+
if ((this.value <= $start.val() || this.value > $working_end.val()) && (!force_keep_values || this.value != old_value)) {
|
274 |
+
var span = document.createElement('span');
|
275 |
+
span.style.display = 'none';
|
276 |
+
span.appendChild(this.cloneNode(true));
|
277 |
+
frag2.appendChild(span);
|
278 |
+
} else {
|
279 |
+
frag2.appendChild(this.cloneNode(true));
|
280 |
+
if (new_value === null || old_value == this.value) {
|
281 |
+
new_value = this.value;
|
282 |
+
}
|
283 |
+
}
|
284 |
+
});
|
285 |
+
$end.empty().append(frag2).val(new_value);
|
286 |
+
}
|
287 |
+
|
288 |
+
function deleteBreak() {
|
289 |
+
var $break_interval_wrapper = $(this).closest('.bookly-intervals-wrapper');
|
290 |
+
if (confirm(obj.options.l10n.are_you_sure)) {
|
291 |
+
var ladda = Ladda.create(this);
|
292 |
+
ladda.start();
|
293 |
+
$.ajax({
|
294 |
+
url: ajaxurl,
|
295 |
+
type: 'POST',
|
296 |
+
data: {action: 'bookly_delete_staff_schedule_break', id: $break_interval_wrapper.data('break_id'), csrf_token: obj.options.l10n.csrf_token},
|
297 |
+
success: function (response) {
|
298 |
+
if (response.success) {
|
299 |
+
$break_interval_wrapper.remove();
|
300 |
+
}
|
301 |
+
},
|
302 |
+
complete: function () {
|
303 |
+
ladda.stop();
|
304 |
+
}
|
305 |
+
});
|
306 |
+
}
|
307 |
+
}
|
308 |
+
};
|
309 |
+
|
310 |
+
Schedule.prototype.options = {
|
311 |
+
get_staff_schedule: {
|
312 |
+
action: 'bookly_get_staff_schedule',
|
313 |
+
staff_id: -1,
|
314 |
+
csrf_token: ''
|
315 |
+
},
|
316 |
+
booklyAlert: window.booklyAlert,
|
317 |
+
l10n: {}
|
318 |
+
};
|
319 |
+
|
320 |
+
window.BooklyStaffSchedule = Schedule;
|
321 |
+
});
|
322 |
+
|
backend/modules/staff/resources/js/staff-services.js
ADDED
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
var Services = function($container, options) {
|
4 |
+
var obj = this;
|
5 |
+
jQuery.extend(obj.options, options);
|
6 |
+
|
7 |
+
// Load services form
|
8 |
+
if (!$container.children().length) {
|
9 |
+
$container.html('<div class="bookly-loading"></div>');
|
10 |
+
$.ajax({
|
11 |
+
type : 'POST',
|
12 |
+
url : ajaxurl,
|
13 |
+
data : obj.options.get_staff_services,
|
14 |
+
dataType : 'json',
|
15 |
+
xhrFields : { withCredentials: true },
|
16 |
+
crossDomain : 'withCredentials' in new XMLHttpRequest(),
|
17 |
+
success : function (response) {
|
18 |
+
$container.html(response.data.html);
|
19 |
+
var $services_form = $('form', $container);
|
20 |
+
$(document.body).trigger('special_hours.tab_init', [$container, obj.options.get_staff_services.staff_id, obj.options.booklyAlert]);
|
21 |
+
var autoTickCheckboxes = function () {
|
22 |
+
// Handle 'select category' checkbox.
|
23 |
+
$('.bookly-services-category .bookly-category-checkbox').each(function () {
|
24 |
+
$(this).prop(
|
25 |
+
'checked',
|
26 |
+
$('.bookly-category-services .bookly-service-checkbox.bookly-category-' + $(this).data('category-id') + ':not(:checked)').length == 0
|
27 |
+
);
|
28 |
+
});
|
29 |
+
// Handle 'select all services' checkbox.
|
30 |
+
$('#bookly-check-all-entities').prop(
|
31 |
+
'checked',
|
32 |
+
$('.bookly-service-checkbox:not(:checked)').length == 0
|
33 |
+
);
|
34 |
+
};
|
35 |
+
var checkCapacityError = function ($form_group) {
|
36 |
+
if (parseInt($form_group.find('.bookly-js-capacity-min').val()) > 1) {
|
37 |
+
$form_group.find('.bookly-js-capacity-min').val(1).prop('readonly', true);
|
38 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
39 |
+
}
|
40 |
+
if (parseInt($form_group.find('.bookly-js-capacity-max').val()) > 1) {
|
41 |
+
$form_group.find('.bookly-js-capacity-max').val(1).prop('readonly', true);
|
42 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
43 |
+
}
|
44 |
+
};
|
45 |
+
|
46 |
+
$services_form
|
47 |
+
// Select all services related to chosen category
|
48 |
+
.on('click', '.bookly-category-checkbox', function () {
|
49 |
+
$('.bookly-category-services .bookly-category-' + $(this).data('category-id')).prop('checked', $(this).is(':checked')).change();
|
50 |
+
autoTickCheckboxes();
|
51 |
+
})
|
52 |
+
// Check and uncheck all services
|
53 |
+
.on('click', '#bookly-check-all-entities', function () {
|
54 |
+
$('.bookly-service-checkbox', $services_form).prop('checked', $(this).is(':checked')).change();
|
55 |
+
$('.bookly-category-checkbox').prop('checked', $(this).is(':checked'));
|
56 |
+
})
|
57 |
+
// Select service
|
58 |
+
.on('click', '.bookly-service-checkbox', function () {
|
59 |
+
autoTickCheckboxes();
|
60 |
+
})
|
61 |
+
// Save services
|
62 |
+
.on('click', '#bookly-services-save', function (e) {
|
63 |
+
e.preventDefault();
|
64 |
+
var ladda = Ladda.create(this);
|
65 |
+
ladda.start();
|
66 |
+
$.ajax({
|
67 |
+
type : 'POST',
|
68 |
+
url : ajaxurl,
|
69 |
+
data : $services_form.serialize(),
|
70 |
+
dataType : 'json',
|
71 |
+
xhrFields : {withCredentials: true},
|
72 |
+
crossDomain: 'withCredentials' in new XMLHttpRequest(),
|
73 |
+
success : function (response) {
|
74 |
+
ladda.stop();
|
75 |
+
if (response.success) {
|
76 |
+
obj.options.booklyAlert({success: [obj.options.l10n.saved]});
|
77 |
+
}
|
78 |
+
}
|
79 |
+
});
|
80 |
+
})
|
81 |
+
// After reset auto tick group checkboxes.
|
82 |
+
.on('click', '#bookly-services-reset', function () {
|
83 |
+
setTimeout(function () {
|
84 |
+
autoTickCheckboxes();
|
85 |
+
$('.bookly-js-capacity-form-group', $services_form).each(function () {
|
86 |
+
checkCapacityError($(this));
|
87 |
+
});
|
88 |
+
$('.bookly-service-checkbox', $services_form).trigger('change');
|
89 |
+
}, 0);
|
90 |
+
});
|
91 |
+
|
92 |
+
$('.bookly-service-checkbox').on('change', function () {
|
93 |
+
var $this = $(this),
|
94 |
+
$service = $this.closest('li'),
|
95 |
+
$inputs = $service.find('input:not(:checkbox)');
|
96 |
+
|
97 |
+
$inputs.attr('disabled', !$this.is(':checked'));
|
98 |
+
|
99 |
+
// Handle package-service connections
|
100 |
+
if ($(this).is(':checked') && $service.data('service-type') == 'package') {
|
101 |
+
$('li[data-service-type="simple"][data-service-id="' + $service.data('sub-service') + '"] .bookly-service-checkbox', $services_form).prop('checked', true).trigger('change');
|
102 |
+
$('.bookly-js-capacity-min', $service).val($('li[data-service-type="simple"][data-service-id="' + $service.data('sub-service') + '"] .bookly-js-capacity-min', $services_form).val());
|
103 |
+
$('.bookly-js-capacity-max', $service).val($('li[data-service-type="simple"][data-service-id="' + $service.data('sub-service') + '"] .bookly-js-capacity-max', $services_form).val());
|
104 |
+
}
|
105 |
+
if (!$(this).is(':checked') && $service.data('service-type') == 'simple') {
|
106 |
+
$('li[data-service-type="package"][data-sub-service="' + $service.data('service-id') + '"] .bookly-service-checkbox', $services_form).prop('checked', false).trigger('change');
|
107 |
+
}
|
108 |
+
});
|
109 |
+
|
110 |
+
$('.bookly-js-capacity').on('keyup change', function () {
|
111 |
+
var $service = $(this).closest('li');
|
112 |
+
if ($service.data('service-type') == 'simple') {
|
113 |
+
if ($(this).hasClass('bookly-js-capacity-min')) {
|
114 |
+
$('li[data-service-type="package"][data-sub-service="' + $service.data('service-id') + '"] .bookly-js-capacity-min', $services_form).val($(this).val());
|
115 |
+
} else {
|
116 |
+
$('li[data-service-type="package"][data-sub-service="' + $service.data('service-id') + '"] .bookly-js-capacity-max', $services_form).val($(this).val());
|
117 |
+
}
|
118 |
+
}
|
119 |
+
checkCapacityError($(this).closest('.form-group'));
|
120 |
+
});
|
121 |
+
autoTickCheckboxes();
|
122 |
+
}
|
123 |
+
});
|
124 |
+
}
|
125 |
+
|
126 |
+
};
|
127 |
+
|
128 |
+
Services.prototype.options = {
|
129 |
+
get_staff_services: {
|
130 |
+
action : 'bookly_get_staff_services',
|
131 |
+
staff_id: -1,
|
132 |
+
csrf_token: ''
|
133 |
+
},
|
134 |
+
booklyAlert: window.booklyAlert,
|
135 |
+
l10n: {}
|
136 |
+
};
|
137 |
+
|
138 |
+
window.BooklyStaffServices = Services;
|
139 |
+
});
|
backend/modules/staff/resources/js/staff.js
CHANGED
@@ -3,39 +3,12 @@ jQuery(function($) {
|
|
3 |
$new_form = $('#bookly-new-staff'),
|
4 |
$wp_user_select = $('#bookly-new-staff-wpuser'),
|
5 |
$name_input = $('#bookly-new-staff-fullname'),
|
6 |
-
$edit_form = $('#bookly-container-edit-staff')
|
7 |
-
|
8 |
function saveNewForm() {
|
9 |
booklyAlert({error: [BooklyL10n.limitations]});
|
10 |
}
|
11 |
|
12 |
-
$edit_form.on('click', '.bookly-pretty-indicator', function (e) {
|
13 |
-
e.preventDefault();
|
14 |
-
e.stopPropagation();
|
15 |
-
var frame = wp.media({
|
16 |
-
library: {type: 'image'},
|
17 |
-
multiple: false
|
18 |
-
});
|
19 |
-
frame.on('select', function () {
|
20 |
-
var selection = frame.state().get('selection').toJSON(),
|
21 |
-
img_src
|
22 |
-
;
|
23 |
-
if (selection.length) {
|
24 |
-
if (selection[0].sizes['thumbnail'] !== undefined) {
|
25 |
-
img_src = selection[0].sizes['thumbnail'].url;
|
26 |
-
} else {
|
27 |
-
img_src = selection[0].url;
|
28 |
-
}
|
29 |
-
$edit_form.find('[name=attachment_id]').val(selection[0].id);
|
30 |
-
$('#bookly-js-staff-avatar').find('.bookly-js-image').css({'background-image': 'url(' + img_src + ')', 'background-size': 'cover'});
|
31 |
-
$('.bookly-thumb-delete').show();
|
32 |
-
$(this).hide();
|
33 |
-
}
|
34 |
-
});
|
35 |
-
|
36 |
-
frame.open();
|
37 |
-
});
|
38 |
-
|
39 |
// Save new staff on enter press
|
40 |
$name_input.on('keypress', function (e) {
|
41 |
var code = (e.keyCode ? e.keyCode : e.which);
|
@@ -48,7 +21,7 @@ jQuery(function($) {
|
|
48 |
$new_form.on('keypress', function (e) {
|
49 |
var code = (e.keyCode ? e.keyCode : e.which);
|
50 |
if (code == 27) {
|
51 |
-
$('#
|
52 |
}
|
53 |
});
|
54 |
|
@@ -56,6 +29,33 @@ jQuery(function($) {
|
|
56 |
e.stopPropagation();
|
57 |
});
|
58 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
/**
|
60 |
* Load staff profile on click on staff in the list.
|
61 |
*/
|
@@ -65,516 +65,110 @@ jQuery(function($) {
|
|
65 |
$staff_list.find('.active').removeClass('active');
|
66 |
$this.addClass('active');
|
67 |
|
68 |
-
var staff_id = $this.data('staff-id');
|
69 |
var active_tab_id = $('.nav .active a').attr('id');
|
70 |
$edit_form.html('<div class="bookly-loading"></div>');
|
71 |
-
$.get(ajaxurl, {
|
72 |
-
$edit_form.html(response.data.html);
|
73 |
booklyAlert(response.data.alert);
|
74 |
-
var $
|
75 |
-
$
|
76 |
-
$services_container = $('#bookly-services-container'),
|
77 |
-
$schedule_container = $('#bookly-schedule-container'),
|
78 |
-
$holidays_container = $('#bookly-holidays-container')
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
callback(countryCode);
|
96 |
-
});
|
97 |
-
},
|
98 |
-
utilsScript: BooklyL10n.intlTelInput.utils
|
99 |
-
});
|
100 |
-
}
|
101 |
-
|
102 |
-
// Delete staff member.
|
103 |
-
$delete_staff_button.on('click', function (e) {
|
104 |
-
e.preventDefault();
|
105 |
-
if (confirm(BooklyL10n.are_you_sure)) {
|
106 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
107 |
}
|
108 |
});
|
109 |
|
110 |
-
//
|
111 |
-
$
|
112 |
-
|
113 |
-
var $form = $(this).closest('form'),
|
114 |
-
data = $form.serializeArray(),
|
115 |
-
ladda = Ladda.create(this),
|
116 |
-
phone;
|
117 |
-
try {
|
118 |
-
phone = BooklyL10n.intlTelInput.enabled ? $staff_phone.intlTelInput('getNumber') : $staff_phone.val();
|
119 |
-
if (phone == '') {
|
120 |
-
phone = $staff_phone.val();
|
121 |
-
}
|
122 |
-
} catch (error) { // In case when intlTelInput can't return phone number.
|
123 |
-
phone = $staff_phone.val();
|
124 |
-
}
|
125 |
-
data.push({name: 'action', value: 'bookly_update_staff'});
|
126 |
-
data.push({name: 'phone', value: phone});
|
127 |
-
ladda.start();
|
128 |
-
$.post(ajaxurl, data, function (response) {
|
129 |
-
if (response.success) {
|
130 |
-
booklyAlert({success : [BooklyL10n.saved]});
|
131 |
-
// Update staff name throughout the page.
|
132 |
-
$('.bookly-js-staff-name-1').text($staff_full_name.val());
|
133 |
-
// Update wp users in new staff form.
|
134 |
-
$wp_user_select.children(':not(:first)').remove();
|
135 |
-
$.each(response.data.wp_users, function (index, wp_user) {
|
136 |
-
var $option = $('<option>')
|
137 |
-
.data('email', wp_user.user_email)
|
138 |
-
.val(wp_user.ID)
|
139 |
-
.text(wp_user.display_name);
|
140 |
-
$wp_user_select.append($option);
|
141 |
-
});
|
142 |
-
} else {
|
143 |
-
booklyAlert({error : [response.data.error]});
|
144 |
-
}
|
145 |
-
ladda.stop();
|
146 |
-
});
|
147 |
});
|
148 |
|
149 |
// Delete staff avatar
|
150 |
-
$('.bookly-thumb-delete').on('click', function () {
|
151 |
var $thumb = $(this).parents('.bookly-js-image');
|
152 |
-
$.post(ajaxurl, {action: 'bookly_delete_staff_avatar', id: 1}, function () {
|
153 |
-
|
154 |
-
|
|
|
|
|
155 |
});
|
156 |
});
|
157 |
|
158 |
-
$staff_wp_user.on('change', function () {
|
159 |
-
if (this.value) {
|
160 |
-
$staff_full_name.val($staff_wp_user.find(':selected').text());
|
161 |
-
$staff_email.val($staff_wp_user.find(':selected').data('email'));
|
162 |
-
}
|
163 |
-
});
|
164 |
-
|
165 |
-
$('input.all-locations, input.location').on('change', function () {
|
166 |
-
var $panel = $(this).parents('.locations-row');
|
167 |
-
if ($(this).hasClass('all-locations')) {
|
168 |
-
$panel.find('.location').prop('checked', $(this).prop('checked'));
|
169 |
-
} else {
|
170 |
-
$panel.find('.all-locations').prop('checked', $panel.find('.location:not(:checked)').length == 0);
|
171 |
-
}
|
172 |
-
updateLocationsButton($panel);
|
173 |
-
});
|
174 |
-
|
175 |
-
function updateLocationsButton($panel) {
|
176 |
-
var locations_checked = $panel.find('.location:checked').length;
|
177 |
-
if (locations_checked == 0) {
|
178 |
-
$panel.find('.locations-count').text(BooklyL10n.selector.nothing_selected);
|
179 |
-
} else if (locations_checked == 1) {
|
180 |
-
$panel.find('.locations-count').text($panel.find('.location:checked').data('location_name'));
|
181 |
-
} else {
|
182 |
-
if (locations_checked == $panel.find('.location').length) {
|
183 |
-
$panel.find('.locations-count').text(BooklyL10n.selector.all_selected);
|
184 |
-
} else {
|
185 |
-
$panel.find('.locations-count').text(locations_checked + '/' + $panel.find('.location').length);
|
186 |
-
}
|
187 |
-
}
|
188 |
-
}
|
189 |
-
updateLocationsButton($('.locations-row'));
|
190 |
-
|
191 |
// Open details tab
|
192 |
-
$('#bookly-details-tab').on('click', function () {
|
193 |
$('.tab-pane > div').hide();
|
194 |
$details_container.show();
|
195 |
});
|
196 |
|
197 |
// Open services tab
|
198 |
-
$('#bookly-services-tab').on('click', function () {
|
199 |
$('.tab-pane > div').hide();
|
200 |
-
$services_container.show();
|
201 |
-
|
202 |
-
// Load services form
|
203 |
-
if (!$services_container.children().length) {
|
204 |
-
$loading_indicator.show();
|
205 |
-
$.post(ajaxurl, {action: 'bookly_staff_services', id: 1}, function (response) {
|
206 |
-
$services_container.html(response);
|
207 |
-
$services_form = $('form', $services_container);
|
208 |
-
$(document.body).trigger( 'special_hours.tab_init', [ $services_container ] );
|
209 |
-
var autoTickCheckboxes = function () {
|
210 |
-
// Handle 'select category' checkbox.
|
211 |
-
$('.ab-services-category .bookly-category-checkbox').each(function () {
|
212 |
-
$(this).prop(
|
213 |
-
'checked',
|
214 |
-
$('.bookly-category-services .ab-service-checkbox.bookly-category-' + $(this).data('category-id') + ':not(:checked)').length == 0
|
215 |
-
);
|
216 |
-
});
|
217 |
-
// Handle 'select all services' checkbox.
|
218 |
-
$('#bookly-check-all-entities').prop(
|
219 |
-
'checked',
|
220 |
-
$('.ab-service-checkbox:not(:checked)').length == 0
|
221 |
-
);
|
222 |
-
};
|
223 |
-
|
224 |
-
$('input[name^="capacity"]', $services_container).on('change', function () {
|
225 |
-
$(this).val(1);
|
226 |
-
$(this).prop('readonly',true);
|
227 |
-
booklyAlert({error: [BooklyL10n.limitations]});
|
228 |
-
});
|
229 |
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
$('.ab-service-checkbox', $services_form).prop('checked', $(this).is(':checked')).change();
|
239 |
-
$('.bookly-category-checkbox').prop('checked', $(this).is(':checked'));
|
240 |
-
});
|
241 |
-
|
242 |
-
// Select service
|
243 |
-
$('.ab-service-checkbox', $services_form).on('click', function () {
|
244 |
-
autoTickCheckboxes();
|
245 |
-
}).on('change', function () {
|
246 |
-
var $this = $(this);
|
247 |
-
var $inputs = $this.closest('li').find('input:not(:checkbox)');
|
248 |
-
$inputs.attr('disabled', ! $this.is(':checked'));
|
249 |
-
});
|
250 |
-
|
251 |
-
// Save services
|
252 |
-
$('#bookly-services-save').on('click', function (e) {
|
253 |
-
e.preventDefault();
|
254 |
-
var ladda = Ladda.create(this);
|
255 |
-
ladda.start();
|
256 |
-
$.post(ajaxurl, $services_form.serialize(), function (response) {
|
257 |
-
ladda.stop();
|
258 |
-
if (response.success) {
|
259 |
-
booklyAlert({success : [BooklyL10n.saved]});
|
260 |
-
}
|
261 |
-
});
|
262 |
-
});
|
263 |
-
|
264 |
-
// After reset auto tick group checkboxes.
|
265 |
-
$('#bookly-services-reset').on('click', function () {
|
266 |
-
setTimeout(function() {
|
267 |
-
autoTickCheckboxes();
|
268 |
-
$('.ab-service-checkbox', $services_form).trigger('change');
|
269 |
-
}, 0);
|
270 |
-
});
|
271 |
|
272 |
-
|
273 |
-
$loading_indicator.hide();
|
274 |
-
});
|
275 |
-
}
|
276 |
});
|
277 |
|
278 |
-
// Open
|
279 |
-
$('#bookly-special-days-tab').on('click', function () {
|
280 |
-
$(
|
|
|
|
|
|
|
|
|
281 |
});
|
282 |
|
283 |
// Open schedule tab
|
284 |
-
$('#bookly-schedule-tab').on('click', function () {
|
285 |
$('.tab-pane > div').hide();
|
286 |
-
$schedule_container.show();
|
287 |
-
|
288 |
-
// Loads schedule list
|
289 |
-
if (!$schedule_container.children().length) {
|
290 |
-
$loading_indicator.show();
|
291 |
-
$.post(ajaxurl, {action: 'bookly_staff_schedule', id: 1}, function (response) {
|
292 |
-
// fill in the container
|
293 |
-
$schedule_container.html(response);
|
294 |
-
$schedule_form = $('form', $schedule_container);
|
295 |
-
|
296 |
-
// Resets initial values
|
297 |
-
$('#bookly-schedule-reset').on('click', function (e) {
|
298 |
-
e.preventDefault();
|
299 |
-
var ladda = Ladda.create(this);
|
300 |
-
ladda.start();
|
301 |
-
|
302 |
-
$('.working-schedule-start', $schedule_container).each(function () {
|
303 |
-
$(this).val($(this).data('default_value'));
|
304 |
-
$(this).trigger('change');
|
305 |
-
});
|
306 |
-
|
307 |
-
$('.working-schedule-end', $schedule_container).each(function () {
|
308 |
-
$(this).val($(this).data('default_value'));
|
309 |
-
});
|
310 |
-
|
311 |
-
// reset breaks
|
312 |
-
$.ajax({
|
313 |
-
url : ajaxurl,
|
314 |
-
type : 'POST',
|
315 |
-
data : { action : 'bookly_reset_breaks', breaks : $(this).data('default-breaks') },
|
316 |
-
dataType : 'json',
|
317 |
-
success : function(response) {
|
318 |
-
for (var k in response) {
|
319 |
-
var $content = $(response[k]);
|
320 |
-
$('[data-staff_schedule_item_id=' + k +'] .breaks', $schedule_container).html($content);
|
321 |
-
$content.find('.bookly-intervals-wrapper .delete-break').on('click', function(){
|
322 |
-
deleteBreak.call(this);
|
323 |
-
});
|
324 |
-
}
|
325 |
-
},
|
326 |
-
complete : function() {
|
327 |
-
ladda.stop();
|
328 |
-
}
|
329 |
-
});
|
330 |
-
});
|
331 |
-
|
332 |
-
$('#bookly-schedule-save').on('click', function (e) {
|
333 |
-
e.preventDefault();
|
334 |
-
var ladda = Ladda.create(this);
|
335 |
-
ladda.start();
|
336 |
-
var data = {};
|
337 |
-
$('select.working-schedule-start, select.working-schedule-end, input:hidden', $('#bookly-schedule-container')).each(function () {
|
338 |
-
data[this.name] = this.value;
|
339 |
-
});
|
340 |
-
$.post(ajaxurl, $.param(data), function (response) {
|
341 |
-
ladda.stop();
|
342 |
-
booklyAlert({success : [BooklyL10n.saved]});
|
343 |
-
});
|
344 |
-
});
|
345 |
-
|
346 |
-
// init 'add break' functionality
|
347 |
-
$('.bookly-js-toggle-popover:not(.break-interval)').popover({
|
348 |
-
html : true,
|
349 |
-
placement: 'bottom',
|
350 |
-
template : '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
351 |
-
trigger : 'manual',
|
352 |
-
content : function () {
|
353 |
-
return $($(this).data('popover-content')).html()
|
354 |
-
}
|
355 |
-
}).on('click', function () {
|
356 |
-
$(this).popover('toggle');
|
357 |
-
|
358 |
-
var $popover = $(this).next('.popover'),
|
359 |
-
working_start = $popover.closest('.row').find('.working-schedule-start').val(),
|
360 |
-
$break_start = $popover.find('.break-start'),
|
361 |
-
$break_end = $popover.find('.break-end'),
|
362 |
-
working_start_time = working_start.split(':'),
|
363 |
-
working_start_hours = parseInt(working_start_time[0], 10),
|
364 |
-
break_start_hours = working_start_hours + 1;
|
365 |
-
if (break_start_hours < 10) {
|
366 |
-
break_start_hours = '0' + break_start_hours;
|
367 |
-
}
|
368 |
-
var break_end_hours = working_start_hours + 2;
|
369 |
-
if (break_end_hours < 10) {
|
370 |
-
break_end_hours = '0' + break_end_hours;
|
371 |
-
}
|
372 |
-
var break_end_hours_str = break_end_hours + ':' + working_start_time[1] + ':' + working_start_time[2],
|
373 |
-
break_start_hours_str = break_start_hours + ':' + working_start_time[1] + ':' + working_start_time[2];
|
374 |
-
|
375 |
-
$break_start.val(break_start_hours_str);
|
376 |
-
$break_end.val(break_end_hours_str);
|
377 |
-
|
378 |
-
hideInaccessibleBreaks($break_start, $break_end);
|
379 |
-
|
380 |
-
$popover.find('.bookly-popover-close').on('click', function () {
|
381 |
-
$popover.popover('hide');
|
382 |
-
});
|
383 |
-
});
|
384 |
-
|
385 |
-
$schedule_container.on('click', '.break-interval', function () {
|
386 |
-
$('.popover').popover('hide');
|
387 |
-
var break_id = $(this).closest('.bookly-intervals-wrapper').data('break_id');
|
388 |
-
$(this).popover({
|
389 |
-
html: true,
|
390 |
-
placement: 'bottom',
|
391 |
-
template: '<div class="popover" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
392 |
-
content: function () {
|
393 |
-
return $('.bookly-js-content-break-' + break_id).html();
|
394 |
-
},
|
395 |
-
trigger: 'manual'
|
396 |
-
});
|
397 |
-
|
398 |
-
$(this).popover('toggle');
|
399 |
-
|
400 |
-
var $popover = $(this).next('.popover'),
|
401 |
-
$break_start = $popover.find('.break-start'),
|
402 |
-
$break_end = $popover.find('.break-end');
|
403 |
-
|
404 |
-
hideInaccessibleBreaks($break_start, $break_end, true);
|
405 |
-
|
406 |
-
$popover.find('.bookly-popover-close').on('click', function () {
|
407 |
-
$popover.popover('hide');
|
408 |
-
});
|
409 |
-
});
|
410 |
-
|
411 |
-
$schedule_container.on('click', '.bookly-js-save-break', function (e) {
|
412 |
-
var $table = $(this).closest('.bookly-js-schedule-form'),
|
413 |
-
$row = $table.parents('.staff-schedule-item-row').first(),
|
414 |
-
$data = {
|
415 |
-
action : 'bookly_staff_schedule_handle_break',
|
416 |
-
staff_schedule_item_id : $row.data('staff_schedule_item_id'),
|
417 |
-
start_time : $table.find('.break-start > option:selected').val(),
|
418 |
-
end_time : $table.find('.break-end > option:selected').val(),
|
419 |
-
working_end : $row.find('.working-schedule-end > option:selected').val(),
|
420 |
-
working_start : $row.find('.working-schedule-start > option:selected').val()
|
421 |
-
},
|
422 |
-
$break_interval_wrapper = $table.parents('.bookly-intervals-wrapper').first(),
|
423 |
-
ladda = Ladda.create(e.currentTarget);
|
424 |
-
ladda.start();
|
425 |
-
|
426 |
-
if ($break_interval_wrapper.data('break_id')) {
|
427 |
-
$data['break_id'] = $break_interval_wrapper.data('break_id');
|
428 |
-
}
|
429 |
-
|
430 |
-
$.post(ajaxurl, $data, function (response) {
|
431 |
-
if (response.success) {
|
432 |
-
if (response['item_content']) {
|
433 |
-
var $new_break_interval_item = $(response['item_content']);
|
434 |
-
$new_break_interval_item
|
435 |
-
.hide()
|
436 |
-
.appendTo($row.find('.breaks-list-content'))
|
437 |
-
.fadeIn('slow');
|
438 |
-
$new_break_interval_item.find('.delete-break').on('click', function () {
|
439 |
-
deleteBreak.call(this);
|
440 |
-
});
|
441 |
-
} else if (response.data.interval) {
|
442 |
-
$break_interval_wrapper
|
443 |
-
.find('.break-interval')
|
444 |
-
.text(response.data.interval);
|
445 |
-
}
|
446 |
-
$('.popover').popover('hide');
|
447 |
-
} else {
|
448 |
-
booklyAlert({error : [response.data.message]});
|
449 |
-
}
|
450 |
-
},
|
451 |
-
'json'
|
452 |
-
).always(function () {
|
453 |
-
ladda.stop()
|
454 |
-
});
|
455 |
-
|
456 |
-
return false;
|
457 |
-
});
|
458 |
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
$end_select = $this.closest('.bookly-flexbox').find('.working-schedule-end'),
|
468 |
-
start_time = $this.val();
|
469 |
-
|
470 |
-
// Hide end time options to keep them within 24 hours after start time.
|
471 |
-
var parts = start_time.split(':');
|
472 |
-
parts[0] = parseInt(parts[0]) + 24;
|
473 |
-
var end_time = parts.join(':');
|
474 |
-
var frag = document.createDocumentFragment();
|
475 |
-
var old_value = $end_select.val();
|
476 |
-
var new_value = null;
|
477 |
-
$('option', $end_select).each(function () {
|
478 |
-
if (this.value <= start_time || this.value > end_time) {
|
479 |
-
var span = document.createElement('span');
|
480 |
-
span.style.display = 'none';
|
481 |
-
span.appendChild(this.cloneNode(true));
|
482 |
-
frag.appendChild(span);
|
483 |
-
} else {
|
484 |
-
frag.appendChild(this.cloneNode(true));
|
485 |
-
if (new_value === null || old_value == this.value) {
|
486 |
-
new_value = this.value;
|
487 |
-
}
|
488 |
-
}
|
489 |
-
});
|
490 |
-
$end_select.empty().append(frag).val(new_value);
|
491 |
-
|
492 |
-
// when the working day is disabled (working start time is set to 'OFF')
|
493 |
-
// hide all the elements inside the row
|
494 |
-
if (!$this.val()) {
|
495 |
-
$this.closest('.row').find('.bookly-hide-on-off').hide();
|
496 |
-
} else {
|
497 |
-
$this.closest('.row').find('.bookly-hide-on-off').show();
|
498 |
-
}
|
499 |
-
}).trigger('change');
|
500 |
-
|
501 |
-
$schedule_container.find('.bookly-intervals-wrapper .delete-break').on('click', function() {
|
502 |
-
deleteBreak.call(this);
|
503 |
-
});
|
504 |
|
505 |
-
|
506 |
-
});
|
507 |
-
}
|
508 |
});
|
509 |
|
510 |
-
// Open
|
511 |
$('#bookly-holidays-tab').on('click', function () {
|
512 |
$('.tab-pane > div').hide();
|
513 |
-
$holidays_container.show();
|
514 |
-
|
515 |
-
if (!$holidays_container.children().length) {
|
516 |
-
$loading_indicator.show();
|
517 |
-
$holidays_container.load(ajaxurl, { action: 'bookly_staff_holidays', id: 1 }, function(){ $loading_indicator.hide(); });
|
518 |
-
}
|
519 |
-
});
|
520 |
-
|
521 |
-
function hideInaccessibleBreaks( $start, $end, force_keep_values ) {
|
522 |
-
var $row = $start.closest('.row'),
|
523 |
-
$working_start = $row.find('.working-schedule-start'),
|
524 |
-
$working_end = $row.find('.working-schedule-end'),
|
525 |
-
frag1 = document.createDocumentFragment(),
|
526 |
-
frag2 = document.createDocumentFragment(),
|
527 |
-
old_value = $start.val(),
|
528 |
-
new_value = null;
|
529 |
-
|
530 |
-
$('option', $start).each(function () {
|
531 |
-
if ((this.value < $working_start.val() || this.value >= $working_end.val()) && (!force_keep_values || this.value != old_value)) {
|
532 |
-
var span = document.createElement('span');
|
533 |
-
span.style.display = 'none';
|
534 |
-
span.appendChild(this.cloneNode(true));
|
535 |
-
frag1.appendChild(span);
|
536 |
-
} else {
|
537 |
-
frag1.appendChild(this.cloneNode(true));
|
538 |
-
if (new_value === null || old_value == this.value) {
|
539 |
-
new_value = this.value;
|
540 |
-
}
|
541 |
-
}
|
542 |
-
});
|
543 |
-
$start.empty().append(frag1).val(new_value);
|
544 |
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
if ((this.value <= $start.val() || this.value > $working_end.val()) && (!force_keep_values || this.value != old_value)) {
|
550 |
-
var span = document.createElement('span');
|
551 |
-
span.style.display = 'none';
|
552 |
-
span.appendChild(this.cloneNode(true));
|
553 |
-
frag2.appendChild(span);
|
554 |
-
} else {
|
555 |
-
frag2.appendChild(this.cloneNode(true));
|
556 |
-
if (new_value === null || old_value == this.value) {
|
557 |
-
new_value = this.value;
|
558 |
-
}
|
559 |
-
}
|
560 |
});
|
561 |
-
$end.empty().append(frag2).val(new_value);
|
562 |
-
}
|
563 |
|
564 |
-
|
565 |
-
|
566 |
-
if (confirm(BooklyL10n.are_you_sure)) {
|
567 |
-
var ladda = Ladda.create(this);
|
568 |
-
ladda.start();
|
569 |
-
$.post(ajaxurl, { action: 'bookly_delete_staff_schedule_break', id: $break_interval_wrapper.data('break_id') }, function (response) {
|
570 |
-
if (response.success) {
|
571 |
-
$break_interval_wrapper.remove();
|
572 |
-
}
|
573 |
-
}).always(function () {
|
574 |
-
ladda.stop()
|
575 |
-
});
|
576 |
-
}
|
577 |
-
}
|
578 |
|
579 |
$('#' + active_tab_id).click();
|
580 |
});
|
@@ -599,12 +193,12 @@ jQuery(function($) {
|
|
599 |
$.ajax({
|
600 |
type : 'POST',
|
601 |
url : ajaxurl,
|
602 |
-
data : {
|
603 |
});
|
604 |
}
|
605 |
});
|
606 |
|
607 |
-
$('#
|
608 |
html: true,
|
609 |
placement: 'bottom',
|
610 |
template: '<div class="popover" style="width: calc(100% - 20px)" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
3 |
$new_form = $('#bookly-new-staff'),
|
4 |
$wp_user_select = $('#bookly-new-staff-wpuser'),
|
5 |
$name_input = $('#bookly-new-staff-fullname'),
|
6 |
+
$edit_form = $('#bookly-container-edit-staff');
|
7 |
+
|
8 |
function saveNewForm() {
|
9 |
booklyAlert({error: [BooklyL10n.limitations]});
|
10 |
}
|
11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
12 |
// Save new staff on enter press
|
13 |
$name_input.on('keypress', function (e) {
|
14 |
var code = (e.keyCode ? e.keyCode : e.which);
|
21 |
$new_form.on('keypress', function (e) {
|
22 |
var code = (e.keyCode ? e.keyCode : e.which);
|
23 |
if (code == 27) {
|
24 |
+
$('#bookly-newstaff-member').popover('hide');
|
25 |
}
|
26 |
});
|
27 |
|
29 |
e.stopPropagation();
|
30 |
});
|
31 |
|
32 |
+
$edit_form
|
33 |
+
.on('click', '.bookly-pretty-indicator', function (e) {
|
34 |
+
e.preventDefault();
|
35 |
+
e.stopPropagation();
|
36 |
+
var frame = wp.media({
|
37 |
+
library: {type: 'image'},
|
38 |
+
multiple: false
|
39 |
+
});
|
40 |
+
frame.on('select', function () {
|
41 |
+
var selection = frame.state().get('selection').toJSON(),
|
42 |
+
img_src;
|
43 |
+
if (selection.length) {
|
44 |
+
if (selection[0].sizes['thumbnail'] !== undefined) {
|
45 |
+
img_src = selection[0].sizes['thumbnail'].url;
|
46 |
+
} else {
|
47 |
+
img_src = selection[0].url;
|
48 |
+
}
|
49 |
+
$edit_form.find('[name=attachment_id]').val(selection[0].id);
|
50 |
+
$('#bookly-js-staff-avatar').find('.bookly-js-image').css({'background-image': 'url(' + img_src + ')', 'background-size': 'cover'});
|
51 |
+
$('.bookly-thumb-delete').show();
|
52 |
+
$(this).hide();
|
53 |
+
}
|
54 |
+
});
|
55 |
+
|
56 |
+
frame.open();
|
57 |
+
});
|
58 |
+
|
59 |
/**
|
60 |
* Load staff profile on click on staff in the list.
|
61 |
*/
|
65 |
$staff_list.find('.active').removeClass('active');
|
66 |
$this.addClass('active');
|
67 |
|
|
|
68 |
var active_tab_id = $('.nav .active a').attr('id');
|
69 |
$edit_form.html('<div class="bookly-loading"></div>');
|
70 |
+
$.get(ajaxurl, {action: 'bookly_edit_staff', id: 1, csrf_token: BooklyL10n.csrf_token}, function (response) {
|
71 |
+
$edit_form.html(response.data.html.edit);
|
72 |
booklyAlert(response.data.alert);
|
73 |
+
var $details_container = $('#bookly-details-container', $edit_form),
|
74 |
+
$loading_indicator = $('.bookly-loading', $edit_form),
|
75 |
+
$services_container = $('#bookly-services-container', $edit_form),
|
76 |
+
$schedule_container = $('#bookly-schedule-container', $edit_form),
|
77 |
+
$holidays_container = $('#bookly-holidays-container', $edit_form)
|
78 |
+
;
|
79 |
+
$details_container.html(response.data.html.details);
|
80 |
+
|
81 |
+
new BooklyStaffDetails($details_container, {
|
82 |
+
get_details : {},
|
83 |
+
intlTelInput : BooklyL10n.intlTelInput,
|
84 |
+
l10n : BooklyL10n,
|
85 |
+
renderWpUsers : function (wp_users) {
|
86 |
+
$wp_user_select.children(':not(:first)').remove();
|
87 |
+
$.each(wp_users, function (index, wp_user) {
|
88 |
+
var $option = $('<option>')
|
89 |
+
.data('email', wp_user.user_email)
|
90 |
+
.val(wp_user.ID)
|
91 |
+
.text(wp_user.display_name);
|
92 |
+
$wp_user_select.append($option);
|
93 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
94 |
}
|
95 |
});
|
96 |
|
97 |
+
// Delete staff member.
|
98 |
+
$('#bookly-staff-delete', $edit_form).on('click', function (e) {
|
99 |
+
booklyAlert({error: [BooklyL10n.limitations]});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
});
|
101 |
|
102 |
// Delete staff avatar
|
103 |
+
$('.bookly-thumb-delete', $edit_form).on('click', function () {
|
104 |
var $thumb = $(this).parents('.bookly-js-image');
|
105 |
+
$.post(ajaxurl, {action: 'bookly_delete_staff_avatar', id: 1, csrf_token: BooklyL10n.csrf_token}, function (response) {
|
106 |
+
if (response.success) {
|
107 |
+
$thumb.attr('style', '');
|
108 |
+
$edit_form.find('[name=attachment_id]').val('');
|
109 |
+
}
|
110 |
});
|
111 |
});
|
112 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
113 |
// Open details tab
|
114 |
+
$('#bookly-details-tab', $edit_form).on('click', function () {
|
115 |
$('.tab-pane > div').hide();
|
116 |
$details_container.show();
|
117 |
});
|
118 |
|
119 |
// Open services tab
|
120 |
+
$('#bookly-services-tab', $edit_form).on('click', function () {
|
121 |
$('.tab-pane > div').hide();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
|
123 |
+
new BooklyStaffServices($services_container, {
|
124 |
+
get_staff_services: {
|
125 |
+
action : 'bookly_get_staff_services',
|
126 |
+
staff_id : 1,
|
127 |
+
csrf_token: BooklyL10n.csrf_token
|
128 |
+
},
|
129 |
+
l10n: BooklyL10n
|
130 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
|
132 |
+
$services_container.show();
|
|
|
|
|
|
|
133 |
});
|
134 |
|
135 |
+
// Open special days tab
|
136 |
+
$('#bookly-special-days-tab', $edit_form).on('click', function () {
|
137 |
+
new BooklyStaffSpecialDays($('.bookly-js-special-days-container'), {
|
138 |
+
staff_id : 1,
|
139 |
+
csrf_token: BooklyL10n.csrf_token,
|
140 |
+
l10n : SpecialDaysL10n
|
141 |
+
});
|
142 |
});
|
143 |
|
144 |
// Open schedule tab
|
145 |
+
$('#bookly-schedule-tab', $edit_form).on('click', function () {
|
146 |
$('.tab-pane > div').hide();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
|
148 |
+
new BooklyStaffSchedule($schedule_container, {
|
149 |
+
get_staff_schedule: {
|
150 |
+
action: 'bookly_get_staff_schedule',
|
151 |
+
staff_id: 1,
|
152 |
+
csrf_token: BooklyL10n.csrf_token
|
153 |
+
},
|
154 |
+
l10n: BooklyL10n
|
155 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
156 |
|
157 |
+
$schedule_container.show();
|
|
|
|
|
158 |
});
|
159 |
|
160 |
+
// Open holiday tab
|
161 |
$('#bookly-holidays-tab').on('click', function () {
|
162 |
$('.tab-pane > div').hide();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
163 |
|
164 |
+
new BooklyStaffDaysOff($holidays_container, {
|
165 |
+
staff_id : 1,
|
166 |
+
csrf_token: BooklyL10n.csrf_token,
|
167 |
+
l10n : BooklyL10n
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
168 |
});
|
|
|
|
|
169 |
|
170 |
+
$holidays_container.show();
|
171 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
|
173 |
$('#' + active_tab_id).click();
|
174 |
});
|
193 |
$.ajax({
|
194 |
type : 'POST',
|
195 |
url : ajaxurl,
|
196 |
+
data : {action: 'bookly_update_staff_position', position: data, csrf_token: BooklyL10n.csrf_token}
|
197 |
});
|
198 |
}
|
199 |
});
|
200 |
|
201 |
+
$('#bookly-newstaff-member').popover({
|
202 |
html: true,
|
203 |
placement: 'bottom',
|
204 |
template: '<div class="popover" style="width: calc(100% - 20px)" role="tooltip"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
|
backend/modules/staff/templates/_breaks.php
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
2 |
$breaks_list = $item->getBreaksList();
|
3 |
?>
|
4 |
<div class="breaks-list">
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var \BooklyLite\Lib\Entities\StaffScheduleItem $item */
|
3 |
$breaks_list = $item->getBreaksList();
|
4 |
?>
|
5 |
<div class="breaks-list">
|
backend/modules/staff/templates/_details.php
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var \BooklyLite\Lib\Entities\Staff $staff */
|
3 |
+
?>
|
4 |
+
<form>
|
5 |
+
<div class="form-group">
|
6 |
+
<label for="bookly-full-name"><?php _e( 'Full name', 'bookly' ) ?></label>
|
7 |
+
<input type="text" class="form-control" id="bookly-full-name" name="full_name" value="<?php echo esc_attr( $staff->getFullName() ) ?>"/>
|
8 |
+
</div>
|
9 |
+
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
10 |
+
<div class="form-group">
|
11 |
+
<label for="bookly-wp-user"><?php _e( 'User', 'bookly' ) ?></label>
|
12 |
+
|
13 |
+
<p class="help-block">
|
14 |
+
<?php _e( 'If this staff member requires separate login to access personal calendar, a regular WP user needs to be created for this purpose.', 'bookly' ) ?>
|
15 |
+
<?php _e( 'User with "Administrator" role will have access to calendars and settings of all staff members, user with another role will have access only to personal calendar and settings.', 'bookly' ) ?>
|
16 |
+
<?php _e( 'If you leave this field blank, this staff member will not be able to access personal calendar using WP backend.', 'bookly' ) ?>
|
17 |
+
</p>
|
18 |
+
|
19 |
+
<select class="form-control" name="wp_user_id" id="bookly-wp-user">
|
20 |
+
<option value=""><?php _e( 'Select from WP users', 'bookly' ) ?></option>
|
21 |
+
<?php foreach ( $users_for_staff as $user ) : ?>
|
22 |
+
<option value="<?php echo $user->ID ?>" data-email="<?php echo $user->user_email ?>" <?php selected( $user->ID, $staff->getWpUserId() ) ?>><?php echo $user->display_name ?></option>
|
23 |
+
<?php endforeach ?>
|
24 |
+
</select>
|
25 |
+
</div>
|
26 |
+
<?php endif ?>
|
27 |
+
|
28 |
+
<div class="row">
|
29 |
+
<div class="col-sm-6">
|
30 |
+
<div class="form-group">
|
31 |
+
<label for="bookly-email"><?php _e( 'Email', 'bookly' ) ?></label>
|
32 |
+
<input class="form-control" id="bookly-email" name="email"
|
33 |
+
value="<?php echo esc_attr( $staff->getEmail() ) ?>"
|
34 |
+
type="text"/>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
<div class="col-sm-6">
|
38 |
+
<div class="form-group">
|
39 |
+
<label for="bookly-phone"><?php _e( 'Phone', 'bookly' ) ?></label>
|
40 |
+
<input class="form-control" id="bookly-phone"
|
41 |
+
value="<?php echo esc_attr( $staff->getPhone() ) ?>"
|
42 |
+
type="text"/>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
</div>
|
46 |
+
|
47 |
+
<div class="form-group">
|
48 |
+
<label for="bookly-info"><?php _e( 'Info', 'bookly' ) ?></label>
|
49 |
+
<p class="help-block">
|
50 |
+
<?php printf( __( 'This text can be inserted into notifications with %s code.', 'bookly' ), '{staff_info}' ) ?>
|
51 |
+
</p>
|
52 |
+
<textarea id="bookly-info" name="info" rows="3" class="form-control"><?php echo esc_textarea( $staff->getInfo() ) ?></textarea>
|
53 |
+
</div>
|
54 |
+
|
55 |
+
<div class="form-group">
|
56 |
+
<label for="bookly-visibility"><?php _e( 'Visibility', 'bookly' ) ?></label>
|
57 |
+
<p class="help-block">
|
58 |
+
<?php _e( 'To make staff member invisible to your customers set the visibility to "Private".', 'bookly' ) ?>
|
59 |
+
</p>
|
60 |
+
<select name="visibility" class="form-control" id="bookly-visibility">
|
61 |
+
<option value="public" <?php selected( $staff->getVisibility(), 'public' ) ?>><?php _e( 'Public', 'bookly' ) ?></option>
|
62 |
+
<option value="private" <?php selected( $staff->getVisibility(), 'private' ) ?>><?php _e( 'Private', 'bookly' ) ?></option>
|
63 |
+
</select>
|
64 |
+
</div>
|
65 |
+
<?php BooklyLite\Lib\Proxy\Shared::renderStaffForm( $staff ) ?>
|
66 |
+
|
67 |
+
<div class="form-group">
|
68 |
+
<h3><?php _e( 'Google Calendar integration', 'bookly' ) ?></h3>
|
69 |
+
<p class="help-block">
|
70 |
+
<?php _e( 'Synchronize staff member appointments with Google Calendar.', 'bookly' ) ?>
|
71 |
+
</p>
|
72 |
+
<p>
|
73 |
+
<?php if ( isset( $authUrl ) ) : ?>
|
74 |
+
<?php if ( $authUrl ) : ?>
|
75 |
+
<a href="<?php echo $authUrl ?>"><?php _e( 'Connect', 'bookly' ) ?></a>
|
76 |
+
<?php else : ?>
|
77 |
+
<?php printf( __( 'Please configure Google Calendar <a href="%s">settings</a> first', 'bookly' ), \BooklyLite\Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Settings\Controller::page_slug, array( 'tab' => 'google_calendar' ) ) ) ?>
|
78 |
+
<?php endif ?>
|
79 |
+
<?php else : ?>
|
80 |
+
<?php _e( 'Connected', 'bookly' ) ?> (<a href="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Staff\Controller::page_slug, array( 'google_logout' => $staff->getId() ) ) ?>"><?php _e( 'disconnect', 'bookly' ) ?></a>)
|
81 |
+
<?php endif ?>
|
82 |
+
</p>
|
83 |
+
</div>
|
84 |
+
<?php if ( ! isset( $authUrl ) ) : ?>
|
85 |
+
<div class="form-group">
|
86 |
+
<label for="bookly-calendar-id"><?php _e( 'Calendar', 'bookly' ) ?></label>
|
87 |
+
<select class="form-control" name="google_calendar_id" id="bookly-calendar-id">
|
88 |
+
<?php foreach ( $google_calendars as $id => $calendar ) : ?>
|
89 |
+
<option
|
90 |
+
<?php selected( $staff->getGoogleCalendarId() == $id || $staff->getGoogleCalendarId() == '' && $calendar['primary'] ) ?>
|
91 |
+
value="<?php echo esc_attr( $id ) ?>">
|
92 |
+
<?php echo esc_html( $calendar['summary'] ) ?>
|
93 |
+
</option>
|
94 |
+
<?php endforeach ?>
|
95 |
+
</select>
|
96 |
+
</div>
|
97 |
+
<?php endif ?>
|
98 |
+
|
99 |
+
<input type="hidden" name="id" value="<?php echo $staff->getId() ?>">
|
100 |
+
<input type="hidden" name="attachment_id" value="<?php echo $staff->getAttachmentId() ?>">
|
101 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
102 |
+
|
103 |
+
<div class="panel-footer">
|
104 |
+
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
105 |
+
<?php \BooklyLite\Lib\Utils\Common::deleteButton( 'bookly-staff-delete', 'btn-lg pull-left' ) ?>
|
106 |
+
<?php endif ?>
|
107 |
+
<?php \BooklyLite\Lib\Utils\Common::customButton( 'bookly-details-save', 'btn-lg btn-success', __( 'Save', 'bookly' ) ) ?>
|
108 |
+
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
109 |
+
</div>
|
110 |
+
</form>
|
backend/modules/staff/templates/_list_item.php
CHANGED
@@ -1,6 +1,5 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
$img = wp_get_attachment_image_src( $staff['attachment_id'], 'thumbnail' );
|
3 |
-
/** @var \BooklyLite\Lib\Entities\Staff $staff */
|
4 |
?>
|
5 |
<li class="bookly-nav-item<?php if ( $active_staff_id == $staff['id'] ) : ?> active<?php endif ?>" id="bookly-staff-<?php echo $staff['id'] ?>" data-staff-id="<?php echo $staff['id'] ?>">
|
6 |
<div class="bookly-flexbox">
|
@@ -9,8 +8,9 @@
|
|
9 |
</div>
|
10 |
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 1%">
|
11 |
<div class="bookly-thumb bookly-thumb-sm bookly-margin-right-lg"
|
12 |
-
<?php echo $img ? 'style="background-image: url(' . $img[0] . '); background-size: cover;background-position:0"' : ''
|
13 |
-
|
|
|
14 |
</div>
|
15 |
<div class="bookly-flex-cell bookly-vertical-middle">
|
16 |
<?php echo esc_html( $staff['full_name'] ) ?>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
$img = wp_get_attachment_image_src( $staff['attachment_id'], 'thumbnail' );
|
|
|
3 |
?>
|
4 |
<li class="bookly-nav-item<?php if ( $active_staff_id == $staff['id'] ) : ?> active<?php endif ?>" id="bookly-staff-<?php echo $staff['id'] ?>" data-staff-id="<?php echo $staff['id'] ?>">
|
5 |
<div class="bookly-flexbox">
|
8 |
</div>
|
9 |
<div class="bookly-flex-cell bookly-vertical-middle" style="width: 1%">
|
10 |
<div class="bookly-thumb bookly-thumb-sm bookly-margin-right-lg"
|
11 |
+
<?php echo $img ? 'style="background-image: url(' . $img[0] . '); background-size: cover;background-position:0"' : '' ?>
|
12 |
+
>
|
13 |
+
</div>
|
14 |
</div>
|
15 |
<div class="bookly-flex-cell bookly-vertical-middle">
|
16 |
<?php echo esc_html( $staff['full_name'] ) ?>
|
backend/modules/staff/templates/_new.php
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
3 |
<div class="form-group">
|
4 |
-
<button id="
|
5 |
<i class="dashicons dashicons-plus-alt"></i>
|
6 |
<?php _e( 'New Staff Member', 'bookly' ) ?>
|
7 |
</button>
|
@@ -13,10 +13,10 @@
|
|
13 |
<label for="bookly-new-staff-wpuser"><?php _e( 'User', 'bookly' ) ?></label>
|
14 |
<p class="help-block">
|
15 |
<?php _e( 'If this staff member requires separate login to access personal calendar, a regular WP user needs to be created for this purpose.', 'bookly' ) ?>
|
16 |
-
<?php _e( 'User with "Administrator" role will have access to calendars and settings of all staff members, user with
|
17 |
-
<?php _e( 'If you
|
18 |
</p>
|
19 |
-
<select class="form-control" name="
|
20 |
<option value=""><?php _e( 'Select from WP users', 'bookly' ) ?></option>
|
21 |
<?php foreach ( $users_for_staff as $user ) : ?>
|
22 |
<option value="<?php echo $user->ID ?>"><?php echo $user->display_name ?></option>
|
@@ -26,7 +26,7 @@
|
|
26 |
<div class="form-group bookly-margin-bottom-md">
|
27 |
<div class="form-field form-required">
|
28 |
<label for="bookly-new-staff-fullname"><?php _e( 'Full name', 'bookly' ) ?></label>
|
29 |
-
<input class="form-control" id="bookly-new-staff-fullname" name="
|
30 |
</div>
|
31 |
</div>
|
32 |
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
3 |
<div class="form-group">
|
4 |
+
<button id="bookly-newstaff-member" type="button" class="btn btn-xlg btn-block btn-success-outline">
|
5 |
<i class="dashicons dashicons-plus-alt"></i>
|
6 |
<?php _e( 'New Staff Member', 'bookly' ) ?>
|
7 |
</button>
|
13 |
<label for="bookly-new-staff-wpuser"><?php _e( 'User', 'bookly' ) ?></label>
|
14 |
<p class="help-block">
|
15 |
<?php _e( 'If this staff member requires separate login to access personal calendar, a regular WP user needs to be created for this purpose.', 'bookly' ) ?>
|
16 |
+
<?php _e( 'User with "Administrator" role will have access to calendars and settings of all staff members, user with another role will have access only to personal calendar and settings.', 'bookly' ) ?>
|
17 |
+
<?php _e( 'If you leave this field blank, this staff member will not be able to access personal calendar using WP backend.', 'bookly' ) ?>
|
18 |
</p>
|
19 |
+
<select class="form-control" name="bookly-new-staff-wpuser" id="bookly-new-staff-wpuser">
|
20 |
<option value=""><?php _e( 'Select from WP users', 'bookly' ) ?></option>
|
21 |
<?php foreach ( $users_for_staff as $user ) : ?>
|
22 |
<option value="<?php echo $user->ID ?>"><?php echo $user->display_name ?></option>
|
26 |
<div class="form-group bookly-margin-bottom-md">
|
27 |
<div class="form-field form-required">
|
28 |
<label for="bookly-new-staff-fullname"><?php _e( 'Full name', 'bookly' ) ?></label>
|
29 |
+
<input class="form-control" id="bookly-new-staff-fullname" name="bookly-new-staff-fullname" type="text">
|
30 |
</div>
|
31 |
</div>
|
32 |
|
backend/modules/staff/templates/edit.php
CHANGED
@@ -1,5 +1,7 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) )
|
2 |
-
|
|
|
|
|
3 |
?>
|
4 |
<div class="panel panel-default bookly-main">
|
5 |
<div class="panel-body">
|
@@ -8,15 +10,15 @@
|
|
8 |
<div id="bookly-js-staff-avatar" class="bookly-thumb bookly-thumb-lg bookly-margin-right-lg">
|
9 |
<div class="bookly-flex-cell" style="width: 100%">
|
10 |
<div class="form-group">
|
11 |
-
<?php $img = wp_get_attachment_image_src( $staff->
|
12 |
|
13 |
<div class="bookly-js-image bookly-thumb bookly-thumb-lg bookly-margin-right-lg"
|
14 |
-
<?php echo $img ? 'style="background-image: url(' . $img[0] . '); background-size: cover;"' : ''
|
15 |
>
|
16 |
<a class="dashicons dashicons-trash text-danger bookly-thumb-delete"
|
17 |
href="javascript:void(0)"
|
18 |
title="<?php esc_attr_e( 'Delete', 'bookly' ) ?>"
|
19 |
-
<?php if (
|
20 |
</a>
|
21 |
<div class="bookly-thumb-edit">
|
22 |
<div class="bookly-pretty">
|
@@ -30,7 +32,7 @@
|
|
30 |
</div>
|
31 |
</div>
|
32 |
</div>
|
33 |
-
<div class="bookly-flex-cell bookly-vertical-top"><h1 class="bookly-js-staff-name-<?php echo $staff->
|
34 |
</div>
|
35 |
|
36 |
<ul class="nav nav-tabs nav-justified bookly-nav-justified">
|
@@ -52,7 +54,7 @@
|
|
52 |
<span class="bookly-nav-tabs-title"><?php _e( 'Schedule', 'bookly' ) ?></span>
|
53 |
</a>
|
54 |
</li>
|
55 |
-
<?php
|
56 |
<li>
|
57 |
<a id="bookly-holidays-tab" href="#daysoff" data-toggle="tab">
|
58 |
<i class="bookly-icon bookly-icon-daysoff"></i>
|
@@ -65,113 +67,7 @@
|
|
65 |
<div style="display: none;" class="bookly-loading"></div>
|
66 |
|
67 |
<div class="tab-pane active" id="details">
|
68 |
-
<div id="bookly-details-container">
|
69 |
-
<form>
|
70 |
-
<div class="form-group">
|
71 |
-
<label for="bookly-full-name"><?php _e( 'Full name', 'bookly' ) ?></label>
|
72 |
-
<input type="text" class="form-control" id="bookly-full-name" name="full_name" value="<?php echo esc_attr( $staff->get( 'full_name' ) ) ?>" />
|
73 |
-
</div>
|
74 |
-
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
75 |
-
<div class="form-group">
|
76 |
-
<label for="bookly-wp-user"><?php _e( 'User', 'bookly' ) ?></label>
|
77 |
-
|
78 |
-
<p class="help-block">
|
79 |
-
<?php _e( 'If this staff member requires separate login to access personal calendar, a regular WP user needs to be created for this purpose.', 'bookly' ) ?>
|
80 |
-
<?php _e( 'User with "Administrator" role will have access to calendars and settings of all staff members, user with some other role will have access only to personal calendar and settings.', 'bookly' ) ?>
|
81 |
-
<?php _e( 'If you will leave this field blank, this staff member will not be able to access personal calendar using WP backend.', 'bookly' ) ?>
|
82 |
-
</p>
|
83 |
-
|
84 |
-
<select class="form-control" name="wp_user_id" id="bookly-wp-user">
|
85 |
-
<option value=""><?php _e( 'Select from WP users', 'bookly' ) ?></option>
|
86 |
-
<?php foreach ( $users_for_staff as $user ) : ?>
|
87 |
-
<option value="<?php echo $user->ID ?>" data-email="<?php echo $user->user_email ?>" <?php selected( $user->ID, $staff->get( 'wp_user_id' ) ) ?>><?php echo $user->display_name ?></option>
|
88 |
-
<?php endforeach ?>
|
89 |
-
</select>
|
90 |
-
</div>
|
91 |
-
<?php endif ?>
|
92 |
-
|
93 |
-
<div class="row">
|
94 |
-
<div class="col-sm-6">
|
95 |
-
<div class="form-group">
|
96 |
-
<label for="bookly-email"><?php _e( 'Email', 'bookly' ) ?></label>
|
97 |
-
<input class="form-control" id="bookly-email" name="email"
|
98 |
-
value="<?php echo esc_attr( $staff->get( 'email' ) ) ?>"
|
99 |
-
type="text" />
|
100 |
-
</div>
|
101 |
-
</div>
|
102 |
-
<div class="col-sm-6">
|
103 |
-
<div class="form-group">
|
104 |
-
<label for="bookly-phone"><?php _e( 'Phone', 'bookly' ) ?></label>
|
105 |
-
<input class="form-control" id="bookly-phone"
|
106 |
-
value="<?php echo esc_attr( $staff->get( 'phone' ) ) ?>"
|
107 |
-
type="text" />
|
108 |
-
</div>
|
109 |
-
</div>
|
110 |
-
</div>
|
111 |
-
|
112 |
-
<div class="form-group">
|
113 |
-
<label for="bookly-info"><?php _e( 'Info', 'bookly' ) ?></label>
|
114 |
-
<p class="help-block">
|
115 |
-
<?php printf( __( 'This text can be inserted into notifications with %s code.', 'bookly' ), '{staff_info}' ) ?>
|
116 |
-
</p>
|
117 |
-
<textarea id="bookly-info" name="info" rows="3" class="form-control"><?php echo esc_textarea( $staff->get( 'info' ) ) ?></textarea>
|
118 |
-
</div>
|
119 |
-
|
120 |
-
<div class="form-group">
|
121 |
-
<label for="bookly-visibility"><?php _e( 'Visibility', 'bookly' ) ?></label>
|
122 |
-
<p class="help-block">
|
123 |
-
<?php _e( 'To make staff member invisible to your customers set the visibility to "Private".', 'bookly' ) ?>
|
124 |
-
</p>
|
125 |
-
<select name="visibility" class="form-control" id="bookly-visibility">
|
126 |
-
<option value="public" <?php selected( $staff->get( 'visibility' ), 'public' ) ?>><?php _e( 'Public', 'bookly' ) ?></option>
|
127 |
-
<option value="private" <?php selected( $staff->get( 'visibility' ), 'private' ) ?>><?php _e( 'Private', 'bookly' ) ?></option>
|
128 |
-
</select>
|
129 |
-
</div>
|
130 |
-
<?php do_action( 'bookly_render_staff_form', $staff ) ?>
|
131 |
-
<div class="form-group">
|
132 |
-
<h3><?php _e( 'Google Calendar integration', 'bookly' ) ?></h3>
|
133 |
-
<p class="help-block">
|
134 |
-
<?php _e( 'Synchronize staff member appointments with Google Calendar.', 'bookly' ) ?>
|
135 |
-
</p>
|
136 |
-
<p>
|
137 |
-
<?php if ( isset( $authUrl ) ) : ?>
|
138 |
-
<?php if ( $authUrl ) : ?>
|
139 |
-
<a href="<?php echo $authUrl ?>"><?php _e( 'Connect', 'bookly' ) ?></a>
|
140 |
-
<?php else : ?>
|
141 |
-
<?php printf( __( 'Please configure Google Calendar <a href="%s">settings</a> first', 'bookly' ), \BooklyLite\Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Settings\Controller::page_slug, array( 'tab' => 'google_calendar' ) ) ) ?>
|
142 |
-
<?php endif ?>
|
143 |
-
<?php else : ?>
|
144 |
-
<?php _e( 'Connected', 'bookly' ) ?> (<a href="<?php echo \BooklyLite\Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Staff\Controller::page_slug, array( 'google_logout' => $staff->get( 'id' ) ) ) ?>" ><?php _e( 'disconnect', 'bookly' ) ?></a>)
|
145 |
-
<?php endif ?>
|
146 |
-
</p>
|
147 |
-
</div>
|
148 |
-
<?php if ( ! isset( $authUrl ) ) : ?>
|
149 |
-
<div class="form-group">
|
150 |
-
<label for="bookly-calendar-id"><?php _e( 'Calendar', 'bookly' ) ?></label>
|
151 |
-
<select class="form-control" name="google_calendar_id" id="bookly-calendar-id">
|
152 |
-
<?php foreach ( $calendar_list as $id => $calendar ) : ?>
|
153 |
-
<option
|
154 |
-
<?php selected( $staff->get( 'google_calendar_id' ) == $id || $staff->get( 'google_calendar_id' ) == '' && $calendar['primary'] ) ?>
|
155 |
-
value="<?php echo esc_attr( $id ) ?>">
|
156 |
-
<?php echo esc_html( $calendar['summary'] ) ?>
|
157 |
-
</option>
|
158 |
-
<?php endforeach ?>
|
159 |
-
</select>
|
160 |
-
</div>
|
161 |
-
<?php endif ?>
|
162 |
-
|
163 |
-
<input type="hidden" name="id" value="<?php echo $staff->get( 'id' ) ?>">
|
164 |
-
<input type="hidden" name="attachment_id" value="<?php echo $staff->get( 'attachment_id' ) ?>">
|
165 |
-
|
166 |
-
<div class="panel-footer">
|
167 |
-
<?php if ( \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
168 |
-
<?php \BooklyLite\Lib\Utils\Common::deleteButton( 'bookly-delete', 'btn-lg pull-left' ) ?>
|
169 |
-
<?php endif ?>
|
170 |
-
<?php \BooklyLite\Lib\Utils\Common::submitButton() ?>
|
171 |
-
<?php \BooklyLite\Lib\Utils\Common::resetButton() ?>
|
172 |
-
</div>
|
173 |
-
</form>
|
174 |
-
</div>
|
175 |
</div>
|
176 |
<div class="tab-pane" id="services">
|
177 |
<div id="bookly-services-container" style="display: none"></div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) {
|
2 |
+
exit;
|
3 |
+
} // Exit if accessed directly
|
4 |
+
/** @var \BooklyLite\Lib\Entities\Staff $staff */
|
5 |
?>
|
6 |
<div class="panel panel-default bookly-main">
|
7 |
<div class="panel-body">
|
10 |
<div id="bookly-js-staff-avatar" class="bookly-thumb bookly-thumb-lg bookly-margin-right-lg">
|
11 |
<div class="bookly-flex-cell" style="width: 100%">
|
12 |
<div class="form-group">
|
13 |
+
<?php $img = wp_get_attachment_image_src( $staff->getAttachmentId(), 'thumbnail' ) ?>
|
14 |
|
15 |
<div class="bookly-js-image bookly-thumb bookly-thumb-lg bookly-margin-right-lg"
|
16 |
+
<?php echo $img ? 'style="background-image: url(' . $img[0] . '); background-size: cover;"' : '' ?>
|
17 |
>
|
18 |
<a class="dashicons dashicons-trash text-danger bookly-thumb-delete"
|
19 |
href="javascript:void(0)"
|
20 |
title="<?php esc_attr_e( 'Delete', 'bookly' ) ?>"
|
21 |
+
<?php if ( ! $img ) : ?>style="display: none;"<?php endif ?>>
|
22 |
</a>
|
23 |
<div class="bookly-thumb-edit">
|
24 |
<div class="bookly-pretty">
|
32 |
</div>
|
33 |
</div>
|
34 |
</div>
|
35 |
+
<div class="bookly-flex-cell bookly-vertical-top"><h1 class="bookly-js-staff-name-<?php echo $staff->getId() ?>"><?php echo $staff->getFullName() ?></h1></div>
|
36 |
</div>
|
37 |
|
38 |
<ul class="nav nav-tabs nav-justified bookly-nav-justified">
|
54 |
<span class="bookly-nav-tabs-title"><?php _e( 'Schedule', 'bookly' ) ?></span>
|
55 |
</a>
|
56 |
</li>
|
57 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderStaffTab( $staff ) ?>
|
58 |
<li>
|
59 |
<a id="bookly-holidays-tab" href="#daysoff" data-toggle="tab">
|
60 |
<i class="bookly-icon bookly-icon-daysoff"></i>
|
67 |
<div style="display: none;" class="bookly-loading"></div>
|
68 |
|
69 |
<div class="tab-pane active" id="details">
|
70 |
+
<div id="bookly-details-container"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
</div>
|
72 |
<div class="tab-pane" id="services">
|
73 |
<div id="bookly-services-container" style="display: none"></div>
|
backend/modules/staff/templates/holidays.php
CHANGED
@@ -15,28 +15,4 @@
|
|
15 |
</div>
|
16 |
</div>
|
17 |
</div>
|
18 |
-
|
19 |
-
<div class="bookly-js-holidays jCal-wrap bookly-margin-top-lg"></div>
|
20 |
-
|
21 |
-
<script>
|
22 |
-
jQuery(function ($) {
|
23 |
-
var d = new Date();
|
24 |
-
$('.bookly-js-holidays').jCal({
|
25 |
-
day : new Date(d.getFullYear(), 0, 1),
|
26 |
-
days : 1,
|
27 |
-
showMonths : 12,
|
28 |
-
scrollSpeed : 350,
|
29 |
-
events : <?php echo $holidays ?>,
|
30 |
-
action : 'bookly_staff_holidays_update',
|
31 |
-
staff_id : <?php echo $staff_id ?>,
|
32 |
-
dayOffset : <?php echo (int)get_option('start_of_week') ?>,
|
33 |
-
loadingImg : <?php echo json_encode( plugins_url( 'bookly-responsive-appointment-booking-tool/backend/resources/images/loading.gif' ) ) ?>
|
34 |
-
});
|
35 |
-
|
36 |
-
$('.bookly-js-jCalBtn').on('click', function(e) {
|
37 |
-
e.preventDefault();
|
38 |
-
var trigger = $(this).data('trigger');
|
39 |
-
$('.bookly-js-holidays').find($(trigger)).trigger('click');
|
40 |
-
})
|
41 |
-
});
|
42 |
-
</script>
|
15 |
</div>
|
16 |
</div>
|
17 |
</div>
|
18 |
+
<div class="bookly-js-holidays jCal-wrap bookly-margin-top-lg"></div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
backend/modules/staff/templates/index.php
CHANGED
@@ -14,7 +14,6 @@
|
|
14 |
</div>
|
15 |
<?php endif ?>
|
16 |
</div>
|
17 |
-
|
18 |
<div class="row">
|
19 |
<div id="bookly-sidebar" class="col-sm-4"
|
20 |
<?php if ( ! \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
14 |
</div>
|
15 |
<?php endif ?>
|
16 |
</div>
|
|
|
17 |
<div class="row">
|
18 |
<div id="bookly-sidebar" class="col-sm-4"
|
19 |
<?php if ( ! \BooklyLite\Lib\Utils\Common::isCurrentUserAdmin() ) : ?>
|
backend/modules/staff/templates/schedule.php
CHANGED
@@ -1,21 +1,24 @@
|
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
4 |
$default_breaks = array( 'staff_id' => 1 );
|
5 |
-
$break_start = new
|
6 |
$break_end = clone $working_end;
|
7 |
?>
|
8 |
<div>
|
9 |
<form>
|
10 |
<?php foreach ( $schedule_items as $item ) : ?>
|
11 |
-
<div data-id="<?php echo $item->
|
12 |
-
data-staff_schedule_item_id="<?php echo $item->
|
13 |
class="staff-schedule-item-row panel panel-default bookly-panel-unborder">
|
14 |
|
15 |
<div class="panel-heading bookly-padding-vertical-md">
|
16 |
<div class="row">
|
17 |
<div class="col-sm-7 col-lg-5">
|
18 |
-
<span class="panel-title"><?php _e( \BooklyLite\Lib\Utils\DateTime::getWeekDayByNumber( $item->
|
19 |
</div>
|
20 |
<div class="col-sm-5 col-lg-7 hidden-xs hidden-sm">
|
21 |
<div class="bookly-font-smaller bookly-color-gray">
|
@@ -26,78 +29,77 @@
|
|
26 |
</div>
|
27 |
|
28 |
<div class="panel-body padding-lr-none">
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
</div>
|
46 |
-
</div>
|
47 |
-
<div class="bookly-flex-cell" style="width: 50%">
|
48 |
-
<?php
|
49 |
-
echo $working_end->render(
|
50 |
-
"end_time[{$item->get( 'day_index' )}]",
|
51 |
-
$item->get( 'end_time' ),
|
52 |
-
array( 'class' => 'working-schedule-end form-control bookly-hide-on-off' )
|
53 |
-
);
|
54 |
-
?>
|
55 |
</div>
|
56 |
</div>
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
|
|
|
|
|
|
|
|
62 |
</div>
|
63 |
|
64 |
-
<
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
<?php _e( 'add break', 'bookly' ) ?>
|
70 |
-
</button>
|
71 |
|
72 |
-
|
73 |
-
|
|
|
|
|
|
|
|
|
|
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
<?php echo $break_end->render( '', $item->get( 'end_time' ), array( 'class' => 'break-end form-control' ) ) ?>
|
87 |
</div>
|
88 |
</div>
|
89 |
-
<
|
90 |
-
|
91 |
-
<?php \BooklyLite\Lib\Utils\Common::submitButton( null, 'bookly-js-save-break' ) ?>
|
92 |
-
<?php \BooklyLite\Lib\Utils\Common::customButton( null, 'bookly-popover-close btn-lg btn-default', __( 'Close', 'bookly' ) ) ?>
|
93 |
</div>
|
94 |
</div>
|
|
|
|
|
|
|
|
|
|
|
95 |
</div>
|
96 |
</div>
|
|
|
97 |
|
98 |
-
|
99 |
-
|
100 |
-
</div>
|
101 |
</div>
|
102 |
</div>
|
103 |
</div>
|
@@ -106,10 +108,11 @@
|
|
106 |
<?php endforeach ?>
|
107 |
|
108 |
<input type="hidden" name="action" value="bookly_staff_schedule_update">
|
|
|
109 |
|
110 |
<div class="panel-footer">
|
111 |
-
<?php
|
112 |
-
<?php
|
113 |
</div>
|
114 |
</form>
|
115 |
</div>
|
1 |
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use BooklyLite\Backend\Modules\Staff\Forms\Widgets\TimeChoice;
|
3 |
+
use BooklyLite\Lib\Utils\Common;
|
4 |
+
/** @var \BooklyLite\Lib\Entities\StaffScheduleItem[] $schedule_items */
|
5 |
+
$working_start = new TimeChoice( array( 'empty_value' => __( 'OFF', 'bookly' ), 'type' => 'from' ) );
|
6 |
+
$working_end = new TimeChoice( array( 'use_empty' => false, 'type' => 'to' ) );
|
7 |
$default_breaks = array( 'staff_id' => 1 );
|
8 |
+
$break_start = new TimeChoice( array( 'use_empty' => false, 'type' => 'break_from' ) );
|
9 |
$break_end = clone $working_end;
|
10 |
?>
|
11 |
<div>
|
12 |
<form>
|
13 |
<?php foreach ( $schedule_items as $item ) : ?>
|
14 |
+
<div data-id="<?php echo $item->getDayIndex() ?>"
|
15 |
+
data-staff_schedule_item_id="<?php echo $item->getId() ?>"
|
16 |
class="staff-schedule-item-row panel panel-default bookly-panel-unborder">
|
17 |
|
18 |
<div class="panel-heading bookly-padding-vertical-md">
|
19 |
<div class="row">
|
20 |
<div class="col-sm-7 col-lg-5">
|
21 |
+
<span class="panel-title"><?php _e( \BooklyLite\Lib\Utils\DateTime::getWeekDayByNumber( $item->getDayIndex() - 1 ) /* take translation from WP catalog */ ) ?></span>
|
22 |
</div>
|
23 |
<div class="col-sm-5 col-lg-7 hidden-xs hidden-sm">
|
24 |
<div class="bookly-font-smaller bookly-color-gray">
|
29 |
</div>
|
30 |
|
31 |
<div class="panel-body padding-lr-none">
|
32 |
+
<div class="row">
|
33 |
+
<div class="col-sm-7 col-lg-5">
|
34 |
+
<div class="bookly-flexbox">
|
35 |
+
<div class="bookly-flex-cell" style="width: 50%">
|
36 |
+
<?php
|
37 |
+
$day_is_not_available = null === $item->getStartTime();
|
38 |
+
echo $working_start->render(
|
39 |
+
"start_time[{$item->getDayIndex()}]",
|
40 |
+
$item->getStartTime(),
|
41 |
+
array( 'class' => 'working-schedule-start form-control' )
|
42 |
+
);
|
43 |
+
?>
|
44 |
+
</div>
|
45 |
+
<div class="bookly-flex-cell text-center" style="width: 1%">
|
46 |
+
<div class="bookly-margin-horizontal-lg bookly-hide-on-off">
|
47 |
+
<?php _e( 'to', 'bookly' ) ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
</div>
|
49 |
</div>
|
50 |
+
<div class="bookly-flex-cell" style="width: 50%">
|
51 |
+
<?php
|
52 |
+
echo $working_end->render(
|
53 |
+
"end_time[{$item->getDayIndex()}]",
|
54 |
+
$item->getEndTime(),
|
55 |
+
array( 'class' => 'working-schedule-end form-control bookly-hide-on-off' )
|
56 |
+
);
|
57 |
+
?>
|
58 |
+
</div>
|
59 |
</div>
|
60 |
|
61 |
+
<input type="hidden"
|
62 |
+
name="days[<?php echo $item->getId() ?>]"
|
63 |
+
value="<?php echo $item->getDayIndex() ?>"
|
64 |
+
>
|
65 |
+
</div>
|
|
|
|
|
66 |
|
67 |
+
<div class="col-sm-5 col-lg-7">
|
68 |
+
<div class="bookly-intervals-wrapper bookly-hide-on-off">
|
69 |
+
<button type="button"
|
70 |
+
class="bookly-js-toggle-popover btn btn-link bookly-btn-unborder bookly-margin-vertical-screenxs-sm"
|
71 |
+
data-popover-content=".bookly-js-content-break-<?php echo $item->getId() ?>">
|
72 |
+
<?php _e( 'add break', 'bookly' ) ?>
|
73 |
+
</button>
|
74 |
|
75 |
+
<div class="bookly-js-content-break-<?php echo $item->getId() ?> hidden">
|
76 |
+
<div class="error" style="display: none"></div>
|
77 |
+
|
78 |
+
<div class="bookly-js-schedule-form">
|
79 |
+
<div class="bookly-flexbox" style="width: 260px">
|
80 |
+
<div class="bookly-flex-cell" style="width: 48%;">
|
81 |
+
<?php echo $break_start->render( '', $item->getStartTime(), array( 'class' => 'break-start form-control' ) ) ?>
|
82 |
+
</div>
|
83 |
+
<div class="bookly-flex-cell" style="width: 4%;">
|
84 |
+
<div class="bookly-margin-horizontal-lg">
|
85 |
+
<?php _e( 'to', 'bookly' ) ?>
|
|
|
86 |
</div>
|
87 |
</div>
|
88 |
+
<div class="bookly-flex-cell" style="width: 48%;">
|
89 |
+
<?php echo $break_end->render( '', $item->getEndTime(), array( 'class' => 'break-end form-control' ) ) ?>
|
|
|
|
|
90 |
</div>
|
91 |
</div>
|
92 |
+
<hr>
|
93 |
+
<div class="text-right">
|
94 |
+
<?php Common::customButton( null, 'bookly-js-save-break btn-lg btn-success', __( 'Save', 'bookly' ) ) ?>
|
95 |
+
<?php Common::customButton( null, 'bookly-popover-close btn-lg btn-default', __( 'Close', 'bookly' ) ) ?>
|
96 |
+
</div>
|
97 |
</div>
|
98 |
</div>
|
99 |
+
</div>
|
100 |
|
101 |
+
<div class="breaks bookly-hide-on-off">
|
102 |
+
<?php include '_breaks.php' ?>
|
|
|
103 |
</div>
|
104 |
</div>
|
105 |
</div>
|
108 |
<?php endforeach ?>
|
109 |
|
110 |
<input type="hidden" name="action" value="bookly_staff_schedule_update">
|
111 |
+
<?php Common::csrf() ?>
|
112 |
|
113 |
<div class="panel-footer">
|
114 |
+
<?php Common::submitButton( 'bookly-schedule-save' ) ?>
|
115 |
+
<?php Common::customButton( 'bookly-schedule-reset', 'btn-lg btn-default', __( 'Reset', 'bookly' ), array( 'data-default-breaks' => esc_attr( json_encode( $default_breaks ) ), 'data-spinner-color' => 'rgb(62, 66, 74)' ) ) ?>
|
116 |
</div>
|
117 |
</form>
|
118 |
</div>
|
backend/modules/staff/templates/services.php
CHANGED
@@ -1,4 +1,6 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
|
|
|
|
2 |
<div>
|
3 |
<?php if ( $categories || $uncategorized_services ) : ?>
|
4 |
<form>
|
@@ -6,7 +8,7 @@
|
|
6 |
<div class="panel panel-default bookly-panel-unborder">
|
7 |
<div class="panel-heading">
|
8 |
<div class="row">
|
9 |
-
<div class="col-
|
10 |
<div class="checkbox bookly-margin-remove">
|
11 |
<label>
|
12 |
<input id="bookly-check-all-entities" type="checkbox">
|
@@ -14,18 +16,15 @@
|
|
14 |
</label>
|
15 |
</div>
|
16 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
-
|
19 |
-
<div class="bookly-font-smaller bookly-color-gray">
|
20 |
-
<?php _e( 'Price', 'bookly' ) ?>
|
21 |
-
</div>
|
22 |
-
</div>
|
23 |
-
|
24 |
-
<?php do_action( 'bookly_deposit_payments_staff_service_label' ) ?>
|
25 |
-
|
26 |
-
<div class="<?php echo apply_filters( 'bookly_staff_service_label_col_size', 'col-md-3' ) ?> hidden-xs hidden-sm">
|
27 |
-
<div class="bookly-font-smaller bookly-color-gray bookly-truncate">
|
28 |
-
<?php _e( 'Capacity', 'bookly' ) ?>
|
29 |
</div>
|
30 |
</div>
|
31 |
</div>
|
@@ -33,12 +32,12 @@
|
|
33 |
|
34 |
<ul class="bookly-category-services list-group bookly-padding-top-md">
|
35 |
<?php foreach ( $uncategorized_services as $service ) : ?>
|
36 |
-
<li class="list-group-item">
|
37 |
<div class="row">
|
38 |
-
<div class="col-
|
39 |
<div class="checkbox">
|
40 |
<label>
|
41 |
-
<input class="
|
42 |
type="checkbox" value="<?php echo $service['id'] ?>"
|
43 |
name="service[<?php echo $service['id'] ?>]"
|
44 |
>
|
@@ -46,30 +45,44 @@
|
|
46 |
</label>
|
47 |
</div>
|
48 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
</div>
|
66 |
-
<input class="form-control" type="number" min=1 <?php disabled( ! array_key_exists( $service['id'], $services_data ) ) ?>
|
67 |
-
name="capacity[<?php echo $service['id'] ?>]"
|
68 |
-
value="<?php echo array_key_exists( $service['id'], $services_data ) ? $services_data[ $service['id'] ]['capacity'] : $service['capacity'] ?>"
|
69 |
-
>
|
70 |
</div>
|
71 |
</div>
|
72 |
-
<?php
|
73 |
</li>
|
74 |
<?php endforeach ?>
|
75 |
</ul>
|
@@ -79,70 +92,84 @@
|
|
79 |
<?php if ( ! empty ( $categories ) ) : ?>
|
80 |
<?php foreach ( $categories as $category ) : ?>
|
81 |
<div class="panel panel-default bookly-panel-unborder">
|
82 |
-
<div class="panel-heading
|
83 |
<div class="row">
|
84 |
-
<div class="col-
|
85 |
<div class="checkbox bookly-margin-remove">
|
86 |
<label>
|
87 |
-
<input type="checkbox" class="bookly-category-checkbox bookly-category-<?php echo $category->
|
88 |
-
data-category-id="<?php echo $category->
|
89 |
-
<b><?php echo esc_html( $category->
|
90 |
</label>
|
91 |
</div>
|
92 |
</div>
|
|
|
|
|
|
|
|
|
|
|
93 |
|
94 |
-
|
95 |
-
|
96 |
-
</div>
|
97 |
-
|
98 |
-
<?php do_action( 'bookly_deposit_payments_staff_service_label' ) ?>
|
99 |
-
|
100 |
-
<div class="<?php echo apply_filters( 'bookly_staff_service_label_col_size', 'col-xs-5 col-md-3')?> hidden-xs hidden-sm">
|
101 |
-
<div class="bookly-font-smaller bookly-color-gray bookly-truncate"><?php _e( 'Capacity', 'bookly' ) ?></div>
|
102 |
</div>
|
103 |
</div>
|
104 |
</div>
|
105 |
|
106 |
<ul class="bookly-category-services list-group bookly-padding-top-md">
|
107 |
<?php foreach ( $category->getServices() as $service ) : ?>
|
108 |
-
|
|
|
109 |
<div class="row">
|
110 |
-
<div class="col-
|
111 |
<div class="checkbox">
|
112 |
<label>
|
113 |
-
<input class="
|
114 |
-
data-category-id="<?php echo $category->
|
115 |
-
type="checkbox" value="<?php echo $service->
|
116 |
-
name="service[<?php echo $service->
|
117 |
>
|
118 |
-
<span class="bookly-toggle-label"><?php echo esc_html( $service->
|
119 |
</label>
|
120 |
</div>
|
121 |
</div>
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
138 |
</div>
|
139 |
-
<input class="form-control" type="number" min="1" <?php disabled( ! array_key_exists( $service->get( 'id' ), $services_data ) ) ?>
|
140 |
-
name="capacity[<?php echo $service->get( 'id' ) ?>]"
|
141 |
-
value="<?php echo array_key_exists( $service->get( 'id' ), $services_data ) ? $services_data[ $service->get( 'id' ) ]['capacity'] : $service->get( 'capacity' ) ?>"
|
142 |
-
>
|
143 |
</div>
|
144 |
</div>
|
145 |
-
<?php
|
146 |
</li>
|
147 |
<?php endforeach ?>
|
148 |
</ul>
|
@@ -152,8 +179,10 @@
|
|
152 |
|
153 |
<input type="hidden" name="action" value="bookly_staff_services_update">
|
154 |
<input type="hidden" name="staff_id" value="<?php echo $staff_id ?>">
|
|
|
155 |
|
156 |
<div class="panel-footer">
|
|
|
157 |
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'bookly-services-save' ) ?>
|
158 |
<?php \BooklyLite\Lib\Utils\Common::resetButton( 'bookly-services-reset' ) ?>
|
159 |
</div>
|
@@ -167,4 +196,7 @@
|
|
167 |
</a>
|
168 |
</p>
|
169 |
<?php endif ?>
|
170 |
-
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var \BooklyLite\Lib\Entities\Category[] $categories */
|
3 |
+
?>
|
4 |
<div>
|
5 |
<?php if ( $categories || $uncategorized_services ) : ?>
|
6 |
<form>
|
8 |
<div class="panel panel-default bookly-panel-unborder">
|
9 |
<div class="panel-heading">
|
10 |
<div class="row">
|
11 |
+
<div class="col-lg-6">
|
12 |
<div class="checkbox bookly-margin-remove">
|
13 |
<label>
|
14 |
<input id="bookly-check-all-entities" type="checkbox">
|
16 |
</label>
|
17 |
</div>
|
18 |
</div>
|
19 |
+
<div class="col-lg-6">
|
20 |
+
<div class="row">
|
21 |
+
<div class="<?php echo \BooklyLite\Lib\Proxy\Shared::prepareStaffServiceLabelClass( 'col-lg-12' ) ?> hidden-xs hidden-sm hidden-md text-right">
|
22 |
+
<div class="bookly-font-smaller bookly-color-gray">
|
23 |
+
<?php _e( 'Price', 'bookly' ) ?>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
|
27 |
+
<?php \BooklyLite\Lib\Proxy\DepositPayments::renderStaffServiceLabel() ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
28 |
</div>
|
29 |
</div>
|
30 |
</div>
|
32 |
|
33 |
<ul class="bookly-category-services list-group bookly-padding-top-md">
|
34 |
<?php foreach ( $uncategorized_services as $service ) : ?>
|
35 |
+
<li class="list-group-item" data-service-id="<?php echo $service['id'] ?>" data-service-type="<?php echo $service['type'] ?>" data-sub-service="<?php echo $service['sub_service_id'] ?>">
|
36 |
<div class="row">
|
37 |
+
<div class="col-lg-6">
|
38 |
<div class="checkbox">
|
39 |
<label>
|
40 |
+
<input class="bookly-service-checkbox" <?php checked( array_key_exists( $service['id'], $services_data ) ) ?>
|
41 |
type="checkbox" value="<?php echo $service['id'] ?>"
|
42 |
name="service[<?php echo $service['id'] ?>]"
|
43 |
>
|
45 |
</label>
|
46 |
</div>
|
47 |
</div>
|
48 |
+
<div class="col-lg-6">
|
49 |
+
<div class="row">
|
50 |
+
<div class="<?php echo \BooklyLite\Lib\Proxy\Shared::prepareStaffServiceInputClass( 'col-xs-12' ) ?>">
|
51 |
+
<div class="bookly-font-smaller bookly-margin-bottom-xs bookly-color-gray visible-xs visible-sm visible-md">
|
52 |
+
<?php _e( 'Price', 'bookly' ) ?>
|
53 |
+
</div>
|
54 |
+
<input class="form-control text-right" type="text" <?php disabled( !array_key_exists( $service['id'], $services_data ) ) ?>
|
55 |
+
name="price[<?php echo $service['id'] ?>]"
|
56 |
+
value="<?php echo array_key_exists( $service['id'], $services_data ) ? $services_data[ $service['id'] ]['price'] : $service['price'] ?>"
|
57 |
+
>
|
58 |
+
</div>
|
59 |
|
60 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderStaffService( $staff_id, $service['id'], $services_data, $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ? array( 'read-only' => array( 'deposit' => true ) ) : array() ) ?>
|
61 |
+
|
62 |
+
<div style="display: none">
|
63 |
+
<div class="form-group bookly-js-capacity-form-group">
|
64 |
+
<div class="row">
|
65 |
+
<div class="col-xs-6">
|
66 |
+
<input class="form-control bookly-js-capacity bookly-js-capacity-min" type="number" min=1 <?php disabled( ! array_key_exists( $service['id'], $services_data ) ) ?>
|
67 |
+
name="capacity_min[<?php echo $service['id'] ?>]"
|
68 |
+
value="1"
|
69 |
+
<?php if ( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ) : ?>readonly<?php endif ?>
|
70 |
+
>
|
71 |
+
</div>
|
72 |
+
<div class="col-xs-6">
|
73 |
+
<input class="form-control bookly-js-capacity bookly-js-capacity-max" type="number" min=1 <?php disabled( ! array_key_exists( $service['id'], $services_data ) ) ?>
|
74 |
+
name="capacity_max[<?php echo $service['id'] ?>]"
|
75 |
+
value="1"
|
76 |
+
<?php if ( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ) : ?>readonly<?php endif ?>
|
77 |
+
>
|
78 |
+
</div>
|
79 |
+
</div>
|
80 |
+
</div>
|
81 |
+
</div>
|
82 |
</div>
|
|
|
|
|
|
|
|
|
83 |
</div>
|
84 |
</div>
|
85 |
+
<?php if ( $service['type'] == \BooklyLite\Lib\Entities\Service::TYPE_SIMPLE ) { \BooklyLite\Lib\Proxy\Shared::renderStaffServiceTail( $staff_id, $service[ 'id' ] ); } ?>
|
86 |
</li>
|
87 |
<?php endforeach ?>
|
88 |
</ul>
|
92 |
<?php if ( ! empty ( $categories ) ) : ?>
|
93 |
<?php foreach ( $categories as $category ) : ?>
|
94 |
<div class="panel panel-default bookly-panel-unborder">
|
95 |
+
<div class="panel-heading bookly-services-category">
|
96 |
<div class="row">
|
97 |
+
<div class="col-lg-6">
|
98 |
<div class="checkbox bookly-margin-remove">
|
99 |
<label>
|
100 |
+
<input type="checkbox" class="bookly-category-checkbox bookly-category-<?php echo $category->getId() ?>"
|
101 |
+
data-category-id="<?php echo $category->getId() ?>">
|
102 |
+
<b><?php echo esc_html( $category->getName() ) ?></b>
|
103 |
</label>
|
104 |
</div>
|
105 |
</div>
|
106 |
+
<div class="col-lg-6">
|
107 |
+
<div class="row">
|
108 |
+
<div class="<?php echo \BooklyLite\Lib\Proxy\Shared::prepareStaffServiceLabelClass( 'col-lg-12' )?> hidden-xs hidden-sm hidden-md text-right">
|
109 |
+
<div class="bookly-font-smaller bookly-color-gray"><?php _e( 'Price', 'bookly' ) ?></div>
|
110 |
+
</div>
|
111 |
|
112 |
+
<?php \BooklyLite\Lib\Proxy\DepositPayments::renderStaffServiceLabel() ?>
|
113 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
114 |
</div>
|
115 |
</div>
|
116 |
</div>
|
117 |
|
118 |
<ul class="bookly-category-services list-group bookly-padding-top-md">
|
119 |
<?php foreach ( $category->getServices() as $service ) : ?>
|
120 |
+
<?php $sub_service = current( $service->getSubServices() ) ?>
|
121 |
+
<li class="list-group-item" data-service-id="<?php echo $service->getId() ?>" data-service-type="<?php echo $service->getType() ?>" data-sub-service="<?php echo empty( $sub_service ) ? null : $sub_service->getId(); ?>">
|
122 |
<div class="row">
|
123 |
+
<div class="col-lg-6">
|
124 |
<div class="checkbox">
|
125 |
<label>
|
126 |
+
<input class="bookly-service-checkbox bookly-category-<?php echo $category->getId() ?>"
|
127 |
+
data-category-id="<?php echo $category->getId() ?>" <?php checked( array_key_exists( $service->getId(), $services_data ) ) ?>
|
128 |
+
type="checkbox" value="<?php echo $service->getId() ?>"
|
129 |
+
name="service[<?php echo $service->getId() ?>]"
|
130 |
>
|
131 |
+
<span class="bookly-toggle-label"><?php echo esc_html( $service->getTitle() ) ?></span>
|
132 |
</label>
|
133 |
</div>
|
134 |
</div>
|
135 |
+
<div class="col-lg-6">
|
136 |
+
<div class="row">
|
137 |
+
<div class="<?php echo \BooklyLite\Lib\Proxy\Shared::prepareStaffServiceInputClass( 'col-xs-12' ) ?>">
|
138 |
+
<div class="bookly-font-smaller bookly-margin-bottom-xs bookly-color-gray visible-xs visible-sm visible-md">
|
139 |
+
<?php _e( 'Price', 'bookly' ) ?>
|
140 |
+
</div>
|
141 |
+
<input class="form-control text-right" type="text" <?php disabled( ! array_key_exists( $service->getId(), $services_data ) ) ?>
|
142 |
+
name="price[<?php echo $service->getId() ?>]"
|
143 |
+
value="<?php echo array_key_exists( $service->getId(), $services_data ) ? $services_data[ $service->getId() ]['price'] : $service->getPrice() ?>"
|
144 |
+
>
|
145 |
+
</div>
|
146 |
+
|
147 |
+
<?php \BooklyLite\Lib\Proxy\Shared::renderStaffService( $staff_id, $service->getId(), $services_data, $service->getType() == \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ? array( 'read-only' => array( 'deposit' => true ) ) : array() ) ?>
|
148 |
+
|
149 |
+
<div style="display: none">
|
150 |
+
<div class="form-group bookly-js-capacity-form-group">
|
151 |
+
<div class="row">
|
152 |
+
<div class="col-xs-6">
|
153 |
+
<input class="form-control bookly-js-capacity bookly-js-capacity-min" type="number" min="1" <?php disabled( ! array_key_exists( $service->getId(), $services_data ) ) ?>
|
154 |
+
name="capacity_min[<?php echo $service->getId() ?>]"
|
155 |
+
value="1"
|
156 |
+
<?php if ( $service->getType() == \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ) : ?>readonly<?php endif ?>
|
157 |
+
>
|
158 |
+
</div>
|
159 |
+
<div class="col-xs-6">
|
160 |
+
<input class="form-control bookly-js-capacity bookly-js-capacity-max" type="number" min="1" <?php disabled( ! array_key_exists( $service->getId(), $services_data ) ) ?>
|
161 |
+
name="capacity_max[<?php echo $service->getId() ?>]"
|
162 |
+
value="1"
|
163 |
+
<?php if ( $service->getType() == \BooklyLite\Lib\Entities\Service::TYPE_PACKAGE ) : ?>readonly<?php endif ?>
|
164 |
+
>
|
165 |
+
</div>
|
166 |
+
</div>
|
167 |
+
</div>
|
168 |
+
</div>
|
169 |
</div>
|
|
|
|
|
|
|
|
|
170 |
</div>
|
171 |
</div>
|
172 |
+
<?php if ( $service->getType() == \BooklyLite\Lib\Entities\Service::TYPE_SIMPLE ) { \BooklyLite\Lib\Proxy\Shared::renderStaffServiceTail( $staff_id, $service->getId() ); } ?>
|
173 |
</li>
|
174 |
<?php endforeach ?>
|
175 |
</ul>
|
179 |
|
180 |
<input type="hidden" name="action" value="bookly_staff_services_update">
|
181 |
<input type="hidden" name="staff_id" value="<?php echo $staff_id ?>">
|
182 |
+
<?php \BooklyLite\Lib\Utils\Common::csrf() ?>
|
183 |
|
184 |
<div class="panel-footer">
|
185 |
+
<span class="bookly-js-services-error text-danger"></span>
|
186 |
<?php \BooklyLite\Lib\Utils\Common::submitButton( 'bookly-services-save' ) ?>
|
187 |
<?php \BooklyLite\Lib\Utils\Common::resetButton( 'bookly-services-reset' ) ?>
|
188 |
</div>
|
196 |
</a>
|
197 |
</p>
|
198 |
<?php endif ?>
|
199 |
+
<div style="display: none">
|
200 |
+
<?php BooklyLite\Lib\Proxy\Shared::renderStaffServices( $staff_id ) ?>
|
201 |
+
</div>
|
202 |
+
</div>
|
backend/modules/support/Components.php
CHANGED
@@ -10,6 +10,8 @@ use BooklyLite\Backend\Modules;
|
|
10 |
*/
|
11 |
class Components extends Lib\Base\Components
|
12 |
{
|
|
|
|
|
13 |
/**
|
14 |
* Render support buttons.
|
15 |
*/
|
@@ -20,7 +22,7 @@ class Components extends Lib\Base\Components
|
|
20 |
) );
|
21 |
|
22 |
$this->enqueueScripts( array(
|
23 |
-
'backend'
|
24 |
'frontend' => array(
|
25 |
'js/spin.min.js' => array( 'jquery' ),
|
26 |
'js/ladda.min.js' => array( 'jquery' ),
|
@@ -44,7 +46,13 @@ class Components extends Lib\Base\Components
|
|
44 |
|
45 |
$current_user = wp_get_current_user();
|
46 |
|
47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
}
|
49 |
|
50 |
/**
|
@@ -56,9 +64,7 @@ class Components extends Lib\Base\Components
|
|
56 |
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_subscribe_notice', true ) ) {
|
57 |
|
58 |
// Show notice 1 day after installation time.
|
59 |
-
|
60 |
-
|
61 |
-
if ( $days_in_use >= 1 ) {
|
62 |
$this->enqueueStyles( array(
|
63 |
'frontend' => array( 'css/ladda.min.css', ),
|
64 |
) );
|
@@ -74,4 +80,39 @@ class Components extends Lib\Base\Components
|
|
74 |
}
|
75 |
}
|
76 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
10 |
*/
|
11 |
class Components extends Lib\Base\Components
|
12 |
{
|
13 |
+
const BOOKLY_WORDPRESS_URL = 'https://wordpress.org/support/plugin/bookly-responsive-appointment-booking-tool/reviews/';
|
14 |
+
|
15 |
/**
|
16 |
* Render support buttons.
|
17 |
*/
|
22 |
) );
|
23 |
|
24 |
$this->enqueueScripts( array(
|
25 |
+
'backend' => array( 'js/alert.js' => array( 'jquery' ), ),
|
26 |
'frontend' => array(
|
27 |
'js/spin.min.js' => array( 'jquery' ),
|
28 |
'js/ladda.min.js' => array( 'jquery' ),
|
46 |
|
47 |
$current_user = wp_get_current_user();
|
48 |
|
49 |
+
wp_localize_script( 'bookly-support.js', 'SupportL10n', array(
|
50 |
+
'csrf_token' => \BooklyLite\Lib\Utils\Common::getCsrfToken()
|
51 |
+
) );
|
52 |
+
$messages = Lib\Entities\Message::query( 'm' )->select( 'm.created, m.subject, m.seen' )->sortBy( 'm.seen, m.message_id' )->order( 'DESC' )->limit( 10 )->fetchArray();
|
53 |
+
$messages_new = Lib\Entities\Message::query( 'm' )->where( 'm.seen', '0' )->count();
|
54 |
+
$messages_link = Lib\Utils\Common::escAdminUrl( \BooklyLite\Backend\Modules\Message\Controller::page_slug );
|
55 |
+
$this->render( '_buttons', compact( 'doc_link', 'show_contact_us_notice', 'show_feedback_notice', 'current_user', 'messages', 'messages_new', 'messages_link' ) );
|
56 |
}
|
57 |
|
58 |
/**
|
64 |
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_subscribe_notice', true ) ) {
|
65 |
|
66 |
// Show notice 1 day after installation time.
|
67 |
+
if ( time() - Lib\Plugin::getInstallationTime() >= DAY_IN_SECONDS ) {
|
|
|
|
|
68 |
$this->enqueueStyles( array(
|
69 |
'frontend' => array( 'css/ladda.min.css', ),
|
70 |
) );
|
80 |
}
|
81 |
}
|
82 |
}
|
83 |
+
|
84 |
+
/**
|
85 |
+
* Render Net Promoter Score notice.
|
86 |
+
*/
|
87 |
+
public function renderNpsNotice()
|
88 |
+
{
|
89 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
90 |
+
$dismiss_value = get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', true );
|
91 |
+
//
|