Version Description
Download this release
Release Info
Developer | Ladela |
Plugin | WordPress Online Booking and Scheduling Plugin – Bookly |
Version | 16.2 |
Comparing to | |
See all releases |
Code changes from version 16.1 to 16.2
- autoload.php +18 -18
- backend/Backend.php +117 -117
- backend/components/appearance/Codes.php +39 -40
- backend/components/appearance/Editable.php +112 -108
- backend/components/appearance/proxy/Pro.php +15 -15
- backend/components/appearance/proxy/Shared.php +14 -14
- backend/components/controls/Buttons.php +126 -126
- backend/components/controls/Inputs.php +21 -21
- backend/components/dialogs/appointment/attach_payment/proxy/Pro.php +14 -14
- backend/components/dialogs/appointment/attach_payment/proxy/Taxes.php +14 -14
- backend/components/dialogs/appointment/customer_details/Dialog.php +18 -18
- backend/components/dialogs/appointment/customer_details/proxy/Files.php +14 -14
- backend/components/dialogs/appointment/customer_details/proxy/Pro.php +14 -14
- backend/components/dialogs/appointment/customer_details/proxy/Shared.php +14 -14
- backend/components/dialogs/appointment/customer_details/templates/customer_details.php +53 -53
- backend/components/dialogs/appointment/delete/Ajax.php +55 -55
- backend/components/dialogs/appointment/delete/Dialog.php +32 -32
- backend/components/dialogs/appointment/delete/resources/js/delete_dialog.js +8 -8
- backend/components/dialogs/appointment/delete/templates/delete.php +28 -28
- backend/components/dialogs/appointment/edit/Ajax.php +852 -807
- backend/components/dialogs/appointment/edit/Dialog.php +63 -63
- backend/components/dialogs/appointment/edit/proxy/Pro.php +16 -16
- backend/components/dialogs/appointment/edit/proxy/RecurringAppointments.php +16 -16
- backend/components/dialogs/appointment/edit/proxy/Shared.php +18 -18
- backend/components/dialogs/appointment/edit/proxy/Tasks.php +14 -14
- backend/components/dialogs/appointment/edit/resources/js/ng-appointment.js +1371 -1340
- backend/components/dialogs/appointment/edit/templates/edit.php +253 -241
- backend/components/dialogs/common/CascadeDelete.php +29 -29
- backend/components/dialogs/common/UnsavedChanges.php +29 -29
- backend/components/dialogs/common/templates/delete_cascade.php +20 -20
- backend/components/dialogs/common/templates/unsaved_changes.php +20 -20
- backend/components/dialogs/customer/delete/Ajax.php +130 -0
- backend/components/dialogs/customer/delete/Dialog.php +36 -0
- backend/components/dialogs/customer/delete/resources/js/delete-customers.js +94 -0
- backend/components/dialogs/customer/delete/templates/dialog.php +42 -0
- backend/components/dialogs/customer/{EditAjax.php → edit/Ajax.php} +102 -102
- backend/components/dialogs/customer/{Edit.php → edit/Dialog.php} +62 -60
- backend/components/dialogs/customer/{forms → edit/forms}/Customer.php +36 -36
- backend/components/dialogs/customer/edit/proxy/CustomerGroups.php +15 -0
- backend/components/dialogs/customer/edit/proxy/CustomerInformation.php +16 -0
- backend/components/dialogs/customer/edit/proxy/Pro.php +16 -0
- backend/components/dialogs/customer/{resources → edit/resources}/js/ng-customer.js +214 -196
- backend/components/dialogs/customer/{templates → edit/templates}/edit.php +82 -83
- backend/components/dialogs/customer/proxy/CustomerGroups.php +13 -15
- backend/components/dialogs/customer/proxy/CustomerInformation.php +13 -15
- backend/components/dialogs/customer/proxy/Pro.php +13 -15
- backend/components/dialogs/payment/Ajax.php +104 -104
- backend/components/dialogs/payment/Dialog.php +31 -31
- backend/components/dialogs/payment/resources/js/ng-payment_details.js +150 -150
- backend/components/dialogs/payment/templates/details.php +216 -216
- backend/components/dialogs/payment/templates/dialog.php +20 -20
- backend/components/dialogs/special_price/proxy/SpecialHours.php +13 -13
- backend/components/notices/CollectStats.php +46 -46
- backend/components/notices/CollectStatsAjax.php +40 -40
- backend/components/notices/Limitation.php +18 -18
- backend/components/notices/LiteRebranding.php +26 -26
- backend/components/notices/LiteRebrandingAjax.php +20 -20
- backend/components/notices/Nps.php +47 -47
- backend/components/notices/NpsAjax.php +39 -39
- backend/components/notices/Subscribe.php +37 -37
- backend/components/notices/SubscribeAjax.php +45 -35
- backend/components/notices/proxy/Pro.php +14 -14
- backend/components/notices/resources/css/bootstrap-stars.css +38 -38
- backend/components/notices/resources/js/collect-stats.js +8 -8
- backend/components/notices/resources/js/lite-rebranding.js +5 -5
- backend/components/notices/resources/js/nps.js +59 -59
- backend/components/notices/resources/js/subscribe.js +23 -23
- backend/components/notices/templates/collect_stats.php +22 -22
- backend/components/notices/templates/limitation.php +2 -2
- backend/components/notices/templates/lite_rebranding.php +11 -11
- backend/components/notices/templates/nps.php +40 -40
- backend/components/notices/templates/subscribe.php +20 -20
- backend/components/settings/Image.php +29 -29
- backend/components/settings/Inputs.php +98 -75
- backend/components/settings/Menu.php +22 -22
- backend/components/settings/Payments.php +40 -40
- backend/components/settings/Selects.php +79 -79
- backend/components/settings/proxy/Pro.php +14 -14
- backend/components/settings/proxy/Taxes.php +14 -14
- backend/components/settings/templates/image.php +47 -47
- backend/components/settings/templates/price_correction.php +17 -17
- backend/components/sms/custom/Notification.php +46 -0
- backend/components/sms/custom/templates/after_event.php +93 -0
- backend/components/sms/custom/templates/existing_event_with_date.php +31 -0
- backend/components/sms/custom/templates/existing_event_with_date_and_time.php +93 -0
- backend/components/sms/custom/templates/existing_event_with_date_before.php +28 -0
- backend/components/sms/custom/templates/layout.php +125 -0
- backend/components/support/Buttons.php +74 -73
- backend/components/support/ButtonsAjax.php +87 -77
- backend/components/support/lib/Urls.php +11 -10
- backend/components/support/resources/js/support.js +173 -135
- backend/components/support/templates/_email_to_support.php +18 -18
- backend/components/support/templates/buttons.php +126 -85
- backend/components/tiny_mce/Tools.php +58 -58
- backend/components/tiny_mce/proxy/DepositPayments.php +14 -14
- backend/components/tiny_mce/proxy/GroupBooking.php +14 -14
- backend/components/tiny_mce/proxy/Shared.php +17 -17
- backend/components/tiny_mce/proxy/SpecialDays.php +14 -14
- backend/components/tiny_mce/proxy/SpecialHours.php +14 -14
- backend/components/tiny_mce/templates/bookly_form.php +424 -423
- backend/modules/appearance/Ajax.php +135 -131
- backend/modules/appearance/Page.php +107 -102
- backend/modules/appearance/proxy/Cart.php +16 -16
- backend/modules/appearance/proxy/ChainAppointments.php +13 -13
- backend/modules/appearance/proxy/Coupons.php +15 -15
- backend/modules/appearance/proxy/CustomDuration.php +14 -14
- backend/modules/appearance/proxy/CustomFields.php +14 -14
- backend/modules/appearance/proxy/CustomerInformation.php +14 -14
- backend/modules/appearance/proxy/DepositPayments.php +14 -14
- backend/modules/appearance/proxy/Files.php +15 -15
- backend/modules/appearance/proxy/GoogleMapsAddress.php +14 -14
- backend/modules/appearance/proxy/GroupBooking.php +15 -15
- backend/modules/appearance/proxy/Locations.php +15 -15
- backend/modules/appearance/proxy/MultiplyAppointments.php +15 -15
- backend/modules/appearance/proxy/Pro.php +22 -22
- backend/modules/appearance/proxy/RecurringAppointments.php +17 -17
- backend/modules/appearance/proxy/ServiceExtras.php +17 -17
- backend/modules/appearance/proxy/Shared.php +18 -18
- backend/modules/appearance/proxy/Tasks.php +15 -0
- backend/modules/appearance/proxy/WaitingList.php +14 -14
- backend/modules/appearance/resources/css/bootstrap-editable.css +663 -663
- backend/modules/appearance/resources/js/appearance.js +837 -781
- backend/modules/appearance/resources/js/bootstrap-editable.bookly.js +124 -124
- backend/modules/appearance/resources/js/bootstrap-editable.min.js +6 -6
- backend/modules/appearance/templates/_1_service.php +166 -165
- backend/modules/appearance/templates/_3_time.php +207 -204
- backend/modules/appearance/templates/_6_details.php +0 -78
autoload.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
|
3 |
-
/**
|
4 |
-
* Bookly autoload.
|
5 |
-
* @param $class
|
6 |
-
*/
|
7 |
-
function bookly_loader( $class )
|
8 |
-
{
|
9 |
-
if ( preg_match( '/^Bookly\\\\(.+)?([^\\\\]+)$/U', ltrim( $class, '\\' ), $match ) ) {
|
10 |
-
$file = __DIR__ . DIRECTORY_SEPARATOR
|
11 |
-
. strtolower( str_replace( '\\', DIRECTORY_SEPARATOR, preg_replace( '/([a-z])([A-Z])/', '$1_$2', $match[1] ) ) )
|
12 |
-
. $match[2]
|
13 |
-
. '.php';
|
14 |
-
if ( is_readable( $file ) ) {
|
15 |
-
require_once $file;
|
16 |
-
}
|
17 |
-
}
|
18 |
-
}
|
19 |
spl_autoload_register( 'bookly_loader', true, true );
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
|
3 |
+
/**
|
4 |
+
* Bookly autoload.
|
5 |
+
* @param $class
|
6 |
+
*/
|
7 |
+
function bookly_loader( $class )
|
8 |
+
{
|
9 |
+
if ( preg_match( '/^Bookly\\\\(.+)?([^\\\\]+)$/U', ltrim( $class, '\\' ), $match ) ) {
|
10 |
+
$file = __DIR__ . DIRECTORY_SEPARATOR
|
11 |
+
. strtolower( str_replace( '\\', DIRECTORY_SEPARATOR, preg_replace( '/([a-z])([A-Z])/', '$1_$2', $match[1] ) ) )
|
12 |
+
. $match[2]
|
13 |
+
. '.php';
|
14 |
+
if ( is_readable( $file ) ) {
|
15 |
+
require_once $file;
|
16 |
+
}
|
17 |
+
}
|
18 |
+
}
|
19 |
spl_autoload_register( 'bookly_loader', true, true );
|
backend/Backend.php
CHANGED
@@ -1,118 +1,118 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Backend
|
8 |
-
* @package Bookly\Backend
|
9 |
-
*/
|
10 |
-
abstract class Backend
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Register hooks.
|
14 |
-
*/
|
15 |
-
public static function registerHooks()
|
16 |
-
{
|
17 |
-
add_action( 'admin_menu', array( __CLASS__, 'addAdminMenu' ) );
|
18 |
-
|
19 |
-
add_action( 'admin_notices', function () {
|
20 |
-
$bookly_page = isset ( $_REQUEST['page'] ) &&
|
21 |
-
if ( $bookly_page ) {
|
22 |
-
// Subscribe notice.
|
23 |
-
Components\Notices\Subscribe::render();
|
24 |
-
// Subscribe notice.
|
25 |
-
Components\Notices\LiteRebranding::render();
|
26 |
-
// NPS notice.
|
27 |
-
Components\Notices\Nps::render();
|
28 |
-
// Collect stats notice.
|
29 |
-
Components\Notices\CollectStats::render();
|
30 |
-
}
|
31 |
-
// Let add-ons render admin notices.
|
32 |
-
Lib\Proxy\Shared::renderAdminNotices( $bookly_page );
|
33 |
-
}, 10, 0 );
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Admin menu.
|
38 |
-
*/
|
39 |
-
public static function addAdminMenu()
|
40 |
-
{
|
41 |
-
/** @var \WP_User $current_user */
|
42 |
-
global $current_user, $submenu;
|
43 |
-
|
44 |
-
if ( $current_user->has_cap( 'administrator' ) || Lib\Entities\Staff::query()->where( 'wp_user_id', $current_user->ID )->count() ) {
|
45 |
-
$dynamic_position = '80.0000001' . mt_rand( 1, 1000 ); // position always is under `Settings`
|
46 |
-
$badge_number = Modules\Messages\Page::getMessagesCount() +
|
47 |
-
Modules\Shop\Page::getNotSeenCount() +
|
48 |
-
Lib\SMS::getUndeliveredSmsCount()
|
49 |
-
;
|
50 |
-
|
51 |
-
if ( $badge_number ) {
|
52 |
-
add_menu_page( 'Bookly', sprintf( 'Bookly <span class="update-plugins count-%d"><span class="update-count">%d</span></span>', $badge_number, $badge_number ), 'read', 'bookly-menu', '',
|
53 |
-
plugins_url( 'resources/images/menu.png', __FILE__ ), $dynamic_position );
|
54 |
-
} else {
|
55 |
-
add_menu_page( 'Bookly', 'Bookly', 'read', 'bookly-menu', '',
|
56 |
-
plugins_url( 'resources/images/menu.png', __FILE__ ), $dynamic_position );
|
57 |
-
}
|
58 |
-
if ( Lib\Proxy\Pro::graceExpired() ) {
|
59 |
-
Lib\Proxy\Pro::addLicenseBooklyMenuItem();
|
60 |
-
} else {
|
61 |
-
// Translated submenu pages.
|
62 |
-
$calendar = __( 'Calendar', 'bookly' );
|
63 |
-
$appointments = __( 'Appointments', 'bookly' );
|
64 |
-
$staff_members = __( 'Staff Members', 'bookly' );
|
65 |
-
$services = __( 'Services', 'bookly' );
|
66 |
-
$notifications = __( 'Email Notifications', 'bookly' );
|
67 |
-
$customers = __( 'Customers', 'bookly' );
|
68 |
-
$payments = __( 'Payments', 'bookly' );
|
69 |
-
$appearance = __( 'Appearance', 'bookly' );
|
70 |
-
$settings = __( 'Settings', 'bookly' );
|
71 |
-
|
72 |
-
add_submenu_page( 'bookly-menu', $calendar, $calendar, 'read',
|
73 |
-
Modules\Calendar\Page::pageSlug(), function () { Modules\Calendar\Page::render(); } );
|
74 |
-
add_submenu_page( 'bookly-menu', $appointments, $appointments, 'manage_options',
|
75 |
-
Modules\Appointments\Page::pageSlug(), function () { Modules\Appointments\Page::render(); } );
|
76 |
-
Lib\Proxy\Locations::addBooklyMenuItem();
|
77 |
-
Lib\Proxy\Packages::addBooklyMenuItem();
|
78 |
-
if ( $current_user->has_cap( 'administrator' ) ) {
|
79 |
-
add_submenu_page( 'bookly-menu', $staff_members, $staff_members, 'manage_options',
|
80 |
-
Modules\Staff\Page::pageSlug(), function () { Modules\Staff\Page::render(); } );
|
81 |
-
} else {
|
82 |
-
if ( get_option( 'bookly_gen_allow_staff_edit_profile' ) == 1 ) {
|
83 |
-
add_submenu_page( 'bookly-menu', __( 'Profile', 'bookly' ), __( 'Profile', 'bookly' ), 'read',
|
84 |
-
Modules\Staff\Page::pageSlug(), function () { Modules\Staff\Page::render(); } );
|
85 |
-
}
|
86 |
-
}
|
87 |
-
add_submenu_page( 'bookly-menu', $services, $services, 'manage_options',
|
88 |
-
Modules\Services\Page::pageSlug(), function () { Modules\Services\Page::render(); } );
|
89 |
-
Lib\Proxy\Taxes::addBooklyMenuItem();
|
90 |
-
add_submenu_page( 'bookly-menu', $customers, $customers, 'manage_options',
|
91 |
-
Modules\Customers\Page::pageSlug(), function () { Modules\Customers\Page::render(); } );
|
92 |
-
Lib\Proxy\CustomerInformation::addBooklyMenuItem();
|
93 |
-
Lib\Proxy\CustomerGroups::addBooklyMenuItem();
|
94 |
-
add_submenu_page( 'bookly-menu', $notifications, $notifications, 'manage_options',
|
95 |
-
Modules\Notifications\Page::pageSlug(), function () { Modules\Notifications\Page::render(); } );
|
96 |
-
Modules\Sms\Page::addBooklyMenuItem();
|
97 |
-
add_submenu_page( 'bookly-menu', $payments, $payments, 'manage_options',
|
98 |
-
Modules\Payments\Page::pageSlug(), function () { Modules\Payments\Page::render(); } );
|
99 |
-
add_submenu_page( 'bookly-menu', $appearance, $appearance, 'manage_options',
|
100 |
-
Modules\Appearance\Page::pageSlug(), function () { Modules\Appearance\Page::render(); } );
|
101 |
-
Lib\Proxy\Coupons::addBooklyMenuItem();
|
102 |
-
Lib\Proxy\CustomFields::addBooklyMenuItem();
|
103 |
-
add_submenu_page( 'bookly-menu', $settings, $settings, 'manage_options',
|
104 |
-
Modules\Settings\Page::pageSlug(), function () { Modules\Settings\Page::render(); } );
|
105 |
-
Modules\Messages\Page::addBooklyMenuItem();
|
106 |
-
Modules\Shop\Page::addBooklyMenuItem();
|
107 |
-
Lib\Proxy\Pro::addAnalyticsBooklyMenuItem();
|
108 |
-
|
109 |
-
if ( isset ( $_GET['page'] ) && $_GET['page'] == 'bookly-debug' ) {
|
110 |
-
add_submenu_page( 'bookly-menu', 'Debug', 'Debug', 'manage_options',
|
111 |
-
Modules\Debug\Page::pageSlug(), function () { Modules\Debug\Page::render(); } );
|
112 |
-
}
|
113 |
-
}
|
114 |
-
|
115 |
-
unset ( $submenu['bookly-menu'][0] );
|
116 |
-
}
|
117 |
-
}
|
118 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Backend
|
8 |
+
* @package Bookly\Backend
|
9 |
+
*/
|
10 |
+
abstract class Backend
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Register hooks.
|
14 |
+
*/
|
15 |
+
public static function registerHooks()
|
16 |
+
{
|
17 |
+
add_action( 'admin_menu', array( __CLASS__, 'addAdminMenu' ) );
|
18 |
+
|
19 |
+
add_action( 'admin_notices', function () {
|
20 |
+
$bookly_page = isset ( $_REQUEST['page'] ) && strncmp( $_REQUEST['page'], 'bookly-', 7 ) === 0;
|
21 |
+
if ( $bookly_page ) {
|
22 |
+
// Subscribe notice.
|
23 |
+
Components\Notices\Subscribe::render();
|
24 |
+
// Subscribe notice.
|
25 |
+
Components\Notices\LiteRebranding::render();
|
26 |
+
// NPS notice.
|
27 |
+
Components\Notices\Nps::render();
|
28 |
+
// Collect stats notice.
|
29 |
+
Components\Notices\CollectStats::render();
|
30 |
+
}
|
31 |
+
// Let add-ons render admin notices.
|
32 |
+
Lib\Proxy\Shared::renderAdminNotices( $bookly_page );
|
33 |
+
}, 10, 0 );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Admin menu.
|
38 |
+
*/
|
39 |
+
public static function addAdminMenu()
|
40 |
+
{
|
41 |
+
/** @var \WP_User $current_user */
|
42 |
+
global $current_user, $submenu;
|
43 |
+
|
44 |
+
if ( $current_user->has_cap( 'administrator' ) || Lib\Entities\Staff::query()->where( 'wp_user_id', $current_user->ID )->count() ) {
|
45 |
+
$dynamic_position = '80.0000001' . mt_rand( 1, 1000 ); // position always is under `Settings`
|
46 |
+
$badge_number = Modules\Messages\Page::getMessagesCount() +
|
47 |
+
Modules\Shop\Page::getNotSeenCount() +
|
48 |
+
Lib\SMS::getUndeliveredSmsCount()
|
49 |
+
;
|
50 |
+
|
51 |
+
if ( $badge_number ) {
|
52 |
+
add_menu_page( 'Bookly', sprintf( 'Bookly <span class="update-plugins count-%d"><span class="update-count">%d</span></span>', $badge_number, $badge_number ), 'read', 'bookly-menu', '',
|
53 |
+
plugins_url( 'resources/images/menu.png', __FILE__ ), $dynamic_position );
|
54 |
+
} else {
|
55 |
+
add_menu_page( 'Bookly', 'Bookly', 'read', 'bookly-menu', '',
|
56 |
+
plugins_url( 'resources/images/menu.png', __FILE__ ), $dynamic_position );
|
57 |
+
}
|
58 |
+
if ( Lib\Proxy\Pro::graceExpired() ) {
|
59 |
+
Lib\Proxy\Pro::addLicenseBooklyMenuItem();
|
60 |
+
} else {
|
61 |
+
// Translated submenu pages.
|
62 |
+
$calendar = __( 'Calendar', 'bookly' );
|
63 |
+
$appointments = __( 'Appointments', 'bookly' );
|
64 |
+
$staff_members = __( 'Staff Members', 'bookly' );
|
65 |
+
$services = __( 'Services', 'bookly' );
|
66 |
+
$notifications = __( 'Email Notifications', 'bookly' );
|
67 |
+
$customers = __( 'Customers', 'bookly' );
|
68 |
+
$payments = __( 'Payments', 'bookly' );
|
69 |
+
$appearance = __( 'Appearance', 'bookly' );
|
70 |
+
$settings = __( 'Settings', 'bookly' );
|
71 |
+
|
72 |
+
add_submenu_page( 'bookly-menu', $calendar, $calendar, 'read',
|
73 |
+
Modules\Calendar\Page::pageSlug(), function () { Modules\Calendar\Page::render(); } );
|
74 |
+
add_submenu_page( 'bookly-menu', $appointments, $appointments, 'manage_options',
|
75 |
+
Modules\Appointments\Page::pageSlug(), function () { Modules\Appointments\Page::render(); } );
|
76 |
+
Lib\Proxy\Locations::addBooklyMenuItem();
|
77 |
+
Lib\Proxy\Packages::addBooklyMenuItem();
|
78 |
+
if ( $current_user->has_cap( 'administrator' ) ) {
|
79 |
+
add_submenu_page( 'bookly-menu', $staff_members, $staff_members, 'manage_options',
|
80 |
+
Modules\Staff\Page::pageSlug(), function () { Modules\Staff\Page::render(); } );
|
81 |
+
} else {
|
82 |
+
if ( get_option( 'bookly_gen_allow_staff_edit_profile' ) == 1 ) {
|
83 |
+
add_submenu_page( 'bookly-menu', __( 'Profile', 'bookly' ), __( 'Profile', 'bookly' ), 'read',
|
84 |
+
Modules\Staff\Page::pageSlug(), function () { Modules\Staff\Page::render(); } );
|
85 |
+
}
|
86 |
+
}
|
87 |
+
add_submenu_page( 'bookly-menu', $services, $services, 'manage_options',
|
88 |
+
Modules\Services\Page::pageSlug(), function () { Modules\Services\Page::render(); } );
|
89 |
+
Lib\Proxy\Taxes::addBooklyMenuItem();
|
90 |
+
add_submenu_page( 'bookly-menu', $customers, $customers, 'manage_options',
|
91 |
+
Modules\Customers\Page::pageSlug(), function () { Modules\Customers\Page::render(); } );
|
92 |
+
Lib\Proxy\CustomerInformation::addBooklyMenuItem();
|
93 |
+
Lib\Proxy\CustomerGroups::addBooklyMenuItem();
|
94 |
+
add_submenu_page( 'bookly-menu', $notifications, $notifications, 'manage_options',
|
95 |
+
Modules\Notifications\Page::pageSlug(), function () { Modules\Notifications\Page::render(); } );
|
96 |
+
Modules\Sms\Page::addBooklyMenuItem();
|
97 |
+
add_submenu_page( 'bookly-menu', $payments, $payments, 'manage_options',
|
98 |
+
Modules\Payments\Page::pageSlug(), function () { Modules\Payments\Page::render(); } );
|
99 |
+
add_submenu_page( 'bookly-menu', $appearance, $appearance, 'manage_options',
|
100 |
+
Modules\Appearance\Page::pageSlug(), function () { Modules\Appearance\Page::render(); } );
|
101 |
+
Lib\Proxy\Coupons::addBooklyMenuItem();
|
102 |
+
Lib\Proxy\CustomFields::addBooklyMenuItem();
|
103 |
+
add_submenu_page( 'bookly-menu', $settings, $settings, 'manage_options',
|
104 |
+
Modules\Settings\Page::pageSlug(), function () { Modules\Settings\Page::render(); } );
|
105 |
+
Modules\Messages\Page::addBooklyMenuItem();
|
106 |
+
Modules\Shop\Page::addBooklyMenuItem();
|
107 |
+
Lib\Proxy\Pro::addAnalyticsBooklyMenuItem();
|
108 |
+
|
109 |
+
if ( isset ( $_GET['page'] ) && $_GET['page'] == 'bookly-debug' ) {
|
110 |
+
add_submenu_page( 'bookly-menu', 'Debug', 'Debug', 'manage_options',
|
111 |
+
Modules\Debug\Page::pageSlug(), function () { Modules\Debug\Page::render(); } );
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
unset ( $submenu['bookly-menu'][0] );
|
116 |
+
}
|
117 |
+
}
|
118 |
}
|
backend/components/appearance/Codes.php
CHANGED
@@ -1,41 +1,40 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Appearance;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Codes
|
8 |
-
* @package Bookly\Backend\Components\Appearance
|
9 |
-
*/
|
10 |
-
class Codes
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Get HTML for appearance codes.
|
14 |
-
*
|
15 |
-
* @param int $step
|
16 |
-
* @param bool $extra_codes
|
17 |
-
* @return string
|
18 |
-
*/
|
19 |
-
public static function getHtml( $step = null, $extra_codes = false )
|
20 |
-
{
|
21 |
-
$codes = array(
|
22 |
-
array( 'code' => 'appointments_count', 'description' => __( 'total quantity of appointments in cart', 'bookly' ), 'flags' => array( 'step' => 7, 'extra_codes' => true ) ),
|
23 |
-
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ), 'flags' => array( 'step' => 8, 'extra_codes' => true ) ),
|
24 |
-
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
25 |
-
array( 'code' => 'login_form', 'description' => __( 'login form', 'bookly' ), 'flags' => array( 'step' => 6, 'extra_codes' => true ) ),
|
26 |
-
array( 'code' => '
|
27 |
-
array( 'code' => '
|
28 |
-
array( 'code' => '
|
29 |
-
array( 'code' => '
|
30 |
-
array( 'code' => '
|
31 |
-
array( 'code' => '
|
32 |
-
array( 'code' => '
|
33 |
-
array( 'code' => '
|
34 |
-
array( 'code' => '
|
35 |
-
array( 'code' => '
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
}
|
41 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Appearance;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Codes
|
8 |
+
* @package Bookly\Backend\Components\Appearance
|
9 |
+
*/
|
10 |
+
class Codes
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Get HTML for appearance codes.
|
14 |
+
*
|
15 |
+
* @param int $step
|
16 |
+
* @param bool $extra_codes
|
17 |
+
* @return string
|
18 |
+
*/
|
19 |
+
public static function getHtml( $step = null, $extra_codes = false )
|
20 |
+
{
|
21 |
+
$codes = array(
|
22 |
+
array( 'code' => 'appointments_count', 'description' => __( 'total quantity of appointments in cart', 'bookly' ), 'flags' => array( 'step' => 7, 'extra_codes' => true ) ),
|
23 |
+
array( 'code' => 'booking_number', 'description' => __( 'booking number', 'bookly' ), 'flags' => array( 'step' => 8, 'extra_codes' => true ) ),
|
24 |
+
array( 'code' => 'category_name', 'description' => __( 'name of category', 'bookly' ) ),
|
25 |
+
array( 'code' => 'login_form', 'description' => __( 'login form', 'bookly' ), 'flags' => array( 'step' => 6, 'extra_codes' => true ) ),
|
26 |
+
array( 'code' => 'service_date', 'description' => __( 'date of service', 'bookly' ), 'flags' => array( 'step' => '>3' ) ),
|
27 |
+
array( 'code' => 'service_duration', 'description' => __( 'duration of service', 'bookly' ) ),
|
28 |
+
array( 'code' => 'service_info', 'description' => __( 'info of service', 'bookly' ) ),
|
29 |
+
array( 'code' => 'service_name', 'description' => __( 'name of service', 'bookly' ) ),
|
30 |
+
array( 'code' => 'service_price', 'description' => __( 'price of service', 'bookly' ) ),
|
31 |
+
array( 'code' => 'service_time', 'description' => __( 'time of service', 'bookly' ), 'flags' => array( 'step' => '>3' ) ),
|
32 |
+
array( 'code' => 'staff_info', 'description' => __( 'info of staff', 'bookly' ) ),
|
33 |
+
array( 'code' => 'staff_name', 'description' => __( 'name of staff', 'bookly' ) ),
|
34 |
+
array( 'code' => 'staff_photo', 'description' => __( 'photo of staff', 'bookly' ), 'flags' => array( 'step' => '>1' ) ),
|
35 |
+
array( 'code' => 'total_price', 'description' => __( 'total price of booking', 'bookly' ) ),
|
36 |
+
);
|
37 |
+
|
38 |
+
return Lib\Utils\Common::codes( Proxy\Shared::prepareCodes( $codes ), array( 'step' => $step, 'extra_codes' => isset ( $extra_codes ) ) );
|
39 |
+
}
|
|
|
40 |
}
|
backend/components/appearance/Editable.php
CHANGED
@@ -1,109 +1,113 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Appearance;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class Editable
|
6 |
-
* @package Bookly\Backend\Components\Appearance
|
7 |
-
*/
|
8 |
-
class Editable
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* Render editable string (single line).
|
12 |
-
*
|
13 |
-
* @param array $options
|
14 |
-
* @param bool $echo
|
15 |
-
* @return string
|
16 |
-
*/
|
17 |
-
public static function renderString( array $options, $echo = true )
|
18 |
-
{
|
19 |
-
return self::_renderEditable( $options, 'span', $echo );
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Render editable label.
|
24 |
-
*
|
25 |
-
* @param array $options
|
26 |
-
* @param bool $echo
|
27 |
-
* @return string
|
28 |
-
*/
|
29 |
-
public static function renderLabel( array $options, $echo = true )
|
30 |
-
{
|
31 |
-
return self::_renderEditable( $options, 'label', $echo );
|
32 |
-
}
|
33 |
-
|
34 |
-
/**
|
35 |
-
* Render editable text (multi-line).
|
36 |
-
*
|
37 |
-
* @param string $option_name
|
38 |
-
* @param string $codes
|
39 |
-
* @param string $placement
|
40 |
-
* @param string $title
|
41 |
-
*/
|
42 |
-
public static function renderText( $option_name, $codes = '', $placement = 'bottom', $title = '' )
|
43 |
-
{
|
44 |
-
$option_value = get_option( $option_name );
|
45 |
-
|
46 |
-
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>',
|
47 |
-
$option_name,
|
48 |
-
esc_attr( json_encode( array( $option_name => $option_value ) ) ),
|
49 |
-
esc_attr( $codes ),
|
50 |
-
esc_attr( $title ),
|
51 |
-
$placement,
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
*
|
59 |
-
*
|
60 |
-
* @param
|
61 |
-
* @param int $
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
esc_attr( $
|
71 |
-
esc_attr( $
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
*
|
80 |
-
*
|
81 |
-
* @param
|
82 |
-
* @
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
$
|
94 |
-
|
95 |
-
$
|
96 |
-
$
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
'{
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
echo
|
108 |
-
|
|
|
|
|
|
|
|
|
109 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Appearance;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class Editable
|
6 |
+
* @package Bookly\Backend\Components\Appearance
|
7 |
+
*/
|
8 |
+
class Editable
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Render editable string (single line).
|
12 |
+
*
|
13 |
+
* @param array $options
|
14 |
+
* @param bool $echo
|
15 |
+
* @return string
|
16 |
+
*/
|
17 |
+
public static function renderString( array $options, $echo = true )
|
18 |
+
{
|
19 |
+
return self::_renderEditable( $options, 'span', $echo );
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Render editable label.
|
24 |
+
*
|
25 |
+
* @param array $options
|
26 |
+
* @param bool $echo
|
27 |
+
* @return string
|
28 |
+
*/
|
29 |
+
public static function renderLabel( array $options, $echo = true )
|
30 |
+
{
|
31 |
+
return self::_renderEditable( $options, 'label', $echo );
|
32 |
+
}
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Render editable text (multi-line).
|
36 |
+
*
|
37 |
+
* @param string $option_name
|
38 |
+
* @param string $codes
|
39 |
+
* @param string $placement
|
40 |
+
* @param string $title
|
41 |
+
*/
|
42 |
+
public static function renderText( $option_name, $codes = '', $placement = 'bottom', $title = '' )
|
43 |
+
{
|
44 |
+
$option_value = get_option( $option_name );
|
45 |
+
|
46 |
+
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" data-option="%s">%s</span>',
|
47 |
+
$option_name,
|
48 |
+
esc_attr( json_encode( array( $option_name => $option_value ) ) ),
|
49 |
+
esc_attr( $codes ),
|
50 |
+
esc_attr( $title ),
|
51 |
+
$placement,
|
52 |
+
$option_name,
|
53 |
+
esc_html( $option_value )
|
54 |
+
);
|
55 |
+
}
|
56 |
+
|
57 |
+
/**
|
58 |
+
* Render editable number.
|
59 |
+
*
|
60 |
+
* @param string $option_name
|
61 |
+
* @param int $min
|
62 |
+
* @param int $step
|
63 |
+
*/
|
64 |
+
public static function renderNumber( $option_name, $min = 1, $step = 1 )
|
65 |
+
{
|
66 |
+
$option_value = get_option( $option_name );
|
67 |
+
|
68 |
+
printf( '<span class="bookly-js-editable bookly-js-option %s editable-pre-wrapped" data-type="bookly" data-fieldType="number" data-values="%s" data-min="%s" data-step="%s" data-option="%s">%s</span>',
|
69 |
+
$option_name,
|
70 |
+
esc_attr( json_encode( array( $option_name => $option_value ) ) ),
|
71 |
+
esc_attr( $min ),
|
72 |
+
esc_attr( $step ),
|
73 |
+
$option_name,
|
74 |
+
esc_html( $option_value )
|
75 |
+
);
|
76 |
+
}
|
77 |
+
|
78 |
+
/**
|
79 |
+
* Render editable element.
|
80 |
+
*
|
81 |
+
* @param array $options
|
82 |
+
* @param string $tag
|
83 |
+
* @param bool $echo
|
84 |
+
* @return string|void
|
85 |
+
*/
|
86 |
+
private static function _renderEditable( array $options, $tag, $echo = true )
|
87 |
+
{
|
88 |
+
$data = array();
|
89 |
+
foreach ( $options as $option_name ) {
|
90 |
+
$data[ $option_name ] = get_option( $option_name );
|
91 |
+
}
|
92 |
+
|
93 |
+
$main_option = $options[0];
|
94 |
+
$class = implode( ' ', $options );
|
95 |
+
$data_values = esc_attr( json_encode( $data ) );
|
96 |
+
$content = esc_html( $data[ $options[0] ] );
|
97 |
+
|
98 |
+
$template = '<{tag} class="bookly-js-editable bookly-js-option {class}" data-type="bookly" data-values="{data-values}" data-option="{data-option}">{content}</{tag}>';
|
99 |
+
$html = strtr( $template, array(
|
100 |
+
'{tag}' => $tag,
|
101 |
+
'{class}' => $class,
|
102 |
+
'{data-values}' => $data_values,
|
103 |
+
'{data-option}' => $main_option,
|
104 |
+
'{content}' => $content,
|
105 |
+
) );
|
106 |
+
|
107 |
+
if ( ! $echo ) {
|
108 |
+
return $html;
|
109 |
+
}
|
110 |
+
|
111 |
+
echo $html;
|
112 |
+
}
|
113 |
}
|
backend/components/appearance/proxy/Pro.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderAddress() Render inputs for address fields in appearance.
|
11 |
-
* @method static void renderBirthday() Render inputs for birthday fields in appearance.
|
12 |
-
*/
|
13 |
-
abstract class Pro extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderAddress() Render inputs for address fields in appearance.
|
11 |
+
* @method static void renderBirthday() Render inputs for birthday fields in appearance.
|
12 |
+
*/
|
13 |
+
abstract class Pro extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
}
|
backend/components/appearance/proxy/Shared.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Shared
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static array prepareCodes( array $codes ) Alter array of codes to be displayed in Bookly Appearance.
|
11 |
-
*/
|
12 |
-
abstract class Shared extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Shared
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static array prepareCodes( array $codes ) Alter array of codes to be displayed in Bookly Appearance.
|
11 |
+
*/
|
12 |
+
abstract class Shared extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/controls/Buttons.php
CHANGED
@@ -1,127 +1,127 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Controls;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class Buttons
|
6 |
-
* @package Bookly\Backend\Components\Controls
|
7 |
-
*/
|
8 |
-
class Buttons
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* Render custom button.
|
12 |
-
*
|
13 |
-
* @param string $id
|
14 |
-
* @param string $class
|
15 |
-
* @param string $caption
|
16 |
-
* @param array $attributes
|
17 |
-
* @param string $caption_template
|
18 |
-
*/
|
19 |
-
public static function renderCustom( $id = null, $class = 'btn-success', $caption = null, array $attributes = array(), $caption_template = '{caption}' )
|
20 |
-
{
|
21 |
-
if ( $caption === null ) {
|
22 |
-
$caption = __( 'Save', 'bookly' );
|
23 |
-
}
|
24 |
-
|
25 |
-
$caption = strtr( $caption_template, array( '{caption}' => esc_html( $caption ) ) );
|
26 |
-
|
27 |
-
echo self::_createButton( 'button', $id, $class, null, $caption, $attributes );
|
28 |
-
}
|
29 |
-
|
30 |
-
/**
|
31 |
-
* Render delete button.
|
32 |
-
*
|
33 |
-
* @param string $id
|
34 |
-
* @param string $extra_class
|
35 |
-
* @param string $caption
|
36 |
-
* @param array $attributes
|
37 |
-
*/
|
38 |
-
public static function renderDelete( $id = 'bookly-delete', $extra_class = null, $caption = null, array $attributes = array() )
|
39 |
-
{
|
40 |
-
if ( $caption === null ) {
|
41 |
-
$caption = __( 'Delete', 'bookly' );
|
42 |
-
}
|
43 |
-
|
44 |
-
echo self::_createButton(
|
45 |
-
'button',
|
46 |
-
$id,
|
47 |
-
'btn-danger',
|
48 |
-
$extra_class,
|
49 |
-
'<i class="glyphicon glyphicon-trash"></i> ' . esc_html( $caption ),
|
50 |
-
$attributes
|
51 |
-
);
|
52 |
-
}
|
53 |
-
|
54 |
-
/**
|
55 |
-
* Render reset button.
|
56 |
-
*
|
57 |
-
* @param string $id
|
58 |
-
* @param string $extra_class
|
59 |
-
* @param string $caption
|
60 |
-
* @param array $attributes
|
61 |
-
*/
|
62 |
-
public static function renderReset( $id = null, $extra_class = null, $caption = null, array $attributes = array() )
|
63 |
-
{
|
64 |
-
if ( $caption === null ) {
|
65 |
-
$caption = __( 'Reset', 'bookly' );
|
66 |
-
}
|
67 |
-
|
68 |
-
echo self::_createButton( 'reset', $id, 'btn-lg btn-default', $extra_class, esc_html( $caption ), $attributes );
|
69 |
-
}
|
70 |
-
|
71 |
-
/**
|
72 |
-
* Render submit button.
|
73 |
-
*
|
74 |
-
* @param string $id
|
75 |
-
* @param string $extra_class
|
76 |
-
* @param string $caption
|
77 |
-
* @param array $attributes
|
78 |
-
*/
|
79 |
-
public static function renderSubmit( $id = 'bookly-save', $extra_class = null, $caption = null, array $attributes = array() )
|
80 |
-
{
|
81 |
-
if ( $caption === null ) {
|
82 |
-
$caption = __( 'Save', 'bookly' );
|
83 |
-
}
|
84 |
-
|
85 |
-
echo self::_createButton( 'submit', $id, 'btn-lg btn-success', $extra_class, esc_html( $caption ), $attributes );
|
86 |
-
}
|
87 |
-
|
88 |
-
/**
|
89 |
-
* Create button.
|
90 |
-
*
|
91 |
-
* @param string $type
|
92 |
-
* @param string $id
|
93 |
-
* @param string $class
|
94 |
-
* @param string $extra_class
|
95 |
-
* @param string $caption_html
|
96 |
-
* @param array $attributes
|
97 |
-
* @return string
|
98 |
-
*/
|
99 |
-
private static function _createButton( $type, $id, $class, $extra_class, $caption_html, array $attributes )
|
100 |
-
{
|
101 |
-
$classes = array( 'btn ladda-button' );
|
102 |
-
if ( $class != '' ) {
|
103 |
-
$classes[] = $class;
|
104 |
-
}
|
105 |
-
if ( $extra_class != '' ) {
|
106 |
-
$classes[] = $extra_class;
|
107 |
-
}
|
108 |
-
|
109 |
-
if ( $id !== null ) {
|
110 |
-
$attributes['id'] = $id;
|
111 |
-
}
|
112 |
-
$attributes_str = '';
|
113 |
-
foreach ( $attributes as $attr => $value ) {
|
114 |
-
$attributes_str .= sprintf( ' %s="%s"', $attr, esc_attr( $value ) );
|
115 |
-
}
|
116 |
-
|
117 |
-
return strtr(
|
118 |
-
'<button type="{type}" class="{class}" data-spinner-size="40" data-style="zoom-in"{attributes}><span class="ladda-label">{caption}</span></button>',
|
119 |
-
array(
|
120 |
-
'{type}' => $type,
|
121 |
-
'{class}' => implode( ' ', $classes ),
|
122 |
-
'{attributes}' => $attributes_str,
|
123 |
-
'{caption}' => $caption_html,
|
124 |
-
)
|
125 |
-
);
|
126 |
-
}
|
127 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Controls;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class Buttons
|
6 |
+
* @package Bookly\Backend\Components\Controls
|
7 |
+
*/
|
8 |
+
class Buttons
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Render custom button.
|
12 |
+
*
|
13 |
+
* @param string $id
|
14 |
+
* @param string $class
|
15 |
+
* @param string $caption
|
16 |
+
* @param array $attributes
|
17 |
+
* @param string $caption_template
|
18 |
+
*/
|
19 |
+
public static function renderCustom( $id = null, $class = 'btn-success', $caption = null, array $attributes = array(), $caption_template = '{caption}' )
|
20 |
+
{
|
21 |
+
if ( $caption === null ) {
|
22 |
+
$caption = __( 'Save', 'bookly' );
|
23 |
+
}
|
24 |
+
|
25 |
+
$caption = strtr( $caption_template, array( '{caption}' => esc_html( $caption ) ) );
|
26 |
+
|
27 |
+
echo self::_createButton( 'button', $id, $class, null, $caption, $attributes );
|
28 |
+
}
|
29 |
+
|
30 |
+
/**
|
31 |
+
* Render delete button.
|
32 |
+
*
|
33 |
+
* @param string $id
|
34 |
+
* @param string $extra_class
|
35 |
+
* @param string $caption
|
36 |
+
* @param array $attributes
|
37 |
+
*/
|
38 |
+
public static function renderDelete( $id = 'bookly-delete', $extra_class = null, $caption = null, array $attributes = array() )
|
39 |
+
{
|
40 |
+
if ( $caption === null ) {
|
41 |
+
$caption = __( 'Delete', 'bookly' );
|
42 |
+
}
|
43 |
+
|
44 |
+
echo self::_createButton(
|
45 |
+
'button',
|
46 |
+
$id,
|
47 |
+
'btn-danger',
|
48 |
+
$extra_class,
|
49 |
+
'<i class="glyphicon glyphicon-trash"></i> ' . esc_html( $caption ),
|
50 |
+
$attributes
|
51 |
+
);
|
52 |
+
}
|
53 |
+
|
54 |
+
/**
|
55 |
+
* Render reset button.
|
56 |
+
*
|
57 |
+
* @param string $id
|
58 |
+
* @param string $extra_class
|
59 |
+
* @param string $caption
|
60 |
+
* @param array $attributes
|
61 |
+
*/
|
62 |
+
public static function renderReset( $id = null, $extra_class = null, $caption = null, array $attributes = array() )
|
63 |
+
{
|
64 |
+
if ( $caption === null ) {
|
65 |
+
$caption = __( 'Reset', 'bookly' );
|
66 |
+
}
|
67 |
+
|
68 |
+
echo self::_createButton( 'reset', $id, 'btn-lg btn-default', $extra_class, esc_html( $caption ), $attributes );
|
69 |
+
}
|
70 |
+
|
71 |
+
/**
|
72 |
+
* Render submit button.
|
73 |
+
*
|
74 |
+
* @param string $id
|
75 |
+
* @param string $extra_class
|
76 |
+
* @param string $caption
|
77 |
+
* @param array $attributes
|
78 |
+
*/
|
79 |
+
public static function renderSubmit( $id = 'bookly-save', $extra_class = null, $caption = null, array $attributes = array() )
|
80 |
+
{
|
81 |
+
if ( $caption === null ) {
|
82 |
+
$caption = __( 'Save', 'bookly' );
|
83 |
+
}
|
84 |
+
|
85 |
+
echo self::_createButton( 'submit', $id, 'btn-lg btn-success', $extra_class, esc_html( $caption ), $attributes );
|
86 |
+
}
|
87 |
+
|
88 |
+
/**
|
89 |
+
* Create button.
|
90 |
+
*
|
91 |
+
* @param string $type
|
92 |
+
* @param string $id
|
93 |
+
* @param string $class
|
94 |
+
* @param string $extra_class
|
95 |
+
* @param string $caption_html
|
96 |
+
* @param array $attributes
|
97 |
+
* @return string
|
98 |
+
*/
|
99 |
+
private static function _createButton( $type, $id, $class, $extra_class, $caption_html, array $attributes )
|
100 |
+
{
|
101 |
+
$classes = array( 'btn ladda-button' );
|
102 |
+
if ( $class != '' ) {
|
103 |
+
$classes[] = $class;
|
104 |
+
}
|
105 |
+
if ( $extra_class != '' ) {
|
106 |
+
$classes[] = $extra_class;
|
107 |
+
}
|
108 |
+
|
109 |
+
if ( $id !== null ) {
|
110 |
+
$attributes['id'] = $id;
|
111 |
+
}
|
112 |
+
$attributes_str = '';
|
113 |
+
foreach ( $attributes as $attr => $value ) {
|
114 |
+
$attributes_str .= sprintf( ' %s="%s"', $attr, esc_attr( $value ) );
|
115 |
+
}
|
116 |
+
|
117 |
+
return strtr(
|
118 |
+
'<button type="{type}" class="{class}" data-spinner-size="40" data-style="zoom-in"{attributes}><span class="ladda-label">{caption}</span></button>',
|
119 |
+
array(
|
120 |
+
'{type}' => $type,
|
121 |
+
'{class}' => implode( ' ', $classes ),
|
122 |
+
'{attributes}' => $attributes_str,
|
123 |
+
'{caption}' => $caption_html,
|
124 |
+
)
|
125 |
+
);
|
126 |
+
}
|
127 |
}
|
backend/components/controls/Inputs.php
CHANGED
@@ -1,22 +1,22 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Controls;
|
3 |
-
|
4 |
-
use Bookly\Lib\Utils\Common;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Inputs
|
8 |
-
* @package Bookly\Backend\Components\Controls
|
9 |
-
*/
|
10 |
-
class Inputs
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Add hidden input with CSRF token.
|
14 |
-
*/
|
15 |
-
public static function renderCsrf()
|
16 |
-
{
|
17 |
-
printf(
|
18 |
-
'<input type="hidden" name="csrf_token" value="%s" />',
|
19 |
-
esc_attr( Common::getCsrfToken() )
|
20 |
-
);
|
21 |
-
}
|
22 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Controls;
|
3 |
+
|
4 |
+
use Bookly\Lib\Utils\Common;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Inputs
|
8 |
+
* @package Bookly\Backend\Components\Controls
|
9 |
+
*/
|
10 |
+
class Inputs
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Add hidden input with CSRF token.
|
14 |
+
*/
|
15 |
+
public static function renderCsrf()
|
16 |
+
{
|
17 |
+
printf(
|
18 |
+
'<input type="hidden" name="csrf_token" value="%s" />',
|
19 |
+
esc_attr( Common::getCsrfToken() )
|
20 |
+
);
|
21 |
+
}
|
22 |
}
|
backend/components/dialogs/appointment/attach_payment/proxy/Pro.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderAttachPaymentDialog() Render attach payment dialog.
|
11 |
-
*/
|
12 |
-
abstract class Pro extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderAttachPaymentDialog() Render attach payment dialog.
|
11 |
+
*/
|
12 |
+
abstract class Pro extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/dialogs/appointment/attach_payment/proxy/Taxes.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Taxes
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderAttachPayment()
|
11 |
-
*/
|
12 |
-
abstract class Taxes extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Taxes
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderAttachPayment()
|
11 |
+
*/
|
12 |
+
abstract class Taxes extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/dialogs/appointment/customer_details/Dialog.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Dialog
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails
|
9 |
-
*/
|
10 |
-
class Dialog extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render customer details dialog.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
static::renderTemplate( 'customer_details' );
|
18 |
-
}
|
19 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Dialog
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails
|
9 |
+
*/
|
10 |
+
class Dialog extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render customer details dialog.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
static::renderTemplate( 'customer_details' );
|
18 |
+
}
|
19 |
}
|
backend/components/dialogs/appointment/customer_details/proxy/Files.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Files
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
-
*
|
10 |
-
* @method static void renderCustomField( \stdClass $custom_field ) Render files in Customer Details
|
11 |
-
*/
|
12 |
-
abstract class Files extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Files
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
+
*
|
10 |
+
* @method static void renderCustomField( \stdClass $custom_field ) Render files in Customer Details
|
11 |
+
*/
|
12 |
+
abstract class Files extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/dialogs/appointment/customer_details/proxy/Pro.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
-
*
|
10 |
-
* @method static void renderTimeZoneSwitcher() Render time zone switcher in Customer Details
|
11 |
-
*/
|
12 |
-
abstract class Pro extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
+
*
|
10 |
+
* @method static void renderTimeZoneSwitcher() Render time zone switcher in Customer Details
|
11 |
+
*/
|
12 |
+
abstract class Pro extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/dialogs/appointment/customer_details/proxy/Shared.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Shared
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
-
*
|
10 |
-
* @method static void renderDetails()
|
11 |
-
*/
|
12 |
-
abstract class Shared extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Shared
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
+
*
|
10 |
+
* @method static void renderDetails()
|
11 |
+
*/
|
12 |
+
abstract class Shared extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/dialogs/appointment/customer_details/templates/customer_details.php
CHANGED
@@ -1,54 +1,54 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
use Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
4 |
-
use Bookly\Lib\Entities\CustomerAppointment;
|
5 |
-
use Bookly\Lib\Utils\Common;
|
6 |
-
use Bookly\Lib\Config;
|
7 |
-
?>
|
8 |
-
<div id="bookly-customer-details-dialog" class="modal fade" tabindex=-1 role="dialog">
|
9 |
-
<div class="modal-dialog">
|
10 |
-
<div class="modal-content">
|
11 |
-
<div class="modal-header">
|
12 |
-
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
13 |
-
<div class="modal-title h2"><?php _e( 'Edit booking details', 'bookly' ) ?></div>
|
14 |
-
</div>
|
15 |
-
<form ng-hide=loading style="z-index: 1050">
|
16 |
-
<div class="modal-body">
|
17 |
-
<div class="form-group">
|
18 |
-
<label for="bookly-appointment-status"><?php _e( 'Status', 'bookly' ) ?></label>
|
19 |
-
<select class="bookly-custom-field form-control" id="bookly-appointment-status">
|
20 |
-
<option value="<?php echo CustomerAppointment::STATUS_PENDING ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?></option>
|
21 |
-
<option value="<?php echo CustomerAppointment::STATUS_APPROVED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?></option>
|
22 |
-
<option value="<?php echo CustomerAppointment::STATUS_CANCELLED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?></option>
|
23 |
-
<option value="<?php echo CustomerAppointment::STATUS_REJECTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ) ?></option>
|
24 |
-
<?php if ( Config::waitingListActive() ) : ?>
|
25 |
-
<option value="<?php echo CustomerAppointment::STATUS_WAITLISTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_WAITLISTED ) ) ?></option>
|
26 |
-
<?php endif ?>
|
27 |
-
<?php if ( Config::tasksActive() ) : ?>
|
28 |
-
<option value="<?php echo CustomerAppointment::STATUS_DONE ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_DONE ) ) ?></option>
|
29 |
-
<?php endif ?>
|
30 |
-
</select>
|
31 |
-
</div>
|
32 |
-
<div class="form-group" <?php if ( ! Config::groupBookingActive() ) echo ' style="display:none"' ?>>
|
33 |
-
<label for="bookly-number-of-persons"><?php _e( 'Number of persons', 'bookly' ) ?></label>
|
34 |
-
<select class="bookly-custom-field form-control" id="bookly-number-of-persons"></select>
|
35 |
-
</div>
|
36 |
-
<?php Proxy\Pro::renderTimeZoneSwitcher() ?>
|
37 |
-
<?php if ( Config::showNotes() ): ?>
|
38 |
-
<div class="form-group">
|
39 |
-
<label for="bookly-appointment-notes"><?php echo Common::getTranslatedOption( 'bookly_l10n_label_notes' ) ?></label>
|
40 |
-
<textarea class="bookly-custom-field form-control" id="bookly-appointment-notes"></textarea>
|
41 |
-
</div>
|
42 |
-
<?php endif ?>
|
43 |
-
|
44 |
-
<?php Proxy\Shared::renderDetails() ?>
|
45 |
-
|
46 |
-
</div>
|
47 |
-
<div class="modal-footer">
|
48 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-success', __( 'Apply', 'bookly' ), array( 'ng-click' => 'saveCustomFields()' ) ) ?>
|
49 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
50 |
-
</div>
|
51 |
-
</form>
|
52 |
-
</div>
|
53 |
-
</div>
|
54 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
use Bookly\Backend\Components\Dialogs\Appointment\CustomerDetails\Proxy;
|
4 |
+
use Bookly\Lib\Entities\CustomerAppointment;
|
5 |
+
use Bookly\Lib\Utils\Common;
|
6 |
+
use Bookly\Lib\Config;
|
7 |
+
?>
|
8 |
+
<div id="bookly-customer-details-dialog" class="modal fade" tabindex=-1 role="dialog">
|
9 |
+
<div class="modal-dialog">
|
10 |
+
<div class="modal-content">
|
11 |
+
<div class="modal-header">
|
12 |
+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
13 |
+
<div class="modal-title h2"><?php _e( 'Edit booking details', 'bookly' ) ?></div>
|
14 |
+
</div>
|
15 |
+
<form ng-hide=loading style="z-index: 1050">
|
16 |
+
<div class="modal-body">
|
17 |
+
<div class="form-group">
|
18 |
+
<label for="bookly-appointment-status"><?php _e( 'Status', 'bookly' ) ?></label>
|
19 |
+
<select class="bookly-custom-field form-control" id="bookly-appointment-status">
|
20 |
+
<option value="<?php echo CustomerAppointment::STATUS_PENDING ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?></option>
|
21 |
+
<option value="<?php echo CustomerAppointment::STATUS_APPROVED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?></option>
|
22 |
+
<option value="<?php echo CustomerAppointment::STATUS_CANCELLED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?></option>
|
23 |
+
<option value="<?php echo CustomerAppointment::STATUS_REJECTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ) ?></option>
|
24 |
+
<?php if ( Config::waitingListActive() ) : ?>
|
25 |
+
<option value="<?php echo CustomerAppointment::STATUS_WAITLISTED ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_WAITLISTED ) ) ?></option>
|
26 |
+
<?php endif ?>
|
27 |
+
<?php if ( Config::tasksActive() ) : ?>
|
28 |
+
<option value="<?php echo CustomerAppointment::STATUS_DONE ?>"><?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_DONE ) ) ?></option>
|
29 |
+
<?php endif ?>
|
30 |
+
</select>
|
31 |
+
</div>
|
32 |
+
<div class="form-group" <?php if ( ! Config::groupBookingActive() ) echo ' style="display:none"' ?>>
|
33 |
+
<label for="bookly-number-of-persons"><?php _e( 'Number of persons', 'bookly' ) ?></label>
|
34 |
+
<select class="bookly-custom-field form-control" id="bookly-number-of-persons"></select>
|
35 |
+
</div>
|
36 |
+
<?php Proxy\Pro::renderTimeZoneSwitcher() ?>
|
37 |
+
<?php if ( Config::showNotes() ): ?>
|
38 |
+
<div class="form-group">
|
39 |
+
<label for="bookly-appointment-notes"><?php echo Common::getTranslatedOption( 'bookly_l10n_label_notes' ) ?></label>
|
40 |
+
<textarea class="bookly-custom-field form-control" id="bookly-appointment-notes"></textarea>
|
41 |
+
</div>
|
42 |
+
<?php endif ?>
|
43 |
+
|
44 |
+
<?php Proxy\Shared::renderDetails() ?>
|
45 |
+
|
46 |
+
</div>
|
47 |
+
<div class="modal-footer">
|
48 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-success', __( 'Apply', 'bookly' ), array( 'ng-click' => 'saveCustomFields()' ) ) ?>
|
49 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
50 |
+
</div>
|
51 |
+
</form>
|
52 |
+
</div>
|
53 |
+
</div>
|
54 |
</div>
|
backend/components/dialogs/appointment/delete/Ajax.php
CHANGED
@@ -1,56 +1,56 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Delete;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Lib\DataHolders\Booking as DataHolders;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Ajax
|
9 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Delete
|
10 |
-
*/
|
11 |
-
class Ajax extends Lib\Base\Ajax
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* @inheritdoc
|
15 |
-
*/
|
16 |
-
protected static function permissions()
|
17 |
-
{
|
18 |
-
return array( '_default' => 'user' );
|
19 |
-
}
|
20 |
-
|
21 |
-
/**
|
22 |
-
* Delete single appointment.
|
23 |
-
*/
|
24 |
-
public static function deleteAppointment()
|
25 |
-
{
|
26 |
-
$appointment_id = self::parameter( 'appointment_id' );
|
27 |
-
$reason = self::parameter( 'reason' );
|
28 |
-
|
29 |
-
if ( self::parameter( 'notify' ) ) {
|
30 |
-
$ca_list = Lib\Entities\CustomerAppointment::query()
|
31 |
-
->where( 'appointment_id', $appointment_id )
|
32 |
-
->find();
|
33 |
-
/** @var Lib\Entities\CustomerAppointment $ca */
|
34 |
-
foreach ( $ca_list as $ca ) {
|
35 |
-
switch ( $ca->getStatus() ) {
|
36 |
-
case Lib\Entities\CustomerAppointment::STATUS_PENDING:
|
37 |
-
case Lib\Entities\CustomerAppointment::STATUS_WAITLISTED:
|
38 |
-
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_REJECTED );
|
39 |
-
break;
|
40 |
-
case Lib\Entities\CustomerAppointment::STATUS_APPROVED:
|
41 |
-
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_CANCELLED );
|
42 |
-
break;
|
43 |
-
}
|
44 |
-
Lib\Notifications\Sender::sendSingle(
|
45 |
-
DataHolders\Simple::create( $ca ),
|
46 |
-
null,
|
47 |
-
array( 'cancellation_reason' => $reason )
|
48 |
-
);
|
49 |
-
}
|
50 |
-
}
|
51 |
-
|
52 |
-
Lib\Entities\Appointment::find( $appointment_id )->delete();
|
53 |
-
|
54 |
-
wp_send_json_success();
|
55 |
-
}
|
56 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Delete;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Lib\DataHolders\Booking as DataHolders;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Ajax
|
9 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Delete
|
10 |
+
*/
|
11 |
+
class Ajax extends Lib\Base\Ajax
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* @inheritdoc
|
15 |
+
*/
|
16 |
+
protected static function permissions()
|
17 |
+
{
|
18 |
+
return array( '_default' => 'user' );
|
19 |
+
}
|
20 |
+
|
21 |
+
/**
|
22 |
+
* Delete single appointment.
|
23 |
+
*/
|
24 |
+
public static function deleteAppointment()
|
25 |
+
{
|
26 |
+
$appointment_id = self::parameter( 'appointment_id' );
|
27 |
+
$reason = self::parameter( 'reason' );
|
28 |
+
|
29 |
+
if ( self::parameter( 'notify' ) ) {
|
30 |
+
$ca_list = Lib\Entities\CustomerAppointment::query()
|
31 |
+
->where( 'appointment_id', $appointment_id )
|
32 |
+
->find();
|
33 |
+
/** @var Lib\Entities\CustomerAppointment $ca */
|
34 |
+
foreach ( $ca_list as $ca ) {
|
35 |
+
switch ( $ca->getStatus() ) {
|
36 |
+
case Lib\Entities\CustomerAppointment::STATUS_PENDING:
|
37 |
+
case Lib\Entities\CustomerAppointment::STATUS_WAITLISTED:
|
38 |
+
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_REJECTED );
|
39 |
+
break;
|
40 |
+
case Lib\Entities\CustomerAppointment::STATUS_APPROVED:
|
41 |
+
$ca->setStatus( Lib\Entities\CustomerAppointment::STATUS_CANCELLED );
|
42 |
+
break;
|
43 |
+
}
|
44 |
+
Lib\Notifications\Sender::sendSingle(
|
45 |
+
DataHolders\Simple::create( $ca ),
|
46 |
+
null,
|
47 |
+
array( 'cancellation_reason' => $reason )
|
48 |
+
);
|
49 |
+
}
|
50 |
+
}
|
51 |
+
|
52 |
+
Lib\Entities\Appointment::find( $appointment_id )->delete();
|
53 |
+
|
54 |
+
wp_send_json_success();
|
55 |
+
}
|
56 |
}
|
backend/components/dialogs/appointment/delete/Dialog.php
CHANGED
@@ -1,33 +1,33 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Delete;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Dialog
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
-
*/
|
10 |
-
class Dialog extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render delete appointment dialog.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
|
18 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
-
) );
|
20 |
-
|
21 |
-
|
22 |
-
'frontend' => array(
|
23 |
-
'js/spin.min.js' => array( 'jquery' ),
|
24 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
25 |
-
),
|
26 |
-
'module' => array(
|
27 |
-
'js/delete_dialog.js' => array( 'jquery' ),
|
28 |
-
),
|
29 |
-
) );
|
30 |
-
|
31 |
-
static::renderTemplate( 'delete' );
|
32 |
-
}
|
33 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Delete;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Dialog
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment
|
9 |
+
*/
|
10 |
+
class Dialog extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render delete appointment dialog.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
self::enqueueStyles( array(
|
18 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
+
) );
|
20 |
+
|
21 |
+
self::enqueueScripts( array(
|
22 |
+
'frontend' => array(
|
23 |
+
'js/spin.min.js' => array( 'jquery' ),
|
24 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
25 |
+
),
|
26 |
+
'module' => array(
|
27 |
+
'js/delete_dialog.js' => array( 'jquery' ),
|
28 |
+
),
|
29 |
+
) );
|
30 |
+
|
31 |
+
static::renderTemplate( 'delete' );
|
32 |
+
}
|
33 |
}
|
backend/components/dialogs/appointment/delete/resources/js/delete_dialog.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
-
/**
|
2 |
-
* Scripts for delete dialog
|
3 |
-
*/
|
4 |
-
|
5 |
-
jQuery(function($) {
|
6 |
-
$("#bookly-delete-notify").on('change', function() {
|
7 |
-
$('#bookly-delete-reason-cover').toggle();
|
8 |
-
})
|
9 |
});
|
1 |
+
/**
|
2 |
+
* Scripts for delete dialog
|
3 |
+
*/
|
4 |
+
|
5 |
+
jQuery(function($) {
|
6 |
+
$("#bookly-delete-notify").on('change', function() {
|
7 |
+
$('#bookly-delete-reason-cover').toggle();
|
8 |
+
})
|
9 |
});
|
backend/components/dialogs/appointment/delete/templates/delete.php
CHANGED
@@ -1,28 +1,28 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
?>
|
4 |
-
<div id="bookly-delete-dialog" class="modal fade" tabindex=-1 role="dialog">
|
5 |
-
<div class="modal-dialog">
|
6 |
-
<div class="modal-content">
|
7 |
-
<div class="modal-header">
|
8 |
-
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
9 |
-
<div class="modal-title h2"><?php _e( 'Delete', 'bookly' ) ?></div>
|
10 |
-
</div>
|
11 |
-
<div class="modal-body">
|
12 |
-
<div class="checkbox">
|
13 |
-
<label>
|
14 |
-
<input id="bookly-delete-notify" type="checkbox" />
|
15 |
-
<?php _e( 'Send notifications', 'bookly' ) ?>
|
16 |
-
</label>
|
17 |
-
</div>
|
18 |
-
<div class="form-group" style="display: none;" id="bookly-delete-reason-cover">
|
19 |
-
<input class="form-control" type="text" id="bookly-delete-reason" placeholder="<?php _e( 'Cancellation reason (optional)', 'bookly' ) ?>" />
|
20 |
-
</div>
|
21 |
-
</div>
|
22 |
-
<div class="modal-footer">
|
23 |
-
<?php Buttons::renderDelete(); ?>
|
24 |
-
<?php Buttons::renderCustom( null, 'btn-default', __( 'Cancel', 'bookly' ), array( 'ng-click' => 'closeDialog()', 'data-dismiss' => 'modal' ) ) ?>
|
25 |
-
</div>
|
26 |
-
</div>
|
27 |
-
</div>
|
28 |
-
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
?>
|
4 |
+
<div id="bookly-delete-dialog" class="modal fade" tabindex=-1 role="dialog">
|
5 |
+
<div class="modal-dialog">
|
6 |
+
<div class="modal-content">
|
7 |
+
<div class="modal-header">
|
8 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
9 |
+
<div class="modal-title h2"><?php _e( 'Delete', 'bookly' ) ?></div>
|
10 |
+
</div>
|
11 |
+
<div class="modal-body">
|
12 |
+
<div class="checkbox">
|
13 |
+
<label>
|
14 |
+
<input id="bookly-delete-notify" type="checkbox" />
|
15 |
+
<?php _e( 'Send notifications', 'bookly' ) ?>
|
16 |
+
</label>
|
17 |
+
</div>
|
18 |
+
<div class="form-group" style="display: none;" id="bookly-delete-reason-cover">
|
19 |
+
<input class="form-control" type="text" id="bookly-delete-reason" placeholder="<?php _e( 'Cancellation reason (optional)', 'bookly' ) ?>" />
|
20 |
+
</div>
|
21 |
+
</div>
|
22 |
+
<div class="modal-footer">
|
23 |
+
<?php Buttons::renderDelete(); ?>
|
24 |
+
<?php Buttons::renderCustom( null, 'btn-default', __( 'Cancel', 'bookly' ), array( 'ng-click' => 'closeDialog()', 'data-dismiss' => 'modal' ) ) ?>
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
</div>
|
backend/components/dialogs/appointment/edit/Ajax.php
CHANGED
@@ -1,808 +1,853 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Lib\DataHolders\Booking as DataHolders;
|
6 |
-
use Bookly\Backend\Modules\Calendar;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class Ajax
|
10 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit
|
11 |
-
*/
|
12 |
-
class Ajax extends Lib\Base\Ajax
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* @inheritdoc
|
16 |
-
*/
|
17 |
-
protected static function permissions()
|
18 |
-
{
|
19 |
-
return array( '_default' => 'user' );
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Get data needed for appointment form initialisation.
|
24 |
-
*/
|
25 |
-
public static function getDataForAppointmentForm()
|
26 |
-
{
|
27 |
-
$type = self::parameter( 'type', false ) == 'package'
|
28 |
-
? Lib\Entities\Service::TYPE_PACKAGE
|
29 |
-
: Lib\Entities\Service::TYPE_SIMPLE;
|
30 |
-
|
31 |
-
$result = array(
|
32 |
-
'staff'
|
33 |
-
'customers'
|
34 |
-
'start_time'
|
35 |
-
'end_time'
|
36 |
-
'app_start_time'
|
37 |
-
'app_end_time'
|
38 |
-
'week_days'
|
39 |
-
'time_interval'
|
40 |
-
'status'
|
41 |
-
'items' => array(
|
42 |
-
'pending' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_PENDING ),
|
43 |
-
'approved' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_APPROVED ),
|
44 |
-
'cancelled' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_CANCELLED ),
|
45 |
-
'rejected' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_REJECTED ),
|
46 |
-
'waitlisted' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_WAITLISTED ),
|
47 |
-
'done' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_DONE ),
|
48 |
-
)
|
49 |
-
),
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
$
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
$
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
'
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
//
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
a.
|
181 |
-
a.
|
182 |
-
a.
|
183 |
-
a.
|
184 |
-
a.
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
$
|
199 |
-
$response['data']['
|
200 |
-
$response['data']['
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
'
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
$response['data']['
|
215 |
-
$response['data']['
|
216 |
-
$response['data']['
|
217 |
-
$response['data']['
|
218 |
-
|
219 |
-
$
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
ca.
|
225 |
-
ca.
|
226 |
-
ca.
|
227 |
-
ca.
|
228 |
-
ca.
|
229 |
-
ca.
|
230 |
-
ca.
|
231 |
-
ca.
|
232 |
-
ca.
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
)
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
$
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
$
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
}
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
$
|
338 |
-
}
|
339 |
-
$
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
$
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
}
|
353 |
-
|
354 |
-
|
355 |
-
$
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
}
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
$
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
->
|
421 |
-
->
|
422 |
-
->
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
Lib\
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
$
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
$
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
$
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
}
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
//
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
$
|
764 |
-
$
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
808 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Lib\DataHolders\Booking as DataHolders;
|
6 |
+
use Bookly\Backend\Modules\Calendar;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Ajax
|
10 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit
|
11 |
+
*/
|
12 |
+
class Ajax extends Lib\Base\Ajax
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* @inheritdoc
|
16 |
+
*/
|
17 |
+
protected static function permissions()
|
18 |
+
{
|
19 |
+
return array( '_default' => 'user' );
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Get data needed for appointment form initialisation.
|
24 |
+
*/
|
25 |
+
public static function getDataForAppointmentForm()
|
26 |
+
{
|
27 |
+
$type = self::parameter( 'type', false ) == 'package'
|
28 |
+
? Lib\Entities\Service::TYPE_PACKAGE
|
29 |
+
: Lib\Entities\Service::TYPE_SIMPLE;
|
30 |
+
|
31 |
+
$result = array(
|
32 |
+
'staff' => array(),
|
33 |
+
'customers' => array(),
|
34 |
+
'start_time' => array(),
|
35 |
+
'end_time' => array(),
|
36 |
+
'app_start_time' => null, // Appointment start time which may not be in the list of start times.
|
37 |
+
'app_end_time' => null, // Appointment end time which may not be in the list of end times.
|
38 |
+
'week_days' => array(),
|
39 |
+
'time_interval' => Lib\Config::getTimeSlotLength(),
|
40 |
+
'status' => array(
|
41 |
+
'items' => array(
|
42 |
+
'pending' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_PENDING ),
|
43 |
+
'approved' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_APPROVED ),
|
44 |
+
'cancelled' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_CANCELLED ),
|
45 |
+
'rejected' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_REJECTED ),
|
46 |
+
'waitlisted' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_WAITLISTED ),
|
47 |
+
'done' => Lib\Entities\CustomerAppointment::statusToString( Lib\Entities\CustomerAppointment::STATUS_DONE ),
|
48 |
+
),
|
49 |
+
),
|
50 |
+
'extras_consider_duration' => (int) Lib\Proxy\ServiceExtras::considerDuration( true ),
|
51 |
+
'extras_multiply_nop' => (int) get_option( 'bookly_service_extras_multiply_nop', 1 ),
|
52 |
+
);
|
53 |
+
|
54 |
+
// Staff list.
|
55 |
+
$staff = Lib\Entities\Staff::query()->findOne();
|
56 |
+
$staff_members = $staff ? Lib\Config::proActive() ? Lib\Entities\Staff::query()->find() : array( $staff ) : array();
|
57 |
+
$postfix_archived = sprintf( ' (%s)', __( 'Archived', 'bookly' ) );
|
58 |
+
|
59 |
+
$max_duration = 0;
|
60 |
+
|
61 |
+
foreach ( $staff_members as $staff_member ) {
|
62 |
+
$services = array();
|
63 |
+
if ( $type == Lib\Entities\Service::TYPE_SIMPLE ) {
|
64 |
+
$services = Proxy\Pro::addCustomService( $services );
|
65 |
+
}
|
66 |
+
foreach ( $staff_member->getStaffServices( $type ) as $staff_service ) {
|
67 |
+
$sub_services = $staff_service->service->getSubServices();
|
68 |
+
if ( $type == Lib\Entities\Service::TYPE_SIMPLE || ! empty( $sub_services ) ) {
|
69 |
+
if ( $staff_service->getLocationId() === null || Lib\Proxy\Locations::prepareStaffLocationId( $staff_service->getLocationId(), $staff_service->getStaffId() ) == $staff_service->getLocationId() ) {
|
70 |
+
if ( ! in_array( $staff_service->service->getId(), array_map( function ( $service ) { return $service['id']; }, $services ) ) ) {
|
71 |
+
$services[] = array(
|
72 |
+
'id' => $staff_service->service->getId(),
|
73 |
+
'title' => sprintf(
|
74 |
+
'%s (%s)',
|
75 |
+
$staff_service->service->getTitle(),
|
76 |
+
Lib\Utils\DateTime::secondsToInterval( $staff_service->service->getDuration() )
|
77 |
+
),
|
78 |
+
'duration' => $staff_service->service->getDuration(),
|
79 |
+
'units_min' => $staff_service->service->getUnitsMin(),
|
80 |
+
'units_max' => $staff_service->service->getUnitsMax(),
|
81 |
+
'locations' => array(
|
82 |
+
( $staff_service->getLocationId() ?: 0 ) => array(
|
83 |
+
'capacity_min' => Lib\Config::groupBookingActive() ? $staff_service->getCapacityMin() : 1,
|
84 |
+
'capacity_max' => Lib\Config::groupBookingActive() ? $staff_service->getCapacityMax() : 1,
|
85 |
+
),
|
86 |
+
),
|
87 |
+
);
|
88 |
+
$max_duration = max( $max_duration, $staff_service->service->getUnitsMax() * $staff_service->service->getDuration() );
|
89 |
+
} else {
|
90 |
+
array_walk( $services, function ( &$item ) use ( $staff_service ) {
|
91 |
+
if ( $item['id'] == $staff_service->service->getId() ) {
|
92 |
+
$item['locations'][ $staff_service->getLocationId() ?: 0 ] = array(
|
93 |
+
'capacity_min' => Lib\Config::groupBookingActive() ? $staff_service->getCapacityMin() : 1,
|
94 |
+
'capacity_max' => Lib\Config::groupBookingActive() ? $staff_service->getCapacityMax() : 1,
|
95 |
+
);
|
96 |
+
}
|
97 |
+
} );
|
98 |
+
}
|
99 |
+
}
|
100 |
+
}
|
101 |
+
}
|
102 |
+
$locations = array();
|
103 |
+
foreach ( (array) Lib\Proxy\Locations::findByStaffId( $staff_member->getId() ) as $location ) {
|
104 |
+
$locations[] = array(
|
105 |
+
'id' => $location->getId(),
|
106 |
+
'name' => $location->getName(),
|
107 |
+
);
|
108 |
+
}
|
109 |
+
$result['staff'][] = array(
|
110 |
+
'id' => $staff_member->getId(),
|
111 |
+
'full_name' => $staff_member->getFullName() . ( $staff_member->getVisibility() == 'archive' ? $postfix_archived : '' ),
|
112 |
+
'archived' => $staff_member->getVisibility() == 'archive',
|
113 |
+
'services' => $services,
|
114 |
+
'locations' => $locations,
|
115 |
+
);
|
116 |
+
}
|
117 |
+
|
118 |
+
/** @var Lib\Entities\Customer $customer */
|
119 |
+
// Customers list.
|
120 |
+
foreach ( Lib\Entities\Customer::query()->sortBy( 'full_name' )->find() as $customer ) {
|
121 |
+
$name = $customer->getFullName();
|
122 |
+
if ( $customer->getEmail() != '' || $customer->getPhone() != '' ) {
|
123 |
+
$name .= ' (' . trim( $customer->getEmail() . ', ' . $customer->getPhone(), ', ' ) . ')';
|
124 |
+
}
|
125 |
+
|
126 |
+
$result['customers'][] = array(
|
127 |
+
'id' => $customer->getId(),
|
128 |
+
'name' => $name,
|
129 |
+
'status' => Lib\Proxy\CustomerGroups::prepareDefaultAppointmentStatus( get_option( 'bookly_gen_default_appointment_status' ), $customer->getGroupId() ),
|
130 |
+
'custom_fields' => array(),
|
131 |
+
'timezone' => Lib\Proxy\Pro::getLastCustomerTimezone( $customer->getId() ),
|
132 |
+
'number_of_persons' => 1,
|
133 |
+
);
|
134 |
+
}
|
135 |
+
|
136 |
+
// Time list.
|
137 |
+
$ts_length = Lib\Config::getTimeSlotLength();
|
138 |
+
$time_start = 0;
|
139 |
+
$time_end = max( $max_duration + DAY_IN_SECONDS, DAY_IN_SECONDS * 2 );
|
140 |
+
|
141 |
+
// Run the loop.
|
142 |
+
while ( $time_start <= $time_end ) {
|
143 |
+
$slot = array(
|
144 |
+
'value' => Lib\Utils\DateTime::buildTimeString( $time_start, false ),
|
145 |
+
'title' => Lib\Utils\DateTime::formatTime( $time_start ),
|
146 |
+
);
|
147 |
+
if ( $time_start < DAY_IN_SECONDS ) {
|
148 |
+
$result['start_time'][] = $slot;
|
149 |
+
}
|
150 |
+
$result['end_time'][] = $slot;
|
151 |
+
$time_start += $ts_length;
|
152 |
+
}
|
153 |
+
|
154 |
+
$days_times = Lib\Config::getDaysAndTimes();
|
155 |
+
$weekdays = array( 1 => 'sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat', );
|
156 |
+
foreach ( $days_times['days'] as $index => $abbrev ) {
|
157 |
+
$result['week_days'][] = $weekdays[ $index ];
|
158 |
+
}
|
159 |
+
|
160 |
+
if ( $type == Lib\Entities\Service::TYPE_PACKAGE ) {
|
161 |
+
$result = Proxy\Shared::prepareDataForPackage( $result );
|
162 |
+
}
|
163 |
+
|
164 |
+
wp_send_json( $result );
|
165 |
+
}
|
166 |
+
|
167 |
+
/**
|
168 |
+
* Get appointment data when editing an appointment.
|
169 |
+
*/
|
170 |
+
public static function getDataForAppointment()
|
171 |
+
{
|
172 |
+
$response = array( 'success' => false, 'data' => array( 'customers' => array() ) );
|
173 |
+
|
174 |
+
$appointment = new Lib\Entities\Appointment();
|
175 |
+
if ( $appointment->load( self::parameter( 'id' ) ) ) {
|
176 |
+
$response['success'] = true;
|
177 |
+
|
178 |
+
$query = Lib\Entities\Appointment::query( 'a' )
|
179 |
+
->select( 'SUM(ca.number_of_persons) AS total_number_of_persons,
|
180 |
+
a.staff_id,
|
181 |
+
a.staff_any,
|
182 |
+
a.service_id,
|
183 |
+
a.custom_service_name,
|
184 |
+
a.custom_service_price,
|
185 |
+
a.start_date,
|
186 |
+
a.end_date,
|
187 |
+
a.internal_note,
|
188 |
+
a.location_id' )
|
189 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
190 |
+
->leftJoin( 'StaffService', 'ss', 'ss.staff_id = a.staff_id AND ss.service_id = a.service_id AND ss.location_id = a.location_id' )
|
191 |
+
->where( 'a.id', $appointment->getId() );
|
192 |
+
if ( Lib\Config::groupBookingActive() ) {
|
193 |
+
$query->addSelect( 'ss.capacity_min AS min_capacity, ss.capacity_max AS max_capacity' );
|
194 |
+
} else {
|
195 |
+
$query->addSelect( '1 AS min_capacity, 1 AS max_capacity' );
|
196 |
+
}
|
197 |
+
|
198 |
+
$info = $query->fetchRow();
|
199 |
+
$response['data']['total_number_of_persons'] = $info['total_number_of_persons'];
|
200 |
+
$response['data']['min_capacity'] = $info['min_capacity'];
|
201 |
+
$response['data']['max_capacity'] = $info['max_capacity'];
|
202 |
+
$response['data']['start_date'] = $info['start_date'];
|
203 |
+
$response['data']['end_date'] = $info['end_date'];
|
204 |
+
$response['data']['start_time'] = $info['start_date'] ?
|
205 |
+
array(
|
206 |
+
'value' => date( 'H:i', strtotime( $info['start_date'] ) ),
|
207 |
+
'title' => Lib\Utils\DateTime::formatTime( $info['start_date'] ),
|
208 |
+
) : null;
|
209 |
+
$response['data']['end_time'] = $info['end_date'] ?
|
210 |
+
array(
|
211 |
+
'value' => date( 'H:i', strtotime( $info['end_date'] ) ),
|
212 |
+
'title' => Lib\Utils\DateTime::formatTime( $info['end_date'] ),
|
213 |
+
) : null;
|
214 |
+
$response['data']['staff_id'] = $info['staff_id'];
|
215 |
+
$response['data']['staff_any'] = (int) $info['staff_any'];
|
216 |
+
$response['data']['service_id'] = $info['service_id'];
|
217 |
+
$response['data']['custom_service_name'] = $info['custom_service_name'];
|
218 |
+
$response['data']['custom_service_price'] = (float) $info['custom_service_price'];
|
219 |
+
$response['data']['internal_note'] = $info['internal_note'];
|
220 |
+
$response['data']['location_id'] = $info['location_id'];
|
221 |
+
|
222 |
+
$customers = Lib\Entities\CustomerAppointment::query( 'ca' )
|
223 |
+
->select( 'ca.id,
|
224 |
+
ca.series_id,
|
225 |
+
ca.customer_id,
|
226 |
+
ca.package_id,
|
227 |
+
ca.custom_fields,
|
228 |
+
ca.extras,
|
229 |
+
ca.extras_multiply_nop,
|
230 |
+
ca.extras_consider_duration,
|
231 |
+
ca.number_of_persons,
|
232 |
+
ca.notes,
|
233 |
+
ca.status,
|
234 |
+
ca.payment_id,
|
235 |
+
ca.collaborative_service_id,
|
236 |
+
ca.collaborative_token,
|
237 |
+
ca.compound_service_id,
|
238 |
+
ca.compound_token,
|
239 |
+
ca.time_zone,
|
240 |
+
ca.time_zone_offset,
|
241 |
+
p.paid AS payment,
|
242 |
+
p.total AS payment_total,
|
243 |
+
p.type AS payment_type,
|
244 |
+
p.details AS payment_details,
|
245 |
+
p.status AS payment_status' )
|
246 |
+
->leftJoin( 'Payment', 'p', 'p.id = ca.payment_id' )
|
247 |
+
->where( 'ca.appointment_id', $appointment->getId() )
|
248 |
+
->fetchArray();
|
249 |
+
foreach ( $customers as $customer ) {
|
250 |
+
$payment_title = '';
|
251 |
+
if ( $customer['payment'] !== null ) {
|
252 |
+
$payment_title = Lib\Utils\Price::format( $customer['payment'] );
|
253 |
+
if ( $customer['payment'] != $customer['payment_total'] ) {
|
254 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $customer['payment_total'] ) );
|
255 |
+
}
|
256 |
+
$payment_title .= sprintf(
|
257 |
+
' %s <span%s>%s</span>',
|
258 |
+
Lib\Entities\Payment::typeToString( $customer['payment_type'] ),
|
259 |
+
$customer['payment_status'] == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
260 |
+
Lib\Entities\Payment::statusToString( $customer['payment_status'] )
|
261 |
+
);
|
262 |
+
}
|
263 |
+
$collaborative_service = '';
|
264 |
+
if ( $customer['collaborative_service_id'] !== null ) {
|
265 |
+
$service = new Lib\Entities\Service();
|
266 |
+
if ( $service->load( $customer['collaborative_service_id'] ) ) {
|
267 |
+
$collaborative_service = $service->getTranslatedTitle();
|
268 |
+
}
|
269 |
+
}
|
270 |
+
$compound_service = '';
|
271 |
+
if ( $customer['compound_service_id'] !== null ) {
|
272 |
+
$service = new Lib\Entities\Service();
|
273 |
+
if ( $service->load( $customer['compound_service_id'] ) ) {
|
274 |
+
$compound_service = $service->getTranslatedTitle();
|
275 |
+
}
|
276 |
+
}
|
277 |
+
$custom_fields = (array) json_decode( $customer['custom_fields'], true );
|
278 |
+
$response['data']['customers'][] = array(
|
279 |
+
'id' => $customer['customer_id'],
|
280 |
+
'ca_id' => $customer['id'],
|
281 |
+
'series_id' => $customer['series_id'],
|
282 |
+
'package_id' => $customer['package_id'],
|
283 |
+
'collaborative_service' => $collaborative_service,
|
284 |
+
'collaborative_token' => $customer['collaborative_token'],
|
285 |
+
'compound_service' => $compound_service,
|
286 |
+
'compound_token' => $customer['compound_token'],
|
287 |
+
'custom_fields' => $custom_fields,
|
288 |
+
'files' => Lib\Proxy\Files::getFileNamesForCustomFields( $custom_fields ),
|
289 |
+
'extras' => (array) json_decode( $customer['extras'], true ),
|
290 |
+
'extras_multiply_nop' => $customer['extras_multiply_nop'],
|
291 |
+
'extras_consider_duration' => (int) $customer['extras_consider_duration'],
|
292 |
+
'number_of_persons' => $customer['number_of_persons'],
|
293 |
+
'notes' => $customer['notes'],
|
294 |
+
'payment_id' => $customer['payment_id'],
|
295 |
+
'payment_type' => $customer['payment'] != $customer['payment_total'] ? 'partial' : 'full',
|
296 |
+
'payment_title' => $payment_title,
|
297 |
+
'status' => $customer['status'],
|
298 |
+
'timezone' => Lib\Proxy\Pro::getCustomerTimezone( $customer['time_zone'], $customer['time_zone_offset'] ),
|
299 |
+
);
|
300 |
+
}
|
301 |
+
}
|
302 |
+
|
303 |
+
wp_send_json( $response );
|
304 |
+
}
|
305 |
+
|
306 |
+
/**
|
307 |
+
* Save appointment form (for both create and edit).
|
308 |
+
*/
|
309 |
+
public static function saveAppointmentForm()
|
310 |
+
{
|
311 |
+
$response = array( 'success' => false );
|
312 |
+
|
313 |
+
$appointment_id = (int) self::parameter( 'id', 0 );
|
314 |
+
$staff_id = (int) self::parameter( 'staff_id', 0 );
|
315 |
+
$service_id = (int) self::parameter( 'service_id', -1 );
|
316 |
+
$custom_service_name = trim( self::parameter( 'custom_service_name' ) );
|
317 |
+
$custom_service_price = trim( self::parameter( 'custom_service_price' ) );
|
318 |
+
$location_id = (int) self::parameter( 'location_id', 0 );
|
319 |
+
$skip_date = self::parameter( 'skip_date', 0 );
|
320 |
+
$start_date = self::parameter( 'start_date' );
|
321 |
+
$end_date = self::parameter( 'end_date' );
|
322 |
+
$repeat = json_decode( self::parameter( 'repeat', '[]' ), true );
|
323 |
+
$schedule = self::parameter( 'schedule', array() );
|
324 |
+
$customers = json_decode( self::parameter( 'customers', '[]' ), true );
|
325 |
+
$notification = self::parameter( 'notification', 'no' );
|
326 |
+
$internal_note = self::parameter( 'internal_note' );
|
327 |
+
$created_from = self::parameter( 'created_from' );
|
328 |
+
|
329 |
+
if ( ! $service_id ) {
|
330 |
+
// Custom service.
|
331 |
+
$service_id = null;
|
332 |
+
}
|
333 |
+
if ( $service_id || $custom_service_name == '' ) {
|
334 |
+
$custom_service_name = null;
|
335 |
+
}
|
336 |
+
if ( $service_id || $custom_service_price == '' ) {
|
337 |
+
$custom_service_price = null;
|
338 |
+
}
|
339 |
+
if ( ! $location_id ) {
|
340 |
+
$location_id = null;
|
341 |
+
}
|
342 |
+
|
343 |
+
// Check for errors.
|
344 |
+
if ( ! $skip_date ) {
|
345 |
+
if ( ! $start_date ) {
|
346 |
+
$response['errors']['time_interval'] = __( 'Start time must not be empty', 'bookly' );
|
347 |
+
} elseif ( ! $end_date ) {
|
348 |
+
$response['errors']['time_interval'] = __( 'End time must not be empty', 'bookly' );
|
349 |
+
} elseif ( $start_date == $end_date ) {
|
350 |
+
$response['errors']['time_interval'] = __( 'End time must not be equal to start time', 'bookly' );
|
351 |
+
}
|
352 |
+
}
|
353 |
+
|
354 |
+
if ( $service_id == -1 ) {
|
355 |
+
$response['errors']['service_required'] = true;
|
356 |
+
} else if ( $service_id === null && $custom_service_name === null ) {
|
357 |
+
$response['errors']['custom_service_name_required'] = true;
|
358 |
+
}
|
359 |
+
$total_number_of_persons = 0;
|
360 |
+
$max_extras_duration = 0;
|
361 |
+
foreach ( $customers as $i => $customer ) {
|
362 |
+
if ( $customer['status'] == Lib\Entities\CustomerAppointment::STATUS_PENDING ||
|
363 |
+
$customer['status'] == Lib\Entities\CustomerAppointment::STATUS_APPROVED
|
364 |
+
) {
|
365 |
+
$total_number_of_persons += $customer['number_of_persons'];
|
366 |
+
if ( $customer['extras_consider_duration'] ) {
|
367 |
+
$extras_duration = Lib\Proxy\ServiceExtras::getTotalDuration( $customer['extras'] );
|
368 |
+
if ( $extras_duration > $max_extras_duration ) {
|
369 |
+
$max_extras_duration = $extras_duration;
|
370 |
+
}
|
371 |
+
}
|
372 |
+
}
|
373 |
+
$customers[ $i ]['created_from'] = ( $created_from == 'backend' ) ? 'backend' : 'frontend';
|
374 |
+
}
|
375 |
+
if ( $service_id ) {
|
376 |
+
$staff_service = new Lib\Entities\StaffService();
|
377 |
+
$staff_service->loadBy( array(
|
378 |
+
'staff_id' => $staff_id,
|
379 |
+
'service_id' => $service_id,
|
380 |
+
'location_id' => $location_id ?: null,
|
381 |
+
) );
|
382 |
+
if ( ! $staff_service->isLoaded() ) {
|
383 |
+
$staff_service->loadBy( array(
|
384 |
+
'staff_id' => $staff_id,
|
385 |
+
'service_id' => $service_id,
|
386 |
+
'location_id' => null,
|
387 |
+
) );
|
388 |
+
}
|
389 |
+
if ( $total_number_of_persons > $staff_service->getCapacityMax() ) {
|
390 |
+
$response['errors']['overflow_capacity'] = sprintf(
|
391 |
+
__( 'The number of customers should not be more than %d', 'bookly' ),
|
392 |
+
$staff_service->getCapacityMax()
|
393 |
+
);
|
394 |
+
}
|
395 |
+
}
|
396 |
+
|
397 |
+
// If no errors then try to save the appointment.
|
398 |
+
if ( ! isset ( $response['errors'] ) ) {
|
399 |
+
$duration = Lib\Slots\DatePoint::fromStr( $end_date )->diff( Lib\Slots\DatePoint::fromStr( $start_date ) );
|
400 |
+
if ( ! $skip_date && $repeat['enabled'] ) {
|
401 |
+
// Series.
|
402 |
+
if ( ! empty ( $schedule ) ) {
|
403 |
+
/** @var DataHolders\Order[] $orders */
|
404 |
+
$orders = array();
|
405 |
+
|
406 |
+
if ( $service_id ) {
|
407 |
+
$service = Lib\Entities\Service::find( $service_id );
|
408 |
+
} else {
|
409 |
+
$service = new Lib\Entities\Service();
|
410 |
+
$service
|
411 |
+
->setTitle( $custom_service_name )
|
412 |
+
->setDuration( $duration )
|
413 |
+
->setPrice( $custom_service_price );
|
414 |
+
}
|
415 |
+
|
416 |
+
foreach ( $customers as $customer ) {
|
417 |
+
// Create new series.
|
418 |
+
$series = new Lib\Entities\Series();
|
419 |
+
$series
|
420 |
+
->setRepeat( self::parameter( 'repeat' ) )
|
421 |
+
->setToken( Lib\Utils\Common::generateToken( get_class( $series ), 'token' ) )
|
422 |
+
->save();
|
423 |
+
|
424 |
+
// Create order
|
425 |
+
if ( $notification != 'no' ) {
|
426 |
+
$orders[ $customer['id'] ] = DataHolders\Order::create( Lib\Entities\Customer::find( $customer['id'] ) )
|
427 |
+
->addItem( 0, DataHolders\Series::create( $series ) );
|
428 |
+
}
|
429 |
+
|
430 |
+
foreach ( $schedule as $slot ) {
|
431 |
+
$slot = json_decode( $slot, true );
|
432 |
+
$start_date = $slot[0][2];
|
433 |
+
$end_date = Lib\Slots\DatePoint::fromStr( $start_date )->modify( $duration )->format( 'Y-m-d H:i:s' );
|
434 |
+
// Try to find existing appointment
|
435 |
+
$appointment = Lib\Entities\Appointment::query( 'a' )
|
436 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'ca.appointment_id = a.id' )
|
437 |
+
->where( 'a.staff_id', $staff_id )
|
438 |
+
->where( 'a.service_id', $service_id )
|
439 |
+
->whereNot( 'ca.status', Lib\Entities\CustomerAppointment::STATUS_CANCELLED )
|
440 |
+
->whereNot( 'ca.status', Lib\Entities\CustomerAppointment::STATUS_REJECTED )
|
441 |
+
->where( 'start_date', $start_date )
|
442 |
+
->findOne();
|
443 |
+
|
444 |
+
$ca_customers = array();
|
445 |
+
if ( ! $appointment ) {
|
446 |
+
// Create appointment.
|
447 |
+
$appointment = new Lib\Entities\Appointment();
|
448 |
+
$appointment
|
449 |
+
->setLocationId( $location_id )
|
450 |
+
->setStaffId( $staff_id )
|
451 |
+
->setServiceId( $service_id )
|
452 |
+
->setCustomServiceName( $custom_service_name )
|
453 |
+
->setCustomServicePrice( $custom_service_price )
|
454 |
+
->setStartDate( $start_date )
|
455 |
+
->setEndDate( $end_date )
|
456 |
+
->setInternalNote( $internal_note )
|
457 |
+
->setExtrasDuration( $max_extras_duration )
|
458 |
+
->save();
|
459 |
+
} else {
|
460 |
+
foreach ( $appointment->getCustomerAppointments( true ) as $ca ) {
|
461 |
+
$ca_customer = $ca->getFields();
|
462 |
+
$ca_customer['ca_id'] = $ca->getId();
|
463 |
+
$ca_customer['extras'] = json_decode( $ca_customer['extras'], true );
|
464 |
+
$ca_customer['custom_fields'] = json_decode( $ca_customer['custom_fields'], true );
|
465 |
+
$ca_customers[] = $ca_customer;
|
466 |
+
}
|
467 |
+
}
|
468 |
+
|
469 |
+
if ( $appointment->getId() ) {
|
470 |
+
// Save customer appointments.
|
471 |
+
$ca_list = $appointment->saveCustomerAppointments( array_merge( $ca_customers, array( $customer ) ), $series->getId() );
|
472 |
+
// Google Calendar.
|
473 |
+
Lib\Proxy\Pro::syncGoogleCalendarEvent( $appointment );
|
474 |
+
// Waiting list.
|
475 |
+
Lib\Proxy\WaitingList::handleParticipantsChange( $appointment );
|
476 |
+
|
477 |
+
if ( $notification != 'no' ) {
|
478 |
+
foreach ( $ca_list as $ca ) {
|
479 |
+
$item = DataHolders\Simple::create( $ca )
|
480 |
+
->setService( $service )
|
481 |
+
->setAppointment( $appointment );
|
482 |
+
$orders[ $ca->getCustomerId() ]->getItem( 0 )->addItem( $item );
|
483 |
+
}
|
484 |
+
}
|
485 |
+
}
|
486 |
+
}
|
487 |
+
if ( $customer['payment_create'] === true ) {
|
488 |
+
Proxy\RecurringAppointments::createBackendPayment( $series, $customer );
|
489 |
+
}
|
490 |
+
}
|
491 |
+
if ( $notification != 'no' ) {
|
492 |
+
foreach ( $orders as $order ) {
|
493 |
+
Lib\Proxy\RecurringAppointments::sendRecurring( $order->getItem( 0 ), $order );
|
494 |
+
}
|
495 |
+
}
|
496 |
+
}
|
497 |
+
$response['success'] = true;
|
498 |
+
$response['data'] = array( 'staffId' => $staff_id ); // make FullCalendar refetch events
|
499 |
+
} else {
|
500 |
+
// Single appointment.
|
501 |
+
$appointment = new Lib\Entities\Appointment();
|
502 |
+
if ( $appointment_id ) {
|
503 |
+
// Edit.
|
504 |
+
$appointment->load( $appointment_id );
|
505 |
+
if ( $appointment->getStaffId() != $staff_id ) {
|
506 |
+
$appointment->setStaffAny( 0 );
|
507 |
+
}
|
508 |
+
}
|
509 |
+
$appointment
|
510 |
+
->setLocationId( $location_id )
|
511 |
+
->setStaffId( $staff_id )
|
512 |
+
->setServiceId( $service_id )
|
513 |
+
->setCustomServiceName( $custom_service_name )
|
514 |
+
->setCustomServicePrice( $custom_service_price )
|
515 |
+
->setStartDate( $skip_date ? null : $start_date )
|
516 |
+
->setEndDate( $skip_date ? null : $end_date )
|
517 |
+
->setInternalNote( $internal_note )
|
518 |
+
->setExtrasDuration( $max_extras_duration );
|
519 |
+
|
520 |
+
if ( $appointment->save() !== false ) {
|
521 |
+
// Save customer appointments.
|
522 |
+
$ca_status_changed = $appointment->saveCustomerAppointments( $customers );
|
523 |
+
|
524 |
+
foreach ( $customers as $customer ) {
|
525 |
+
if ( $customer['payment_create'] === true && $customer['series_id'] ) {
|
526 |
+
Proxy\RecurringAppointments::createBackendPayment( Lib\Entities\Series::find( $customer['series_id'] ), $customer );
|
527 |
+
}
|
528 |
+
}
|
529 |
+
|
530 |
+
// Google Calendar.
|
531 |
+
Lib\Proxy\Pro::syncGoogleCalendarEvent( $appointment );
|
532 |
+
// Waiting list.
|
533 |
+
Lib\Proxy\WaitingList::handleParticipantsChange( $appointment );
|
534 |
+
|
535 |
+
// Send notifications.
|
536 |
+
if ( $notification == 'changed_status' ) {
|
537 |
+
foreach ( $ca_status_changed as $ca ) {
|
538 |
+
Lib\Notifications\Sender::sendSingle( DataHolders\Simple::create( $ca )->setAppointment( $appointment ) );
|
539 |
+
}
|
540 |
+
} elseif ( $notification == 'all' ) {
|
541 |
+
$ca_list = $appointment->getCustomerAppointments( true );
|
542 |
+
foreach ( $ca_status_changed as $ca ) {
|
543 |
+
// The value "just_created" was initialized for the objects of this array
|
544 |
+
Lib\Notifications\Sender::sendSingle( DataHolders\Simple::create( $ca )->setAppointment( $appointment ) );
|
545 |
+
unset( $ca_list[ $ca->getId() ] );
|
546 |
+
}
|
547 |
+
foreach ( $ca_list as $ca ) {
|
548 |
+
Lib\Notifications\Sender::sendSingle( DataHolders\Simple::create( $ca )->setAppointment( $appointment ) );
|
549 |
+
}
|
550 |
+
}
|
551 |
+
|
552 |
+
$response['success'] = true;
|
553 |
+
$response['data'] = self::_getAppointmentForFC( $staff_id, $appointment->getId() );
|
554 |
+
} else {
|
555 |
+
$response['errors'] = array( 'db' => __( 'Could not save appointment in database.', 'bookly' ) );
|
556 |
+
}
|
557 |
+
}
|
558 |
+
}
|
559 |
+
update_user_meta( get_current_user_id(), 'bookly_appointment_form_send_notifications', $notification );
|
560 |
+
|
561 |
+
wp_send_json( $response );
|
562 |
+
}
|
563 |
+
|
564 |
+
/**
|
565 |
+
* Check whether appointment settings produce errors.
|
566 |
+
*/
|
567 |
+
public static function checkAppointmentErrors()
|
568 |
+
{
|
569 |
+
$start_date = self::parameter( 'start_date' );
|
570 |
+
$end_date = self::parameter( 'end_date' );
|
571 |
+
$staff_id = (int) self::parameter( 'staff_id' );
|
572 |
+
$service_id = (int) self::parameter( 'service_id' );
|
573 |
+
$location_id = Lib\Proxy\Locations::prepareStaffScheduleLocationId( self::parameter( 'location_id' ), $staff_id ) ?: null;
|
574 |
+
$appointment_id = (int) self::parameter( 'appointment_id' );
|
575 |
+
$appointment_duration = strtotime( $end_date ) - strtotime( $start_date );
|
576 |
+
$customers = json_decode( self::parameter( 'customers', '[]' ), true );
|
577 |
+
$service = Lib\Entities\Service::find( $service_id );
|
578 |
+
$service_duration = $service ? $service->getDuration() : 0;
|
579 |
+
|
580 |
+
$result = array(
|
581 |
+
'date_interval_not_available' => false,
|
582 |
+
'date_interval_warning' => false,
|
583 |
+
'interval_not_in_staff_schedule' => false,
|
584 |
+
'interval_not_in_service_schedule' => false,
|
585 |
+
'staff_reaches_working_time_limit' => false,
|
586 |
+
'customers_appointments_limit' => array(),
|
587 |
+
);
|
588 |
+
|
589 |
+
$max_extras_duration = 0;
|
590 |
+
foreach ( $customers as $customer ) {
|
591 |
+
if ( in_array( $customer['status'], array( Lib\Entities\CustomerAppointment::STATUS_PENDING, Lib\Entities\CustomerAppointment::STATUS_APPROVED ) ) ) {
|
592 |
+
if ( $customer['extras_consider_duration'] ) {
|
593 |
+
$extras_duration = Lib\Proxy\ServiceExtras::getTotalDuration( $customer['extras'] );
|
594 |
+
if ( $extras_duration > $max_extras_duration ) {
|
595 |
+
$max_extras_duration = $extras_duration;
|
596 |
+
}
|
597 |
+
}
|
598 |
+
}
|
599 |
+
}
|
600 |
+
if ( $start_date && $end_date ) {
|
601 |
+
$total_end_date = $end_date;
|
602 |
+
if ( $max_extras_duration > 0 ) {
|
603 |
+
$total_end_date = date_create( $end_date )->modify( '+' . $max_extras_duration . ' sec' )->format( 'Y-m-d H:i:s' );
|
604 |
+
}
|
605 |
+
if ( ! self::_dateIntervalIsAvailableForAppointment( $start_date, $total_end_date, $staff_id, $appointment_id ) ) {
|
606 |
+
$result['date_interval_not_available'] = true;
|
607 |
+
}
|
608 |
+
|
609 |
+
// Check if selected interval fit into staff schedule.
|
610 |
+
$interval_valid = true;
|
611 |
+
if ( $staff_id && $start_date ) {
|
612 |
+
$staff = Lib\Entities\Staff::find( $staff_id );
|
613 |
+
|
614 |
+
// Check if interval is suitable for staff's hours limit
|
615 |
+
$result['staff_reaches_working_time_limit'] = Lib\Proxy\Pro::getWorkingTimeLimitError( $staff, $start_date, $end_date, $appointment_duration + $max_extras_duration, $appointment_id ) ?: false;
|
616 |
+
|
617 |
+
if ( $service_duration >= DAY_IN_SECONDS ) {
|
618 |
+
// For services with duration 24+ hours check holidays and days off
|
619 |
+
for ( $day = 0; $day < $service_duration / DAY_IN_SECONDS; $day ++ ) {
|
620 |
+
$work_date = date_create( $start_date )->modify( sprintf( '%s days', $day ) );
|
621 |
+
$week_day = $work_date->format( 'w' ) + 1;
|
622 |
+
// Check staff schedule for days off
|
623 |
+
if ( $staff->isOnHoliday( $work_date ) ||
|
624 |
+
! Lib\Entities\StaffScheduleItem::query()
|
625 |
+
->select( 'id' )
|
626 |
+
->where( 'staff_id', $staff_id )
|
627 |
+
->where( 'location_id', $location_id )
|
628 |
+
->where( 'day_index', $week_day )
|
629 |
+
->whereNot( 'start_time', null )
|
630 |
+
->fetchRow()
|
631 |
+
) {
|
632 |
+
$interval_valid = false;
|
633 |
+
break;
|
634 |
+
}
|
635 |
+
}
|
636 |
+
} else {
|
637 |
+
// Check day before and current day to get night schedule from previous day.
|
638 |
+
$interval_valid = false;
|
639 |
+
for ( $day = 0; $day <= 1; $day ++ ) {
|
640 |
+
$day_start_date = date_create( $start_date )->modify( sprintf( '%s days', $day - 1 ) );
|
641 |
+
$day_end_date = date_create( $end_date )->modify( sprintf( '%s days', $day - 1 ) );
|
642 |
+
if ( ! $staff->isOnHoliday( $day_start_date ) ) {
|
643 |
+
$day_start_hour = ( 1 - $day ) * 24 + $day_start_date->format( 'G' );
|
644 |
+
$day_end_hour = ( 1 - $day ) * 24 + $day_end_date->format( 'G' );
|
645 |
+
$day_start_time = sprintf( '%02d:%02d:00', $day_start_hour, $day_start_date->format( 'i' ) );
|
646 |
+
$day_end_time = sprintf( '%02d:%02d:00', $day_end_hour >= $day_start_hour ? $day_end_hour : $day_end_hour + 24, $day_end_date->format( 'i' ) );
|
647 |
+
|
648 |
+
$special_days = (array) Lib\Proxy\SpecialDays::getSchedule( array( $staff_id ), $day_start_date, $day_start_date );
|
649 |
+
if ( ! empty( $special_days ) ) {
|
650 |
+
// Check if interval fit into special day schedule.
|
651 |
+
$special_day = current( $special_days );
|
652 |
+
if ( ( $special_day['start_time'] <= $day_start_time ) && ( $special_day['end_time'] >= $day_end_time ) ) {
|
653 |
+
if ( ! ( $special_day['break_start'] && ( $special_day['break_start'] < $day_end_time ) && ( $special_day['break_end'] > $day_start_time ) ) ) {
|
654 |
+
$interval_valid = true;
|
655 |
+
break;
|
656 |
+
}
|
657 |
+
}
|
658 |
+
} else {
|
659 |
+
// Check if interval fit into regular staff working schedule.
|
660 |
+
$week_day = $day_start_date->format( 'w' ) + 1;
|
661 |
+
$ssi = Lib\Entities\StaffScheduleItem::query()
|
662 |
+
->select( 'id' )
|
663 |
+
->where( 'staff_id', $staff_id )
|
664 |
+
->where( 'location_id', $location_id )
|
665 |
+
->where( 'day_index', $week_day )
|
666 |
+
->whereNot( 'start_time', null )
|
667 |
+
->whereLte( 'start_time', $day_start_time )
|
668 |
+
->whereGte( 'end_time', $day_end_time )
|
669 |
+
->fetchRow();
|
670 |
+
if ( $ssi ) {
|
671 |
+
// Check if interval not intercept with breaks.
|
672 |
+
if ( Lib\Entities\ScheduleItemBreak::query()
|
673 |
+
->where( 'staff_schedule_item_id', $ssi['id'] )
|
674 |
+
->whereLt( 'start_time', $day_end_time )
|
675 |
+
->whereGt( 'end_time', $day_start_time )
|
676 |
+
->count() == 0
|
677 |
+
) {
|
678 |
+
$interval_valid = true;
|
679 |
+
break;
|
680 |
+
}
|
681 |
+
}
|
682 |
+
}
|
683 |
+
}
|
684 |
+
}
|
685 |
+
}
|
686 |
+
}
|
687 |
+
if ( ! $interval_valid ) {
|
688 |
+
$result['interval_not_in_staff_schedule'] = true;
|
689 |
+
}
|
690 |
+
if ( $service ) {
|
691 |
+
if ( $service_duration >= DAY_IN_SECONDS ) {
|
692 |
+
// For services with duration 24+ hours check days off
|
693 |
+
$service_schedule = (array) Lib\Proxy\ServiceSchedule::getSchedule( $service_id );
|
694 |
+
$interval_valid = true;
|
695 |
+
|
696 |
+
// Check service schedule and service special days
|
697 |
+
for ( $day = 0; $day < $service_duration / DAY_IN_SECONDS; $day ++ ) {
|
698 |
+
$work_date = date_create( $start_date )->modify( sprintf( '%s days', $day ) );
|
699 |
+
$week_day = $work_date->format( 'w' ) + 1;
|
700 |
+
// Check service schedule for days off
|
701 |
+
$service_schedule_valid = true;
|
702 |
+
if ( Lib\Config::serviceScheduleActive() ) {
|
703 |
+
$service_schedule_valid = false;
|
704 |
+
foreach ( $service_schedule as $day_schedule ) {
|
705 |
+
if ( $day_schedule['day_index'] == $week_day && $day_schedule['start_time'] ) {
|
706 |
+
$service_schedule_valid = true;
|
707 |
+
break;
|
708 |
+
}
|
709 |
+
}
|
710 |
+
}
|
711 |
+
if ( ! $service_schedule_valid ) {
|
712 |
+
$interval_valid = false;
|
713 |
+
break;
|
714 |
+
}
|
715 |
+
// Check service special days for days off
|
716 |
+
$service_special_days_valid = true;
|
717 |
+
if ( Lib\Config::specialDaysActive() ) {
|
718 |
+
$special_days = (array) Lib\Proxy\SpecialDays::getServiceSchedule( $service_id, $work_date, $work_date );
|
719 |
+
if ( ! empty( $special_days ) ) {
|
720 |
+
$service_special_days_valid = false;
|
721 |
+
$schedule = current( $special_days );
|
722 |
+
if ( $schedule['start_time'] ) {
|
723 |
+
$service_special_days_valid = true;
|
724 |
+
}
|
725 |
+
}
|
726 |
+
}
|
727 |
+
if ( ! $service_special_days_valid ) {
|
728 |
+
$interval_valid = false;
|
729 |
+
break;
|
730 |
+
}
|
731 |
+
}
|
732 |
+
if ( ! $interval_valid ) {
|
733 |
+
$result['interval_not_in_service_schedule'] = true;
|
734 |
+
}
|
735 |
+
// Check staff schedule and staff special days
|
736 |
+
$interval_valid = true;
|
737 |
+
for ( $day = 0; $day < $service_duration / DAY_IN_SECONDS; $day ++ ) {
|
738 |
+
$work_date = date_create( $start_date )->modify( sprintf( '%s days', $day ) );
|
739 |
+
$week_day = $work_date->format( 'w' ) + 1;
|
740 |
+
if ( Lib\Entities\StaffScheduleItem::query()
|
741 |
+
->where( 'staff_id', $staff_id )
|
742 |
+
->where( 'day_index', $week_day )
|
743 |
+
->whereNot( 'start_time', null )
|
744 |
+
->count() == 0
|
745 |
+
) {
|
746 |
+
$interval_valid = false;
|
747 |
+
break;
|
748 |
+
}
|
749 |
+
}
|
750 |
+
if ( ! $interval_valid ) {
|
751 |
+
$result['interval_not_in_staff_schedule'] = true;
|
752 |
+
}
|
753 |
+
} else {
|
754 |
+
// Check if selected interval fit into service schedule.
|
755 |
+
$interval_valid = false;
|
756 |
+
// Check day before and current day to get night schedule from previous day.
|
757 |
+
for ( $day = 0; $day <= 1; $day ++ ) {
|
758 |
+
$day_start_date = date_create( $start_date )->modify( sprintf( '%s days', $day - 1 ) );
|
759 |
+
$day_end_date = date_create( $end_date )->modify( sprintf( '%s days', $day - 1 ) );
|
760 |
+
|
761 |
+
$day_start_hour = ( 1 - $day ) * 24 + $day_start_date->format( 'G' );
|
762 |
+
$day_end_hour = ( 1 - $day ) * 24 + $day_end_date->format( 'G' );
|
763 |
+
$day_start_time = sprintf( '%02d:%02d:00', $day_start_hour, $day_start_date->format( 'i' ) );
|
764 |
+
$day_end_time = sprintf( '%02d:%02d:00', $day_end_hour >= $day_start_hour ? $day_end_hour : $day_end_hour + 24, $day_end_date->format( 'i' ) );
|
765 |
+
|
766 |
+
$special_days = (array) Lib\Proxy\SpecialDays::getServiceSchedule( $service_id, $day_start_date, $day_start_date );
|
767 |
+
if ( ! empty( $special_days ) ) {
|
768 |
+
// Check if interval fit into special day schedule.
|
769 |
+
$special_day = current( $special_days );
|
770 |
+
if ( ( $special_day['start_time'] <= $day_start_time ) && ( $special_day['end_time'] >= $day_end_time ) ) {
|
771 |
+
if ( ! ( $special_day['break_start'] && ( $special_day['break_start'] < $day_end_time ) && ( $special_day['break_end'] > $day_start_time ) ) ) {
|
772 |
+
$interval_valid = true;
|
773 |
+
break;
|
774 |
+
}
|
775 |
+
}
|
776 |
+
} else {
|
777 |
+
// Check if interval fit into service working schedule.
|
778 |
+
$schedule = (array) Lib\Proxy\ServiceSchedule::getSchedule( $service_id );
|
779 |
+
if ( ! empty ( $schedule ) ) {
|
780 |
+
$week_day = $day_start_date->format( 'w' ) + 1;
|
781 |
+
foreach ( $schedule as $schedule_day ) {
|
782 |
+
if ( $schedule_day['day_index'] == $week_day ) {
|
783 |
+
if ( ( $schedule_day['start_time'] <= $day_start_time ) && ( $schedule_day['end_time'] >= $day_end_time ) ) {
|
784 |
+
$interval_valid = true;
|
785 |
+
if ( $schedule_day['break_start'] && ( $schedule_day['break_start'] < $day_end_time ) && ( $schedule_day['break_end'] > $day_start_time ) ) {
|
786 |
+
$interval_valid = false;
|
787 |
+
break;
|
788 |
+
}
|
789 |
+
}
|
790 |
+
}
|
791 |
+
}
|
792 |
+
} else {
|
793 |
+
$interval_valid = true;
|
794 |
+
break;
|
795 |
+
}
|
796 |
+
}
|
797 |
+
}
|
798 |
+
if ( ! $interval_valid ) {
|
799 |
+
$result['interval_not_in_service_schedule'] = true;
|
800 |
+
}
|
801 |
+
// Service duration interval is not equal to.
|
802 |
+
$result['date_interval_warning'] = ! ( $appointment_duration >= $service->getMinDuration() && $appointment_duration <= $service->getMaxDuration() && ( $service_duration == 0 || $appointment_duration % $service_duration == 0 ) );
|
803 |
+
}
|
804 |
+
|
805 |
+
// Check customers for appointments limit
|
806 |
+
foreach ( $customers as $index => $customer ) {
|
807 |
+
if ( $service->appointmentsLimitReached( $customer['id'], array( $start_date ) ) ) {
|
808 |
+
$customer_error = Lib\Entities\Customer::find( $customer['id'] );
|
809 |
+
$result['customers_appointments_limit'][] = sprintf( __( '%s has reached the limit of bookings for this service', 'bookly' ), $customer_error->getFullName() );
|
810 |
+
}
|
811 |
+
}
|
812 |
+
}
|
813 |
+
}
|
814 |
+
|
815 |
+
wp_send_json( $result );
|
816 |
+
}
|
817 |
+
|
818 |
+
/**
|
819 |
+
* Get appointment for FullCalendar.
|
820 |
+
*
|
821 |
+
* @param integer $staff_id
|
822 |
+
* @param int $appointment_id
|
823 |
+
* @return array
|
824 |
+
*/
|
825 |
+
private static function _getAppointmentForFC( $staff_id, $appointment_id )
|
826 |
+
{
|
827 |
+
$query = Lib\Entities\Appointment::query( 'a' )
|
828 |
+
->where( 'a.id', $appointment_id );
|
829 |
+
|
830 |
+
$appointments = Calendar\Page::buildAppointmentsForFC( $staff_id, $query );
|
831 |
+
|
832 |
+
return $appointments[0];
|
833 |
+
}
|
834 |
+
|
835 |
+
/**
|
836 |
+
* Check whether interval is available for given appointment.
|
837 |
+
*
|
838 |
+
* @param $start_date
|
839 |
+
* @param $end_date
|
840 |
+
* @param $staff_id
|
841 |
+
* @param $appointment_id
|
842 |
+
* @return bool
|
843 |
+
*/
|
844 |
+
private static function _dateIntervalIsAvailableForAppointment( $start_date, $end_date, $staff_id, $appointment_id )
|
845 |
+
{
|
846 |
+
return Lib\Entities\Appointment::query( 'a' )
|
847 |
+
->whereNot( 'a.id', $appointment_id )
|
848 |
+
->where( 'a.staff_id', $staff_id )
|
849 |
+
->whereLt( 'a.start_date', $end_date )
|
850 |
+
->whereGt( 'a.end_date', $start_date )
|
851 |
+
->count() == 0;
|
852 |
+
}
|
853 |
}
|
backend/components/dialogs/appointment/edit/Dialog.php
CHANGED
@@ -1,64 +1,64 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Edit
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit
|
9 |
-
*/
|
10 |
-
class Dialog extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render create/edit appointment dialog.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
global $wp_locale;
|
18 |
-
|
19 |
-
self::enqueueStyles( array(
|
20 |
-
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', 'css/select2.min.css', 'css/fontawesome-all.min.css' ),
|
21 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
22 |
-
) );
|
23 |
-
|
24 |
-
self::enqueueScripts( array(
|
25 |
-
'backend' => array(
|
26 |
-
'js/angular.min.js' => array( 'jquery' ),
|
27 |
-
'js/angular-ui-date-0.0.8.js' => array( 'bookly-angular.min.js' ),
|
28 |
-
'js/moment.min.js' => array( 'jquery' ),
|
29 |
-
'js/select2.full.min.js' => array( 'jquery' ),
|
30 |
-
'js/help.js' => array( 'jquery' ),
|
31 |
-
),
|
32 |
-
'frontend' => array(
|
33 |
-
'js/spin.min.js' => array( 'jquery' ),
|
34 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
35 |
-
),
|
36 |
-
'module' => array(
|
37 |
-
'js/ng-appointment.js' => array( 'bookly-angular-ui-date-0.0.8.js', 'jquery-ui-datepicker' ),
|
38 |
-
)
|
39 |
-
) );
|
40 |
-
|
41 |
-
wp_localize_script( 'bookly-ng-appointment.js', 'BooklyL10nAppDialog', array(
|
42 |
-
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
43 |
-
'dateOptions' => array(
|
44 |
-
'dateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_JQUERY_DATEPICKER ),
|
45 |
-
'monthNamesShort' => array_values( $wp_locale->month_abbrev ),
|
46 |
-
'monthNames' => array_values( $wp_locale->month ),
|
47 |
-
'dayNamesMin' => array_values( $wp_locale->weekday_abbrev ),
|
48 |
-
'longDays' => array_values( $wp_locale->weekday ),
|
49 |
-
'firstDay' => (int) get_option( 'start_of_week' ),
|
50 |
-
),
|
51 |
-
'cf_per_service' => (int) Lib\Config::customFieldsPerService(),
|
52 |
-
'no_result_found' => __( 'No result found', 'bookly' ),
|
53 |
-
'staff_any' => get_option( 'bookly_l10n_option_employee' ),
|
54 |
-
'title' => array(
|
55 |
-
'edit_appointment' => __( 'Edit appointment', 'bookly' ),
|
56 |
-
'new_appointment' => __( 'New appointment', 'bookly' ),
|
57 |
-
),
|
58 |
-
) );
|
59 |
-
|
60 |
-
Proxy\Shared::enqueueAssets();
|
61 |
-
|
62 |
-
self::renderTemplate( 'edit' );
|
63 |
-
}
|
64 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Edit
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit
|
9 |
+
*/
|
10 |
+
class Dialog extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render create/edit appointment dialog.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
global $wp_locale;
|
18 |
+
|
19 |
+
self::enqueueStyles( array(
|
20 |
+
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', 'css/select2.min.css', 'css/fontawesome-all.min.css' ),
|
21 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
22 |
+
) );
|
23 |
+
|
24 |
+
self::enqueueScripts( array(
|
25 |
+
'backend' => array(
|
26 |
+
'js/angular.min.js' => array( 'jquery' ),
|
27 |
+
'js/angular-ui-date-0.0.8.js' => array( 'bookly-angular.min.js' ),
|
28 |
+
'js/moment.min.js' => array( 'jquery' ),
|
29 |
+
'js/select2.full.min.js' => array( 'jquery' ),
|
30 |
+
'js/help.js' => array( 'jquery' ),
|
31 |
+
),
|
32 |
+
'frontend' => array(
|
33 |
+
'js/spin.min.js' => array( 'jquery' ),
|
34 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
35 |
+
),
|
36 |
+
'module' => array(
|
37 |
+
'js/ng-appointment.js' => array( 'bookly-angular-ui-date-0.0.8.js', 'jquery-ui-datepicker' ),
|
38 |
+
)
|
39 |
+
) );
|
40 |
+
|
41 |
+
wp_localize_script( 'bookly-ng-appointment.js', 'BooklyL10nAppDialog', array(
|
42 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
43 |
+
'dateOptions' => array(
|
44 |
+
'dateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_JQUERY_DATEPICKER ),
|
45 |
+
'monthNamesShort' => array_values( $wp_locale->month_abbrev ),
|
46 |
+
'monthNames' => array_values( $wp_locale->month ),
|
47 |
+
'dayNamesMin' => array_values( $wp_locale->weekday_abbrev ),
|
48 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
49 |
+
'firstDay' => (int) get_option( 'start_of_week' ),
|
50 |
+
),
|
51 |
+
'cf_per_service' => (int) Lib\Config::customFieldsPerService(),
|
52 |
+
'no_result_found' => __( 'No result found', 'bookly' ),
|
53 |
+
'staff_any' => get_option( 'bookly_l10n_option_employee' ),
|
54 |
+
'title' => array(
|
55 |
+
'edit_appointment' => __( 'Edit appointment', 'bookly' ),
|
56 |
+
'new_appointment' => __( 'New appointment', 'bookly' ),
|
57 |
+
),
|
58 |
+
) );
|
59 |
+
|
60 |
+
Proxy\Shared::enqueueAssets();
|
61 |
+
|
62 |
+
self::renderTemplate( 'edit' );
|
63 |
+
}
|
64 |
}
|
backend/components/dialogs/appointment/edit/proxy/Pro.php
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
-
*
|
10 |
-
* @method static array addCustomService( array $services ) Add custom service to given array of services.
|
11 |
-
* @method static void renderAttachPaymentButton() Render attach payment button.
|
12 |
-
* @method static void renderCustomServiceFields() Render custom service name and price fields.
|
13 |
-
*/
|
14 |
-
abstract class Pro extends Lib\Base\Proxy
|
15 |
-
{
|
16 |
-
|
17 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static array addCustomService( array $services ) Add custom service to given array of services.
|
11 |
+
* @method static void renderAttachPaymentButton() Render attach payment button.
|
12 |
+
* @method static void renderCustomServiceFields() Render custom service name and price fields.
|
13 |
+
*/
|
14 |
+
abstract class Pro extends Lib\Base\Proxy
|
15 |
+
{
|
16 |
+
|
17 |
}
|
backend/components/dialogs/appointment/edit/proxy/RecurringAppointments.php
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class RecurringAppointments
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
-
*
|
10 |
-
* @method static void createBackendPayment( Lib\Entities\Series $series, array $customer ) Create payment for series.
|
11 |
-
* @method static void renderSchedule() Render schedule in edit appointment dialog.
|
12 |
-
* @method static void renderSubForm() Add Recurring sub form in edit appointment dialog.
|
13 |
-
*/
|
14 |
-
abstract class RecurringAppointments extends Lib\Base\Proxy
|
15 |
-
{
|
16 |
-
|
17 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class RecurringAppointments
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static void createBackendPayment( Lib\Entities\Series $series, array $customer ) Create payment for series.
|
11 |
+
* @method static void renderSchedule() Render schedule in edit appointment dialog.
|
12 |
+
* @method static void renderSubForm() Add Recurring sub form in edit appointment dialog.
|
13 |
+
*/
|
14 |
+
abstract class RecurringAppointments extends Lib\Base\Proxy
|
15 |
+
{
|
16 |
+
|
17 |
}
|
backend/components/dialogs/appointment/edit/proxy/Shared.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Shared
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
-
*
|
10 |
-
* @method static array prepareDataForPackage( array $result )
|
11 |
-
* @method static void renderAppointmentDialogCustomersList() Render content in AppointmentForm for customers.
|
12 |
-
* @method static void renderAppointmentDialogFooter() Render buttons in appointments dialog footer.
|
13 |
-
* @method static void renderComponents()
|
14 |
-
* @method static void enqueueAssets()
|
15 |
-
*/
|
16 |
-
abstract class Shared extends Lib\Base\Proxy
|
17 |
-
{
|
18 |
-
|
19 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Shared
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static array prepareDataForPackage( array $result )
|
11 |
+
* @method static void renderAppointmentDialogCustomersList() Render content in AppointmentForm for customers.
|
12 |
+
* @method static void renderAppointmentDialogFooter() Render buttons in appointments dialog footer.
|
13 |
+
* @method static void renderComponents()
|
14 |
+
* @method static void enqueueAssets()
|
15 |
+
*/
|
16 |
+
abstract class Shared extends Lib\Base\Proxy
|
17 |
+
{
|
18 |
+
|
19 |
}
|
backend/components/dialogs/appointment/edit/proxy/Tasks.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class RecurringAppointments
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderSkipDate()
|
11 |
-
*/
|
12 |
-
abstract class Tasks extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class RecurringAppointments
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderSkipDate()
|
11 |
+
*/
|
12 |
+
abstract class Tasks extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/dialogs/appointment/edit/resources/js/ng-appointment.js
CHANGED
@@ -1,1341 +1,1372 @@
|
|
1 |
-
;(function() {
|
2 |
-
|
3 |
-
var module = angular.module('appointmentDialog', ['ui.date', 'customerDialog', 'paymentDetailsDialog']);
|
4 |
-
|
5 |
-
/**
|
6 |
-
* DataSource service.
|
7 |
-
*/
|
8 |
-
module.factory('dataSource', function($q) {
|
9 |
-
var ds = {
|
10 |
-
loaded : false,
|
11 |
-
data : {
|
12 |
-
staff : [],
|
13 |
-
customers : [],
|
14 |
-
start_time : [],
|
15 |
-
end_time : [],
|
16 |
-
app_start_time : null,
|
17 |
-
app_end_time : null,
|
18 |
-
time_interval : 900,
|
19 |
-
status : {
|
20 |
-
items: []
|
21 |
-
}
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
}
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
customer.
|
149 |
-
customer.
|
150 |
-
customer.
|
151 |
-
customer.
|
152 |
-
customer.
|
153 |
-
customer.
|
154 |
-
customer.
|
155 |
-
customer.
|
156 |
-
customer.
|
157 |
-
customer.
|
158 |
-
customer.
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
}
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
}
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
}
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
}
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
},
|
270 |
-
|
271 |
-
var result = 0;
|
272 |
-
ds.form.customers.forEach(function (item) {
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
;
|
295 |
-
|
296 |
-
return
|
297 |
-
}
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
$scope.
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
}
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
clone.
|
472 |
-
clone.
|
473 |
-
clone.
|
474 |
-
clone.
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
}
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
checkAppointmentErrors();
|
603 |
-
};
|
604 |
-
|
605 |
-
$scope.
|
606 |
-
checkAppointmentErrors();
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
customers
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
}
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
|
793 |
-
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
|
806 |
-
|
807 |
-
|
808 |
-
|
809 |
-
|
810 |
-
|
811 |
-
|
812 |
-
|
813 |
-
|
814 |
-
|
815 |
-
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
|
828 |
-
$
|
829 |
-
|
830 |
-
|
831 |
-
|
832 |
-
|
833 |
-
|
834 |
-
|
835 |
-
|
836 |
-
|
837 |
-
|
838 |
-
|
839 |
-
|
840 |
-
|
841 |
-
|
842 |
-
|
843 |
-
|
844 |
-
|
845 |
-
|
846 |
-
|
847 |
-
|
848 |
-
|
849 |
-
|
850 |
-
|
851 |
-
|
852 |
-
|
853 |
-
|
854 |
-
|
855 |
-
|
856 |
-
|
857 |
-
|
858 |
-
|
859 |
-
jQuery('#bookly-
|
860 |
-
}
|
861 |
-
|
862 |
-
|
863 |
-
|
864 |
-
|
865 |
-
|
866 |
-
|
867 |
-
|
868 |
-
|
869 |
-
|
870 |
-
|
871 |
-
|
872 |
-
|
873 |
-
|
874 |
-
|
875 |
-
|
876 |
-
|
877 |
-
|
878 |
-
|
879 |
-
|
880 |
-
|
881 |
-
|
882 |
-
|
883 |
-
|
884 |
-
|
885 |
-
|
886 |
-
|
887 |
-
|
888 |
-
|
889 |
-
|
890 |
-
|
891 |
-
|
892 |
-
|
893 |
-
|
894 |
-
|
895 |
-
|
896 |
-
|
897 |
-
|
898 |
-
$
|
899 |
-
|
900 |
-
|
901 |
-
|
902 |
-
|
903 |
-
|
904 |
-
|
905 |
-
$
|
906 |
-
|
907 |
-
|
908 |
-
|
909 |
-
|
910 |
-
|
911 |
-
|
912 |
-
|
913 |
-
|
914 |
-
|
915 |
-
|
916 |
-
|
917 |
-
|
918 |
-
|
919 |
-
|
920 |
-
|
921 |
-
|
922 |
-
|
923 |
-
|
924 |
-
|
925 |
-
|
926 |
-
|
927 |
-
|
928 |
-
|
929 |
-
|
930 |
-
|
931 |
-
|
932 |
-
|
933 |
-
|
934 |
-
|
935 |
-
|
936 |
-
|
937 |
-
|
938 |
-
|
939 |
-
|
940 |
-
|
941 |
-
|
942 |
-
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
|
958 |
-
|
959 |
-
|
960 |
-
|
961 |
-
|
962 |
-
|
963 |
-
|
964 |
-
|
965 |
-
|
966 |
-
|
967 |
-
|
968 |
-
|
969 |
-
|
970 |
-
|
971 |
-
|
972 |
-
});
|
973 |
-
}
|
974 |
-
|
975 |
-
|
976 |
-
|
977 |
-
|
978 |
-
|
979 |
-
|
980 |
-
|
981 |
-
|
982 |
-
|
983 |
-
|
984 |
-
|
985 |
-
|
986 |
-
|
987 |
-
|
988 |
-
|
989 |
-
|
990 |
-
|
991 |
-
|
992 |
-
|
993 |
-
|
994 |
-
|
995 |
-
|
996 |
-
|
997 |
-
|
998 |
-
|
999 |
-
|
1000 |
-
|
1001 |
-
}
|
1002 |
-
|
1003 |
-
|
1004 |
-
|
1005 |
-
|
1006 |
-
|
1007 |
-
|
1008 |
-
|
1009 |
-
|
1010 |
-
|
1011 |
-
|
1012 |
-
|
1013 |
-
|
1014 |
-
|
1015 |
-
|
1016 |
-
|
1017 |
-
|
1018 |
-
|
1019 |
-
|
1020 |
-
|
1021 |
-
|
1022 |
-
|
1023 |
-
|
1024 |
-
|
1025 |
-
|
1026 |
-
|
1027 |
-
|
1028 |
-
|
1029 |
-
|
1030 |
-
|
1031 |
-
|
1032 |
-
|
1033 |
-
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
1040 |
-
|
1041 |
-
|
1042 |
-
|
1043 |
-
|
1044 |
-
|
1045 |
-
|
1046 |
-
|
1047 |
-
|
1048 |
-
|
1049 |
-
|
1050 |
-
|
1051 |
-
|
1052 |
-
|
1053 |
-
|
1054 |
-
|
1055 |
-
|
1056 |
-
|
1057 |
-
|
1058 |
-
|
1059 |
-
|
1060 |
-
|
1061 |
-
|
1062 |
-
|
1063 |
-
|
1064 |
-
|
1065 |
-
|
1066 |
-
|
1067 |
-
|
1068 |
-
|
1069 |
-
|
1070 |
-
|
1071 |
-
|
1072 |
-
|
1073 |
-
|
1074 |
-
|
1075 |
-
|
1076 |
-
$scope.
|
1077 |
-
}
|
1078 |
-
|
1079 |
-
|
1080 |
-
|
1081 |
-
|
1082 |
-
|
1083 |
-
|
1084 |
-
|
1085 |
-
|
1086 |
-
|
1087 |
-
|
1088 |
-
|
1089 |
-
|
1090 |
-
|
1091 |
-
|
1092 |
-
|
1093 |
-
|
1094 |
-
|
1095 |
-
|
1096 |
-
|
1097 |
-
|
1098 |
-
|
1099 |
-
|
1100 |
-
|
1101 |
-
|
1102 |
-
|
1103 |
-
|
1104 |
-
|
1105 |
-
|
1106 |
-
|
1107 |
-
|
1108 |
-
|
1109 |
-
|
1110 |
-
|
1111 |
-
|
1112 |
-
|
1113 |
-
|
1114 |
-
|
1115 |
-
|
1116 |
-
|
1117 |
-
|
1118 |
-
|
1119 |
-
|
1120 |
-
|
1121 |
-
|
1122 |
-
|
1123 |
-
|
1124 |
-
|
1125 |
-
|
1126 |
-
|
1127 |
-
|
1128 |
-
|
1129 |
-
|
1130 |
-
|
1131 |
-
|
1132 |
-
|
1133 |
-
|
1134 |
-
|
1135 |
-
|
1136 |
-
|
1137 |
-
|
1138 |
-
|
1139 |
-
|
1140 |
-
|
1141 |
-
|
1142 |
-
|
1143 |
-
|
1144 |
-
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
1148 |
-
};
|
1149 |
-
$scope.
|
1150 |
-
|
1151 |
-
|
1152 |
-
|
1153 |
-
|
1154 |
-
|
1155 |
-
|
1156 |
-
|
1157 |
-
|
1158 |
-
|
1159 |
-
|
1160 |
-
|
1161 |
-
|
1162 |
-
}
|
1163 |
-
|
1164 |
-
|
1165 |
-
$scope.
|
1166 |
-
};
|
1167 |
-
$scope.
|
1168 |
-
var
|
1169 |
-
$scope.form.
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
1175 |
-
|
1176 |
-
|
1177 |
-
|
1178 |
-
|
1179 |
-
|
1180 |
-
|
1181 |
-
|
1182 |
-
|
1183 |
-
|
1184 |
-
|
1185 |
-
|
1186 |
-
|
1187 |
-
|
1188 |
-
|
1189 |
-
|
1190 |
-
|
1191 |
-
|
1192 |
-
|
1193 |
-
|
1194 |
-
|
1195 |
-
|
1196 |
-
|
1197 |
-
|
1198 |
-
|
1199 |
-
|
1200 |
-
|
1201 |
-
|
1202 |
-
|
1203 |
-
|
1204 |
-
|
1205 |
-
|
1206 |
-
|
1207 |
-
|
1208 |
-
|
1209 |
-
|
1210 |
-
|
1211 |
-
|
1212 |
-
|
1213 |
-
|
1214 |
-
|
1215 |
-
|
1216 |
-
|
1217 |
-
|
1218 |
-
|
1219 |
-
|
1220 |
-
|
1221 |
-
|
1222 |
-
|
1223 |
-
|
1224 |
-
|
1225 |
-
|
1226 |
-
|
1227 |
-
|
1228 |
-
|
1229 |
-
|
1230 |
-
|
1231 |
-
|
1232 |
-
|
1233 |
-
|
1234 |
-
|
1235 |
-
|
1236 |
-
|
1237 |
-
|
1238 |
-
|
1239 |
-
|
1240 |
-
|
1241 |
-
|
1242 |
-
|
1243 |
-
|
1244 |
-
|
1245 |
-
|
1246 |
-
|
1247 |
-
|
1248 |
-
|
1249 |
-
|
1250 |
-
|
1251 |
-
|
1252 |
-
|
1253 |
-
|
1254 |
-
|
1255 |
-
|
1256 |
-
|
1257 |
-
|
1258 |
-
|
1259 |
-
|
1260 |
-
|
1261 |
-
|
1262 |
-
|
1263 |
-
|
1264 |
-
|
1265 |
-
|
1266 |
-
|
1267 |
-
|
1268 |
-
|
1269 |
-
|
1270 |
-
|
1271 |
-
|
1272 |
-
|
1273 |
-
|
1274 |
-
|
1275 |
-
|
1276 |
-
|
1277 |
-
|
1278 |
-
|
1279 |
-
|
1280 |
-
|
1281 |
-
|
1282 |
-
|
1283 |
-
|
1284 |
-
|
1285 |
-
|
1286 |
-
|
1287 |
-
|
1288 |
-
|
1289 |
-
|
1290 |
-
|
1291 |
-
|
1292 |
-
|
1293 |
-
|
1294 |
-
|
1295 |
-
|
1296 |
-
|
1297 |
-
|
1298 |
-
|
1299 |
-
|
1300 |
-
|
1301 |
-
|
1302 |
-
|
1303 |
-
})
|
1304 |
-
|
1305 |
-
/**
|
1306 |
-
|
1307 |
-
|
1308 |
-
|
1309 |
-
|
1310 |
-
|
1311 |
-
|
1312 |
-
|
1313 |
-
|
1314 |
-
|
1315 |
-
|
1316 |
-
|
1317 |
-
|
1318 |
-
|
1319 |
-
|
1320 |
-
|
1321 |
-
|
1322 |
-
|
1323 |
-
|
1324 |
-
|
1325 |
-
|
1326 |
-
|
1327 |
-
|
1328 |
-
|
1329 |
-
|
1330 |
-
|
1331 |
-
|
1332 |
-
|
1333 |
-
}
|
1334 |
-
|
1335 |
-
|
1336 |
-
|
1337 |
-
|
1338 |
-
|
1339 |
-
|
1340 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1341 |
};
|
1 |
+
;(function() {
|
2 |
+
|
3 |
+
var module = angular.module('appointmentDialog', ['ui.date', 'customerDialog', 'paymentDetailsDialog']);
|
4 |
+
|
5 |
+
/**
|
6 |
+
* DataSource service.
|
7 |
+
*/
|
8 |
+
module.factory('dataSource', function($q) {
|
9 |
+
var ds = {
|
10 |
+
loaded : false,
|
11 |
+
data : {
|
12 |
+
staff : [],
|
13 |
+
customers : [],
|
14 |
+
start_time : [],
|
15 |
+
end_time : [],
|
16 |
+
app_start_time : null,
|
17 |
+
app_end_time : null,
|
18 |
+
time_interval : 900,
|
19 |
+
status : {
|
20 |
+
items: []
|
21 |
+
},
|
22 |
+
extras_consider_duration: true,
|
23 |
+
extras_multiply_nop : true
|
24 |
+
},
|
25 |
+
form : {
|
26 |
+
screen : null,
|
27 |
+
id : null,
|
28 |
+
staff : null,
|
29 |
+
staff_any : null,
|
30 |
+
service : null,
|
31 |
+
custom_service_name : null,
|
32 |
+
custom_service_price: null,
|
33 |
+
location : null,
|
34 |
+
skip_date : null,
|
35 |
+
date : null,
|
36 |
+
start_time : null,
|
37 |
+
end_time : null,
|
38 |
+
repeat : {
|
39 |
+
enabled : null,
|
40 |
+
repeat : null,
|
41 |
+
daily : { every : null },
|
42 |
+
weekly : { on : null },
|
43 |
+
biweekly : { on : null },
|
44 |
+
monthly : { on : null, day : null, weekday : null },
|
45 |
+
until : null
|
46 |
+
},
|
47 |
+
schedule : {
|
48 |
+
items : [],
|
49 |
+
edit : null,
|
50 |
+
page : null,
|
51 |
+
another_time : []
|
52 |
+
},
|
53 |
+
customers : [],
|
54 |
+
notification : null,
|
55 |
+
series_id : null,
|
56 |
+
expand_customers_list : false
|
57 |
+
},
|
58 |
+
l10n : {
|
59 |
+
staff_any: BooklyL10nAppDialog.staff_any
|
60 |
+
},
|
61 |
+
loadData : function() {
|
62 |
+
var deferred = $q.defer();
|
63 |
+
if (!ds.loaded) {
|
64 |
+
jQuery.get(
|
65 |
+
ajaxurl,
|
66 |
+
{ action : 'bookly_get_data_for_appointment_form', csrf_token : BooklyL10nAppDialog.csrf_token },
|
67 |
+
function(data) {
|
68 |
+
ds.loaded = true;
|
69 |
+
ds.data = data;
|
70 |
+
|
71 |
+
if (data.staff.length) {
|
72 |
+
ds.form.staff = data.staff[0];
|
73 |
+
}
|
74 |
+
|
75 |
+
ds.form.start_time = data.start_time[0];
|
76 |
+
ds.form.end_time = data.end_time[1];
|
77 |
+
deferred.resolve();
|
78 |
+
},
|
79 |
+
'json'
|
80 |
+
);
|
81 |
+
} else {
|
82 |
+
deferred.resolve();
|
83 |
+
}
|
84 |
+
|
85 |
+
return deferred.promise;
|
86 |
+
},
|
87 |
+
findStaff : function(id) {
|
88 |
+
var result = null;
|
89 |
+
jQuery.each(ds.data.staff, function(key, item) {
|
90 |
+
if (item.id == id) {
|
91 |
+
result = item;
|
92 |
+
return false;
|
93 |
+
}
|
94 |
+
});
|
95 |
+
return result;
|
96 |
+
},
|
97 |
+
findService : function(staff_id, id) {
|
98 |
+
var result = null,
|
99 |
+
staff = ds.findStaff(staff_id);
|
100 |
+
|
101 |
+
if (staff !== null) {
|
102 |
+
jQuery.each(staff.services, function(key, item) {
|
103 |
+
if (item.id == id) {
|
104 |
+
result = item;
|
105 |
+
return false;
|
106 |
+
}
|
107 |
+
});
|
108 |
+
}
|
109 |
+
return result;
|
110 |
+
},
|
111 |
+
findLocation : function(staff_id, id) {
|
112 |
+
var result = null,
|
113 |
+
staff = ds.findStaff(staff_id);
|
114 |
+
|
115 |
+
if (staff !== null) {
|
116 |
+
jQuery.each(staff.locations, function(key, item) {
|
117 |
+
if (item.id == id) {
|
118 |
+
result = item;
|
119 |
+
return false;
|
120 |
+
}
|
121 |
+
});
|
122 |
+
}
|
123 |
+
return result;
|
124 |
+
},
|
125 |
+
findTime : function(source, value) {
|
126 |
+
var result = null,
|
127 |
+
time = source == 'start' ? ds.getDataForStartTime() : ds.form.end_time_data;
|
128 |
+
jQuery.each(time, function(key, item) {
|
129 |
+
if (item.value >= value) {
|
130 |
+
result = item;
|
131 |
+
return false;
|
132 |
+
}
|
133 |
+
});
|
134 |
+
return result;
|
135 |
+
},
|
136 |
+
findCustomer : function(id) {
|
137 |
+
var result = null;
|
138 |
+
jQuery.each(ds.data.customers, function(key, item) {
|
139 |
+
if (item.id == id) {
|
140 |
+
result = item;
|
141 |
+
return false;
|
142 |
+
}
|
143 |
+
});
|
144 |
+
return result;
|
145 |
+
},
|
146 |
+
resetCustomers : function() {
|
147 |
+
ds.data.customers.forEach(function(customer) {
|
148 |
+
customer.custom_fields = [];
|
149 |
+
customer.extras = [];
|
150 |
+
customer.extras_consider_duration = ds.data.extras_consider_duration;
|
151 |
+
customer.extras_multiply_nop = ds.data.extras_multiply_nop;
|
152 |
+
customer.number_of_persons = 1;
|
153 |
+
customer.notes = null;
|
154 |
+
customer.collaborative_token = null;
|
155 |
+
customer.collaborative_service = null;
|
156 |
+
customer.compound_token = null;
|
157 |
+
customer.compound_service = null;
|
158 |
+
customer.payment_id = null;
|
159 |
+
customer.payment_type = null;
|
160 |
+
customer.payment_title = null;
|
161 |
+
customer.payment_create = false;
|
162 |
+
customer.payment_price = null;
|
163 |
+
customer.payment_tax = null;
|
164 |
+
customer.package_id = null;
|
165 |
+
customer.series_id = null;
|
166 |
+
customer.ca_id = null;
|
167 |
+
});
|
168 |
+
},
|
169 |
+
getDataForStartTime : function() {
|
170 |
+
var result = ds.data.start_time.slice();
|
171 |
+
if (
|
172 |
+
ds.data.app_start_time &&
|
173 |
+
result.every(function (item) {return item.value !== ds.data.app_start_time.value;})
|
174 |
+
) {
|
175 |
+
result.push(ds.data.app_start_time);
|
176 |
+
result.sort(function (a, b) {
|
177 |
+
return a.value < b.value ? -1 : (a.value > b.value ? 1 : 0);
|
178 |
+
});
|
179 |
+
}
|
180 |
+
return result;
|
181 |
+
},
|
182 |
+
getDataForEndTime : function() {
|
183 |
+
var result = [];
|
184 |
+
if (ds.form.start_time) {
|
185 |
+
if (ds.form.service && parseInt(ds.form.service.units_max) > 1) {
|
186 |
+
var units_min = parseInt(ds.form.service.units_min),
|
187 |
+
units_max = parseInt(ds.form.service.units_max),
|
188 |
+
start_time = moment(ds.form.start_time.value, 'HH:mm');
|
189 |
+
for (var units = units_min; units <= units_max; units++) {
|
190 |
+
var end_time = moment(start_time).add(units * ds.form.service.duration, 'seconds'),
|
191 |
+
end_hour = parseInt(moment(end_time).format('HH')) + Math.floor((end_time.diff(start_time)) / 3600 / 24000) * 24;
|
192 |
+
jQuery.each(ds.data.end_time, function (key, item) {
|
193 |
+
if (item.value == (end_hour < 10 ? '0' + end_hour : end_hour) + ':' + moment(end_time).format('mm')) {
|
194 |
+
unit_item = jQuery.extend({}, item);
|
195 |
+
unit_item.title = item.title + ' (' + units +')';
|
196 |
+
result.push(unit_item);
|
197 |
+
}
|
198 |
+
});
|
199 |
+
}
|
200 |
+
} else {
|
201 |
+
var start_time = ds.form.start_time.value.split(':'),
|
202 |
+
end = (24 + parseInt(start_time[0])) + ':' + start_time[1];
|
203 |
+
jQuery.each(ds.data.end_time, function (key, item) {
|
204 |
+
if (item.value > end) {
|
205 |
+
return false;
|
206 |
+
}
|
207 |
+
if (item.value > ds.form.start_time.value) {
|
208 |
+
result.push(item);
|
209 |
+
}
|
210 |
+
});
|
211 |
+
if (
|
212 |
+
ds.data.app_end_time &&
|
213 |
+
ds.data.app_end_time.value > ds.form.start_time.value &&
|
214 |
+
result.every(function (item) {
|
215 |
+
return item.value !== ds.data.app_end_time.value;
|
216 |
+
})
|
217 |
+
) {
|
218 |
+
result.push(ds.data.app_end_time);
|
219 |
+
result.sort(function (a, b) {
|
220 |
+
return a.value < b.value ? -1 : (a.value > b.value ? 1 : 0);
|
221 |
+
});
|
222 |
+
}
|
223 |
+
}
|
224 |
+
}
|
225 |
+
return result;
|
226 |
+
},
|
227 |
+
setEndTimeBasedOnService : function() {
|
228 |
+
ds.form.end_time_data = ds.getDataForEndTime();
|
229 |
+
var d = ds.form.service ? ds.form.service.duration * ds.form.service.units_min : ds.data.time_interval;
|
230 |
+
if (d < 86400) {
|
231 |
+
ds.form.end_time = ds.findTime('end', moment(ds.form.start_time.value, 'HH:mm').add(d, 'seconds').format('HH:mm'));
|
232 |
+
}
|
233 |
+
},
|
234 |
+
getStartAndEndDates : function() {
|
235 |
+
if (ds.form.skip_date) {
|
236 |
+
return {
|
237 |
+
start_date: null,
|
238 |
+
end_date : null
|
239 |
+
}
|
240 |
+
}
|
241 |
+
var start_date = moment(ds.form.date.getTime()),
|
242 |
+
end_date = moment(ds.form.date.getTime()),
|
243 |
+
start_time = [0,0],
|
244 |
+
end_time = [0,0]
|
245 |
+
;
|
246 |
+
if (ds.form.service && ds.form.service.duration >= 86400) {
|
247 |
+
if (ds.form.end_time) {
|
248 |
+
var _start_time = ds.form.start_time.value.split(':');
|
249 |
+
var _end_time = ds.form.end_time.value.split(':');
|
250 |
+
var duration = Math.max(ds.form.service.duration, 60 * (_end_time[0] * 60 + parseInt(_end_time[1]) - _start_time[0] * 60 - parseInt(_start_time[1])));
|
251 |
+
end_date.add(duration, 'seconds');
|
252 |
+
} else if (ds.form.service && ds.form.service.units_max > 1) {
|
253 |
+
end_date.add(ds.form.service.duration * ds.form.service.units_min, 'seconds');
|
254 |
+
} else {
|
255 |
+
end_date.add(ds.form.service.duration, 'seconds');
|
256 |
+
}
|
257 |
+
} else {
|
258 |
+
start_time = ds.form.start_time.value.split(':');
|
259 |
+
end_time = ds.form.end_time.value.split(':');
|
260 |
+
}
|
261 |
+
start_date.hours(start_time[0]);
|
262 |
+
start_date.minutes(start_time[1]);
|
263 |
+
end_date.hours(end_time[0]);
|
264 |
+
end_date.minutes(end_time[1]);
|
265 |
+
return {
|
266 |
+
start_date : start_date.format('YYYY-MM-DD HH:mm:00'),
|
267 |
+
end_date : end_date.format('YYYY-MM-DD HH:mm:00')
|
268 |
+
};
|
269 |
+
},
|
270 |
+
getTotalNumberOfPersons : function () {
|
271 |
+
var result = 0;
|
272 |
+
ds.form.customers.forEach(function (item) {
|
273 |
+
result += parseInt(item.number_of_persons);
|
274 |
+
});
|
275 |
+
|
276 |
+
return result;
|
277 |
+
},
|
278 |
+
getTotalNumberOfNotCancelledPersons: function (exceptCustomer) {
|
279 |
+
var result = 0;
|
280 |
+
ds.form.customers.forEach(function (item) {
|
281 |
+
if ((!exceptCustomer || item.id != exceptCustomer.id) && item.status != 'cancelled' && item.status != 'rejected' && item.status != 'waitlisted') {
|
282 |
+
result += parseInt(item.number_of_persons);
|
283 |
+
}
|
284 |
+
});
|
285 |
+
|
286 |
+
return result;
|
287 |
+
},
|
288 |
+
getTotalNumberOfCancelledPersons: function () {
|
289 |
+
var result = 0;
|
290 |
+
ds.form.customers.forEach(function (item) {
|
291 |
+
if (item.status == 'cancelled' || item.status == 'rejected' || item.status == 'waitlisted') {
|
292 |
+
result += parseInt(item.number_of_persons);
|
293 |
+
}
|
294 |
+
});
|
295 |
+
|
296 |
+
return result;
|
297 |
+
},
|
298 |
+
getServiceDuration: function () {
|
299 |
+
var dates = ds.getStartAndEndDates(),
|
300 |
+
start_date = moment(dates.start_date),
|
301 |
+
end_date = moment(dates.end_date)
|
302 |
+
;
|
303 |
+
|
304 |
+
return end_date.diff(start_date, 'seconds');
|
305 |
+
}
|
306 |
+
};
|
307 |
+
|
308 |
+
return ds;
|
309 |
+
});
|
310 |
+
|
311 |
+
/**
|
312 |
+
* Controller for 'create/edit appointment' dialog form.
|
313 |
+
*/
|
314 |
+
module.controller('appointmentDialogCtrl', function($scope, $element, dataSource) {
|
315 |
+
// Set up initial data.
|
316 |
+
$scope.$calendar = null;
|
317 |
+
// Set up data source.
|
318 |
+
$scope.dataSource = dataSource;
|
319 |
+
$scope.form = dataSource.form; // shortcut
|
320 |
+
// Error messages.
|
321 |
+
$scope.errors = {};
|
322 |
+
// Callback to be called after editing appointment.
|
323 |
+
var callback = null;
|
324 |
+
|
325 |
+
// Hide archived staff
|
326 |
+
$scope.filterStaff = function(staff) {
|
327 |
+
return (staff.archived == false || $scope.form.staff == staff);
|
328 |
+
};
|
329 |
+
|
330 |
+
/**
|
331 |
+
* Prepare the form for new event.
|
332 |
+
*
|
333 |
+
* @param int staff_id
|
334 |
+
* @param moment start_date
|
335 |
+
* @param function _callback
|
336 |
+
*/
|
337 |
+
$scope.configureNewForm = function(staff_id, start_date, _callback) {
|
338 |
+
var weekday = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][start_date.format('d')],
|
339 |
+
staff = dataSource.findStaff(staff_id),
|
340 |
+
service = staff && staff.services.length == 2 ? staff.services[1] : null,
|
341 |
+
location = staff && staff.locations.length == 1 ? staff.locations[0] : null
|
342 |
+
;
|
343 |
+
$scope.dataSource.data.app_start_time = null;
|
344 |
+
$scope.dataSource.data.app_end_time = null;
|
345 |
+
jQuery.extend($scope.form, {
|
346 |
+
screen : 'main',
|
347 |
+
id : null,
|
348 |
+
staff : staff,
|
349 |
+
staff_any : null,
|
350 |
+
service : service,
|
351 |
+
custom_service_name : null,
|
352 |
+
custom_service_price : 0,
|
353 |
+
location : location,
|
354 |
+
date : start_date.clone().local().toDate(),
|
355 |
+
skip_date : null,
|
356 |
+
start_time : dataSource.findTime('start', start_date.format('HH:mm')),
|
357 |
+
end_time : null,
|
358 |
+
end_time_data : [],
|
359 |
+
series_id : null,
|
360 |
+
repeat : {
|
361 |
+
enabled : 0,
|
362 |
+
repeat : 'daily',
|
363 |
+
daily : { every: 1 },
|
364 |
+
weekly : { on : [weekday] },
|
365 |
+
biweekly : { on : [weekday] },
|
366 |
+
monthly : { on : 'day', day : start_date.format('D'), weekday : weekday },
|
367 |
+
until : start_date.clone().add(1, 'month').format('YYYY-MM-DD')
|
368 |
+
},
|
369 |
+
schedule : {
|
370 |
+
items : [],
|
371 |
+
edit : 0,
|
372 |
+
page : 0,
|
373 |
+
another_time : []
|
374 |
+
},
|
375 |
+
customers : [],
|
376 |
+
internal_note : null,
|
377 |
+
expand_customers_list : false
|
378 |
+
});
|
379 |
+
$scope.errors = {};
|
380 |
+
dataSource.setEndTimeBasedOnService();
|
381 |
+
callback = _callback;
|
382 |
+
|
383 |
+
$scope.prepareExtras();
|
384 |
+
$scope.prepareCustomFields();
|
385 |
+
$scope.dataSource.resetCustomers();
|
386 |
+
$scope.onRepeatChange();
|
387 |
+
if (staff) {
|
388 |
+
$scope.onStaffChange();
|
389 |
+
}
|
390 |
+
};
|
391 |
+
|
392 |
+
/**
|
393 |
+
* Prepare the form for editing an event.
|
394 |
+
*/
|
395 |
+
$scope.configureEditForm = function(appointment_id, _callback) {
|
396 |
+
$scope.loading = true;
|
397 |
+
jQuery.post(
|
398 |
+
ajaxurl,
|
399 |
+
{action: 'bookly_get_data_for_appointment', id: appointment_id, csrf_token : BooklyL10nAppDialog.csrf_token},
|
400 |
+
function(response) {
|
401 |
+
$scope.$apply(function($scope) {
|
402 |
+
if (response.success) {
|
403 |
+
var start_date = response.data.start_date === null ? null : moment(response.data.start_date),
|
404 |
+
end_date = response.data.start_date === null ? null : moment(response.data.end_date),
|
405 |
+
staff = $scope.dataSource.findStaff(response.data.staff_id);
|
406 |
+
$scope.dataSource.data.app_start_time = response.data.start_time;
|
407 |
+
$scope.dataSource.data.app_end_time = response.data.end_time;
|
408 |
+
jQuery.extend($scope.form, {
|
409 |
+
screen : 'main',
|
410 |
+
id : appointment_id,
|
411 |
+
staff : staff,
|
412 |
+
staff_any : response.data.staff_any ? staff : null,
|
413 |
+
service : $scope.dataSource.findService(response.data.staff_id, response.data.service_id),
|
414 |
+
custom_service_name : response.data.custom_service_name,
|
415 |
+
custom_service_price : response.data.custom_service_price,
|
416 |
+
location : $scope.dataSource.findLocation(response.data.staff_id, response.data.location_id),
|
417 |
+
skip_date : start_date === null ? 1 : 0,
|
418 |
+
end_time : null,
|
419 |
+
end_time_data : [],
|
420 |
+
repeat : {
|
421 |
+
enabled : 0,
|
422 |
+
repeat : 'daily',
|
423 |
+
daily : {every: 1},
|
424 |
+
weekly : {on: []},
|
425 |
+
biweekly: {on: []},
|
426 |
+
monthly : {on: 'day', day: '1', weekday: 'mon'},
|
427 |
+
until : start_date === null ? moment().add(1, 'month').format('YYYY-MM-DD') : start_date.clone().add(1, 'month').format('YYYY-MM-DD')
|
428 |
+
},
|
429 |
+
schedule : {
|
430 |
+
items : [],
|
431 |
+
edit : 0,
|
432 |
+
page : 0,
|
433 |
+
another_time: []
|
434 |
+
},
|
435 |
+
customers : [],
|
436 |
+
internal_note : response.data.internal_note,
|
437 |
+
series_id : response.data.series_id,
|
438 |
+
expand_customers_list: false
|
439 |
+
});
|
440 |
+
$scope.form.end_time_data = $scope.dataSource.getDataForEndTime();
|
441 |
+
if (start_date !== null) {
|
442 |
+
$scope.form.date = start_date.clone().local().toDate();
|
443 |
+
$scope.form.start_time = $scope.dataSource.findTime('start', start_date.format('HH:mm'));
|
444 |
+
$scope.dataSource.setEndTimeBasedOnService();
|
445 |
+
$scope.form.end_time = start_date.format('YYYY-MM-DD') == end_date.format('YYYY-MM-DD')
|
446 |
+
? $scope.dataSource.findTime('end', end_date.format('HH:mm'))
|
447 |
+
: $scope.dataSource.findTime('end', (Math.floor((end_date - start_date) / 3600000) + start_date.hour()) + end_date.format(':mm'));
|
448 |
+
} else {
|
449 |
+
$scope.form.date = moment().local().toDate();
|
450 |
+
$scope.form.start_time = $scope.dataSource.findTime('start', moment().format('HH:mm'));
|
451 |
+
$scope.dataSource.setEndTimeBasedOnService();
|
452 |
+
}
|
453 |
+
|
454 |
+
$scope.prepareExtras();
|
455 |
+
$scope.prepareCustomFields();
|
456 |
+
$scope.dataSource.resetCustomers();
|
457 |
+
$scope.onLocationChange();
|
458 |
+
$scope.onRepeatChange();
|
459 |
+
|
460 |
+
var customers_ids = [];
|
461 |
+
response.data.customers.forEach(function (item, i, arr) {
|
462 |
+
var customer = $scope.dataSource.findCustomer(item.id),
|
463 |
+
clone = {};
|
464 |
+
if (customers_ids.indexOf(item.id) === -1) {
|
465 |
+
customers_ids.push(item.id);
|
466 |
+
clone = customer;
|
467 |
+
} else {
|
468 |
+
// For Error: ngRepeat:dupes & chosen directive
|
469 |
+
angular.copy(customer, clone);
|
470 |
+
}
|
471 |
+
clone.ca_id = item.ca_id;
|
472 |
+
clone.series_id = item.series_id;
|
473 |
+
clone.package_id = item.package_id;
|
474 |
+
clone.extras = item.extras;
|
475 |
+
clone.extras_multiply_nop = item.extras_multiply_nop;
|
476 |
+
clone.extras_consider_duration = item.extras_consider_duration;
|
477 |
+
clone.status = item.status;
|
478 |
+
clone.custom_fields = item.custom_fields;
|
479 |
+
clone.files = item.files;
|
480 |
+
clone.number_of_persons = item.number_of_persons;
|
481 |
+
clone.timezone = item.timezone;
|
482 |
+
clone.notes = item.notes;
|
483 |
+
clone.payment_id = item.payment_id;
|
484 |
+
clone.payment_type = item.payment_type;
|
485 |
+
clone.payment_title = item.payment_title;
|
486 |
+
clone.payment_create = item.payment_create;
|
487 |
+
clone.payment_price = item.payment_price;
|
488 |
+
clone.payment_tax = item.payment_tax;
|
489 |
+
clone.collaborative_token = item.collaborative_token;
|
490 |
+
clone.collaborative_service = item.collaborative_service;
|
491 |
+
clone.collaborative_service = item.collaborative_service;
|
492 |
+
clone.compound_token = item.compound_token;
|
493 |
+
clone.compound_service = item.compound_service;
|
494 |
+
$scope.form.customers.push(clone);
|
495 |
+
});
|
496 |
+
}
|
497 |
+
$scope.loading = false;
|
498 |
+
});
|
499 |
+
},
|
500 |
+
'json'
|
501 |
+
);
|
502 |
+
$scope.errors = {};
|
503 |
+
callback = _callback;
|
504 |
+
};
|
505 |
+
|
506 |
+
var checkAppointmentErrors = function() {
|
507 |
+
if ($scope.form.staff) {
|
508 |
+
var dates = $scope.dataSource.getStartAndEndDates(),
|
509 |
+
customers = [];
|
510 |
+
|
511 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
512 |
+
var customer_extras = {};
|
513 |
+
if ($scope.form.service) {
|
514 |
+
jQuery('#bookly-extras .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
515 |
+
var extra_id = jQuery(this).data('id');
|
516 |
+
if (item.extras[extra_id] !== undefined) {
|
517 |
+
customer_extras[extra_id] = item.extras[extra_id];
|
518 |
+
}
|
519 |
+
});
|
520 |
+
}
|
521 |
+
customers.push({
|
522 |
+
id : item.id,
|
523 |
+
ca_id : item.ca_id,
|
524 |
+
custom_fields : item.custom_fields,
|
525 |
+
extras : customer_extras,
|
526 |
+
extras_multiply_nop : item.extras_multiply_nop,
|
527 |
+
extras_consider_duration: item.extras_consider_duration,
|
528 |
+
number_of_persons : item.number_of_persons,
|
529 |
+
timezone : item.timezone,
|
530 |
+
status : item.status
|
531 |
+
});
|
532 |
+
});
|
533 |
+
|
534 |
+
jQuery.post(
|
535 |
+
ajaxurl,
|
536 |
+
{
|
537 |
+
action : 'bookly_check_appointment_errors',
|
538 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
539 |
+
start_date : dates.start_date,
|
540 |
+
end_date : dates.end_date,
|
541 |
+
appointment_id : $scope.form.id,
|
542 |
+
customers : JSON.stringify(customers),
|
543 |
+
staff_id : $scope.form.staff.id,
|
544 |
+
service_id : $scope.form.service ? $scope.form.service.id : null,
|
545 |
+
location_id : $scope.form.location ? $scope.form.location.id : null
|
546 |
+
},
|
547 |
+
function (response) {
|
548 |
+
$scope.$apply(function ($scope) {
|
549 |
+
angular.forEach(response, function (value, error) {
|
550 |
+
$scope.errors[error] = value;
|
551 |
+
});
|
552 |
+
});
|
553 |
+
},
|
554 |
+
'json'
|
555 |
+
);
|
556 |
+
}
|
557 |
+
};
|
558 |
+
|
559 |
+
$scope.onServiceChange = function() {
|
560 |
+
$scope.dataSource.setEndTimeBasedOnService();
|
561 |
+
$scope.prepareExtras();
|
562 |
+
$scope.prepareCustomFields();
|
563 |
+
$scope.onLocationChange();
|
564 |
+
checkAppointmentErrors();
|
565 |
+
};
|
566 |
+
|
567 |
+
$scope.onLocationChange = function () {
|
568 |
+
if ($scope.form.staff && $scope.form.service) {
|
569 |
+
var current_service = $scope.dataSource.findService($scope.form.staff.id, $scope.form.service.id),
|
570 |
+
location_id = $scope.form.location ? $scope.form.location.id : 0;
|
571 |
+
if (current_service.locations.hasOwnProperty(location_id)) {
|
572 |
+
$scope.form.service.capacity_min = current_service.locations[location_id].capacity_min;
|
573 |
+
$scope.form.service.capacity_max = current_service.locations[location_id].capacity_max;
|
574 |
+
} else if (current_service.locations.hasOwnProperty(0)) {
|
575 |
+
$scope.form.service.capacity_min = current_service.locations[0].capacity_min;
|
576 |
+
$scope.form.service.capacity_max = current_service.locations[0].capacity_max;
|
577 |
+
} else {
|
578 |
+
$scope.form.service.capacity_min = 1;
|
579 |
+
$scope.form.service.capacity_max = 1;
|
580 |
+
}
|
581 |
+
checkAppointmentErrors();
|
582 |
+
}
|
583 |
+
};
|
584 |
+
|
585 |
+
$scope.onStaffChange = function() {
|
586 |
+
if ($scope.form.staff.services.length == 2) {
|
587 |
+
$scope.form.service = $scope.form.staff.services[1];
|
588 |
+
$scope.onServiceChange();
|
589 |
+
} else {
|
590 |
+
$scope.form.service = null;
|
591 |
+
}
|
592 |
+
$scope.form.location = $scope.form.staff.locations.length == 1 ? $scope.form.staff.locations[0] : null;
|
593 |
+
$scope.onLocationChange();
|
594 |
+
};
|
595 |
+
|
596 |
+
$scope.onStartTimeChange = function() {
|
597 |
+
$scope.dataSource.setEndTimeBasedOnService();
|
598 |
+
checkAppointmentErrors();
|
599 |
+
};
|
600 |
+
|
601 |
+
$scope.onEndTimeChange = function() {
|
602 |
+
checkAppointmentErrors();
|
603 |
+
};
|
604 |
+
|
605 |
+
$scope.onDateChange = function() {
|
606 |
+
checkAppointmentErrors();
|
607 |
+
$scope.onRepeatChange();
|
608 |
+
};
|
609 |
+
|
610 |
+
$scope.onCustomersChange = function(old_customers, old_nop) {
|
611 |
+
if (dataSource.form.service && dataSource.form.customers.length > old_customers.length) {
|
612 |
+
var ids = jQuery.map(old_customers, function(customer) {
|
613 |
+
return customer.id;
|
614 |
+
});
|
615 |
+
var nop = dataSource.form.service.capacity_min - old_nop;
|
616 |
+
dataSource.form.customers.some(function (item) {
|
617 |
+
if (jQuery.inArray(item.id, ids) == -1) {
|
618 |
+
item.number_of_persons = nop > 0 ? nop : 1;
|
619 |
+
return true;
|
620 |
+
}
|
621 |
+
});
|
622 |
+
}
|
623 |
+
$scope.errors.customers_appointments_limit = [];
|
624 |
+
checkAppointmentErrors();
|
625 |
+
};
|
626 |
+
|
627 |
+
$scope.onSkipDateChange = function() {
|
628 |
+
checkAppointmentErrors();
|
629 |
+
};
|
630 |
+
|
631 |
+
$scope.processForm = function() {
|
632 |
+
$scope.loading = true;
|
633 |
+
|
634 |
+
$scope.errors = {};
|
635 |
+
|
636 |
+
var dates = $scope.dataSource.getStartAndEndDates(),
|
637 |
+
schedule = [],
|
638 |
+
customers = []
|
639 |
+
;
|
640 |
+
|
641 |
+
angular.forEach($scope.form.schedule.items, function (item) {
|
642 |
+
if (!item.deleted) {
|
643 |
+
schedule.push(item.slots);
|
644 |
+
}
|
645 |
+
});
|
646 |
+
|
647 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
648 |
+
var customer_extras = {};
|
649 |
+
if ($scope.form.service) {
|
650 |
+
jQuery('#bookly-extras .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
651 |
+
var extra_id = jQuery(this).data('id');
|
652 |
+
if (item.extras[extra_id] !== undefined) {
|
653 |
+
customer_extras[extra_id] = item.extras[extra_id];
|
654 |
+
}
|
655 |
+
});
|
656 |
+
}
|
657 |
+
customers.push({
|
658 |
+
id : item.id,
|
659 |
+
ca_id : item.ca_id,
|
660 |
+
series_id : item.series_id,
|
661 |
+
custom_fields : item.custom_fields,
|
662 |
+
extras : customer_extras,
|
663 |
+
extras_multiply_nop : item.extras_multiply_nop,
|
664 |
+
extras_consider_duration : item.extras_consider_duration,
|
665 |
+
number_of_persons : item.number_of_persons,
|
666 |
+
timezone : item.timezone,
|
667 |
+
notes : item.notes,
|
668 |
+
status : item.status,
|
669 |
+
payment_id : item.payment_id,
|
670 |
+
payment_create : item.payment_create,
|
671 |
+
payment_price : item.payment_price,
|
672 |
+
payment_tax : item.payment_tax
|
673 |
+
});
|
674 |
+
});
|
675 |
+
jQuery.post(
|
676 |
+
ajaxurl,
|
677 |
+
{
|
678 |
+
action : 'bookly_save_appointment_form',
|
679 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
680 |
+
id : $scope.form.id || undefined,
|
681 |
+
staff_id : $scope.form.staff ? $scope.form.staff.id : undefined,
|
682 |
+
service_id : $scope.form.service ? $scope.form.service.id : undefined,
|
683 |
+
custom_service_name : $scope.form.custom_service_name,
|
684 |
+
custom_service_price : $scope.form.custom_service_price,
|
685 |
+
location_id : $scope.form.location ? $scope.form.location.id : undefined,
|
686 |
+
skip_date : $scope.form.skip_date,
|
687 |
+
start_date : dates.start_date,
|
688 |
+
end_date : dates.end_date,
|
689 |
+
repeat : JSON.stringify($scope.form.repeat),
|
690 |
+
schedule : schedule,
|
691 |
+
customers : JSON.stringify(customers),
|
692 |
+
notification : $scope.form.notification,
|
693 |
+
internal_note : $scope.form.internal_note,
|
694 |
+
created_from : typeof BooklySCCalendarL10n !== 'undefined' ? 'staff-cabinet' : 'backend'
|
695 |
+
},
|
696 |
+
function (response) {
|
697 |
+
$scope.$apply(function($scope) {
|
698 |
+
if (response.success) {
|
699 |
+
if (callback) {
|
700 |
+
// Call callback.
|
701 |
+
callback(response.data);
|
702 |
+
}
|
703 |
+
// Close the dialog.
|
704 |
+
$element.children().modal('hide');
|
705 |
+
} else {
|
706 |
+
$scope.errors = response.errors;
|
707 |
+
}
|
708 |
+
$scope.loading = false;
|
709 |
+
});
|
710 |
+
},
|
711 |
+
'json'
|
712 |
+
);
|
713 |
+
};
|
714 |
+
|
715 |
+
// On 'Cancel' button click.
|
716 |
+
$scope.closeDialog = function () {
|
717 |
+
// Close the dialog.
|
718 |
+
$element.children().modal('hide');
|
719 |
+
};
|
720 |
+
|
721 |
+
$scope.statusToString = function (status) {
|
722 |
+
return dataSource.data.status.items[status];
|
723 |
+
};
|
724 |
+
|
725 |
+
/**************************************************************************************************************
|
726 |
+
* New customer *
|
727 |
+
**************************************************************************************************************/
|
728 |
+
|
729 |
+
/**
|
730 |
+
* Create new customer.
|
731 |
+
* @param customer
|
732 |
+
*/
|
733 |
+
$scope.createCustomer = function(customer) {
|
734 |
+
// Add new customer to the list.
|
735 |
+
var nop = 1;
|
736 |
+
if (dataSource.form.service) {
|
737 |
+
nop = dataSource.form.service.capacity_min - dataSource.getTotalNumberOfNotCancelledPersons();
|
738 |
+
if (nop < 1) {
|
739 |
+
nop = 1;
|
740 |
+
}
|
741 |
+
}
|
742 |
+
var new_customer = {
|
743 |
+
id : customer.id.toString(),
|
744 |
+
name : customer.full_name,
|
745 |
+
custom_fields : customer.custom_fields,
|
746 |
+
extras : customer.extras,
|
747 |
+
extras_consider_duration : dataSource.data.extras_consider_duration,
|
748 |
+
extras_multiply_nop : dataSource.data.extras_multiply_nop,
|
749 |
+
status : customer.status,
|
750 |
+
timezone : customer.timezone,
|
751 |
+
number_of_persons : nop,
|
752 |
+
notes : null,
|
753 |
+
collaborative_token : null,
|
754 |
+
collaborative_service : null,
|
755 |
+
compound_token : null,
|
756 |
+
compound_service : null,
|
757 |
+
payment_id : null,
|
758 |
+
payment_type : null,
|
759 |
+
payment_title : null,
|
760 |
+
payment_create : false,
|
761 |
+
payment_price : null,
|
762 |
+
payment_tax : null
|
763 |
+
};
|
764 |
+
|
765 |
+
if (customer.email || customer.phone){
|
766 |
+
new_customer.name += ' (' + [customer.email, customer.phone].filter(Boolean).join(', ') + ')';
|
767 |
+
}
|
768 |
+
|
769 |
+
dataSource.data.customers.push(new_customer);
|
770 |
+
|
771 |
+
// Make it selected.
|
772 |
+
if (!dataSource.form.service || dataSource.form.customers.length < dataSource.form.service.capacity_max) {
|
773 |
+
dataSource.form.customers.push(new_customer);
|
774 |
+
}
|
775 |
+
};
|
776 |
+
|
777 |
+
$scope.removeCustomer = function(customer) {
|
778 |
+
$scope.form.customers.splice($scope.form.customers.indexOf(customer), 1);
|
779 |
+
checkAppointmentErrors();
|
780 |
+
};
|
781 |
+
|
782 |
+
$scope.openNewCustomerDialog = function() {
|
783 |
+
var $dialog = jQuery('#bookly-customer-dialog');
|
784 |
+
$dialog.modal({show: true});
|
785 |
+
};
|
786 |
+
|
787 |
+
/**************************************************************************************************************
|
788 |
+
* Customer Details *
|
789 |
+
**************************************************************************************************************/
|
790 |
+
|
791 |
+
$scope.editCustomerDetails = function(customer) {
|
792 |
+
var $dialog = jQuery('#bookly-customer-details-dialog');
|
793 |
+
$dialog.find('input.bookly-custom-field:text, textarea.bookly-custom-field, select.bookly-custom-field, input.bookly-js-file').val('');
|
794 |
+
$dialog.find('input.bookly-custom-field:checkbox, input.bookly-custom-field:radio').prop('checked', false);
|
795 |
+
$dialog.find('#bookly-extras :checkbox').prop('checked', false);
|
796 |
+
|
797 |
+
customer.custom_fields.forEach(function (field) {
|
798 |
+
var $custom_field = $dialog.find('#bookly-js-custom-fields > *[data-id="' + field.id + '"]');
|
799 |
+
switch ($custom_field.data('type')) {
|
800 |
+
case 'checkboxes':
|
801 |
+
field.value.forEach(function (value) {
|
802 |
+
$custom_field.find('.bookly-custom-field').filter(function () {
|
803 |
+
return this.value == value;
|
804 |
+
}).prop('checked', true);
|
805 |
+
});
|
806 |
+
break;
|
807 |
+
case 'radio-buttons':
|
808 |
+
$custom_field.find('.bookly-custom-field').filter(function () {
|
809 |
+
return this.value == field.value;
|
810 |
+
}).prop('checked', true);
|
811 |
+
break;
|
812 |
+
default:
|
813 |
+
$custom_field.find('.bookly-custom-field').val(field.value);
|
814 |
+
break;
|
815 |
+
}
|
816 |
+
});
|
817 |
+
|
818 |
+
$dialog.find('#bookly-extras .extras-count').val(0);
|
819 |
+
angular.forEach(customer.extras, function (extra_count, extra_id) {
|
820 |
+
$dialog.find('#bookly-extras .extras-count[data-id="' + extra_id + '"]').val(extra_count);
|
821 |
+
});
|
822 |
+
|
823 |
+
// Prepare select for number of persons.
|
824 |
+
var $number_of_persons = $dialog.find('#bookly-number-of-persons');
|
825 |
+
|
826 |
+
var max = $scope.form.service
|
827 |
+
? ($scope.form.service.id
|
828 |
+
? parseInt($scope.form.service.capacity_max) - $scope.dataSource.getTotalNumberOfNotCancelledPersons(customer)
|
829 |
+
: 999)
|
830 |
+
: 1;
|
831 |
+
$number_of_persons.empty();
|
832 |
+
for (var i = 1; i <= max; ++i) {
|
833 |
+
$number_of_persons.append('<option value="' + i + '">' + i + '</option>');
|
834 |
+
}
|
835 |
+
if (customer.number_of_persons > max) {
|
836 |
+
$number_of_persons.append('<option value="' + customer.number_of_persons + '">' + customer.number_of_persons + '</option>');
|
837 |
+
}
|
838 |
+
$number_of_persons.val(customer.number_of_persons);
|
839 |
+
$dialog.find('#bookly-appointment-status').val(customer.status);
|
840 |
+
$dialog.find('#bookly-appointment-notes').val(customer.notes);
|
841 |
+
$dialog.find('#bookly-deposit-due').val(customer.due);
|
842 |
+
$dialog.find('#bookly-customer-time-zone').val(customer.timezone ? customer.timezone : '');
|
843 |
+
$scope.edit_customer = customer;
|
844 |
+
|
845 |
+
$dialog.modal({show: true})
|
846 |
+
.on('hidden.bs.modal', function () {
|
847 |
+
jQuery('body').addClass('modal-open');
|
848 |
+
});
|
849 |
+
|
850 |
+
jQuery(document.body).trigger('bookly.edit.customer_details', [$dialog, $scope.edit_customer]);
|
851 |
+
};
|
852 |
+
|
853 |
+
$scope.prepareExtras = function () {
|
854 |
+
if ($scope.form.service) {
|
855 |
+
jQuery('#bookly-extras > *').hide();
|
856 |
+
var $service_extras = jQuery('#bookly-extras .service_' + $scope.form.service.id);
|
857 |
+
if ($service_extras.length) {
|
858 |
+
$service_extras.show();
|
859 |
+
jQuery('#bookly-extras').show();
|
860 |
+
} else {
|
861 |
+
jQuery('#bookly-extras').hide();
|
862 |
+
}
|
863 |
+
} else {
|
864 |
+
jQuery('#bookly-extras').hide();
|
865 |
+
}
|
866 |
+
};
|
867 |
+
|
868 |
+
// Hide or unhide custom fields for current service
|
869 |
+
$scope.prepareCustomFields = function () {
|
870 |
+
if (BooklyL10nAppDialog.cf_per_service == 1) {
|
871 |
+
var show = false;
|
872 |
+
jQuery('#bookly-js-custom-fields div[data-services]').each(function() {
|
873 |
+
var $this = jQuery(this);
|
874 |
+
if (dataSource.form.service !== null) {
|
875 |
+
var services = $this.data('services');
|
876 |
+
if (services && jQuery.inArray(dataSource.form.service.id, services) > -1) {
|
877 |
+
$this.show();
|
878 |
+
show = true;
|
879 |
+
} else {
|
880 |
+
$this.hide();
|
881 |
+
}
|
882 |
+
} else {
|
883 |
+
$this.hide();
|
884 |
+
}
|
885 |
+
});
|
886 |
+
if (show) {
|
887 |
+
jQuery('#bookly-js-custom-fields').show();
|
888 |
+
} else {
|
889 |
+
jQuery('#bookly-js-custom-fields').hide();
|
890 |
+
}
|
891 |
+
}
|
892 |
+
};
|
893 |
+
|
894 |
+
$scope.saveCustomFields = function() {
|
895 |
+
var result = [],
|
896 |
+
extras = {},
|
897 |
+
$fields = jQuery('#bookly-js-custom-fields > *'),
|
898 |
+
$status = jQuery('#bookly-appointment-status'),
|
899 |
+
$timezone = jQuery('#bookly-customer-time-zone'),
|
900 |
+
$number_of_persons = jQuery('#bookly-number-of-persons'),
|
901 |
+
$notes = jQuery('#bookly-appointment-notes'),
|
902 |
+
$extras = jQuery('#bookly-extras')
|
903 |
+
;
|
904 |
+
|
905 |
+
$fields.each(function () {
|
906 |
+
var $this = jQuery(this),
|
907 |
+
value;
|
908 |
+
if ($this.is(':visible')) {
|
909 |
+
switch ($this.data('type')) {
|
910 |
+
case 'checkboxes':
|
911 |
+
value = [];
|
912 |
+
$this.find('.bookly-custom-field:checked').each(function () {
|
913 |
+
value.push(this.value);
|
914 |
+
});
|
915 |
+
break;
|
916 |
+
case 'radio-buttons':
|
917 |
+
value = $this.find('.bookly-custom-field:checked').val();
|
918 |
+
break;
|
919 |
+
default:
|
920 |
+
value = $this.find('.bookly-custom-field').val();
|
921 |
+
break;
|
922 |
+
}
|
923 |
+
result.push({id: $this.data('id'), value: value});
|
924 |
+
}
|
925 |
+
});
|
926 |
+
|
927 |
+
if ($scope.form.service) {
|
928 |
+
$extras.find(' .service_' + $scope.form.service.id + ' input.extras-count').each(function () {
|
929 |
+
if (this.value > 0) {
|
930 |
+
extras[jQuery(this).data('id')] = this.value;
|
931 |
+
}
|
932 |
+
});
|
933 |
+
}
|
934 |
+
|
935 |
+
$scope.edit_customer.status = $status.val();
|
936 |
+
$scope.edit_customer.timezone = $timezone.val();
|
937 |
+
$scope.edit_customer.number_of_persons = $number_of_persons.val();
|
938 |
+
$scope.edit_customer.notes = $notes.val();
|
939 |
+
$scope.edit_customer.custom_fields = result;
|
940 |
+
$scope.edit_customer.extras = extras;
|
941 |
+
|
942 |
+
jQuery('#bookly-customer-details-dialog').modal('hide');
|
943 |
+
if ($extras.length > 0) {
|
944 |
+
// Check if intersection with another appointment exists.
|
945 |
+
checkAppointmentErrors();
|
946 |
+
}
|
947 |
+
};
|
948 |
+
|
949 |
+
/**************************************************************************************************************
|
950 |
+
* Payment Details *
|
951 |
+
**************************************************************************************************************/
|
952 |
+
|
953 |
+
$scope.attachPaymentModal = function (customer) {
|
954 |
+
var $dialog = jQuery('#bookly-payment-attach-modal');
|
955 |
+
$scope.form.attach = {
|
956 |
+
customer_id : customer.id,
|
957 |
+
payment_method: 'create',
|
958 |
+
payment_price : null,
|
959 |
+
payment_tax : null,
|
960 |
+
payment_id : null
|
961 |
+
};
|
962 |
+
$dialog.modal({show: true}).on('hidden.bs.modal', function () {
|
963 |
+
jQuery('body').addClass('modal-open');
|
964 |
+
});
|
965 |
+
};
|
966 |
+
|
967 |
+
$scope.attachPayment = function (attach_method, price, tax, payment_id, customer_id) {
|
968 |
+
var $dialog = jQuery('#bookly-payment-details-modal');
|
969 |
+
if (attach_method == 'search') {
|
970 |
+
$dialog.data('payment_id', payment_id).data('payment_bind', true).data('customer_id', customer_id).modal({show: true}).on('hidden.bs.modal', function () {
|
971 |
+
jQuery('body').addClass('modal-open');
|
972 |
+
});
|
973 |
+
} else {
|
974 |
+
jQuery.each($scope.dataSource.data.customers, function (key, item) {
|
975 |
+
if (item.id == customer_id) {
|
976 |
+
item.payment_create = true;
|
977 |
+
item.payment_price = price;
|
978 |
+
item.payment_tax = tax;
|
979 |
+
item.payment_type = 'partial';
|
980 |
+
}
|
981 |
+
});
|
982 |
+
}
|
983 |
+
};
|
984 |
+
|
985 |
+
$scope.callbackPayment = function (payment_action, payment_id, payment_title, customer_id, payment_type) {
|
986 |
+
if (payment_action == 'bind') {
|
987 |
+
// Bind payment
|
988 |
+
jQuery.each($scope.dataSource.data.customers, function (key, item) {
|
989 |
+
if (item.id == customer_id) {
|
990 |
+
item.payment_id = payment_id;
|
991 |
+
item.payment_type = payment_type;
|
992 |
+
item.payment_title = payment_title;
|
993 |
+
}
|
994 |
+
});
|
995 |
+
} else {
|
996 |
+
// Complete payment
|
997 |
+
jQuery.each($scope.dataSource.data.customers, function (key, item) {
|
998 |
+
if (item.payment_id == payment_id) {
|
999 |
+
item.payment_type = 'full';
|
1000 |
+
item.payment_title = payment_title;
|
1001 |
+
}
|
1002 |
+
});
|
1003 |
+
}
|
1004 |
+
};
|
1005 |
+
|
1006 |
+
/**************************************************************************************************************
|
1007 |
+
* Package Schedule *
|
1008 |
+
**************************************************************************************************************/
|
1009 |
+
|
1010 |
+
$scope.editPackageSchedule = function(customer) {
|
1011 |
+
jQuery(document.body).trigger('bookly_packages.schedule_dialog', [customer.package_id, function (deleted) {
|
1012 |
+
if (jQuery.inArray(Number(customer.ca_id), deleted) != -1) {
|
1013 |
+
$scope.removeCustomer(customer);
|
1014 |
+
}
|
1015 |
+
if (callback) {
|
1016 |
+
// Call callback.
|
1017 |
+
callback('refresh');
|
1018 |
+
}
|
1019 |
+
}, true]);
|
1020 |
+
};
|
1021 |
+
|
1022 |
+
/**************************************************************************************************************
|
1023 |
+
* Repeat Times in Recurring Appointments *
|
1024 |
+
**************************************************************************************************************/
|
1025 |
+
$scope.isDateMatchesSelections = function (current_date) {
|
1026 |
+
var current_day = ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'][current_date.format('d')];
|
1027 |
+
switch ($scope.form.repeat.repeat) {
|
1028 |
+
case 'daily':
|
1029 |
+
if (($scope.form.repeat.daily.every > 6 || jQuery.inArray(current_day, $scope.dataSource.data.week_days) != -1) && (current_date.diff(moment($scope.dataSource.form.date.getTime()), 'days') % $scope.form.repeat.daily.every == 0)) {
|
1030 |
+
return true;
|
1031 |
+
}
|
1032 |
+
break;
|
1033 |
+
case 'weekly':
|
1034 |
+
case 'biweekly':
|
1035 |
+
if (($scope.form.repeat.repeat == 'weekly' || current_date.diff(moment($scope.dataSource.form.date.getTime()).startOf('isoWeek'), 'weeks') % 2 == 0) && (jQuery.inArray(current_day, $scope.form.repeat.weekly.on) != -1)) {
|
1036 |
+
return true;
|
1037 |
+
}
|
1038 |
+
break;
|
1039 |
+
case 'monthly':
|
1040 |
+
switch ($scope.form.repeat.monthly.on) {
|
1041 |
+
case 'day':
|
1042 |
+
if (current_date.format('D') == $scope.form.repeat.monthly.day) {
|
1043 |
+
return true;
|
1044 |
+
}
|
1045 |
+
break;
|
1046 |
+
case 'last':
|
1047 |
+
if (current_day == $scope.form.repeat.monthly.weekday && current_date.clone().endOf('month').diff(current_date, 'days') < 7) {
|
1048 |
+
return true;
|
1049 |
+
}
|
1050 |
+
break;
|
1051 |
+
default:
|
1052 |
+
var month_diff = current_date.diff(current_date.clone().startOf('month'), 'days'),
|
1053 |
+
weeks = ['first', 'second', 'third', 'fourth'],
|
1054 |
+
week_number = weeks.indexOf($scope.form.repeat.monthly.on);
|
1055 |
+
|
1056 |
+
if (current_day == $scope.form.repeat.monthly.weekday && month_diff >= week_number * 7 && month_diff < (week_number + 1) * 7) {
|
1057 |
+
return true;
|
1058 |
+
}
|
1059 |
+
}
|
1060 |
+
break;
|
1061 |
+
}
|
1062 |
+
|
1063 |
+
return false;
|
1064 |
+
};
|
1065 |
+
$scope.onRepeatChange = function () {
|
1066 |
+
if (jQuery('#bookly-repeat-enabled').length && !$scope.form.skip_date) {
|
1067 |
+
var number_of_times = 0,
|
1068 |
+
date_until = moment($scope.form.repeat.until).add(1, 'days'),
|
1069 |
+
current_date = moment($scope.dataSource.form.date.getTime());
|
1070 |
+
do {
|
1071 |
+
if ($scope.isDateMatchesSelections(current_date)) {
|
1072 |
+
number_of_times++;
|
1073 |
+
}
|
1074 |
+
current_date.add(1, 'days');
|
1075 |
+
} while (current_date.isBefore(date_until));
|
1076 |
+
$scope.form.repeat.times = number_of_times;
|
1077 |
+
}
|
1078 |
+
};
|
1079 |
+
$scope.onRepeatChangeTimes = function () {
|
1080 |
+
var number_of_times = 0,
|
1081 |
+
date_until = moment($scope.dataSource.form.date.getTime()).add(5, 'years'),
|
1082 |
+
current_date = moment($scope.dataSource.form.date.getTime());
|
1083 |
+
do {
|
1084 |
+
if ($scope.isDateMatchesSelections(current_date)) {
|
1085 |
+
number_of_times++
|
1086 |
+
}
|
1087 |
+
current_date.add(1, 'days');
|
1088 |
+
} while (number_of_times < $scope.form.repeat.times && current_date.isBefore(date_until));
|
1089 |
+
$scope.form.repeat.until = current_date.subtract(1, 'days').format('YYYY-MM-DD');
|
1090 |
+
};
|
1091 |
+
|
1092 |
+
/**************************************************************************************************************
|
1093 |
+
* Schedule of Recurring Appointments *
|
1094 |
+
**************************************************************************************************************/
|
1095 |
+
|
1096 |
+
$scope.schSchedule = function ($event) {
|
1097 |
+
var extras = [];
|
1098 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
1099 |
+
extras.push(item.extras);
|
1100 |
+
});
|
1101 |
+
|
1102 |
+
if (
|
1103 |
+
($scope.form.repeat.repeat == 'weekly' || $scope.form.repeat.repeat == 'biweekly') &&
|
1104 |
+
$scope.form.repeat[$scope.form.repeat.repeat].on.length == 0
|
1105 |
+
) {
|
1106 |
+
$scope.errors.repeat_weekdays_empty = true;
|
1107 |
+
} else {
|
1108 |
+
delete $scope.errors.repeat_weekdays_empty;
|
1109 |
+
var ladda = Ladda.create($event.currentTarget);
|
1110 |
+
ladda.start();
|
1111 |
+
var dates = $scope.dataSource.getStartAndEndDates();
|
1112 |
+
jQuery.post(
|
1113 |
+
ajaxurl,
|
1114 |
+
{
|
1115 |
+
action : 'bookly_recurring_appointments_get_schedule',
|
1116 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
1117 |
+
staff_id : $scope.form.staff.id,
|
1118 |
+
service_id : $scope.form.service.id,
|
1119 |
+
location_id : $scope.form.location ? $scope.form.location.id : null,
|
1120 |
+
datetime : dates.start_date,
|
1121 |
+
until : $scope.form.repeat.until,
|
1122 |
+
repeat : $scope.form.repeat.repeat,
|
1123 |
+
params : $scope.form.repeat[$scope.form.repeat.repeat],
|
1124 |
+
extras : extras,
|
1125 |
+
nop : $scope.dataSource.getTotalNumberOfPersons(),
|
1126 |
+
duration : $scope.form.service.id ? undefined : $scope.dataSource.getServiceDuration()
|
1127 |
+
},
|
1128 |
+
function (response) {
|
1129 |
+
$scope.$apply(function($scope) {
|
1130 |
+
$scope.form.schedule.items = response.data;
|
1131 |
+
$scope.form.schedule.page = 0;
|
1132 |
+
$scope.form.schedule.another_time = [];
|
1133 |
+
angular.forEach($scope.form.schedule.items, function (item) {
|
1134 |
+
if (item.another_time) {
|
1135 |
+
var page = parseInt( ( item.index - 1 ) / 10 ) + 1;
|
1136 |
+
if ($scope.form.schedule.another_time.indexOf(page) < 0) {
|
1137 |
+
$scope.form.schedule.another_time.push(page);
|
1138 |
+
}
|
1139 |
+
}
|
1140 |
+
});
|
1141 |
+
$scope.form.screen = 'schedule';
|
1142 |
+
ladda.stop();
|
1143 |
+
});
|
1144 |
+
},
|
1145 |
+
'json'
|
1146 |
+
);
|
1147 |
+
}
|
1148 |
+
};
|
1149 |
+
$scope.schFormatDate = function(date) {
|
1150 |
+
var m = moment(date),
|
1151 |
+
weekday = m.format('d'),
|
1152 |
+
month = m.format('M'),
|
1153 |
+
day = m.format('DD');
|
1154 |
+
|
1155 |
+
return BooklyL10nAppDialog.dateOptions.dayNamesMin[weekday] + ', ' + BooklyL10nAppDialog.dateOptions.monthNamesShort[month-1] + ' ' + day;
|
1156 |
+
};
|
1157 |
+
$scope.schFormatTime = function(slots, options) {
|
1158 |
+
for (var i = 0; i < options.length; ++ i) {
|
1159 |
+
if (slots == options[i].value) {
|
1160 |
+
return options[i].title;
|
1161 |
+
}
|
1162 |
+
}
|
1163 |
+
};
|
1164 |
+
$scope.schFirstPage = function() {
|
1165 |
+
return $scope.form.schedule.page == 0;
|
1166 |
+
};
|
1167 |
+
$scope.schLastPage = function() {
|
1168 |
+
var lastPageNum = Math.ceil($scope.form.schedule.items.length / 10 - 1);
|
1169 |
+
return $scope.form.schedule.page == lastPageNum;
|
1170 |
+
};
|
1171 |
+
$scope.schNumberOfPages = function() {
|
1172 |
+
return Math.ceil($scope.form.schedule.items.length / 10);
|
1173 |
+
};
|
1174 |
+
$scope.schStartingItem = function() {
|
1175 |
+
return $scope.form.schedule.page * 10;
|
1176 |
+
};
|
1177 |
+
$scope.schPageBack = function() {
|
1178 |
+
$scope.form.schedule.page = $scope.form.schedule.page - 1;
|
1179 |
+
};
|
1180 |
+
$scope.schPageForward = function() {
|
1181 |
+
$scope.form.schedule.page = $scope.form.schedule.page + 1;
|
1182 |
+
};
|
1183 |
+
$scope.schOnWeekdayClick = function (weekday) {
|
1184 |
+
var idx = $scope.form.repeat.weekly.on.indexOf(weekday);
|
1185 |
+
|
1186 |
+
// is currently selected
|
1187 |
+
if (idx > -1) {
|
1188 |
+
$scope.form.repeat.weekly.on.splice(idx, 1);
|
1189 |
+
}
|
1190 |
+
// is newly selected
|
1191 |
+
else {
|
1192 |
+
$scope.form.repeat.weekly.on.push(weekday);
|
1193 |
+
}
|
1194 |
+
// copy weekly to biweekly
|
1195 |
+
$scope.form.repeat.biweekly.on = $scope.form.repeat.weekly.on.slice();
|
1196 |
+
$scope.onRepeatChange();
|
1197 |
+
};
|
1198 |
+
$scope.schOnDateChange = function(item) {
|
1199 |
+
var extras = [];
|
1200 |
+
$scope.form.customers.forEach(function (item, i, arr) {
|
1201 |
+
extras.push(item.extras);
|
1202 |
+
});
|
1203 |
+
|
1204 |
+
var exclude = [];
|
1205 |
+
angular.forEach($scope.form.schedule.items, function (_item) {
|
1206 |
+
if (item.slots != _item.slots && !_item.deleted) {
|
1207 |
+
exclude.push(_item.slots);
|
1208 |
+
}
|
1209 |
+
});
|
1210 |
+
jQuery.post(
|
1211 |
+
ajaxurl,
|
1212 |
+
{
|
1213 |
+
action : 'bookly_recurring_appointments_get_schedule',
|
1214 |
+
csrf_token : BooklyL10nAppDialog.csrf_token,
|
1215 |
+
staff_id : $scope.form.staff.id,
|
1216 |
+
service_id : $scope.form.service.id,
|
1217 |
+
location_id : $scope.form.location ? $scope.form.location.id : null,
|
1218 |
+
datetime : item.date + ' 00:00',
|
1219 |
+
until : item.date,
|
1220 |
+
repeat : 'daily',
|
1221 |
+
params : {every: 1},
|
1222 |
+
with_options : 1,
|
1223 |
+
exclude : exclude,
|
1224 |
+
extras : extras,
|
1225 |
+
duration : $scope.form.service.id ? undefined : $scope.dataSource.getServiceDuration()
|
1226 |
+
},
|
1227 |
+
function (response) {
|
1228 |
+
$scope.$apply(function($scope) {
|
1229 |
+
if (response.data.length) {
|
1230 |
+
item.options = response.data[0].options;
|
1231 |
+
var found = false;
|
1232 |
+
jQuery.each(item.options, function (key, option) {
|
1233 |
+
if (option.value == item.slots) {
|
1234 |
+
found = true;
|
1235 |
+
return false;
|
1236 |
+
}
|
1237 |
+
});
|
1238 |
+
if (!found) {
|
1239 |
+
jQuery.each(item.options, function (key, option) {
|
1240 |
+
if (!option.disabled) {
|
1241 |
+
item.slots = option.value;
|
1242 |
+
return false;
|
1243 |
+
}
|
1244 |
+
});
|
1245 |
+
}
|
1246 |
+
} else {
|
1247 |
+
item.options = [];
|
1248 |
+
}
|
1249 |
+
});
|
1250 |
+
},
|
1251 |
+
'json'
|
1252 |
+
);
|
1253 |
+
};
|
1254 |
+
$scope.schIsScheduleEmpty = function () {
|
1255 |
+
return $scope.form.schedule.items.every(function(item) {
|
1256 |
+
return item.deleted;
|
1257 |
+
});
|
1258 |
+
};
|
1259 |
+
$scope.schDateOptions = jQuery.extend({}, BooklyL10nAppDialog.dateOptions, {dateFormat: 'D, M dd, yy'});
|
1260 |
+
$scope.schViewSeries = function ( customer ) {
|
1261 |
+
jQuery(document.body).trigger( 'recurring_appointments.series_dialog', [ customer.series_id, function (event) {
|
1262 |
+
// Switch to the event owner tab.
|
1263 |
+
jQuery('li[data-staff_id=' + event.staffId + ']').click();
|
1264 |
+
} ] );
|
1265 |
+
};
|
1266 |
+
|
1267 |
+
/**
|
1268 |
+
* Datepicker options.
|
1269 |
+
*/
|
1270 |
+
$scope.dateOptions = BooklyL10nAppDialog.dateOptions;
|
1271 |
+
});
|
1272 |
+
|
1273 |
+
/**
|
1274 |
+
* Directive for slide up/down.
|
1275 |
+
*/
|
1276 |
+
module.directive('mySlideUp', function() {
|
1277 |
+
return function(scope, element, attrs) {
|
1278 |
+
element.hide();
|
1279 |
+
// watch the expression, and update the UI on change.
|
1280 |
+
scope.$watch(attrs.mySlideUp, function(value) {
|
1281 |
+
if (value) {
|
1282 |
+
element.delay(0).slideDown();
|
1283 |
+
} else {
|
1284 |
+
element.slideUp();
|
1285 |
+
}
|
1286 |
+
});
|
1287 |
+
};
|
1288 |
+
});
|
1289 |
+
|
1290 |
+
/**
|
1291 |
+
* Directive for Popover jQuery plugin.
|
1292 |
+
*/
|
1293 |
+
module.directive('popover', function() {
|
1294 |
+
return function(scope, element, attrs) {
|
1295 |
+
element.popover({
|
1296 |
+
trigger : 'hover',
|
1297 |
+
content : function() { return this.getAttribute('popover'); },
|
1298 |
+
html : true,
|
1299 |
+
placement: 'top',
|
1300 |
+
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>'
|
1301 |
+
});
|
1302 |
+
};
|
1303 |
+
});
|
1304 |
+
|
1305 |
+
/**
|
1306 |
+
* Filters for pagination in Schedule.
|
1307 |
+
*/
|
1308 |
+
module.filter('startFrom', function() {
|
1309 |
+
return function(input, start){
|
1310 |
+
start = +start;
|
1311 |
+
return input.slice(start);
|
1312 |
+
}
|
1313 |
+
});
|
1314 |
+
module.filter('range', function() {
|
1315 |
+
return function(input, total) {
|
1316 |
+
total = parseInt(total);
|
1317 |
+
|
1318 |
+
for (var i = 1; i <= total; ++ i) {
|
1319 |
+
input.push(i);
|
1320 |
+
}
|
1321 |
+
|
1322 |
+
return input;
|
1323 |
+
};
|
1324 |
+
});
|
1325 |
+
|
1326 |
+
jQuery('#bookly-select2').select2({
|
1327 |
+
width: '100%',
|
1328 |
+
theme: 'bootstrap',
|
1329 |
+
allowClear: false,
|
1330 |
+
language : {
|
1331 |
+
noResults: function() { return BooklyL10nAppDialog.no_result_found; }
|
1332 |
+
}
|
1333 |
+
});
|
1334 |
+
})();
|
1335 |
+
|
1336 |
+
/**
|
1337 |
+
* @param int appointment_id
|
1338 |
+
* @param int staff_id
|
1339 |
+
* @param moment start_date
|
1340 |
+
* @param function callback
|
1341 |
+
*/
|
1342 |
+
var showAppointmentDialog = function (appointment_id, staff_id, start_date, callback) {
|
1343 |
+
var $dialog = jQuery('#bookly-appointment-dialog');
|
1344 |
+
var $scope = angular.element($dialog[0]).scope();
|
1345 |
+
$scope.$apply(function ($scope) {
|
1346 |
+
$scope.loading = true;
|
1347 |
+
$dialog
|
1348 |
+
.find('.modal-title')
|
1349 |
+
.text(appointment_id ? BooklyL10nAppDialog.title.edit_appointment : BooklyL10nAppDialog.title.new_appointment);
|
1350 |
+
// Populate data source.
|
1351 |
+
$scope.dataSource.loadData().then(function() {
|
1352 |
+
$scope.loading = false;
|
1353 |
+
if (appointment_id) {
|
1354 |
+
$scope.configureEditForm(appointment_id, callback);
|
1355 |
+
} else {
|
1356 |
+
$scope.configureNewForm(staff_id, start_date, callback);
|
1357 |
+
}
|
1358 |
+
});
|
1359 |
+
});
|
1360 |
+
|
1361 |
+
// hide customer details dialog, if it remained opened.
|
1362 |
+
if (jQuery('#bookly-customer-details-dialog').hasClass('in')) {
|
1363 |
+
jQuery('#bookly-customer-details-dialog').modal('hide');
|
1364 |
+
}
|
1365 |
+
|
1366 |
+
// hide new customer dialog, if it remained opened.
|
1367 |
+
if (jQuery('#bookly-customer-dialog').hasClass('in')) {
|
1368 |
+
jQuery('#bookly-customer-dialog').modal('hide');
|
1369 |
+
}
|
1370 |
+
|
1371 |
+
$dialog.modal('show');
|
1372 |
};
|
backend/components/dialogs/appointment/edit/templates/edit.php
CHANGED
@@ -1,241 +1,253 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
use Bookly\Backend\Components\Dialogs;
|
4 |
-
use Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
5 |
-
use Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy as AttachPaymentProxy;
|
6 |
-
use Bookly\Lib\Config;
|
7 |
-
use Bookly\Lib\Entities\CustomerAppointment;
|
8 |
-
?>
|
9 |
-
<div ng-app="appointmentDialog" ng-controller="appointmentDialogCtrl">
|
10 |
-
<div id=bookly-appointment-dialog class="modal fade" tabindex=-1 role="dialog">
|
11 |
-
<div class="modal-dialog">
|
12 |
-
<div class="modal-content">
|
13 |
-
<form ng-submit=processForm()>
|
14 |
-
<div class="modal-header">
|
15 |
-
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
16 |
-
<div class="modal-title h2"><?php
|
17 |
-
</div>
|
18 |
-
<div ng-show=loading class="modal-body">
|
19 |
-
<div class="bookly-loading"></div>
|
20 |
-
</div>
|
21 |
-
<div ng-hide="loading || form.screen != 'main'" class="modal-body">
|
22 |
-
<div class=form-group>
|
23 |
-
<label for="bookly-provider"><?php
|
24 |
-
<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>
|
25 |
-
</div>
|
26 |
-
|
27 |
-
<div class=form-group>
|
28 |
-
<label for="bookly-service"><?php
|
29 |
-
<select id="bookly-service" class="form-control" ng-model="form.service"
|
30 |
-
ng-options="s.title for s in form.staff.services" ng-change="onServiceChange()">
|
31 |
-
<option value=""><?php
|
32 |
-
</select>
|
33 |
-
<p class="text-danger" my-slide-up="errors.service_required">
|
34 |
-
<?php
|
35 |
-
</p>
|
36 |
-
</div>
|
37 |
-
|
38 |
-
<?php Proxy\Pro::renderCustomServiceFields() ?>
|
39 |
-
|
40 |
-
<?php if ( Config::locationsActive() ): ?>
|
41 |
-
<div class="form-group">
|
42 |
-
<label for="bookly-appointment-location"><?php
|
43 |
-
<select id="bookly-appointment-location" class="form-control" ng-model="form.location"
|
44 |
-
ng-options="l.name for l in form.staff.locations" ng-change="onLocationChange()">
|
45 |
-
<option value=""></option>
|
46 |
-
</select>
|
47 |
-
</div>
|
48 |
-
<?php endif ?>
|
49 |
-
|
50 |
-
<?php Proxy\Tasks::renderSkipDate() ?>
|
51 |
-
|
52 |
-
<div ng-hide="form.skip_date">
|
53 |
-
<div class=form-group>
|
54 |
-
<div class="row">
|
55 |
-
<div class="col-sm-4">
|
56 |
-
<label for="bookly-date"><?php
|
57 |
-
<input id="bookly-date" class="form-control" type=text
|
58 |
-
ng-model=form.date ui-date="dateOptions" autocomplete="off"
|
59 |
-
ng-change=onDateChange()>
|
60 |
-
</div>
|
61 |
-
<div class="col-sm-8">
|
62 |
-
<div ng-hide="form.service.duration >= 86400">
|
63 |
-
<label for="bookly-period"><?php
|
64 |
-
<div class="bookly-flexbox">
|
65 |
-
<div class="bookly-flex-cell">
|
66 |
-
<select id="bookly-period" class="form-control" ng-model=form.start_time
|
67 |
-
ng-options="t.title for t in dataSource.getDataForStartTime()"
|
68 |
-
ng-change=onStartTimeChange()></select>
|
69 |
-
</div>
|
70 |
-
<div class="bookly-flex-cell" style="width: 4%">
|
71 |
-
<div class="bookly-margin-horizontal-md"><?php
|
72 |
-
</div>
|
73 |
-
<div class="bookly-flex-cell" style="width: 48%">
|
74 |
-
<select class="form-control" ng-model=form.end_time
|
75 |
-
ng-options="t.title for t in form.end_time_data"
|
76 |
-
ng-change=onEndTimeChange()></select>
|
77 |
-
</div>
|
78 |
-
</div>
|
79 |
-
<p class="text-success" my-slide-up=errors.date_interval_warning id=date_interval_warning_msg>
|
80 |
-
<?php
|
81 |
-
</p>
|
82 |
-
<p class="text-success" my-slide-up="errors.time_interval" ng-bind="errors.time_interval"></p>
|
83 |
-
</div>
|
84 |
-
</div>
|
85 |
-
<div class="text-success col-sm-12" my-slide-up=errors.date_interval_not_available id=date_interval_not_available_msg>
|
86 |
-
<?php
|
87 |
-
</div>
|
88 |
-
</div>
|
89 |
-
<p class="text-success" my-slide-up=errors.interval_not_in_staff_schedule id=interval_not_in_staff_schedule_msg>
|
90 |
-
<?php
|
91 |
-
</p>
|
92 |
-
<p class="text-success" my-slide-up=errors.interval_not_in_service_schedule id=interval_not_in_service_schedule_msg>
|
93 |
-
<?php
|
94 |
-
</p>
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
<?php
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
<?php
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
<?php
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
<?php
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
</
|
215 |
-
</div>
|
216 |
-
|
217 |
-
<div class=form-group>
|
218 |
-
<label for="bookly-
|
219 |
-
<
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
use Bookly\Backend\Components\Dialogs;
|
4 |
+
use Bookly\Backend\Components\Dialogs\Appointment\Edit\Proxy;
|
5 |
+
use Bookly\Backend\Components\Dialogs\Appointment\AttachPayment\Proxy as AttachPaymentProxy;
|
6 |
+
use Bookly\Lib\Config;
|
7 |
+
use Bookly\Lib\Entities\CustomerAppointment;
|
8 |
+
?>
|
9 |
+
<div ng-app="appointmentDialog" ng-controller="appointmentDialogCtrl">
|
10 |
+
<div id=bookly-appointment-dialog class="modal fade" tabindex=-1 role="dialog">
|
11 |
+
<div class="modal-dialog">
|
12 |
+
<div class="modal-content">
|
13 |
+
<form ng-submit=processForm()>
|
14 |
+
<div class="modal-header">
|
15 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
16 |
+
<div class="modal-title h2"><?php esc_html_e( 'New appointment', 'bookly' ) ?></div>
|
17 |
+
</div>
|
18 |
+
<div ng-show=loading class="modal-body">
|
19 |
+
<div class="bookly-loading"></div>
|
20 |
+
</div>
|
21 |
+
<div ng-hide="loading || form.screen != 'main'" class="modal-body">
|
22 |
+
<div class=form-group>
|
23 |
+
<label for="bookly-provider"><?php esc_html_e( 'Provider', 'bookly' ) ?></label>
|
24 |
+
<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 | filter:filterStaff" ng-change="onStaffChange()"></select>
|
25 |
+
</div>
|
26 |
+
|
27 |
+
<div class=form-group>
|
28 |
+
<label for="bookly-service"><?php esc_html_e( 'Service', 'bookly' ) ?></label>
|
29 |
+
<select id="bookly-service" class="form-control" ng-model="form.service"
|
30 |
+
ng-options="s.title for s in form.staff.services" ng-change="onServiceChange()">
|
31 |
+
<option value=""><?php esc_html_e( '-- Select a service --', 'bookly' ) ?></option>
|
32 |
+
</select>
|
33 |
+
<p class="text-danger" my-slide-up="errors.service_required">
|
34 |
+
<?php esc_html_e( 'Please select a service', 'bookly' ) ?>
|
35 |
+
</p>
|
36 |
+
</div>
|
37 |
+
|
38 |
+
<?php Proxy\Pro::renderCustomServiceFields() ?>
|
39 |
+
|
40 |
+
<?php if ( Config::locationsActive() ): ?>
|
41 |
+
<div class="form-group">
|
42 |
+
<label for="bookly-appointment-location"><?php esc_html_e( 'Location', 'bookly' ) ?></label>
|
43 |
+
<select id="bookly-appointment-location" class="form-control" ng-model="form.location"
|
44 |
+
ng-options="l.name for l in form.staff.locations" ng-change="onLocationChange()">
|
45 |
+
<option value=""></option>
|
46 |
+
</select>
|
47 |
+
</div>
|
48 |
+
<?php endif ?>
|
49 |
+
|
50 |
+
<?php Proxy\Tasks::renderSkipDate() ?>
|
51 |
+
|
52 |
+
<div ng-hide="form.skip_date">
|
53 |
+
<div class=form-group>
|
54 |
+
<div class="row">
|
55 |
+
<div class="col-sm-4">
|
56 |
+
<label for="bookly-date"><?php esc_html_e( 'Date', 'bookly' ) ?></label>
|
57 |
+
<input id="bookly-date" class="form-control" type=text
|
58 |
+
ng-model=form.date ui-date="dateOptions" autocomplete="off"
|
59 |
+
ng-change=onDateChange()>
|
60 |
+
</div>
|
61 |
+
<div class="col-sm-8">
|
62 |
+
<div ng-hide="form.service.duration >= 86400">
|
63 |
+
<label for="bookly-period"><?php esc_html_e( 'Period', 'bookly' ) ?></label>
|
64 |
+
<div class="bookly-flexbox">
|
65 |
+
<div class="bookly-flex-cell">
|
66 |
+
<select id="bookly-period" class="form-control" ng-model=form.start_time
|
67 |
+
ng-options="t.title for t in dataSource.getDataForStartTime()"
|
68 |
+
ng-change=onStartTimeChange()></select>
|
69 |
+
</div>
|
70 |
+
<div class="bookly-flex-cell" style="width: 4%">
|
71 |
+
<div class="bookly-margin-horizontal-md"><?php esc_html_e( 'to', 'bookly' ) ?></div>
|
72 |
+
</div>
|
73 |
+
<div class="bookly-flex-cell" style="width: 48%">
|
74 |
+
<select class="form-control" ng-model=form.end_time
|
75 |
+
ng-options="t.title for t in form.end_time_data"
|
76 |
+
ng-change=onEndTimeChange()></select>
|
77 |
+
</div>
|
78 |
+
</div>
|
79 |
+
<p class="text-success" my-slide-up=errors.date_interval_warning id=date_interval_warning_msg>
|
80 |
+
<?php esc_html_e( 'Selected period doesn\'t match service duration', 'bookly' ) ?>
|
81 |
+
</p>
|
82 |
+
<p class="text-success" my-slide-up="errors.time_interval" ng-bind="errors.time_interval"></p>
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
<div class="text-success col-sm-12" my-slide-up=errors.date_interval_not_available id=date_interval_not_available_msg>
|
86 |
+
<?php esc_html_e( 'The selected period is occupied by another appointment', 'bookly' ) ?>
|
87 |
+
</div>
|
88 |
+
</div>
|
89 |
+
<p class="text-success" my-slide-up=errors.interval_not_in_staff_schedule id=interval_not_in_staff_schedule_msg>
|
90 |
+
<?php esc_html_e( 'Selected period doesn\'t match provider\'s schedule', 'bookly' ) ?>
|
91 |
+
</p>
|
92 |
+
<p class="text-success" my-slide-up=errors.interval_not_in_service_schedule id=interval_not_in_service_schedule_msg>
|
93 |
+
<?php esc_html_e( 'Selected period doesn\'t match service schedule', 'bookly' ) ?>
|
94 |
+
</p>
|
95 |
+
<p class="text-success" my-slide-up=errors.staff_reaches_working_time_limit id=staff_reaches_working_time_limit_msg>
|
96 |
+
<?php is_admin() ?
|
97 |
+
esc_html_e( 'Booking exceeds the working hours limit for staff member', 'bookly' ) :
|
98 |
+
esc_html_e( 'Booking exceeds your working hours limit', 'bookly' ) ?>
|
99 |
+
</p>
|
100 |
+
</div>
|
101 |
+
|
102 |
+
<?php Proxy\RecurringAppointments::renderSubForm() ?>
|
103 |
+
</div>
|
104 |
+
|
105 |
+
<div class=form-group>
|
106 |
+
<label for="bookly-select2"><?php esc_html_e( 'Customers', 'bookly' ) ?></label>
|
107 |
+
<span ng-show="form.service && form.service.id" title="<?php esc_attr_e( 'Selected / maximum', 'bookly' ) ?>">
|
108 |
+
({{dataSource.getTotalNumberOfPersons()}}/{{form.service.capacity_max}})
|
109 |
+
</span>
|
110 |
+
<span ng-show="form.customers.length > 5" ng-click="form.expand_customers_list = !form.expand_customers_list" role="button">
|
111 |
+
<i class="fa fa-fw" ng-class="{'fa-angle-down':!form.expand_customers_list, 'fa-angle-up':form.expand_customers_list}"></i>
|
112 |
+
</span>
|
113 |
+
<p class="text-success" ng-show=form.service my-slide-up="form.service.capacity_min > 1 && form.service.capacity_min > dataSource.getTotalNumberOfPersons()">
|
114 |
+
<?php esc_html_e( 'Minimum capacity', 'bookly' ) ?>: {{form.service.capacity_min}}
|
115 |
+
</p>
|
116 |
+
<ul class="bookly-flexbox">
|
117 |
+
<li ng-repeat="customer in form.customers" class="bookly-flex-row" ng-hide="$index > 4 && !form.expand_customers_list">
|
118 |
+
<div class="bookly-flex-cell-sm">
|
119 |
+
<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>
|
120 |
+
</div>
|
121 |
+
<div class="bookly-flex-cell-sm text-right text-nowrap bookly-padding-bottom-sm">
|
122 |
+
<?php Proxy\Shared::renderAppointmentDialogCustomersList() ?>
|
123 |
+
<span class="dropdown">
|
124 |
+
<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)}}">
|
125 |
+
<span ng-class="{'fa fa-fw': true, 'fa-clock': customer.status == 'pending', 'fa-check': customer.status == 'approved', 'fa-times': customer.status == 'cancelled', 'fa-times-circle': customer.status == 'rejected', 'fa-list-alt': customer.status == 'waitlisted', 'fa-check-circle': customer.status == 'done'}"></span>
|
126 |
+
<span class="caret"></span>
|
127 |
+
</button>
|
128 |
+
<ul class="dropdown-menu">
|
129 |
+
<li>
|
130 |
+
<a href ng-click="customer.status = 'pending'">
|
131 |
+
<span class="fa fa-fw fa-clock"></span>
|
132 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_PENDING ) ) ?>
|
133 |
+
</a>
|
134 |
+
</li>
|
135 |
+
<li>
|
136 |
+
<a href ng-click="customer.status = 'approved'">
|
137 |
+
<span class="fa fa-fw fa-check"></span>
|
138 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_APPROVED ) ) ?>
|
139 |
+
</a>
|
140 |
+
</li>
|
141 |
+
<li>
|
142 |
+
<a href ng-click="customer.status = 'cancelled'">
|
143 |
+
<span class="fa fa-fw fa-times"></span>
|
144 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_CANCELLED ) ) ?>
|
145 |
+
</a>
|
146 |
+
</li>
|
147 |
+
<li>
|
148 |
+
<a href ng-click="customer.status = 'rejected'">
|
149 |
+
<span class="fa fa-fw fa-times-circle"></span>
|
150 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_REJECTED ) ) ?>
|
151 |
+
</a>
|
152 |
+
</li>
|
153 |
+
<?php if ( Config::waitingListActive() ): ?>
|
154 |
+
<li>
|
155 |
+
<a href ng-click="customer.status = 'waitlisted'">
|
156 |
+
<span class="fa fa-fw fa-list-alt"></span>
|
157 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_WAITLISTED ) ) ?>
|
158 |
+
</a>
|
159 |
+
</li>
|
160 |
+
<?php endif ?>
|
161 |
+
<?php if ( Config::tasksActive() ): ?>
|
162 |
+
<li>
|
163 |
+
<a href ng-click="customer.status = 'done'">
|
164 |
+
<span class="fa fa-fw fa-check-circle"></span>
|
165 |
+
<?php echo esc_html( CustomerAppointment::statusToString( CustomerAppointment::STATUS_DONE ) ) ?>
|
166 |
+
</a>
|
167 |
+
</li>
|
168 |
+
<?php endif ?>
|
169 |
+
</ul>
|
170 |
+
</span>
|
171 |
+
<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 || customer.payment_create" popover="<?php esc_attr_e( 'Payment', 'bookly' ) ?>: {{customer.payment_title}}" ng-disabled="customer.payment_create">
|
172 |
+
<span ng-class="{'bookly-js-toggle-popover fa fa-fw': true, 'fa-clipboard-check': customer.payment_type == 'full', 'fa-hourglass': customer.payment_type == 'partial'}"></span>
|
173 |
+
</button>
|
174 |
+
|
175 |
+
<?php Proxy\Pro::renderAttachPaymentButton() ?>
|
176 |
+
|
177 |
+
<span class="btn btn-sm btn-default disabled bookly-margin-left-xs" style="opacity:1;cursor:default;"><i class="fa fa-fw fa-user"></i>×{{customer.number_of_persons}}</span>
|
178 |
+
<?php if ( Config::packagesActive() ) : ?>
|
179 |
+
<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' ) ?>">
|
180 |
+
<span class="fa fa-fw fa-calendar-alt"></span>
|
181 |
+
</button>
|
182 |
+
<?php endif ?>
|
183 |
+
<?php if ( Config::recurringAppointmentsActive() ) : ?>
|
184 |
+
<button type="button" class="btn btn-sm btn-default bookly-margin-left-xs" ng-click="schViewSeries(customer)" ng-show="customer.series_id" popover="<?php esc_attr_e( 'View series', 'bookly' ) ?>">
|
185 |
+
<span class="fa fa-fw fa-link"></span>
|
186 |
+
</button>
|
187 |
+
<?php endif ?>
|
188 |
+
<a ng-click="removeCustomer(customer)" class="fa fa-fw fa-trash-alt text-danger bookly-vertical-middle" href="#"
|
189 |
+
popover="<?php esc_attr_e( 'Remove customer', 'bookly' ) ?>"></a>
|
190 |
+
</div>
|
191 |
+
</li>
|
192 |
+
</ul>
|
193 |
+
<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>
|
194 |
+
<div <?php if ( ! Config::waitingListActive() ): ?>ng-show="!form.service || dataSource.getTotalNumberOfNotCancelledPersons() < form.service.capacity_max"<?php endif ?>>
|
195 |
+
<div class="form-group">
|
196 |
+
<div class="input-group">
|
197 |
+
<select id="bookly-select2" multiple data-placeholder="<?php esc_attr_e( '-- Search customers --', 'bookly' ) ?>"
|
198 |
+
class="form-control"
|
199 |
+
ng-model="form.customers" ng-options="c.name for c in dataSource.data.customers"
|
200 |
+
ng-change="onCustomersChange({{form.customers}}, {{dataSource.getTotalNumberOfNotCancelledPersons()}})">
|
201 |
+
</select>
|
202 |
+
<span class="input-group-btn">
|
203 |
+
<a class="btn btn-success" ng-click="openNewCustomerDialog()">
|
204 |
+
<i class="fa fa-fw fa-plus"></i>
|
205 |
+
<?php esc_html_e( 'New customer', 'bookly' ) ?>
|
206 |
+
</a>
|
207 |
+
</span>
|
208 |
+
</div>
|
209 |
+
</div>
|
210 |
+
</div>
|
211 |
+
<p class="text-danger" my-slide-up="errors.overflow_capacity" ng-bind="errors.overflow_capacity"></p>
|
212 |
+
<p class="text-success" my-slide-up="errors.customers_appointments_limit" ng-repeat="customer_error in errors.customers_appointments_limit">
|
213 |
+
{{customer_error}}
|
214 |
+
</p>
|
215 |
+
</div>
|
216 |
+
|
217 |
+
<div class=form-group>
|
218 |
+
<label for="bookly-notification"><?php esc_html_e( 'Send notifications', 'bookly' ) ?></label>
|
219 |
+
<p class="help-block"><?php is_admin() ?
|
220 |
+
esc_html_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' ) :
|
221 |
+
esc_html_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>
|
222 |
+
<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'" >
|
223 |
+
<option value="no"><?php esc_html_e( 'Don\'t send', 'bookly' ) ?></option>
|
224 |
+
<option value="changed_status"><?php esc_html_e( 'If status changed', 'bookly' ) ?></option>
|
225 |
+
<option value="all"><?php esc_html_e( 'To all customers', 'bookly' ) ?></option>
|
226 |
+
</select>
|
227 |
+
</div>
|
228 |
+
|
229 |
+
<div class=form-group>
|
230 |
+
<label for="bookly-internal-note"><?php esc_html_e( 'Internal note', 'bookly' ) ?></label>
|
231 |
+
<textarea class="form-control" ng-model=form.internal_note id="bookly-internal-note"></textarea>
|
232 |
+
</div>
|
233 |
+
</div>
|
234 |
+
<?php Proxy\RecurringAppointments::renderSchedule() ?>
|
235 |
+
<div class="modal-footer">
|
236 |
+
<div ng-hide=loading>
|
237 |
+
<?php Proxy\Shared::renderAppointmentDialogFooter() ?>
|
238 |
+
<?php Buttons::renderSubmit( null, null, null, array( 'ng-hide' => 'form.repeat.enabled && !form.skip_date && form.screen == \'main\'', 'ng-disabled' => '!form.skip_date && form.repeat.enabled && schIsScheduleEmpty()', 'formnovalidate' => '' ) ) ?>
|
239 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'ng-click' => 'closeDialog()', 'data-dismiss' => 'modal' ) ) ?>
|
240 |
+
</div>
|
241 |
+
</div>
|
242 |
+
</form>
|
243 |
+
</div>
|
244 |
+
</div>
|
245 |
+
</div>
|
246 |
+
<div customer-dialog=createCustomer(customer)></div>
|
247 |
+
<div payment-details-dialog="callbackPayment(payment_action, payment_id, payment_title, customer_id, payment_type)"></div>
|
248 |
+
|
249 |
+
<?php Dialogs\Appointment\CustomerDetails\Dialog::render() ?>
|
250 |
+
<?php AttachPaymentProxy\Pro::renderAttachPaymentDialog() ?>
|
251 |
+
<?php Dialogs\Customer\Edit\Dialog::render() ?>
|
252 |
+
<?php Dialogs\Payment\Dialog::render() ?>
|
253 |
+
</div>
|
backend/components/dialogs/common/CascadeDelete.php
CHANGED
@@ -1,30 +1,30 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Common;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class CascadeDelete
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Common
|
9 |
-
*/
|
10 |
-
class CascadeDelete extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render cascade delete dialog (used in services and staff lists).
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
self::enqueueStyles( array(
|
18 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
-
) );
|
20 |
-
|
21 |
-
self::enqueueScripts( array(
|
22 |
-
'frontend' => array(
|
23 |
-
'js/spin.min.js' => array( 'jquery' ),
|
24 |
-
'js/ladda.min.js' => array( 'bookly-spin.min.js', 'jquery' ),
|
25 |
-
)
|
26 |
-
) );
|
27 |
-
|
28 |
-
self::renderTemplate( 'delete_cascade' );
|
29 |
-
}
|
30 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Common;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CascadeDelete
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Common
|
9 |
+
*/
|
10 |
+
class CascadeDelete extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render cascade delete dialog (used in services and staff lists).
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
self::enqueueStyles( array(
|
18 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
+
) );
|
20 |
+
|
21 |
+
self::enqueueScripts( array(
|
22 |
+
'frontend' => array(
|
23 |
+
'js/spin.min.js' => array( 'jquery' ),
|
24 |
+
'js/ladda.min.js' => array( 'bookly-spin.min.js', 'jquery' ),
|
25 |
+
)
|
26 |
+
) );
|
27 |
+
|
28 |
+
self::renderTemplate( 'delete_cascade' );
|
29 |
+
}
|
30 |
}
|
backend/components/dialogs/common/UnsavedChanges.php
CHANGED
@@ -1,30 +1,30 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Common;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class UnsavedChanges
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Common
|
9 |
-
*/
|
10 |
-
class UnsavedChanges extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render unsaved data confirm dialog.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
self::enqueueStyles( array(
|
18 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
-
) );
|
20 |
-
|
21 |
-
self::enqueueScripts( array(
|
22 |
-
'frontend' => array(
|
23 |
-
'js/spin.min.js' => array( 'jquery' ),
|
24 |
-
'js/ladda.min.js' => array( 'bookly-spin.min.js', 'jquery' ),
|
25 |
-
)
|
26 |
-
) );
|
27 |
-
|
28 |
-
self::renderTemplate( 'unsaved_changes' );
|
29 |
-
}
|
30 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Common;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class UnsavedChanges
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Common
|
9 |
+
*/
|
10 |
+
class UnsavedChanges extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render unsaved data confirm dialog.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
self::enqueueStyles( array(
|
18 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
+
) );
|
20 |
+
|
21 |
+
self::enqueueScripts( array(
|
22 |
+
'frontend' => array(
|
23 |
+
'js/spin.min.js' => array( 'jquery' ),
|
24 |
+
'js/ladda.min.js' => array( 'bookly-spin.min.js', 'jquery' ),
|
25 |
+
)
|
26 |
+
) );
|
27 |
+
|
28 |
+
self::renderTemplate( 'unsaved_changes' );
|
29 |
+
}
|
30 |
}
|
backend/components/dialogs/common/templates/delete_cascade.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
?>
|
4 |
-
<div class="modal fade bookly-js-delete-cascade-confirm" tabindex="-1" role="dialog">
|
5 |
-
<div class="modal-dialog modal-lg" role="document">
|
6 |
-
<div class="modal-content">
|
7 |
-
<div class="modal-header">
|
8 |
-
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
9 |
-
<div class="modal-title h4"><?php _e( 'Are you sure?', 'bookly' ) ?></div>
|
10 |
-
</div>
|
11 |
-
<div class="modal-body">
|
12 |
-
<p><?php _e( 'You are going to delete item which is involved in upcoming appointments. All related appointments will be deleted. Please double check and edit appointments before this item deletion if needed.', 'bookly' ) ?></p>
|
13 |
-
</div>
|
14 |
-
<div class="modal-footer">
|
15 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-danger bookly-js-delete', __( 'Delete', 'bookly' ) ) ?>
|
16 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-success bookly-js-edit', __( 'Edit appointments', 'bookly' ) ) ?>
|
17 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
18 |
-
</div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
?>
|
4 |
+
<div class="modal fade bookly-js-delete-cascade-confirm" tabindex="-1" role="dialog">
|
5 |
+
<div class="modal-dialog modal-lg" role="document">
|
6 |
+
<div class="modal-content">
|
7 |
+
<div class="modal-header">
|
8 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
9 |
+
<div class="modal-title h4"><?php _e( 'Are you sure?', 'bookly' ) ?></div>
|
10 |
+
</div>
|
11 |
+
<div class="modal-body">
|
12 |
+
<p><?php _e( 'You are going to delete item which is involved in upcoming appointments. All related appointments will be deleted. Please double check and edit appointments before this item deletion if needed.', 'bookly' ) ?></p>
|
13 |
+
</div>
|
14 |
+
<div class="modal-footer">
|
15 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-danger bookly-js-delete', __( 'Delete', 'bookly' ) ) ?>
|
16 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-success bookly-js-edit', __( 'Edit appointments', 'bookly' ) ) ?>
|
17 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
</div>
|
backend/components/dialogs/common/templates/unsaved_changes.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
?>
|
4 |
-
<div class="modal fade bookly-js-unsaved-changes" tabindex="-1" role="dialog">
|
5 |
-
<div class="modal-dialog modal-lg" role="document">
|
6 |
-
<div class="modal-content">
|
7 |
-
<div class="modal-header">
|
8 |
-
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
9 |
-
<div class="modal-title h4"><?php _e( 'Are you sure?', 'bookly' ) ?></div>
|
10 |
-
</div>
|
11 |
-
<div class="modal-body">
|
12 |
-
<p><?php _e( 'All unsaved changes will be lost.', 'bookly' ) ?></p>
|
13 |
-
</div>
|
14 |
-
<div class="modal-footer">
|
15 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-success bookly-js-save-changes', __( 'Save', 'bookly' ) ) ?>
|
16 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-danger bookly-js-ignore-changes', __( 'Don\'t save', 'bookly' ) ) ?>
|
17 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
18 |
-
</div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
?>
|
4 |
+
<div class="modal fade bookly-js-unsaved-changes" tabindex="-1" role="dialog">
|
5 |
+
<div class="modal-dialog modal-lg" role="document">
|
6 |
+
<div class="modal-content">
|
7 |
+
<div class="modal-header">
|
8 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
9 |
+
<div class="modal-title h4"><?php _e( 'Are you sure?', 'bookly' ) ?></div>
|
10 |
+
</div>
|
11 |
+
<div class="modal-body">
|
12 |
+
<p><?php _e( 'All unsaved changes will be lost.', 'bookly' ) ?></p>
|
13 |
+
</div>
|
14 |
+
<div class="modal-footer">
|
15 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-success bookly-js-save-changes', __( 'Save', 'bookly' ) ) ?>
|
16 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-danger bookly-js-ignore-changes', __( 'Don\'t save', 'bookly' ) ) ?>
|
17 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
</div>
|
backend/components/dialogs/customer/delete/Ajax.php
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Delete;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Ajax
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Delete
|
9 |
+
*/
|
10 |
+
class Ajax extends Lib\Base\Ajax
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @inheritdoc
|
14 |
+
*/
|
15 |
+
protected static function permissions()
|
16 |
+
{
|
17 |
+
return array( '_default' => 'user' );
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Delete customers.
|
22 |
+
*/
|
23 |
+
public static function deleteCustomers()
|
24 |
+
{
|
25 |
+
$customer_ids = array_unique( (array) self::parameter( 'customers' ) );
|
26 |
+
if ( $customer_ids ) {
|
27 |
+
update_user_meta(
|
28 |
+
get_current_user_id(),
|
29 |
+
'bookly_delete_customers_options',
|
30 |
+
self::parameter( 'remember' ) ? array( 'with_wp_users' => self::parameter( 'with_wp_users' ), 'with_events' => self::parameter( 'with_events' ) ) : ''
|
31 |
+
);
|
32 |
+
/** @var Lib\Entities\Customer[] $customers */
|
33 |
+
$customers = Lib\Entities\Customer::query()
|
34 |
+
->whereIn( 'id', $customer_ids )
|
35 |
+
->indexBy( 'id' )
|
36 |
+
->find();
|
37 |
+
|
38 |
+
$appointments = Lib\Entities\Appointment::query( 'a' )
|
39 |
+
->select( 'a.id, ca.id as ca_id, ca.customer_id, a.internal_note' )
|
40 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'a.id = ca.appointment_id' )
|
41 |
+
->whereIn( 'ca.customer_id', $customer_ids )
|
42 |
+
->fetchArray();
|
43 |
+
|
44 |
+
if ( $appointments ) {
|
45 |
+
/** @var Lib\Entities\CustomerAppointment[] $ca_list */
|
46 |
+
$ca_list = Lib\Entities\CustomerAppointment::query()
|
47 |
+
->whereIn( 'id', array_map( function ( $appointment ) { return $appointment['ca_id']; }, $appointments ) )
|
48 |
+
->indexBy( 'id' )
|
49 |
+
->find();
|
50 |
+
|
51 |
+
$info = sprintf( '%s, %s: ',
|
52 |
+
Lib\Utils\DateTime::formatDateTime( Lib\Slots\DatePoint::now()->format( 'Y-m-d H:i:s' ) ),
|
53 |
+
__( 'Deleted Customer', 'bookly' ) );
|
54 |
+
foreach ( $appointments as $appointment ) {
|
55 |
+
$note = Lib\Query::escape( $info . $customers[ $appointment['customer_id'] ]->getFullName() );
|
56 |
+
Lib\Entities\Appointment::query( 'a' )
|
57 |
+
->update()
|
58 |
+
->setRaw( 'internal_note = CONCAT_WS(%s,internal_note,%s)', array( $appointment['internal_note'] == '' ? '' : PHP_EOL, $note ) )
|
59 |
+
->where( 'id', $appointment['id'] )
|
60 |
+
->execute();
|
61 |
+
$ca_list[ $appointment['ca_id'] ]->delete();
|
62 |
+
}
|
63 |
+
}
|
64 |
+
foreach ( $customers as $customer ) {
|
65 |
+
$customer->deleteWithWPUser( (bool) self::parameter( 'with_wp_users' ) );
|
66 |
+
}
|
67 |
+
}
|
68 |
+
|
69 |
+
wp_send_json_success();
|
70 |
+
}
|
71 |
+
|
72 |
+
public static function checkCustomers()
|
73 |
+
{
|
74 |
+
$customer_ids = array_unique( (array) self::parameter( 'customers' ) );
|
75 |
+
$events = Lib\Entities\Appointment::query( 'a' )
|
76 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'a.id = ca.appointment_id' )
|
77 |
+
->whereIn( 'ca.customer_id', $customer_ids )
|
78 |
+
->whereIn( 'ca.status', array( Lib\Entities\CustomerAppointment::STATUS_APPROVED, Lib\Entities\CustomerAppointment::STATUS_PENDING ) )
|
79 |
+
->whereGte( 'a.start_date', current_time( 'mysql' ) )
|
80 |
+
->count() > 0;
|
81 |
+
$tasks = Lib\Entities\Appointment::query( 'a' )
|
82 |
+
->leftJoin( 'CustomerAppointment', 'ca', 'a.id = ca.appointment_id' )
|
83 |
+
->whereIn( 'ca.customer_id', $customer_ids )
|
84 |
+
->whereIn( 'ca.status', array( Lib\Entities\CustomerAppointment::STATUS_APPROVED, Lib\Entities\CustomerAppointment::STATUS_PENDING ) )
|
85 |
+
->where( 'a.start_date', null )
|
86 |
+
->count() > 0;
|
87 |
+
$meta = get_user_meta( get_current_user_id(), 'bookly_delete_customers_options', true );
|
88 |
+
if ( $meta != '' ) {
|
89 |
+
$remember = true;
|
90 |
+
$with_events = isset( $meta['with_events'] ) && $meta['with_events'];
|
91 |
+
$with_wp_users = isset( $meta['with_wp_users'] ) && $meta['with_wp_users'];
|
92 |
+
|
93 |
+
} else {
|
94 |
+
$remember = false;
|
95 |
+
$with_events = false;
|
96 |
+
$with_wp_users = false;
|
97 |
+
}
|
98 |
+
wp_send_json_success( array(
|
99 |
+
'with_events' => $with_events,
|
100 |
+
'with_wp_users' => $with_wp_users,
|
101 |
+
'remember' => $remember,
|
102 |
+
'exists_events' => $events || $tasks,
|
103 |
+
) );
|
104 |
+
}
|
105 |
+
|
106 |
+
/**
|
107 |
+
* Check if the current user has access to the action.
|
108 |
+
*
|
109 |
+
* @param string $action
|
110 |
+
* @return bool
|
111 |
+
*/
|
112 |
+
protected static function hasAccess( $action )
|
113 |
+
{
|
114 |
+
if ( parent::hasAccess( $action ) ) {
|
115 |
+
if ( ! Lib\Utils\Common::isCurrentUserAdmin() ) {
|
116 |
+
switch ( $action ) {
|
117 |
+
case 'deleteCustomers':
|
118 |
+
case 'checkCustomers':
|
119 |
+
return Lib\Entities\Staff::query()
|
120 |
+
->where( 'wp_user_id', get_current_user_id() )
|
121 |
+
->count() > 0;
|
122 |
+
}
|
123 |
+
} else {
|
124 |
+
return true;
|
125 |
+
}
|
126 |
+
}
|
127 |
+
|
128 |
+
return false;
|
129 |
+
}
|
130 |
+
}
|
backend/components/dialogs/customer/delete/Dialog.php
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Delete;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Dialog
|
9 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Delete
|
10 |
+
*/
|
11 |
+
class Dialog extends Lib\Base\Component
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Render customer dialog.
|
15 |
+
*/
|
16 |
+
public static function render()
|
17 |
+
{
|
18 |
+
self::enqueueScripts( array(
|
19 |
+
'module' => array( 'js/delete-customers.js' => array( 'jquery' ), )
|
20 |
+
) );
|
21 |
+
|
22 |
+
wp_localize_script( 'bookly-delete-customers.js', 'BooklyL10nCustomerDelete', array(
|
23 |
+
'csrfToken' => Lib\Utils\Common::getCsrfToken(),
|
24 |
+
) );
|
25 |
+
|
26 |
+
static::renderTemplate( 'dialog' );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Render delete button on page (sub Customers table)
|
31 |
+
*/
|
32 |
+
public static function renderDeleteButton()
|
33 |
+
{
|
34 |
+
Buttons::renderDelete();
|
35 |
+
}
|
36 |
+
}
|
backend/components/dialogs/customer/delete/resources/js/delete-customers.js
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(function ($) {
|
2 |
+
|
3 |
+
var
|
4 |
+
$customersList = $('#bookly-customers-list'),
|
5 |
+
$initDeletingButton = $('#bookly-delete'),
|
6 |
+
$deleteDialog = $('#bookly-delete-dialog'),
|
7 |
+
$deleteButton = $('.bookly-js-delete', $deleteDialog),
|
8 |
+
$rememberCheckbox = $('.bookly-js-remember-choice-checkbox', $deleteDialog),
|
9 |
+
$deleteEventsCheckbox = $('.bookly-js-delete-with-events-checkbox', $deleteDialog),
|
10 |
+
$deleteWPUserCheckbox = $('.bookly-js-delete-with-wp-user-checkbox', $deleteDialog)
|
11 |
+
;
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Delete customers.
|
15 |
+
*/
|
16 |
+
$initDeletingButton.on('click', function () {
|
17 |
+
var ladda = Ladda.create(this),
|
18 |
+
customers = [],
|
19 |
+
$checkboxes = $customersList.find('tbody input:checked');
|
20 |
+
|
21 |
+
ladda.start();
|
22 |
+
$checkboxes.each(function () {
|
23 |
+
customers.push(this.value);
|
24 |
+
});
|
25 |
+
|
26 |
+
if (customers.length > 0) {
|
27 |
+
$.ajax({
|
28 |
+
url : ajaxurl,
|
29 |
+
type : 'POST',
|
30 |
+
data : {
|
31 |
+
action : 'bookly_check_customers',
|
32 |
+
csrf_token: BooklyL10nCustomerDelete.csrfToken,
|
33 |
+
customers : customers
|
34 |
+
},
|
35 |
+
dataType: 'json',
|
36 |
+
success : function (response) {
|
37 |
+
ladda.stop();
|
38 |
+
$('.bookly-js-delete-with-events', $deleteDialog).toggle(response.data.exists_events);
|
39 |
+
$('.bookly-js-delete-without-events', $deleteDialog).toggle(!response.data.exists_events);
|
40 |
+
|
41 |
+
$deleteButton.prop('disabled', response.data.exists_events && !response.data.with_events);
|
42 |
+
|
43 |
+
$deleteEventsCheckbox.prop('checked', response.data.with_events);
|
44 |
+
$deleteWPUserCheckbox.prop('checked', response.data.with_wp_users);
|
45 |
+
$rememberCheckbox.prop('checked', response.data.remember);
|
46 |
+
$deleteDialog.modal('show');
|
47 |
+
}
|
48 |
+
});
|
49 |
+
} else {
|
50 |
+
setTimeout(function () {
|
51 |
+
ladda.stop();
|
52 |
+
}, 200);
|
53 |
+
}
|
54 |
+
});
|
55 |
+
|
56 |
+
$deleteEventsCheckbox.on('change', function () {
|
57 |
+
$deleteButton.prop('disabled', !$deleteEventsCheckbox.prop('checked'));
|
58 |
+
});
|
59 |
+
|
60 |
+
$deleteButton.on('click', function () {
|
61 |
+
var ladda = Ladda.create(this),
|
62 |
+
customers = [],
|
63 |
+
$checkboxes = $customersList.find('tbody input:checked')
|
64 |
+
;
|
65 |
+
|
66 |
+
ladda.start();
|
67 |
+
$checkboxes.each(function () {
|
68 |
+
customers.push(this.value);
|
69 |
+
});
|
70 |
+
|
71 |
+
$.ajax({
|
72 |
+
url : ajaxurl,
|
73 |
+
type : 'POST',
|
74 |
+
data: {
|
75 |
+
action : 'bookly_delete_customers',
|
76 |
+
csrf_token : BooklyL10nCustomerDelete.csrfToken,
|
77 |
+
customers : customers,
|
78 |
+
with_wp_users: $deleteWPUserCheckbox.prop('checked') ? 1 : 0,
|
79 |
+
with_events : $deleteEventsCheckbox.prop('checked') ? 1 : 0,
|
80 |
+
remember : $rememberCheckbox.prop('checked') ? 1 : 0
|
81 |
+
},
|
82 |
+
dataType: 'json',
|
83 |
+
success : function (response) {
|
84 |
+
ladda.stop();
|
85 |
+
$deleteDialog.modal('hide');
|
86 |
+
if (response.success) {
|
87 |
+
$customersList.DataTable().ajax.reload(null, false);
|
88 |
+
} else {
|
89 |
+
alert(response.data.message);
|
90 |
+
}
|
91 |
+
}
|
92 |
+
});
|
93 |
+
});
|
94 |
+
});
|
backend/components/dialogs/customer/delete/templates/dialog.php
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
?>
|
4 |
+
<form id="bookly-delete-dialog" class="modal fade" tabindex=-1>
|
5 |
+
<div class="modal-dialog">
|
6 |
+
<div class="modal-content">
|
7 |
+
<div class="modal-header">
|
8 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
9 |
+
<div class="modal-title h2"><?php esc_html_e( 'Delete customers', 'bookly' ) ?></div>
|
10 |
+
</div>
|
11 |
+
<div class="modal-body">
|
12 |
+
<p class="bookly-js-delete-with-events"><?php esc_html_e( 'You are going to delete customers with existing bookings. Notifications will not be sent to them.', 'bookly' ) ?></p>
|
13 |
+
<p class="bookly-js-delete-without-events"><?php esc_html_e( 'You are going to delete customers, are you sure?', 'bookly' ) ?></p>
|
14 |
+
<div class="bookly-js-delete-with-events bookly-margin-bottom-sm collapse">
|
15 |
+
<div class="checkbox">
|
16 |
+
<label>
|
17 |
+
<input class="bookly-js-delete-with-events-checkbox" type="checkbox"/><?php esc_html_e( 'Delete customers with existing bookings', 'bookly' ) ?>
|
18 |
+
</label>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
<div>
|
22 |
+
<div class="checkbox">
|
23 |
+
<label>
|
24 |
+
<input class="bookly-js-delete-with-wp-user-checkbox" type="checkbox"/><?php esc_html_e( 'Delete customers\' WordPress accounts if there are any', 'bookly' ) ?>
|
25 |
+
</label>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
<div style="margin-top: 80px;">
|
29 |
+
<div class="checkbox">
|
30 |
+
<label>
|
31 |
+
<input class="bookly-js-remember-choice-checkbox" type="checkbox"/><?php esc_html_e( 'Remember my choice', 'bookly' ) ?>
|
32 |
+
</label>
|
33 |
+
</div>
|
34 |
+
</div>
|
35 |
+
</div>
|
36 |
+
<div class="modal-footer">
|
37 |
+
<?php Buttons::renderCustom( null, 'btn-danger ladda-button bookly-js-delete btn-lg', esc_html__( 'Delete', 'bookly' ) ) ?>
|
38 |
+
<?php Buttons::renderCustom( null, 'btn-default btn-lg', esc_html__( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
+
</div>
|
42 |
+
</form>
|
backend/components/dialogs/customer/{EditAjax.php → edit/Ajax.php}
RENAMED
@@ -1,103 +1,103 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Customer;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Customer
|
9 |
-
*/
|
10 |
-
class
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* @inheritdoc
|
14 |
-
*/
|
15 |
-
protected static function permissions()
|
16 |
-
{
|
17 |
-
return array( '_default' => 'user' );
|
18 |
-
}
|
19 |
-
|
20 |
-
/**
|
21 |
-
* Create or edit a customer.
|
22 |
-
*/
|
23 |
-
public static function saveCustomer()
|
24 |
-
{
|
25 |
-
$response = array();
|
26 |
-
|
27 |
-
$params = self::postParameters();
|
28 |
-
$errors = array();
|
29 |
-
|
30 |
-
// Check for errors.
|
31 |
-
if ( get_option( 'bookly_cst_first_last_name' ) ) {
|
32 |
-
if ( $params['first_name'] == '' ) {
|
33 |
-
$errors['first_name'] = array( 'required' );
|
34 |
-
}
|
35 |
-
if ( $params['last_name'] == '' ) {
|
36 |
-
$errors['last_name'] = array( 'required' );
|
37 |
-
}
|
38 |
-
} else if ( $params['full_name'] == '' ) {
|
39 |
-
$errors['full_name'] = array( 'required' );
|
40 |
-
}
|
41 |
-
|
42 |
-
if ( empty ( $errors ) ) {
|
43 |
-
if ( ! $params['wp_user_id'] ) {
|
44 |
-
$params['wp_user_id'] = null;
|
45 |
-
}
|
46 |
-
if ( ! $params['birthday'] ) {
|
47 |
-
$params['birthday'] = null;
|
48 |
-
}
|
49 |
-
if ( ! $params['group_id'] ) {
|
50 |
-
$params['group_id'] = null;
|
51 |
-
}
|
52 |
-
$params = Proxy\CustomerInformation::prepareCustomerFormData( $params );
|
53 |
-
$params['info_fields'] = json_encode( $params['info_fields'] );
|
54 |
-
$form = new Forms\Customer();
|
55 |
-
$form->bind( $params );
|
56 |
-
/** @var Lib\Entities\Customer $customer */
|
57 |
-
$customer = $form->save();
|
58 |
-
$response['success'] = true;
|
59 |
-
$response['customer'] = array(
|
60 |
-
'id' => $customer->getId(),
|
61 |
-
'wp_user_id' => $customer->getWpUserId(),
|
62 |
-
'group_id' => $customer->getGroupId(),
|
63 |
-
'full_name' => $customer->getFullName(),
|
64 |
-
'first_name' => $customer->getFirstName(),
|
65 |
-
'last_name' => $customer->getLastName(),
|
66 |
-
'phone' => $customer->getPhone(),
|
67 |
-
'email' => $customer->getEmail(),
|
68 |
-
'notes' => $customer->getNotes(),
|
69 |
-
'birthday' => $customer->getBirthday(),
|
70 |
-
'info_fields' => json_decode( $customer->getInfoFields() ),
|
71 |
-
);
|
72 |
-
} else {
|
73 |
-
$response['success'] = false;
|
74 |
-
$response['errors'] = $errors;
|
75 |
-
}
|
76 |
-
|
77 |
-
wp_send_json( $response );
|
78 |
-
}
|
79 |
-
|
80 |
-
/**
|
81 |
-
* Check if the current user has access to the action.
|
82 |
-
*
|
83 |
-
* @param string $action
|
84 |
-
* @return bool
|
85 |
-
*/
|
86 |
-
protected static function hasAccess( $action )
|
87 |
-
{
|
88 |
-
if ( parent::hasAccess( $action ) ) {
|
89 |
-
if ( ! Lib\Utils\Common::isCurrentUserAdmin() ) {
|
90 |
-
switch ( $action ) {
|
91 |
-
case 'saveCustomer':
|
92 |
-
return Lib\Entities\Staff::query()
|
93 |
-
->where( 'wp_user_id', get_current_user_id() )
|
94 |
-
->count() > 0;
|
95 |
-
}
|
96 |
-
} else {
|
97 |
-
return true;
|
98 |
-
}
|
99 |
-
}
|
100 |
-
|
101 |
-
return false;
|
102 |
-
}
|
103 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Edit;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Ajax
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Edit
|
9 |
+
*/
|
10 |
+
class Ajax extends Lib\Base\Ajax
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @inheritdoc
|
14 |
+
*/
|
15 |
+
protected static function permissions()
|
16 |
+
{
|
17 |
+
return array( '_default' => 'user' );
|
18 |
+
}
|
19 |
+
|
20 |
+
/**
|
21 |
+
* Create or edit a customer.
|
22 |
+
*/
|
23 |
+
public static function saveCustomer()
|
24 |
+
{
|
25 |
+
$response = array();
|
26 |
+
|
27 |
+
$params = self::postParameters();
|
28 |
+
$errors = array();
|
29 |
+
|
30 |
+
// Check for errors.
|
31 |
+
if ( get_option( 'bookly_cst_first_last_name' ) ) {
|
32 |
+
if ( $params['first_name'] == '' ) {
|
33 |
+
$errors['first_name'] = array( 'required' );
|
34 |
+
}
|
35 |
+
if ( $params['last_name'] == '' ) {
|
36 |
+
$errors['last_name'] = array( 'required' );
|
37 |
+
}
|
38 |
+
} else if ( $params['full_name'] == '' ) {
|
39 |
+
$errors['full_name'] = array( 'required' );
|
40 |
+
}
|
41 |
+
|
42 |
+
if ( empty ( $errors ) ) {
|
43 |
+
if ( ! $params['wp_user_id'] ) {
|
44 |
+
$params['wp_user_id'] = null;
|
45 |
+
}
|
46 |
+
if ( ! $params['birthday'] ) {
|
47 |
+
$params['birthday'] = null;
|
48 |
+
}
|
49 |
+
if ( ! $params['group_id'] ) {
|
50 |
+
$params['group_id'] = null;
|
51 |
+
}
|
52 |
+
$params = Proxy\CustomerInformation::prepareCustomerFormData( $params );
|
53 |
+
$params['info_fields'] = json_encode( $params['info_fields'] );
|
54 |
+
$form = new Forms\Customer();
|
55 |
+
$form->bind( $params );
|
56 |
+
/** @var Lib\Entities\Customer $customer */
|
57 |
+
$customer = $form->save();
|
58 |
+
$response['success'] = true;
|
59 |
+
$response['customer'] = array(
|
60 |
+
'id' => $customer->getId(),
|
61 |
+
'wp_user_id' => $customer->getWpUserId(),
|
62 |
+
'group_id' => $customer->getGroupId(),
|
63 |
+
'full_name' => $customer->getFullName(),
|
64 |
+
'first_name' => $customer->getFirstName(),
|
65 |
+
'last_name' => $customer->getLastName(),
|
66 |
+
'phone' => $customer->getPhone(),
|
67 |
+
'email' => $customer->getEmail(),
|
68 |
+
'notes' => $customer->getNotes(),
|
69 |
+
'birthday' => $customer->getBirthday(),
|
70 |
+
'info_fields' => json_decode( $customer->getInfoFields() ),
|
71 |
+
);
|
72 |
+
} else {
|
73 |
+
$response['success'] = false;
|
74 |
+
$response['errors'] = $errors;
|
75 |
+
}
|
76 |
+
|
77 |
+
wp_send_json( $response );
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Check if the current user has access to the action.
|
82 |
+
*
|
83 |
+
* @param string $action
|
84 |
+
* @return bool
|
85 |
+
*/
|
86 |
+
protected static function hasAccess( $action )
|
87 |
+
{
|
88 |
+
if ( parent::hasAccess( $action ) ) {
|
89 |
+
if ( ! Lib\Utils\Common::isCurrentUserAdmin() ) {
|
90 |
+
switch ( $action ) {
|
91 |
+
case 'saveCustomer':
|
92 |
+
return Lib\Entities\Staff::query()
|
93 |
+
->where( 'wp_user_id', get_current_user_id() )
|
94 |
+
->count() > 0;
|
95 |
+
}
|
96 |
+
} else {
|
97 |
+
return true;
|
98 |
+
}
|
99 |
+
}
|
100 |
+
|
101 |
+
return false;
|
102 |
+
}
|
103 |
}
|
backend/components/dialogs/customer/{Edit.php → edit/Dialog.php}
RENAMED
@@ -1,61 +1,63 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Customer;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Customer
|
9 |
-
*/
|
10 |
-
class
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render customer dialog.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
global $wp_locale;
|
18 |
-
|
19 |
-
|
20 |
-
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', ),
|
21 |
-
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
22 |
-
? array()
|
23 |
-
: array( 'css/intlTelInput.css' ),
|
24 |
-
) );
|
25 |
-
|
26 |
-
|
27 |
-
'backend' => array(
|
28 |
-
'js/angular.min.js' => array( 'jquery' ),
|
29 |
-
'js/
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
'
|
40 |
-
'
|
41 |
-
'
|
42 |
-
|
43 |
-
'
|
44 |
-
'
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
52 |
-
'
|
53 |
-
'
|
54 |
-
'
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
61 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Edit;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Dialog
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Edit
|
9 |
+
*/
|
10 |
+
class Dialog extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render customer dialog.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
global $wp_locale;
|
18 |
+
|
19 |
+
self::enqueueStyles( array(
|
20 |
+
'backend' => array( 'css/jquery-ui-theme/jquery-ui.min.css', 'css/select2.min.css', ),
|
21 |
+
'frontend' => get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
22 |
+
? array()
|
23 |
+
: array( 'css/intlTelInput.css' ),
|
24 |
+
) );
|
25 |
+
|
26 |
+
self::enqueueScripts( array(
|
27 |
+
'backend' => array(
|
28 |
+
'js/angular.min.js' => array( 'jquery' ),
|
29 |
+
'js/select2.full.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' ) ),
|
35 |
+
'module' => array( 'js/ng-customer.js' => array( 'bookly-angular.min.js' ), )
|
36 |
+
) );
|
37 |
+
|
38 |
+
wp_localize_script( 'bookly-ng-customer.js', 'BooklyL10nCustDialog', array(
|
39 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
40 |
+
'first_last_name' => (int) Lib\Config::showFirstLastName(),
|
41 |
+
'default_status' => get_option( 'bookly_gen_default_appointment_status' ),
|
42 |
+
'intlTelInput' => array(
|
43 |
+
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
44 |
+
'utils' => is_rtl() ? '' : plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
45 |
+
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
46 |
+
),
|
47 |
+
'dateOptions' => array(
|
48 |
+
'dateFormat' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_JQUERY_DATEPICKER ),
|
49 |
+
'monthNamesShort' => array_values( $wp_locale->month_abbrev ),
|
50 |
+
'monthNames' => array_values( $wp_locale->month ),
|
51 |
+
'dayNamesMin' => array_values( $wp_locale->weekday_abbrev ),
|
52 |
+
'longDays' => array_values( $wp_locale->weekday ),
|
53 |
+
'firstDay' => (int) get_option( 'start_of_week' ),
|
54 |
+
'yearRange' => sprintf( '%s:%s', date_create()->modify( '-100 years' )->format( 'Y' ), date( 'Y' ) ),
|
55 |
+
'changeYear' => true,
|
56 |
+
),
|
57 |
+
'infoFields' => (array) Lib\Proxy\CustomerInformation::getFieldsWhichMayHaveData(),
|
58 |
+
'noResultFound' => __( 'No result found', 'bookly' ),
|
59 |
+
) );
|
60 |
+
|
61 |
+
static::renderTemplate( 'edit' );
|
62 |
+
}
|
63 |
}
|
backend/components/dialogs/customer/{forms → edit/forms}/Customer.php
RENAMED
@@ -1,36 +1,36 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Customer\Forms;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Customer
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Customer\Forms
|
9 |
-
*/
|
10 |
-
class Customer extends Lib\Base\Form
|
11 |
-
{
|
12 |
-
protected static $entity_class = 'Customer';
|
13 |
-
|
14 |
-
public function configure()
|
15 |
-
{
|
16 |
-
$this->setFields( array(
|
17 |
-
'wp_user_id',
|
18 |
-
'group_id',
|
19 |
-
'full_name',
|
20 |
-
'first_name',
|
21 |
-
'last_name',
|
22 |
-
'phone',
|
23 |
-
'email',
|
24 |
-
'country',
|
25 |
-
'state',
|
26 |
-
'postcode',
|
27 |
-
'city',
|
28 |
-
'street',
|
29 |
-
'street_number',
|
30 |
-
'additional_address',
|
31 |
-
'notes',
|
32 |
-
'birthday',
|
33 |
-
'info_fields',
|
34 |
-
) );
|
35 |
-
}
|
36 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Edit\Forms;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Customer
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Forms
|
9 |
+
*/
|
10 |
+
class Customer extends Lib\Base\Form
|
11 |
+
{
|
12 |
+
protected static $entity_class = 'Customer';
|
13 |
+
|
14 |
+
public function configure()
|
15 |
+
{
|
16 |
+
$this->setFields( array(
|
17 |
+
'wp_user_id',
|
18 |
+
'group_id',
|
19 |
+
'full_name',
|
20 |
+
'first_name',
|
21 |
+
'last_name',
|
22 |
+
'phone',
|
23 |
+
'email',
|
24 |
+
'country',
|
25 |
+
'state',
|
26 |
+
'postcode',
|
27 |
+
'city',
|
28 |
+
'street',
|
29 |
+
'street_number',
|
30 |
+
'additional_address',
|
31 |
+
'notes',
|
32 |
+
'birthday',
|
33 |
+
'info_fields',
|
34 |
+
) );
|
35 |
+
}
|
36 |
+
}
|
backend/components/dialogs/customer/edit/proxy/CustomerGroups.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CustomerGroups
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCustomerDialog() Render 'Customer Group' row in edit customer dialog.
|
11 |
+
*/
|
12 |
+
abstract class CustomerGroups extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
+
}
|
backend/components/dialogs/customer/edit/proxy/CustomerInformation.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CustomerInformation
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCustomerDialog() Render 'Customer Information' row in edit customer dialog.
|
11 |
+
* @method static array prepareCustomerFormData( array $params ) Prepare customer info fields before saving customer form.
|
12 |
+
*/
|
13 |
+
abstract class CustomerInformation extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
+
}
|
backend/components/dialogs/customer/edit/proxy/Pro.php
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCustomerDialogAddress() Render address fields in edit customer dialog.
|
11 |
+
* @method static void renderCustomerDialogBirthday() Render birthday fields in edit customer dialog.
|
12 |
+
*/
|
13 |
+
abstract class Pro extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
+
}
|
backend/components/dialogs/customer/{resources → edit/resources}/js/ng-customer.js
RENAMED
@@ -1,197 +1,215 @@
|
|
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 |
-
group_id : '',
|
21 |
-
full_name : '',
|
22 |
-
first_name : '',
|
23 |
-
last_name : '',
|
24 |
-
phone : '',
|
25 |
-
email : '',
|
26 |
-
country : '',
|
27 |
-
state : '',
|
28 |
-
postcode : '',
|
29 |
-
city : '',
|
30 |
-
street : '',
|
31 |
-
street_number : '',
|
32 |
-
additional_address : '',
|
33 |
-
info_fields : [],
|
34 |
-
notes : '',
|
35 |
-
birthday : ''
|
36 |
-
};
|
37 |
-
BooklyL10nCustDialog.infoFields.forEach(function (field) {
|
38 |
-
scope.form.info_fields.push({id: field.id, value: field.type === 'checkboxes' ? [] : ''});
|
39 |
-
});
|
40 |
-
}
|
41 |
-
// Form errors.
|
42 |
-
scope.errors = {
|
43 |
-
name: {required: false}
|
44 |
-
};
|
45 |
-
scope.$watch('form', function(newValue, oldValue) {
|
46 |
-
if (newValue.name) {
|
47 |
-
scope.errors.name.required = false;
|
48 |
-
}
|
49 |
-
});
|
50 |
-
// Loading indicator.
|
51 |
-
scope.loading = false;
|
52 |
-
|
53 |
-
// Init intlTelInput.
|
54 |
-
if (BooklyL10nCustDialog.intlTelInput.enabled) {
|
55 |
-
element.find('#phone').intlTelInput({
|
56 |
-
preferredCountries: [BooklyL10nCustDialog.intlTelInput.country],
|
57 |
-
initialCountry: BooklyL10nCustDialog.intlTelInput.country,
|
58 |
-
geoIpLookup: function (callback) {
|
59 |
-
jQuery.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
60 |
-
var countryCode = (resp && resp.country) ? resp.country : '';
|
61 |
-
callback(countryCode);
|
62 |
-
});
|
63 |
-
},
|
64 |
-
utilsScript: BooklyL10nCustDialog.intlTelInput.utils
|
65 |
-
});
|
66 |
-
}
|
67 |
-
|
68 |
-
//
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
jQuery(
|
73 |
-
}
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
197 |
})();
|
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 |
+
group_id : '',
|
21 |
+
full_name : '',
|
22 |
+
first_name : '',
|
23 |
+
last_name : '',
|
24 |
+
phone : '',
|
25 |
+
email : '',
|
26 |
+
country : '',
|
27 |
+
state : '',
|
28 |
+
postcode : '',
|
29 |
+
city : '',
|
30 |
+
street : '',
|
31 |
+
street_number : '',
|
32 |
+
additional_address : '',
|
33 |
+
info_fields : [],
|
34 |
+
notes : '',
|
35 |
+
birthday : ''
|
36 |
+
};
|
37 |
+
BooklyL10nCustDialog.infoFields.forEach(function (field) {
|
38 |
+
scope.form.info_fields.push({id: field.id, value: field.type === 'checkboxes' ? [] : ''});
|
39 |
+
});
|
40 |
+
}
|
41 |
+
// Form errors.
|
42 |
+
scope.errors = {
|
43 |
+
name: {required: false}
|
44 |
+
};
|
45 |
+
scope.$watch('form', function(newValue, oldValue) {
|
46 |
+
if (newValue.name) {
|
47 |
+
scope.errors.name.required = false;
|
48 |
+
}
|
49 |
+
});
|
50 |
+
// Loading indicator.
|
51 |
+
scope.loading = false;
|
52 |
+
|
53 |
+
// Init intlTelInput.
|
54 |
+
if (BooklyL10nCustDialog.intlTelInput.enabled) {
|
55 |
+
element.find('#phone').intlTelInput({
|
56 |
+
preferredCountries: [BooklyL10nCustDialog.intlTelInput.country],
|
57 |
+
initialCountry: BooklyL10nCustDialog.intlTelInput.country,
|
58 |
+
geoIpLookup: function (callback) {
|
59 |
+
jQuery.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
60 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
61 |
+
callback(countryCode);
|
62 |
+
});
|
63 |
+
},
|
64 |
+
utilsScript: BooklyL10nCustDialog.intlTelInput.utils
|
65 |
+
});
|
66 |
+
}
|
67 |
+
|
68 |
+
// Init select2 for wp_users.
|
69 |
+
jQuery('#wp_user')
|
70 |
+
.on('select2:unselecting', function(e) {
|
71 |
+
e.preventDefault();
|
72 |
+
jQuery(this).val(null).trigger('change');
|
73 |
+
})
|
74 |
+
.select2({
|
75 |
+
width: '100%',
|
76 |
+
theme: 'bootstrap',
|
77 |
+
allowClear: true,
|
78 |
+
dropdownParent: jQuery('#bookly-customer-dialog'),
|
79 |
+
language: {
|
80 |
+
noResults: function () {
|
81 |
+
return BooklyL10nCustDialog.noResultFound;
|
82 |
+
}
|
83 |
+
}
|
84 |
+
});
|
85 |
+
|
86 |
+
// Do stuff on modal hide.
|
87 |
+
element.on('hidden.bs.modal', function () {
|
88 |
+
// Fix scroll issues when another modal is shown.
|
89 |
+
if (jQuery('.modal-backdrop').length) {
|
90 |
+
jQuery('body').addClass('modal-open');
|
91 |
+
}
|
92 |
+
});
|
93 |
+
scope.changeWpUser = function () {
|
94 |
+
var $user = jQuery('#wp_user option:selected'),
|
95 |
+
email = $user.attr('data-email') != undefined ? $user.attr('data-email') : '',
|
96 |
+
first_name = $user.attr('data-first-name') != undefined ? $user.attr('data-first-name') : '',
|
97 |
+
last_name = $user.attr('data-last-name') != undefined ? $user.attr('data-last-name') : '',
|
98 |
+
phone = $user.attr('data-phone') != undefined ? $user.attr('data-phone') : '',
|
99 |
+
display_name = $user.text().trim();
|
100 |
+
if (BooklyL10nCustDialog.first_last_name == 1) {
|
101 |
+
if (!first_name.length && !last_name.length) {
|
102 |
+
var name_parts = display_name.split(' ');
|
103 |
+
first_name = name_parts[0];
|
104 |
+
name_parts.splice(0, 1);
|
105 |
+
last_name = name_parts.join(' ');
|
106 |
+
}
|
107 |
+
if (first_name.length) {
|
108 |
+
scope.form.first_name = first_name;
|
109 |
+
}
|
110 |
+
if (last_name.length) {
|
111 |
+
scope.form.last_name = last_name;
|
112 |
+
}
|
113 |
+
} else {
|
114 |
+
if (first_name.length || last_name.length) {
|
115 |
+
scope.form.full_name = (first_name + ' ' + last_name).trim();
|
116 |
+
} else {
|
117 |
+
scope.form.full_name = display_name;
|
118 |
+
}
|
119 |
+
}
|
120 |
+
if (email.length) {
|
121 |
+
scope.form.email = email;
|
122 |
+
}
|
123 |
+
if (phone.length) {
|
124 |
+
scope.form.phone = phone;
|
125 |
+
}
|
126 |
+
};
|
127 |
+
/**
|
128 |
+
* Send form to server.
|
129 |
+
*/
|
130 |
+
scope.processForm = function() {
|
131 |
+
scope.errors = {};
|
132 |
+
scope.loading = true;
|
133 |
+
scope.form.phone = BooklyL10nCustDialog.intlTelInput.enabled
|
134 |
+
? element.find('#phone').intlTelInput('getNumber')
|
135 |
+
: element.find('#phone').val();
|
136 |
+
jQuery.ajax({
|
137 |
+
url : ajaxurl,
|
138 |
+
type : 'POST',
|
139 |
+
data : jQuery.extend({ action : 'bookly_save_customer', csrf_token : BooklyL10nCustDialog.csrf_token }, scope.form),
|
140 |
+
dataType : 'json',
|
141 |
+
success : function ( response ) {
|
142 |
+
scope.$apply(function(scope) {
|
143 |
+
if (response.success) {
|
144 |
+
response.customer.custom_fields = [];
|
145 |
+
response.customer.extras = [];
|
146 |
+
response.customer.status = BooklyL10nCustDialog.default_status;
|
147 |
+
// Send new customer to the parent scope.
|
148 |
+
scope.callback({customer : response.customer});
|
149 |
+
scope.form = {
|
150 |
+
id : '',
|
151 |
+
wp_user_id : '',
|
152 |
+
group_id : '',
|
153 |
+
full_name : '',
|
154 |
+
first_name : '',
|
155 |
+
last_name : '',
|
156 |
+
phone : '',
|
157 |
+
email : '',
|
158 |
+
country : '',
|
159 |
+
state : '',
|
160 |
+
postcode : '',
|
161 |
+
city : '',
|
162 |
+
street : '',
|
163 |
+
street_number : '',
|
164 |
+
additional_address : '',
|
165 |
+
info_fields : [],
|
166 |
+
notes : '',
|
167 |
+
birthday : ''
|
168 |
+
};
|
169 |
+
// Close the dialog.
|
170 |
+
element.modal('hide');
|
171 |
+
} else {
|
172 |
+
// Set errors.
|
173 |
+
jQuery.each(response.errors, function(field, errors) {
|
174 |
+
scope.errors[field] = {};
|
175 |
+
jQuery.each(errors, function(key, error) {
|
176 |
+
scope.errors[field][error] = true;
|
177 |
+
});
|
178 |
+
});
|
179 |
+
}
|
180 |
+
scope.loading = false;
|
181 |
+
});
|
182 |
+
},
|
183 |
+
error : function() {
|
184 |
+
scope.$apply(function(scope) {
|
185 |
+
scope.loading = false;
|
186 |
+
});
|
187 |
+
}
|
188 |
+
});
|
189 |
+
};
|
190 |
+
|
191 |
+
/**
|
192 |
+
* Datepicker options.
|
193 |
+
*/
|
194 |
+
scope.dateOptions = BooklyL10nCustDialog.dateOptions;
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Toggle checkbox info field.
|
198 |
+
*/
|
199 |
+
scope.toggleCheckbox = function (i, value) {
|
200 |
+
var idx = scope.form.info_fields[i].value.indexOf(value);
|
201 |
+
|
202 |
+
// Is currently selected.
|
203 |
+
if (idx > -1) {
|
204 |
+
scope.form.info_fields[i].value.splice(idx, 1);
|
205 |
+
}
|
206 |
+
// Is newly selected.
|
207 |
+
else {
|
208 |
+
scope.form.info_fields[i].value.push(value);
|
209 |
+
}
|
210 |
+
};
|
211 |
+
}
|
212 |
+
};
|
213 |
+
});
|
214 |
+
|
215 |
})();
|
backend/components/dialogs/customer/{templates → edit/templates}/edit.php
RENAMED
@@ -1,84 +1,83 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
use Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
4 |
-
use Bookly\Lib\Config;
|
5 |
-
?>
|
6 |
-
<script type="text/ng-template" id="bookly-customer-dialog.tpl">
|
7 |
-
<div id="bookly-customer-dialog" class="modal fade" tabindex=-1 role="dialog">
|
8 |
-
<div class="modal-dialog">
|
9 |
-
<div class="modal-content">
|
10 |
-
<div class="modal-header">
|
11 |
-
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
12 |
-
<div class="modal-title h2"><?php esc_html_e( 'New Customer', 'bookly' ) ?></div>
|
13 |
-
</div>
|
14 |
-
<div ng-show=loading class="modal-body">
|
15 |
-
<div class="bookly-loading"></div>
|
16 |
-
</div>
|
17 |
-
<div class="modal-body" ng-hide="loading">
|
18 |
-
<div class="form-group">
|
19 |
-
<label for="wp_user"><?php esc_html_e( 'User', 'bookly' ) ?></label>
|
20 |
-
<select ng-model="form.wp_user_id" class="form-control" id="wp_user" ng-change="changeWpUser()">
|
21 |
-
|
22 |
-
|
23 |
-
<?php $user_data =
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
<
|
36 |
-
<
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
<
|
41 |
-
<
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
<
|
49 |
-
<
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
<
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
<
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
<?php Proxy\Pro::
|
65 |
-
<?php Proxy\
|
66 |
-
<?php Proxy\
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
<
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
<?php Buttons::renderCustom( null, 'btn-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
</div>
|
84 |
</script>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
use Bookly\Backend\Components\Dialogs\Customer\Edit\Proxy;
|
4 |
+
use Bookly\Lib\Config;
|
5 |
+
?>
|
6 |
+
<script type="text/ng-template" id="bookly-customer-dialog.tpl">
|
7 |
+
<div id="bookly-customer-dialog" class="modal fade" tabindex=-1 role="dialog">
|
8 |
+
<div class="modal-dialog">
|
9 |
+
<div class="modal-content">
|
10 |
+
<div class="modal-header">
|
11 |
+
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
12 |
+
<div class="modal-title h2"><?php esc_html_e( 'New Customer', 'bookly' ) ?></div>
|
13 |
+
</div>
|
14 |
+
<div ng-show=loading class="modal-body">
|
15 |
+
<div class="bookly-loading"></div>
|
16 |
+
</div>
|
17 |
+
<div class="modal-body" ng-hide="loading">
|
18 |
+
<div class="form-group">
|
19 |
+
<label for="wp_user"><?php esc_html_e( 'User', 'bookly' ) ?></label>
|
20 |
+
<select ng-model="form.wp_user_id" class="form-control" id="wp_user" ng-change="changeWpUser()">
|
21 |
+
<?php foreach ( get_users( array( 'fields' => array( 'ID', 'display_name', 'user_email' ), 'orderby' => 'display_name' ) ) as $wp_user ) : ?>
|
22 |
+
<?php $user_data = get_userdata( $wp_user->ID ) ?>
|
23 |
+
<option value="<?php echo $wp_user->ID ?>" data-email="<?php echo esc_html( $wp_user->user_email ) ?>" data-first-name="<?php echo esc_html( $user_data->first_name ) ?>" data-last-name="<?php echo esc_html( $user_data->last_name ) ?>" data-phone="<?php echo esc_html( get_user_meta( $wp_user->ID, 'billing_phone', true ) ) ?>">
|
24 |
+
<?php echo $wp_user->display_name ?>
|
25 |
+
</option>
|
26 |
+
<?php endforeach ?>
|
27 |
+
</select>
|
28 |
+
</div>
|
29 |
+
|
30 |
+
<?php if ( Config::showFirstLastName() ) : ?>
|
31 |
+
<div class="form-group">
|
32 |
+
<div class="row">
|
33 |
+
<div class="col-sm-6">
|
34 |
+
<label for="first_name"><?php esc_html_e( 'First name', 'bookly' ) ?></label>
|
35 |
+
<input class="form-control" type="text" ng-model="form.first_name" id="first_name" />
|
36 |
+
<span style="font-size: 11px;color: red" ng-show="errors.first_name.required"><?php esc_html_e( 'Required', 'bookly' ) ?></span>
|
37 |
+
</div>
|
38 |
+
<div class="col-sm-6">
|
39 |
+
<label for="last_name"><?php esc_html_e( 'Last name', 'bookly' ) ?></label>
|
40 |
+
<input class="form-control" type="text" ng-model="form.last_name" id="last_name" />
|
41 |
+
<span style="font-size: 11px;color: red" ng-show="errors.last_name.required"><?php esc_html_e( 'Required', 'bookly' ) ?></span>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
</div>
|
45 |
+
<?php else : ?>
|
46 |
+
<div class="form-group">
|
47 |
+
<label for="full_name"><?php esc_html_e( 'Name', 'bookly' ) ?></label>
|
48 |
+
<input class="form-control" type="text" ng-model="form.full_name" id="full_name" />
|
49 |
+
<span style="font-size: 11px;color: red" ng-show="errors.full_name.required"><?php esc_html_e( 'Required', 'bookly' ) ?></span>
|
50 |
+
</div>
|
51 |
+
<?php endif ?>
|
52 |
+
|
53 |
+
<div class="form-group">
|
54 |
+
<label for="phone"><?php esc_html_e( 'Phone', 'bookly' ) ?></label>
|
55 |
+
<input class="form-control" type="text" ng-model=form.phone id="phone" />
|
56 |
+
</div>
|
57 |
+
|
58 |
+
<div class="form-group">
|
59 |
+
<label for="email"><?php esc_html_e( 'Email', 'bookly' ) ?></label>
|
60 |
+
<input class="form-control" type="text" ng-model=form.email id="email" />
|
61 |
+
</div>
|
62 |
+
|
63 |
+
<?php Proxy\Pro::renderCustomerDialogBirthday() ?>
|
64 |
+
<?php Proxy\Pro::renderCustomerDialogAddress() ?>
|
65 |
+
<?php Proxy\CustomerInformation::renderCustomerDialog() ?>
|
66 |
+
<?php Proxy\CustomerGroups::renderCustomerDialog() ?>
|
67 |
+
|
68 |
+
<div class="form-group">
|
69 |
+
<label for="notes"><?php esc_html_e( 'Notes', 'bookly' ) ?></label>
|
70 |
+
<textarea class="form-control" ng-model=form.notes id="notes"></textarea>
|
71 |
+
</div>
|
72 |
+
|
73 |
+
</div>
|
74 |
+
<div class="modal-footer">
|
75 |
+
<div ng-hide=loading>
|
76 |
+
<?php Buttons::renderCustom( null, 'btn-success btn-lg', null, array( 'ng-click' => 'processForm()' ) ) ?>
|
77 |
+
<?php Buttons::renderCustom( null, 'btn-default btn-lg', esc_html__( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
78 |
+
</div>
|
79 |
+
</div>
|
80 |
+
</div>
|
81 |
+
</div>
|
82 |
+
</div>
|
|
|
83 |
</script>
|
backend/components/dialogs/customer/proxy/CustomerGroups.php
CHANGED
@@ -1,16 +1,14 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
*
|
8 |
-
* @
|
9 |
-
*
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* @since Bookly 16.2
|
8 |
+
* @deprecated
|
9 |
+
* Proxy file was moved
|
10 |
+
*/
|
11 |
+
abstract class CustomerGroups extends Lib\Base\Proxy
|
12 |
+
{
|
13 |
+
|
|
|
|
|
14 |
}
|
backend/components/dialogs/customer/proxy/CustomerInformation.php
CHANGED
@@ -1,16 +1,14 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
*
|
8 |
-
* @
|
9 |
-
*
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* @since Bookly 16.2
|
8 |
+
* @deprecated
|
9 |
+
* Proxy file was moved
|
10 |
+
*/
|
11 |
+
abstract class CustomerInformation extends Lib\Base\Proxy
|
12 |
+
{
|
13 |
+
|
|
|
|
|
14 |
}
|
backend/components/dialogs/customer/proxy/Pro.php
CHANGED
@@ -1,16 +1,14 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
*
|
8 |
-
* @
|
9 |
-
*
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Customer\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* @since Bookly 16.2
|
8 |
+
* @deprecated
|
9 |
+
* Proxy file was moved
|
10 |
+
*/
|
11 |
+
abstract class Pro extends Lib\Base\Proxy
|
12 |
+
{
|
13 |
+
|
|
|
|
|
14 |
}
|
backend/components/dialogs/payment/Ajax.php
CHANGED
@@ -1,105 +1,105 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Payment;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Ajax
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Payment
|
9 |
-
*/
|
10 |
-
class Ajax extends Lib\Base\Ajax
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* @inheritdoc
|
14 |
-
*/
|
15 |
-
protected static function permissions()
|
16 |
-
{
|
17 |
-
return array(
|
18 |
-
'completePayment' => 'user',
|
19 |
-
'getPaymentDetails' => 'user',
|
20 |
-
'getPaymentInfo' => 'user',
|
21 |
-
);
|
22 |
-
}
|
23 |
-
|
24 |
-
/**
|
25 |
-
* Get payment details.
|
26 |
-
*/
|
27 |
-
public static function getPaymentDetails()
|
28 |
-
{
|
29 |
-
$payment = Lib\Entities\Payment::find( self::parameter( 'payment_id' ) );
|
30 |
-
if ( $payment ) {
|
31 |
-
$data = $payment->getPaymentData();
|
32 |
-
$show_deposit = Lib\Config::depositPaymentsActive();
|
33 |
-
if ( ! $show_deposit ) {
|
34 |
-
foreach ( $data['payment']['items'] as $item ) {
|
35 |
-
if ( isset( $item['deposit_format'] ) ) {
|
36 |
-
$show_deposit = true;
|
37 |
-
break;
|
38 |
-
}
|
39 |
-
}
|
40 |
-
}
|
41 |
-
|
42 |
-
$data['show'] = array(
|
43 |
-
'coupons' => Lib\Config::couponsActive(),
|
44 |
-
'customer_groups' => Lib\Config::customerGroupsActive(),
|
45 |
-
'deposit' => (int) $show_deposit,
|
46 |
-
'gateway' => \Bookly\Backend\Modules\Payments\Proxy\Shared::paymentSpecificPriceExists( $data['payment']['type'] ) === true,
|
47 |
-
'taxes' => (int) ( Lib\Config::taxesActive() || $data['payment']['tax_total'] > 0 ),
|
48 |
-
);
|
49 |
-
wp_send_json_success( array( 'html' => self::renderTemplate( 'details', $data, false ) ) );
|
50 |
-
}
|
51 |
-
|
52 |
-
wp_send_json_error( array( 'html' => __( 'Payment is not found.', 'bookly' ) ) );
|
53 |
-
}
|
54 |
-
|
55 |
-
/**
|
56 |
-
* Complete payment.
|
57 |
-
*/
|
58 |
-
public static function completePayment()
|
59 |
-
{
|
60 |
-
$payment = Lib\Entities\Payment::find( self::parameter( 'payment_id' ) );
|
61 |
-
$details = json_decode( $payment->getDetails(), true );
|
62 |
-
$details['tax_paid'] = $payment->getTax();
|
63 |
-
$payment
|
64 |
-
->setPaid( $payment->getTotal() )
|
65 |
-
->setStatus( Lib\Entities\Payment::STATUS_COMPLETED )
|
66 |
-
->setDetails( json_encode( $details ) )
|
67 |
-
->save();
|
68 |
-
|
69 |
-
$payment_title = Lib\Utils\Price::format( $payment->getPaid() );
|
70 |
-
if ( $payment->getPaid() != $payment->getTotal() ) {
|
71 |
-
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $payment->getTotal() ) );
|
72 |
-
}
|
73 |
-
$payment_title .= sprintf(
|
74 |
-
' %s <span%s>%s</span>',
|
75 |
-
Lib\Entities\Payment::typeToString( $payment->getType() ),
|
76 |
-
$payment->getStatus() == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
77 |
-
Lib\Entities\Payment::statusToString( $payment->getStatus() )
|
78 |
-
);
|
79 |
-
|
80 |
-
wp_send_json_success( array( 'payment_title' => $payment_title ) );
|
81 |
-
}
|
82 |
-
|
83 |
-
/**
|
84 |
-
* Get payment info
|
85 |
-
*/
|
86 |
-
public static function getPaymentInfo()
|
87 |
-
{
|
88 |
-
$payment = Lib\Entities\Payment::find( self::parameter( 'payment_id' ) );
|
89 |
-
|
90 |
-
if ( $payment ) {
|
91 |
-
$payment_title = Lib\Utils\Price::format( $payment->getPaid() );
|
92 |
-
if ( $payment->getPaid() != $payment->getTotal() ) {
|
93 |
-
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $payment->getTotal() ) );
|
94 |
-
}
|
95 |
-
$payment_title .= sprintf(
|
96 |
-
' %s <span%s>%s</span>',
|
97 |
-
Lib\Entities\Payment::typeToString( $payment->getType() ),
|
98 |
-
$payment->getStatus() == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
99 |
-
Lib\Entities\Payment::statusToString( $payment->getStatus() )
|
100 |
-
);
|
101 |
-
|
102 |
-
wp_send_json_success( array( 'payment_title' => $payment_title, 'payment_type' => $payment->getPaid() == $payment->getTotal() ? 'full' : 'partial' ) );
|
103 |
-
}
|
104 |
-
}
|
105 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Payment;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Ajax
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Payment
|
9 |
+
*/
|
10 |
+
class Ajax extends Lib\Base\Ajax
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* @inheritdoc
|
14 |
+
*/
|
15 |
+
protected static function permissions()
|
16 |
+
{
|
17 |
+
return array(
|
18 |
+
'completePayment' => 'user',
|
19 |
+
'getPaymentDetails' => 'user',
|
20 |
+
'getPaymentInfo' => 'user',
|
21 |
+
);
|
22 |
+
}
|
23 |
+
|
24 |
+
/**
|
25 |
+
* Get payment details.
|
26 |
+
*/
|
27 |
+
public static function getPaymentDetails()
|
28 |
+
{
|
29 |
+
$payment = Lib\Entities\Payment::find( self::parameter( 'payment_id' ) );
|
30 |
+
if ( $payment ) {
|
31 |
+
$data = $payment->getPaymentData();
|
32 |
+
$show_deposit = Lib\Config::depositPaymentsActive();
|
33 |
+
if ( ! $show_deposit ) {
|
34 |
+
foreach ( $data['payment']['items'] as $item ) {
|
35 |
+
if ( isset( $item['deposit_format'] ) ) {
|
36 |
+
$show_deposit = true;
|
37 |
+
break;
|
38 |
+
}
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
$data['show'] = array(
|
43 |
+
'coupons' => Lib\Config::couponsActive(),
|
44 |
+
'customer_groups' => Lib\Config::customerGroupsActive(),
|
45 |
+
'deposit' => (int) $show_deposit,
|
46 |
+
'gateway' => \Bookly\Backend\Modules\Payments\Proxy\Shared::paymentSpecificPriceExists( $data['payment']['type'] ) === true,
|
47 |
+
'taxes' => (int) ( Lib\Config::taxesActive() || $data['payment']['tax_total'] > 0 ),
|
48 |
+
);
|
49 |
+
wp_send_json_success( array( 'html' => self::renderTemplate( 'details', $data, false ) ) );
|
50 |
+
}
|
51 |
+
|
52 |
+
wp_send_json_error( array( 'html' => __( 'Payment is not found.', 'bookly' ) ) );
|
53 |
+
}
|
54 |
+
|
55 |
+
/**
|
56 |
+
* Complete payment.
|
57 |
+
*/
|
58 |
+
public static function completePayment()
|
59 |
+
{
|
60 |
+
$payment = Lib\Entities\Payment::find( self::parameter( 'payment_id' ) );
|
61 |
+
$details = json_decode( $payment->getDetails(), true );
|
62 |
+
$details['tax_paid'] = $payment->getTax();
|
63 |
+
$payment
|
64 |
+
->setPaid( $payment->getTotal() )
|
65 |
+
->setStatus( Lib\Entities\Payment::STATUS_COMPLETED )
|
66 |
+
->setDetails( json_encode( $details ) )
|
67 |
+
->save();
|
68 |
+
|
69 |
+
$payment_title = Lib\Utils\Price::format( $payment->getPaid() );
|
70 |
+
if ( $payment->getPaid() != $payment->getTotal() ) {
|
71 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $payment->getTotal() ) );
|
72 |
+
}
|
73 |
+
$payment_title .= sprintf(
|
74 |
+
' %s <span%s>%s</span>',
|
75 |
+
Lib\Entities\Payment::typeToString( $payment->getType() ),
|
76 |
+
$payment->getStatus() == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
77 |
+
Lib\Entities\Payment::statusToString( $payment->getStatus() )
|
78 |
+
);
|
79 |
+
|
80 |
+
wp_send_json_success( array( 'payment_title' => $payment_title ) );
|
81 |
+
}
|
82 |
+
|
83 |
+
/**
|
84 |
+
* Get payment info
|
85 |
+
*/
|
86 |
+
public static function getPaymentInfo()
|
87 |
+
{
|
88 |
+
$payment = Lib\Entities\Payment::find( self::parameter( 'payment_id' ) );
|
89 |
+
|
90 |
+
if ( $payment ) {
|
91 |
+
$payment_title = Lib\Utils\Price::format( $payment->getPaid() );
|
92 |
+
if ( $payment->getPaid() != $payment->getTotal() ) {
|
93 |
+
$payment_title = sprintf( __( '%s of %s', 'bookly' ), $payment_title, Lib\Utils\Price::format( $payment->getTotal() ) );
|
94 |
+
}
|
95 |
+
$payment_title .= sprintf(
|
96 |
+
' %s <span%s>%s</span>',
|
97 |
+
Lib\Entities\Payment::typeToString( $payment->getType() ),
|
98 |
+
$payment->getStatus() == Lib\Entities\Payment::STATUS_PENDING ? ' class="text-danger"' : '',
|
99 |
+
Lib\Entities\Payment::statusToString( $payment->getStatus() )
|
100 |
+
);
|
101 |
+
|
102 |
+
wp_send_json_success( array( 'payment_title' => $payment_title, 'payment_type' => $payment->getPaid() == $payment->getTotal() ? 'full' : 'partial' ) );
|
103 |
+
}
|
104 |
+
}
|
105 |
}
|
backend/components/dialogs/payment/Dialog.php
CHANGED
@@ -1,32 +1,32 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\Payment;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Details
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\Payment
|
9 |
-
*/
|
10 |
-
class Dialog extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render payment details dialog.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
self::enqueueStyles( array(
|
18 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
-
) );
|
20 |
-
|
21 |
-
self::enqueueScripts( array(
|
22 |
-
'backend' => array( 'js/angular.min.js' => array( 'jquery' ), ),
|
23 |
-
'frontend' => array(
|
24 |
-
'js/spin.min.js' => array( 'jquery' ),
|
25 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
26 |
-
),
|
27 |
-
'module' => array( 'js/ng-payment_details.js' => array( 'bookly-angular.min.js' ), ),
|
28 |
-
) );
|
29 |
-
|
30 |
-
self::renderTemplate( 'dialog' );
|
31 |
-
}
|
32 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\Payment;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Details
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\Payment
|
9 |
+
*/
|
10 |
+
class Dialog extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render payment details dialog.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
self::enqueueStyles( array(
|
18 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
19 |
+
) );
|
20 |
+
|
21 |
+
self::enqueueScripts( array(
|
22 |
+
'backend' => array( 'js/angular.min.js' => array( 'jquery' ), ),
|
23 |
+
'frontend' => array(
|
24 |
+
'js/spin.min.js' => array( 'jquery' ),
|
25 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
26 |
+
),
|
27 |
+
'module' => array( 'js/ng-payment_details.js' => array( 'bookly-angular.min.js' ), ),
|
28 |
+
) );
|
29 |
+
|
30 |
+
self::renderTemplate( 'dialog' );
|
31 |
+
}
|
32 |
}
|
backend/components/dialogs/payment/resources/js/ng-payment_details.js
CHANGED
@@ -1,151 +1,151 @@
|
|
1 |
-
;(function() {
|
2 |
-
|
3 |
-
angular.module('paymentDetailsDialog', []).directive('paymentDetailsDialog', function() {
|
4 |
-
return {
|
5 |
-
restrict: 'A',
|
6 |
-
replace: true,
|
7 |
-
scope: {
|
8 |
-
callback: '&paymentDetailsDialog'
|
9 |
-
},
|
10 |
-
templateUrl: 'bookly-payment-details-dialog.tpl',
|
11 |
-
// The linking function will add behavior to the template.
|
12 |
-
link: function (scope, element, attrs) {
|
13 |
-
var $body = element.find('.modal-body'),
|
14 |
-
spinner = $body.html();
|
15 |
-
|
16 |
-
element
|
17 |
-
.on('show.bs.modal refresh', function (e, payment_id) {
|
18 |
-
if (payment_id === undefined) {
|
19 |
-
if (e.relatedTarget) {
|
20 |
-
payment_id = e.relatedTarget.getAttribute('data-payment_id');
|
21 |
-
var payment_bind = e.relatedTarget.getAttribute('data-payment_bind'),
|
22 |
-
customer_id = e.relatedTarget.getAttribute('data-customer_id');
|
23 |
-
} else if (element.data('payment_id')) {
|
24 |
-
payment_id = element.data('payment_id');
|
25 |
-
var payment_bind = element.data('payment_bind'),
|
26 |
-
customer_id = element.data('customer_id');
|
27 |
-
}
|
28 |
-
}
|
29 |
-
jQuery.ajax({
|
30 |
-
url: ajaxurl,
|
31 |
-
data: {action: 'bookly_get_payment_details', payment_id: payment_id, csrf_token : BooklyL10n.csrf_token},
|
32 |
-
dataType: 'json',
|
33 |
-
success: function (response) {
|
34 |
-
if (response.success) {
|
35 |
-
$body.html(response.data.html);
|
36 |
-
if (payment_bind) {
|
37 |
-
jQuery('.bookly-js-details-main-controls').hide();
|
38 |
-
jQuery('.bookly-js-details-bind-controls').show();
|
39 |
-
}
|
40 |
-
$body.find('#bookly-complete-payment').on('click',function () {
|
41 |
-
var ladda = Ladda.create(this);
|
42 |
-
ladda.start();
|
43 |
-
jQuery.ajax({
|
44 |
-
url: ajaxurl,
|
45 |
-
data: {action: 'bookly_complete_payment', payment_id: payment_id, csrf_token : BooklyL10n.csrf_token},
|
46 |
-
dataType: 'json',
|
47 |
-
type: 'POST',
|
48 |
-
success: function (response) {
|
49 |
-
if (response.success) {
|
50 |
-
element.trigger('refresh', [payment_id]);
|
51 |
-
if (scope.callback) {
|
52 |
-
scope.$apply(function ($scope) {
|
53 |
-
$scope.callback({
|
54 |
-
payment_action: 'complete',
|
55 |
-
payment_id : payment_id,
|
56 |
-
payment_title : response.data.payment_title
|
57 |
-
});
|
58 |
-
});
|
59 |
-
}
|
60 |
-
// Reload DataTable.
|
61 |
-
var $table = jQuery('table#bookly-payments-list.dataTable');
|
62 |
-
if ($table.length) {
|
63 |
-
$table.DataTable().ajax.reload();
|
64 |
-
}
|
65 |
-
}
|
66 |
-
}
|
67 |
-
});
|
68 |
-
});
|
69 |
-
jQuery('#bookly-js-attach-payment', $body).on('click', function () {
|
70 |
-
var ladda = Ladda.create(this);
|
71 |
-
ladda.start();
|
72 |
-
|
73 |
-
jQuery.ajax({
|
74 |
-
url : ajaxurl,
|
75 |
-
data : {action: 'bookly_get_payment_info', payment_id: payment_id, csrf_token: BooklyL10n.csrf_token},
|
76 |
-
dataType: 'json',
|
77 |
-
type : 'POST',
|
78 |
-
success : function (response) {
|
79 |
-
if (response.success) {
|
80 |
-
if (scope.callback) {
|
81 |
-
scope.$apply(function ($scope) {
|
82 |
-
$scope.callback({
|
83 |
-
payment_action: 'bind',
|
84 |
-
payment_id : payment_id,
|
85 |
-
payment_title : response.data.payment_title,
|
86 |
-
payment_type : response.data.payment_type,
|
87 |
-
customer_id : customer_id
|
88 |
-
});
|
89 |
-
});
|
90 |
-
}
|
91 |
-
}
|
92 |
-
}
|
93 |
-
});
|
94 |
-
jQuery(element).modal('hide');
|
95 |
-
});
|
96 |
-
var $adjust_button = jQuery('#bookly-js-adjustment-button', $body),
|
97 |
-
$adjust_field = jQuery('#bookly-js-adjustment-field', $body),
|
98 |
-
$adjust_reason = jQuery('#bookly-js-adjustment-reason', $body),
|
99 |
-
$adjust_amount = jQuery('#bookly-js-adjustment-amount', $body),
|
100 |
-
$adjust_tax = jQuery('#bookly-js-adjustment-tax', $body),
|
101 |
-
$adjust_apply = jQuery('#bookly-js-adjustment-apply', $body),
|
102 |
-
$adjust_cancel = jQuery('#bookly-js-adjustment-cancel', $body);
|
103 |
-
$adjust_button.on('click', function () {
|
104 |
-
$adjust_field.show();
|
105 |
-
$adjust_reason.focus();
|
106 |
-
});
|
107 |
-
$adjust_cancel.on('click', function () {
|
108 |
-
$adjust_field.hide();
|
109 |
-
});
|
110 |
-
$adjust_apply.on('click', function () {
|
111 |
-
$body.html('<div class="bookly-loading"></div>');
|
112 |
-
jQuery.ajax({
|
113 |
-
url : ajaxurl,
|
114 |
-
data : {
|
115 |
-
action : 'bookly_pro_add_payment_adjustment',
|
116 |
-
payment_id: payment_id,
|
117 |
-
reason: $adjust_reason.val(),
|
118 |
-
amount: $adjust_amount.val(),
|
119 |
-
tax : $adjust_tax.val() || 0,
|
120 |
-
csrf_token: BooklyL10n.csrf_token
|
121 |
-
},
|
122 |
-
dataType: 'json',
|
123 |
-
type : 'POST',
|
124 |
-
success : function (response) {
|
125 |
-
if (response.success) {
|
126 |
-
element.trigger('refresh', [payment_id]);
|
127 |
-
// Reload DataTable.
|
128 |
-
var $table = jQuery('table#bookly-payments-list.dataTable');
|
129 |
-
if ($table.length) {
|
130 |
-
$table.DataTable().ajax.reload();
|
131 |
-
}
|
132 |
-
}
|
133 |
-
}
|
134 |
-
});
|
135 |
-
});
|
136 |
-
} else {
|
137 |
-
$body.html(response.data.html);
|
138 |
-
}
|
139 |
-
}
|
140 |
-
});
|
141 |
-
})
|
142 |
-
.on('hidden.bs.modal', function () {
|
143 |
-
$body.html(spinner);
|
144 |
-
if ((jQuery("#bookly-appointment-dialog").data('bs.modal') || {isShown: false}).isShown) {
|
145 |
-
jQuery('body').addClass('modal-open');
|
146 |
-
}
|
147 |
-
});
|
148 |
-
}
|
149 |
-
}
|
150 |
-
});
|
151 |
})();
|
1 |
+
;(function() {
|
2 |
+
|
3 |
+
angular.module('paymentDetailsDialog', []).directive('paymentDetailsDialog', function() {
|
4 |
+
return {
|
5 |
+
restrict: 'A',
|
6 |
+
replace: true,
|
7 |
+
scope: {
|
8 |
+
callback: '&paymentDetailsDialog'
|
9 |
+
},
|
10 |
+
templateUrl: 'bookly-payment-details-dialog.tpl',
|
11 |
+
// The linking function will add behavior to the template.
|
12 |
+
link: function (scope, element, attrs) {
|
13 |
+
var $body = element.find('.modal-body'),
|
14 |
+
spinner = $body.html();
|
15 |
+
|
16 |
+
element
|
17 |
+
.on('show.bs.modal refresh', function (e, payment_id) {
|
18 |
+
if (payment_id === undefined) {
|
19 |
+
if (e.relatedTarget) {
|
20 |
+
payment_id = e.relatedTarget.getAttribute('data-payment_id');
|
21 |
+
var payment_bind = e.relatedTarget.getAttribute('data-payment_bind'),
|
22 |
+
customer_id = e.relatedTarget.getAttribute('data-customer_id');
|
23 |
+
} else if (element.data('payment_id')) {
|
24 |
+
payment_id = element.data('payment_id');
|
25 |
+
var payment_bind = element.data('payment_bind'),
|
26 |
+
customer_id = element.data('customer_id');
|
27 |
+
}
|
28 |
+
}
|
29 |
+
jQuery.ajax({
|
30 |
+
url: ajaxurl,
|
31 |
+
data: {action: 'bookly_get_payment_details', payment_id: payment_id, csrf_token : BooklyL10n.csrf_token},
|
32 |
+
dataType: 'json',
|
33 |
+
success: function (response) {
|
34 |
+
if (response.success) {
|
35 |
+
$body.html(response.data.html);
|
36 |
+
if (payment_bind) {
|
37 |
+
jQuery('.bookly-js-details-main-controls').hide();
|
38 |
+
jQuery('.bookly-js-details-bind-controls').show();
|
39 |
+
}
|
40 |
+
$body.find('#bookly-complete-payment').on('click',function () {
|
41 |
+
var ladda = Ladda.create(this);
|
42 |
+
ladda.start();
|
43 |
+
jQuery.ajax({
|
44 |
+
url: ajaxurl,
|
45 |
+
data: {action: 'bookly_complete_payment', payment_id: payment_id, csrf_token : BooklyL10n.csrf_token},
|
46 |
+
dataType: 'json',
|
47 |
+
type: 'POST',
|
48 |
+
success: function (response) {
|
49 |
+
if (response.success) {
|
50 |
+
element.trigger('refresh', [payment_id]);
|
51 |
+
if (scope.callback) {
|
52 |
+
scope.$apply(function ($scope) {
|
53 |
+
$scope.callback({
|
54 |
+
payment_action: 'complete',
|
55 |
+
payment_id : payment_id,
|
56 |
+
payment_title : response.data.payment_title
|
57 |
+
});
|
58 |
+
});
|
59 |
+
}
|
60 |
+
// Reload DataTable.
|
61 |
+
var $table = jQuery('table#bookly-payments-list.dataTable');
|
62 |
+
if ($table.length) {
|
63 |
+
$table.DataTable().ajax.reload();
|
64 |
+
}
|
65 |
+
}
|
66 |
+
}
|
67 |
+
});
|
68 |
+
});
|
69 |
+
jQuery('#bookly-js-attach-payment', $body).on('click', function () {
|
70 |
+
var ladda = Ladda.create(this);
|
71 |
+
ladda.start();
|
72 |
+
|
73 |
+
jQuery.ajax({
|
74 |
+
url : ajaxurl,
|
75 |
+
data : {action: 'bookly_get_payment_info', payment_id: payment_id, csrf_token: BooklyL10n.csrf_token},
|
76 |
+
dataType: 'json',
|
77 |
+
type : 'POST',
|
78 |
+
success : function (response) {
|
79 |
+
if (response.success) {
|
80 |
+
if (scope.callback) {
|
81 |
+
scope.$apply(function ($scope) {
|
82 |
+
$scope.callback({
|
83 |
+
payment_action: 'bind',
|
84 |
+
payment_id : payment_id,
|
85 |
+
payment_title : response.data.payment_title,
|
86 |
+
payment_type : response.data.payment_type,
|
87 |
+
customer_id : customer_id
|
88 |
+
});
|
89 |
+
});
|
90 |
+
}
|
91 |
+
}
|
92 |
+
}
|
93 |
+
});
|
94 |
+
jQuery(element).modal('hide');
|
95 |
+
});
|
96 |
+
var $adjust_button = jQuery('#bookly-js-adjustment-button', $body),
|
97 |
+
$adjust_field = jQuery('#bookly-js-adjustment-field', $body),
|
98 |
+
$adjust_reason = jQuery('#bookly-js-adjustment-reason', $body),
|
99 |
+
$adjust_amount = jQuery('#bookly-js-adjustment-amount', $body),
|
100 |
+
$adjust_tax = jQuery('#bookly-js-adjustment-tax', $body),
|
101 |
+
$adjust_apply = jQuery('#bookly-js-adjustment-apply', $body),
|
102 |
+
$adjust_cancel = jQuery('#bookly-js-adjustment-cancel', $body);
|
103 |
+
$adjust_button.on('click', function () {
|
104 |
+
$adjust_field.show();
|
105 |
+
$adjust_reason.focus();
|
106 |
+
});
|
107 |
+
$adjust_cancel.on('click', function () {
|
108 |
+
$adjust_field.hide();
|
109 |
+
});
|
110 |
+
$adjust_apply.on('click', function () {
|
111 |
+
$body.html('<div class="bookly-loading"></div>');
|
112 |
+
jQuery.ajax({
|
113 |
+
url : ajaxurl,
|
114 |
+
data : {
|
115 |
+
action : 'bookly_pro_add_payment_adjustment',
|
116 |
+
payment_id: payment_id,
|
117 |
+
reason: $adjust_reason.val(),
|
118 |
+
amount: $adjust_amount.val(),
|
119 |
+
tax : $adjust_tax.val() || 0,
|
120 |
+
csrf_token: BooklyL10n.csrf_token
|
121 |
+
},
|
122 |
+
dataType: 'json',
|
123 |
+
type : 'POST',
|
124 |
+
success : function (response) {
|
125 |
+
if (response.success) {
|
126 |
+
element.trigger('refresh', [payment_id]);
|
127 |
+
// Reload DataTable.
|
128 |
+
var $table = jQuery('table#bookly-payments-list.dataTable');
|
129 |
+
if ($table.length) {
|
130 |
+
$table.DataTable().ajax.reload();
|
131 |
+
}
|
132 |
+
}
|
133 |
+
}
|
134 |
+
});
|
135 |
+
});
|
136 |
+
} else {
|
137 |
+
$body.html(response.data.html);
|
138 |
+
}
|
139 |
+
}
|
140 |
+
});
|
141 |
+
})
|
142 |
+
.on('hidden.bs.modal', function () {
|
143 |
+
$body.html(spinner);
|
144 |
+
if ((jQuery("#bookly-appointment-dialog").data('bs.modal') || {isShown: false}).isShown) {
|
145 |
+
jQuery('body').addClass('modal-open');
|
146 |
+
}
|
147 |
+
});
|
148 |
+
}
|
149 |
+
}
|
150 |
+
});
|
151 |
})();
|
backend/components/dialogs/payment/templates/details.php
CHANGED
@@ -1,217 +1,217 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
use Bookly\Backend\Modules\Payments\Proxy;
|
4 |
-
use Bookly\Lib\Utils\Price;
|
5 |
-
use Bookly\Lib\Utils\DateTime;
|
6 |
-
use Bookly\Lib\Entities;
|
7 |
-
use Bookly\Lib\Config;
|
8 |
-
/** @var array $show = ['deposit' => int, 'taxes' => int, 'gateway' => bool, 'customer_groups' => bool, 'coupons' => bool] */
|
9 |
-
?>
|
10 |
-
<?php if ( $payment ) : ?>
|
11 |
-
<div class="table-responsive">
|
12 |
-
<table class="table table-bordered">
|
13 |
-
<thead>
|
14 |
-
<tr>
|
15 |
-
<th width="50%"><?php _e( 'Customer', 'bookly' ) ?></th>
|
16 |
-
<th width="50%"><?php _e( 'Payment', 'bookly' ) ?></th>
|
17 |
-
</tr>
|
18 |
-
</thead>
|
19 |
-
<tbody>
|
20 |
-
<tr>
|
21 |
-
<td><?php echo esc_html( $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>
|
29 |
-
</table>
|
30 |
-
</div>
|
31 |
-
|
32 |
-
<div class="table-responsive">
|
33 |
-
<table class="table table-bordered">
|
34 |
-
<thead>
|
35 |
-
<tr>
|
36 |
-
<th><?php _e( 'Service', 'bookly' ) ?></th>
|
37 |
-
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
38 |
-
<th><?php _e( 'Provider', 'bookly' ) ?></th>
|
39 |
-
<?php if ( $show['deposit'] ): ?>
|
40 |
-
<th class="text-right"><?php _e( 'Deposit', 'bookly' ) ?></th>
|
41 |
-
<?php endif ?>
|
42 |
-
<th class="text-right"><?php _e( 'Price', 'bookly' ) ?></th>
|
43 |
-
<?php if ( $show['taxes'] ): ?>
|
44 |
-
<th class="text-right"><?php _e( 'Tax', 'bookly' ) ?></th>
|
45 |
-
<?php endif ?>
|
46 |
-
</tr>
|
47 |
-
</thead>
|
48 |
-
<tbody>
|
49 |
-
<?php foreach ( $payment['items'] as $item ) : ?>
|
50 |
-
<tr>
|
51 |
-
<td>
|
52 |
-
<?php if ( $item['number_of_persons'] > 1 ) echo $item['number_of_persons'] . ' × ' ?><?php echo esc_html( $item['service_name'] ) ?><?php if ( isset( $item['units'], $item['duration'] ) && $item['units'] > 1 ) echo ' (' . DateTime::secondsToInterval( $item['units'] * $item['duration'] ) . ')' ?>
|
53 |
-
<?php if ( ! empty ( $item['extras'] ) ) : ?>
|
54 |
-
<ul class="bookly-list list-dots">
|
55 |
-
<?php foreach ( $item['extras'] as $extra ) : ?>
|
56 |
-
<li><?php if ( $extra['quantity'] > 1 ) echo $extra['quantity'] . ' × ' ?><?php echo esc_html( $extra['title'] ) ?></li>
|
57 |
-
<?php endforeach ?>
|
58 |
-
</ul>
|
59 |
-
<?php endif ?>
|
60 |
-
</td>
|
61 |
-
<td><?php echo $item['appointment_date'] === null ? __( 'N/A', 'bookly' ) : DateTime::formatDateTime( $item['appointment_date'] ) ?></td>
|
62 |
-
<td><?php echo esc_html( $item['staff_name'] ) ?></td>
|
63 |
-
<?php if ( $show['deposit'] ) : ?>
|
64 |
-
<td class="text-right"><?php echo $item['deposit_format'] ?></td>
|
65 |
-
<?php endif ?>
|
66 |
-
<td class="text-right">
|
67 |
-
<?php $service_price = Price::format( $item['service_price'] ) ?>
|
68 |
-
<?php if ( $payment['from_backend'] ) : ?>
|
69 |
-
<?php echo $service_price ?>
|
70 |
-
<?php else : ?>
|
71 |
-
<?php if ( $item['number_of_persons'] > 1 ) $service_price = $item['number_of_persons'] . ' × ' . $service_price ?>
|
72 |
-
<?php echo $service_price ?>
|
73 |
-
<ul class="bookly-list">
|
74 |
-
<?php foreach ( $item['extras'] as $extra ) : ?>
|
75 |
-
<li>
|
76 |
-
<?php printf( '%s%s%s',
|
77 |
-
( $item['number_of_persons'] > 1 && $payment['extras_multiply_nop'] ) ? $item['number_of_persons'] . ' × ' : '',
|
78 |
-
( $extra['quantity'] > 1 ) ? $extra['quantity'] . ' × ' : '',
|
79 |
-
Price::format( $extra['price'] )
|
80 |
-
) ?>
|
81 |
-
</li>
|
82 |
-
<?php endforeach ?>
|
83 |
-
</ul>
|
84 |
-
<?php endif ?>
|
85 |
-
</td>
|
86 |
-
<?php if ( $show['taxes'] ) : ?>
|
87 |
-
<td class="text-right"><?php echo $item['service_tax'] !== null
|
88 |
-
? sprintf( $payment['tax_in_price'] == 'included' ? '(%s)' : '%s', Price::format( $item['service_tax'] ) )
|
89 |
-
: '-' ?></td>
|
90 |
-
<?php endif ?>
|
91 |
-
</tr>
|
92 |
-
<?php endforeach ?>
|
93 |
-
</tbody>
|
94 |
-
<tfoot>
|
95 |
-
<tr>
|
96 |
-
<th style="border-left-color: white; border-bottom-color: white;"></th>
|
97 |
-
<th colspan="2"><?php _e( 'Subtotal', 'bookly' ) ?></th>
|
98 |
-
<?php if ( $show['deposit'] ) : ?>
|
99 |
-
<th class="text-right"><?php echo Price::format( $payment['subtotal']['deposit'] ) ?></th>
|
100 |
-
<?php endif ?>
|
101 |
-
<th class="text-right"><?php echo Price::format( $payment['subtotal']['price'] ) ?></th>
|
102 |
-
<?php if ( $show['taxes'] ) : ?><th></th><?php endif ?>
|
103 |
-
</tr>
|
104 |
-
<?php if ( $show['coupons'] || $payment['coupon'] ) : ?>
|
105 |
-
<tr>
|
106 |
-
<th style="border-left-color: white; border-bottom-color: white;"></th>
|
107 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
108 |
-
<?php _e( 'Coupon discount', 'bookly' ) ?>
|
109 |
-
<?php if ( $payment['coupon'] ) : ?><div><small>(<?php echo $payment['coupon']['code'] ?>)</small></div><?php endif ?>
|
110 |
-
</th>
|
111 |
-
<th class="text-right">
|
112 |
-
<?php if ( $payment['coupon'] ) : ?>
|
113 |
-
<?php if ( $payment['coupon']['discount'] ) : ?>
|
114 |
-
<div><?php echo $payment['coupon']['discount'] ?>%</div>
|
115 |
-
<?php endif ?>
|
116 |
-
<?php if ( $payment['coupon']['deduction'] ) : ?>
|
117 |
-
<div><?php echo Price::format( $payment['coupon']['deduction'] ) ?></div>
|
118 |
-
<?php endif ?>
|
119 |
-
<?php else : ?>
|
120 |
-
<?php echo Price::format( 0 ) ?>
|
121 |
-
<?php endif ?>
|
122 |
-
</th>
|
123 |
-
<?php if ( $show['taxes'] ) : ?>
|
124 |
-
<th></th>
|
125 |
-
<?php endif ?>
|
126 |
-
</tr>
|
127 |
-
<?php endif ?>
|
128 |
-
<?php if ( $show['customer_groups'] || $payment['group_discount'] ) : ?>
|
129 |
-
<tr>
|
130 |
-
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
131 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
132 |
-
<?php _e( 'Group discount', 'bookly' ) ?>
|
133 |
-
</th>
|
134 |
-
<th class="text-right">
|
135 |
-
<?php echo $payment['group_discount'] ?: Price::format( 0 ) ?>
|
136 |
-
</th>
|
137 |
-
<?php if ( $show['taxes'] ) : ?><th></th><?php endif ?>
|
138 |
-
</tr>
|
139 |
-
<?php endif ?>
|
140 |
-
<?php foreach ( $adjustments as $adjustment ) : ?>
|
141 |
-
<tr>
|
142 |
-
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
143 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
144 |
-
<?php echo esc_html( $adjustment['reason'] ) ?>
|
145 |
-
</th>
|
146 |
-
<th class="text-right"><?php echo Price::format( $adjustment['amount'] ) ?></th>
|
147 |
-
<?php if ( $show['taxes'] ) : ?>
|
148 |
-
<th class="text-right"><?php echo Price::format( $adjustment['tax'] ) ?></th>
|
149 |
-
<?php endif ?>
|
150 |
-
</tr>
|
151 |
-
<?php endforeach ?>
|
152 |
-
|
153 |
-
<?php Proxy\Pro::renderManualAdjustmentForm( $show ) ?>
|
154 |
-
|
155 |
-
<?php if ( $show['gateway'] || (float) $payment['price_correction'] ) : ?>
|
156 |
-
<tr>
|
157 |
-
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
158 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
159 |
-
<?php echo Entities\Payment::typeToString( $payment['type'] ) ?>
|
160 |
-
</th>
|
161 |
-
<th class="text-right">
|
162 |
-
<?php echo Price::format( $payment['price_correction'] ) ?>
|
163 |
-
</th>
|
164 |
-
<?php if ( $show['taxes'] ) : ?>
|
165 |
-
<td class="text-right">-</td>
|
166 |
-
<?php endif ?>
|
167 |
-
</tr>
|
168 |
-
<?php endif ?>
|
169 |
-
<tr>
|
170 |
-
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
171 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>"><?php _e( 'Total', 'bookly' ) ?></th>
|
172 |
-
<th class="text-right"><?php echo Price::format( $payment['total'] ) ?></th>
|
173 |
-
<?php if ( $show['taxes'] ) : ?>
|
174 |
-
<th class="text-right">
|
175 |
-
(<?php echo Price::format( $payment['tax_total'] ) ?>)
|
176 |
-
</th>
|
177 |
-
<?php endif ?>
|
178 |
-
</tr>
|
179 |
-
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
180 |
-
<tr>
|
181 |
-
<th rowspan="2" style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
182 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>"><i><?php _e( 'Paid', 'bookly' ) ?></i></th>
|
183 |
-
<th class="text-right"><i><?php echo Price::format( $payment['paid'] ) ?></i></th>
|
184 |
-
<?php if ( $show['taxes'] ) : ?>
|
185 |
-
<th class="text-right"><i>(<?php echo Price::format( $payment['tax_paid'] ) ?>)</i></th>
|
186 |
-
<?php endif ?>
|
187 |
-
</tr>
|
188 |
-
<tr>
|
189 |
-
<th colspan="<?php echo 2 + $show['deposit'] ?>"><i><?php _e( 'Due', 'bookly' ) ?></i></th>
|
190 |
-
<th class="text-right">
|
191 |
-
<i><?php echo Price::format( $payment['total'] - $payment['paid'] ) ?></i>
|
192 |
-
</th>
|
193 |
-
<?php if ( $show['taxes'] ) : ?>
|
194 |
-
<th class="text-right"><i>(<?php echo Price::format( $payment['tax_total'] - $payment['tax_paid'] ) ?>)</i></th>
|
195 |
-
<?php endif ?>
|
196 |
-
</tr>
|
197 |
-
<?php endif ?>
|
198 |
-
<?php if ( Config::proActive() || ( $payment['total'] != $payment['paid'] ) ) : ?>
|
199 |
-
<tr>
|
200 |
-
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
201 |
-
<th colspan="<?php echo 3 + $show['deposit'] + $show['taxes'] ?>" class="text-right">
|
202 |
-
<div class="bookly-js-details-main-controls">
|
203 |
-
<?php Proxy\Pro::renderManualAdjustmentButton() ?>
|
204 |
-
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
205 |
-
<button type="button" class="btn btn-success ladda-button" id="bookly-complete-payment" data-spinner-size="40" data-style="zoom-in"><i><?php _e( 'Complete payment', 'bookly' ) ?></i></button>
|
206 |
-
<?php endif ?>
|
207 |
-
</div>
|
208 |
-
<div class="bookly-js-details-bind-controls collapse">
|
209 |
-
<?php Buttons::renderCustom( 'bookly-js-attach-payment', 'btn-success', __( 'Bind payment', 'bookly' ) ) ?>
|
210 |
-
</div>
|
211 |
-
</th>
|
212 |
-
</tr>
|
213 |
-
<?php endif ?>
|
214 |
-
</tfoot>
|
215 |
-
</table>
|
216 |
-
</div>
|
217 |
<?php endif ?>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
use Bookly\Backend\Modules\Payments\Proxy;
|
4 |
+
use Bookly\Lib\Utils\Price;
|
5 |
+
use Bookly\Lib\Utils\DateTime;
|
6 |
+
use Bookly\Lib\Entities;
|
7 |
+
use Bookly\Lib\Config;
|
8 |
+
/** @var array $show = ['deposit' => int, 'taxes' => int, 'gateway' => bool, 'customer_groups' => bool, 'coupons' => bool] */
|
9 |
+
?>
|
10 |
+
<?php if ( $payment ) : ?>
|
11 |
+
<div class="table-responsive">
|
12 |
+
<table class="table table-bordered">
|
13 |
+
<thead>
|
14 |
+
<tr>
|
15 |
+
<th width="50%"><?php _e( 'Customer', 'bookly' ) ?></th>
|
16 |
+
<th width="50%"><?php _e( 'Payment', 'bookly' ) ?></th>
|
17 |
+
</tr>
|
18 |
+
</thead>
|
19 |
+
<tbody>
|
20 |
+
<tr>
|
21 |
+
<td><?php echo esc_html( $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>
|
29 |
+
</table>
|
30 |
+
</div>
|
31 |
+
|
32 |
+
<div class="table-responsive">
|
33 |
+
<table class="table table-bordered">
|
34 |
+
<thead>
|
35 |
+
<tr>
|
36 |
+
<th><?php _e( 'Service', 'bookly' ) ?></th>
|
37 |
+
<th><?php _e( 'Date', 'bookly' ) ?></th>
|
38 |
+
<th><?php _e( 'Provider', 'bookly' ) ?></th>
|
39 |
+
<?php if ( $show['deposit'] ): ?>
|
40 |
+
<th class="text-right"><?php _e( 'Deposit', 'bookly' ) ?></th>
|
41 |
+
<?php endif ?>
|
42 |
+
<th class="text-right"><?php _e( 'Price', 'bookly' ) ?></th>
|
43 |
+
<?php if ( $show['taxes'] ): ?>
|
44 |
+
<th class="text-right"><?php _e( 'Tax', 'bookly' ) ?></th>
|
45 |
+
<?php endif ?>
|
46 |
+
</tr>
|
47 |
+
</thead>
|
48 |
+
<tbody>
|
49 |
+
<?php foreach ( $payment['items'] as $item ) : ?>
|
50 |
+
<tr>
|
51 |
+
<td>
|
52 |
+
<?php if ( $item['number_of_persons'] > 1 ) echo $item['number_of_persons'] . ' × ' ?><?php echo esc_html( $item['service_name'] ) ?><?php if ( isset( $item['units'], $item['duration'] ) && $item['units'] > 1 ) echo ' (' . DateTime::secondsToInterval( $item['units'] * $item['duration'] ) . ')' ?>
|
53 |
+
<?php if ( ! empty ( $item['extras'] ) ) : ?>
|
54 |
+
<ul class="bookly-list list-dots">
|
55 |
+
<?php foreach ( $item['extras'] as $extra ) : ?>
|
56 |
+
<li><?php if ( $payment['extras_multiply_nop'] && $item['number_of_persons'] > 1 ) echo $item['number_of_persons'] . ' × ' ?><?php if ( $extra['quantity'] > 1 ) echo $extra['quantity'] . ' × ' ?><?php echo esc_html( $extra['title'] ) ?></li>
|
57 |
+
<?php endforeach ?>
|
58 |
+
</ul>
|
59 |
+
<?php endif ?>
|
60 |
+
</td>
|
61 |
+
<td><?php echo $item['appointment_date'] === null ? __( 'N/A', 'bookly' ) : DateTime::formatDateTime( $item['appointment_date'] ) ?></td>
|
62 |
+
<td><?php echo esc_html( $item['staff_name'] ) ?></td>
|
63 |
+
<?php if ( $show['deposit'] ) : ?>
|
64 |
+
<td class="text-right"><?php echo $item['deposit_format'] ?></td>
|
65 |
+
<?php endif ?>
|
66 |
+
<td class="text-right">
|
67 |
+
<?php $service_price = Price::format( $item['service_price'] ) ?>
|
68 |
+
<?php if ( $payment['from_backend'] ) : ?>
|
69 |
+
<?php echo $service_price ?>
|
70 |
+
<?php else : ?>
|
71 |
+
<?php if ( $item['number_of_persons'] > 1 ) $service_price = $item['number_of_persons'] . ' × ' . $service_price ?>
|
72 |
+
<?php echo $service_price ?>
|
73 |
+
<ul class="bookly-list">
|
74 |
+
<?php foreach ( $item['extras'] as $extra ) : ?>
|
75 |
+
<li>
|
76 |
+
<?php printf( '%s%s%s',
|
77 |
+
( $item['number_of_persons'] > 1 && $payment['extras_multiply_nop'] ) ? $item['number_of_persons'] . ' × ' : '',
|
78 |
+
( $extra['quantity'] > 1 ) ? $extra['quantity'] . ' × ' : '',
|
79 |
+
Price::format( $extra['price'] )
|
80 |
+
) ?>
|
81 |
+
</li>
|
82 |
+
<?php endforeach ?>
|
83 |
+
</ul>
|
84 |
+
<?php endif ?>
|
85 |
+
</td>
|
86 |
+
<?php if ( $show['taxes'] ) : ?>
|
87 |
+
<td class="text-right"><?php echo $item['service_tax'] !== null
|
88 |
+
? sprintf( $payment['tax_in_price'] == 'included' ? '(%s)' : '%s', Price::format( $item['service_tax'] ) )
|
89 |
+
: '-' ?></td>
|
90 |
+
<?php endif ?>
|
91 |
+
</tr>
|
92 |
+
<?php endforeach ?>
|
93 |
+
</tbody>
|
94 |
+
<tfoot>
|
95 |
+
<tr>
|
96 |
+
<th style="border-left-color: white; border-bottom-color: white;"></th>
|
97 |
+
<th colspan="2"><?php _e( 'Subtotal', 'bookly' ) ?></th>
|
98 |
+
<?php if ( $show['deposit'] ) : ?>
|
99 |
+
<th class="text-right"><?php echo Price::format( $payment['subtotal']['deposit'] ) ?></th>
|
100 |
+
<?php endif ?>
|
101 |
+
<th class="text-right"><?php echo Price::format( $payment['subtotal']['price'] ) ?></th>
|
102 |
+
<?php if ( $show['taxes'] ) : ?><th></th><?php endif ?>
|
103 |
+
</tr>
|
104 |
+
<?php if ( $show['coupons'] || $payment['coupon'] ) : ?>
|
105 |
+
<tr>
|
106 |
+
<th style="border-left-color: white; border-bottom-color: white;"></th>
|
107 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
108 |
+
<?php _e( 'Coupon discount', 'bookly' ) ?>
|
109 |
+
<?php if ( $payment['coupon'] ) : ?><div><small>(<?php echo $payment['coupon']['code'] ?>)</small></div><?php endif ?>
|
110 |
+
</th>
|
111 |
+
<th class="text-right">
|
112 |
+
<?php if ( $payment['coupon'] ) : ?>
|
113 |
+
<?php if ( $payment['coupon']['discount'] ) : ?>
|
114 |
+
<div><?php echo $payment['coupon']['discount'] ?>%</div>
|
115 |
+
<?php endif ?>
|
116 |
+
<?php if ( $payment['coupon']['deduction'] ) : ?>
|
117 |
+
<div><?php echo Price::format( $payment['coupon']['deduction'] ) ?></div>
|
118 |
+
<?php endif ?>
|
119 |
+
<?php else : ?>
|
120 |
+
<?php echo Price::format( 0 ) ?>
|
121 |
+
<?php endif ?>
|
122 |
+
</th>
|
123 |
+
<?php if ( $show['taxes'] ) : ?>
|
124 |
+
<th></th>
|
125 |
+
<?php endif ?>
|
126 |
+
</tr>
|
127 |
+
<?php endif ?>
|
128 |
+
<?php if ( $show['customer_groups'] || $payment['group_discount'] ) : ?>
|
129 |
+
<tr>
|
130 |
+
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
131 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
132 |
+
<?php _e( 'Group discount', 'bookly' ) ?>
|
133 |
+
</th>
|
134 |
+
<th class="text-right">
|
135 |
+
<?php echo $payment['group_discount'] ?: Price::format( 0 ) ?>
|
136 |
+
</th>
|
137 |
+
<?php if ( $show['taxes'] ) : ?><th></th><?php endif ?>
|
138 |
+
</tr>
|
139 |
+
<?php endif ?>
|
140 |
+
<?php foreach ( $adjustments as $adjustment ) : ?>
|
141 |
+
<tr>
|
142 |
+
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
143 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
144 |
+
<?php echo esc_html( $adjustment['reason'] ) ?>
|
145 |
+
</th>
|
146 |
+
<th class="text-right"><?php echo Price::format( $adjustment['amount'] ) ?></th>
|
147 |
+
<?php if ( $show['taxes'] ) : ?>
|
148 |
+
<th class="text-right"><?php echo Price::format( $adjustment['tax'] ) ?></th>
|
149 |
+
<?php endif ?>
|
150 |
+
</tr>
|
151 |
+
<?php endforeach ?>
|
152 |
+
|
153 |
+
<?php Proxy\Pro::renderManualAdjustmentForm( $show ) ?>
|
154 |
+
|
155 |
+
<?php if ( $show['gateway'] || (float) $payment['price_correction'] ) : ?>
|
156 |
+
<tr>
|
157 |
+
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
158 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>">
|
159 |
+
<?php echo Entities\Payment::typeToString( $payment['type'] ) ?>
|
160 |
+
</th>
|
161 |
+
<th class="text-right">
|
162 |
+
<?php echo Price::format( $payment['price_correction'] ) ?>
|
163 |
+
</th>
|
164 |
+
<?php if ( $show['taxes'] ) : ?>
|
165 |
+
<td class="text-right">-</td>
|
166 |
+
<?php endif ?>
|
167 |
+
</tr>
|
168 |
+
<?php endif ?>
|
169 |
+
<tr>
|
170 |
+
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
171 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>"><?php _e( 'Total', 'bookly' ) ?></th>
|
172 |
+
<th class="text-right"><?php echo Price::format( $payment['total'] ) ?></th>
|
173 |
+
<?php if ( $show['taxes'] ) : ?>
|
174 |
+
<th class="text-right">
|
175 |
+
(<?php echo Price::format( $payment['tax_total'] ) ?>)
|
176 |
+
</th>
|
177 |
+
<?php endif ?>
|
178 |
+
</tr>
|
179 |
+
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
180 |
+
<tr>
|
181 |
+
<th rowspan="2" style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
182 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>"><i><?php _e( 'Paid', 'bookly' ) ?></i></th>
|
183 |
+
<th class="text-right"><i><?php echo Price::format( $payment['paid'] ) ?></i></th>
|
184 |
+
<?php if ( $show['taxes'] ) : ?>
|
185 |
+
<th class="text-right"><i>(<?php echo Price::format( $payment['tax_paid'] ) ?>)</i></th>
|
186 |
+
<?php endif ?>
|
187 |
+
</tr>
|
188 |
+
<tr>
|
189 |
+
<th colspan="<?php echo 2 + $show['deposit'] ?>"><i><?php _e( 'Due', 'bookly' ) ?></i></th>
|
190 |
+
<th class="text-right">
|
191 |
+
<i><?php echo Price::format( $payment['total'] - $payment['paid'] ) ?></i>
|
192 |
+
</th>
|
193 |
+
<?php if ( $show['taxes'] ) : ?>
|
194 |
+
<th class="text-right"><i>(<?php echo Price::format( $payment['tax_total'] - $payment['tax_paid'] ) ?>)</i></th>
|
195 |
+
<?php endif ?>
|
196 |
+
</tr>
|
197 |
+
<?php endif ?>
|
198 |
+
<?php if ( Config::proActive() || ( $payment['total'] != $payment['paid'] ) ) : ?>
|
199 |
+
<tr>
|
200 |
+
<th style="border-left-color:#fff;border-bottom-color:#fff;"></th>
|
201 |
+
<th colspan="<?php echo 3 + $show['deposit'] + $show['taxes'] ?>" class="text-right">
|
202 |
+
<div class="bookly-js-details-main-controls">
|
203 |
+
<?php Proxy\Pro::renderManualAdjustmentButton() ?>
|
204 |
+
<?php if ( $payment['total'] != $payment['paid'] ) : ?>
|
205 |
+
<button type="button" class="btn btn-success ladda-button" id="bookly-complete-payment" data-spinner-size="40" data-style="zoom-in"><i><?php _e( 'Complete payment', 'bookly' ) ?></i></button>
|
206 |
+
<?php endif ?>
|
207 |
+
</div>
|
208 |
+
<div class="bookly-js-details-bind-controls collapse">
|
209 |
+
<?php Buttons::renderCustom( 'bookly-js-attach-payment', 'btn-success', __( 'Bind payment', 'bookly' ) ) ?>
|
210 |
+
</div>
|
211 |
+
</th>
|
212 |
+
</tr>
|
213 |
+
<?php endif ?>
|
214 |
+
</tfoot>
|
215 |
+
</table>
|
216 |
+
</div>
|
217 |
<?php endif ?>
|
backend/components/dialogs/payment/templates/dialog.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
?>
|
4 |
-
<script type="text/ng-template" id="bookly-payment-details-dialog.tpl">
|
5 |
-
<div class="modal fade" id="bookly-payment-details-modal" tabindex="-1" role="dialog">
|
6 |
-
<div class="modal-dialog" role="document">
|
7 |
-
<div class="modal-content">
|
8 |
-
<div class="modal-header">
|
9 |
-
<button type="button" class="close" data-dismiss="modal" aria-label="<?php esc_attr_e( 'Close', 'bookly' ) ?>"><span aria-hidden="true">×</span></button>
|
10 |
-
<div class="modal-title h2"><?php _e( 'Payment', 'bookly' ) ?></div>
|
11 |
-
</div>
|
12 |
-
<div class="modal-body">
|
13 |
-
<div class="bookly-loading"></div>
|
14 |
-
</div>
|
15 |
-
<div class="modal-footer">
|
16 |
-
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Close', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
17 |
-
</div>
|
18 |
-
</div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
</script>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
?>
|
4 |
+
<script type="text/ng-template" id="bookly-payment-details-dialog.tpl">
|
5 |
+
<div class="modal fade" id="bookly-payment-details-modal" tabindex="-1" role="dialog">
|
6 |
+
<div class="modal-dialog" role="document">
|
7 |
+
<div class="modal-content">
|
8 |
+
<div class="modal-header">
|
9 |
+
<button type="button" class="close" data-dismiss="modal" aria-label="<?php esc_attr_e( 'Close', 'bookly' ) ?>"><span aria-hidden="true">×</span></button>
|
10 |
+
<div class="modal-title h2"><?php _e( 'Payment', 'bookly' ) ?></div>
|
11 |
+
</div>
|
12 |
+
<div class="modal-body">
|
13 |
+
<div class="bookly-loading"></div>
|
14 |
+
</div>
|
15 |
+
<div class="modal-footer">
|
16 |
+
<?php Buttons::renderCustom( null, 'btn-lg btn-default', __( 'Close', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
</script>
|
backend/components/dialogs/special_price/proxy/SpecialHours.php
CHANGED
@@ -1,14 +1,14 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Dialogs\SpecialPrice\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib as BooklyLib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class SpecialHours
|
8 |
-
* @package Bookly\Backend\Components\Dialogs\SpecialPrice\ProxyProviders
|
9 |
-
*
|
10 |
-
* @method static void renderSpecialPricePopup( int $staff_id ) Render popup for special price.
|
11 |
-
*/
|
12 |
-
abstract class SpecialHours extends BooklyLib\Base\Proxy
|
13 |
-
{
|
14 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Dialogs\SpecialPrice\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib as BooklyLib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class SpecialHours
|
8 |
+
* @package Bookly\Backend\Components\Dialogs\SpecialPrice\ProxyProviders
|
9 |
+
*
|
10 |
+
* @method static void renderSpecialPricePopup( int $staff_id ) Render popup for special price.
|
11 |
+
*/
|
12 |
+
abstract class SpecialHours extends BooklyLib\Base\Proxy
|
13 |
+
{
|
14 |
}
|
backend/components/notices/CollectStats.php
CHANGED
@@ -1,47 +1,47 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class CollectStats
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class CollectStats extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render collect stats notice.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
if ( self::needShowCollectStatNotice() ) {
|
18 |
-
self::enqueueStyles( array(
|
19 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
20 |
-
) );
|
21 |
-
self::enqueueScripts( array(
|
22 |
-
'module' => array( 'js/collect-stats.js' => array( 'jquery' ), ),
|
23 |
-
) );
|
24 |
-
|
25 |
-
self::renderTemplate( 'collect_stats', array( 'enabled' => get_option( 'bookly_gen_collect_stats' ) == '1' ) );
|
26 |
-
}
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* @return bool
|
31 |
-
*/
|
32 |
-
public static function needShowCollectStatNotice()
|
33 |
-
{
|
34 |
-
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
35 |
-
$enabled = get_option( 'bookly_gen_collect_stats' ) == '1';
|
36 |
-
$user_id = get_current_user_id();
|
37 |
-
if (
|
38 |
-
$enabled && get_user_meta( $user_id, 'bookly_show_collecting_stats_notice', true ) ||
|
39 |
-
! $enabled && ! get_user_meta( $user_id, 'bookly_dismiss_collect_stats_notice', true )
|
40 |
-
) {
|
41 |
-
return true;
|
42 |
-
}
|
43 |
-
}
|
44 |
-
|
45 |
-
return false;
|
46 |
-
}
|
47 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CollectStats
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class CollectStats extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render collect stats notice.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
if ( self::needShowCollectStatNotice() ) {
|
18 |
+
self::enqueueStyles( array(
|
19 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
20 |
+
) );
|
21 |
+
self::enqueueScripts( array(
|
22 |
+
'module' => array( 'js/collect-stats.js' => array( 'jquery' ), ),
|
23 |
+
) );
|
24 |
+
|
25 |
+
self::renderTemplate( 'collect_stats', array( 'enabled' => get_option( 'bookly_gen_collect_stats' ) == '1' ) );
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* @return bool
|
31 |
+
*/
|
32 |
+
public static function needShowCollectStatNotice()
|
33 |
+
{
|
34 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
35 |
+
$enabled = get_option( 'bookly_gen_collect_stats' ) == '1';
|
36 |
+
$user_id = get_current_user_id();
|
37 |
+
if (
|
38 |
+
$enabled && get_user_meta( $user_id, 'bookly_show_collecting_stats_notice', true ) ||
|
39 |
+
! $enabled && ! get_user_meta( $user_id, 'bookly_dismiss_collect_stats_notice', true )
|
40 |
+
) {
|
41 |
+
return true;
|
42 |
+
}
|
43 |
+
}
|
44 |
+
|
45 |
+
return false;
|
46 |
+
}
|
47 |
}
|
backend/components/notices/CollectStatsAjax.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class CollectStatsAjax
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class CollectStatsAjax extends Lib\Base\Ajax
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Dismiss 'Collecting stats' notice.
|
14 |
-
*/
|
15 |
-
public static function dismissCollectingStatsNotice()
|
16 |
-
{
|
17 |
-
delete_user_meta( get_current_user_id(), 'bookly_show_collecting_stats_notice' );
|
18 |
-
|
19 |
-
wp_send_json_success();
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Dismiss 'Collect stats' notice.
|
24 |
-
*/
|
25 |
-
public static function dismissCollectStatsNotice()
|
26 |
-
{
|
27 |
-
update_user_meta( get_current_user_id(), 'bookly_dismiss_collect_stats_notice', 1 );
|
28 |
-
|
29 |
-
wp_send_json_success();
|
30 |
-
}
|
31 |
-
|
32 |
-
/**
|
33 |
-
* Enable collecting stats.
|
34 |
-
*/
|
35 |
-
public static function enableCollectingStats()
|
36 |
-
{
|
37 |
-
update_option( 'bookly_gen_collect_stats', '1' );
|
38 |
-
|
39 |
-
wp_send_json_success();
|
40 |
-
}
|
41 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CollectStatsAjax
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class CollectStatsAjax extends Lib\Base\Ajax
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Dismiss 'Collecting stats' notice.
|
14 |
+
*/
|
15 |
+
public static function dismissCollectingStatsNotice()
|
16 |
+
{
|
17 |
+
delete_user_meta( get_current_user_id(), 'bookly_show_collecting_stats_notice' );
|
18 |
+
|
19 |
+
wp_send_json_success();
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Dismiss 'Collect stats' notice.
|
24 |
+
*/
|
25 |
+
public static function dismissCollectStatsNotice()
|
26 |
+
{
|
27 |
+
update_user_meta( get_current_user_id(), 'bookly_dismiss_collect_stats_notice', 1 );
|
28 |
+
|
29 |
+
wp_send_json_success();
|
30 |
+
}
|
31 |
+
|
32 |
+
/**
|
33 |
+
* Enable collecting stats.
|
34 |
+
*/
|
35 |
+
public static function enableCollectingStats()
|
36 |
+
{
|
37 |
+
update_option( 'bookly_gen_collect_stats', '1' );
|
38 |
+
|
39 |
+
wp_send_json_success();
|
40 |
+
}
|
41 |
}
|
backend/components/notices/Limitation.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Limitation
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class Limitation extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render limitation notice.
|
14 |
-
*/
|
15 |
-
public static function getHtml()
|
16 |
-
{
|
17 |
-
return self::renderTemplate( 'limitation', array(), false );
|
18 |
-
}
|
19 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Limitation
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class Limitation extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render limitation notice.
|
14 |
+
*/
|
15 |
+
public static function getHtml()
|
16 |
+
{
|
17 |
+
return self::renderTemplate( 'limitation', array(), false );
|
18 |
+
}
|
19 |
}
|
backend/components/notices/LiteRebranding.php
CHANGED
@@ -1,27 +1,27 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class LiteRebranding
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class LiteRebranding extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render subscribe notice.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
if ( Lib\Utils\Common::isCurrentUserAdmin() &&
|
18 |
-
get_user_meta( get_current_user_id(), 'bookly_show_lite_rebranding_notice', true ) ) {
|
19 |
-
|
20 |
-
self::enqueueScripts( array(
|
21 |
-
'module' => array( 'js/lite-rebranding.js' => array( 'jquery' ), ),
|
22 |
-
) );
|
23 |
-
|
24 |
-
self::renderTemplate( 'lite_rebranding' );
|
25 |
-
}
|
26 |
-
}
|
27 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class LiteRebranding
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class LiteRebranding extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render subscribe notice.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() &&
|
18 |
+
get_user_meta( get_current_user_id(), 'bookly_show_lite_rebranding_notice', true ) ) {
|
19 |
+
|
20 |
+
self::enqueueScripts( array(
|
21 |
+
'module' => array( 'js/lite-rebranding.js' => array( 'jquery' ), ),
|
22 |
+
) );
|
23 |
+
|
24 |
+
self::renderTemplate( 'lite_rebranding' );
|
25 |
+
}
|
26 |
+
}
|
27 |
}
|
backend/components/notices/LiteRebrandingAjax.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class LiteRebrandingAjax
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class LiteRebrandingAjax extends Lib\Base\Ajax
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Dismiss 'Lite Rebranding' notice.
|
14 |
-
*/
|
15 |
-
public static function dismissLiteRebrandingNotice()
|
16 |
-
{
|
17 |
-
delete_user_meta( get_current_user_id(), 'bookly_show_lite_rebranding_notice' );
|
18 |
-
|
19 |
-
wp_send_json_success();
|
20 |
-
}
|
21 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class LiteRebrandingAjax
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class LiteRebrandingAjax extends Lib\Base\Ajax
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Dismiss 'Lite Rebranding' notice.
|
14 |
+
*/
|
15 |
+
public static function dismissLiteRebrandingNotice()
|
16 |
+
{
|
17 |
+
delete_user_meta( get_current_user_id(), 'bookly_show_lite_rebranding_notice' );
|
18 |
+
|
19 |
+
wp_send_json_success();
|
20 |
+
}
|
21 |
}
|
backend/components/notices/Nps.php
CHANGED
@@ -1,48 +1,48 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Backend\Modules;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Nps
|
9 |
-
* @package Bookly\Backend\Components\Notices
|
10 |
-
*/
|
11 |
-
class Nps extends Lib\Base\Component
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* Render Net Promoter Score notice.
|
15 |
-
*/
|
16 |
-
public static function render()
|
17 |
-
{
|
18 |
-
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
19 |
-
$dismiss_value = get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', true );
|
20 |
-
// Show notice 1 month after it was closed the last time.
|
21 |
-
if ( ! $dismiss_value || $dismiss_value > 1 && time() - $dismiss_value >= 30 * DAY_IN_SECONDS ) {
|
22 |
-
// Show notice 1 month after installation time.
|
23 |
-
if ( time() - Lib\Plugin::getInstallationTime() >= 30 * DAY_IN_SECONDS ) {
|
24 |
-
self::enqueueStyles( array(
|
25 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
26 |
-
'module' => array( 'css/bootstrap-stars.css', ),
|
27 |
-
) );
|
28 |
-
|
29 |
-
self::enqueueScripts( array(
|
30 |
-
'backend' => array(
|
31 |
-
'js/alert.js' => array( 'jquery' ),
|
32 |
-
),
|
33 |
-
'frontend' => array(
|
34 |
-
'js/spin.min.js' => array( 'jquery' ),
|
35 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
36 |
-
),
|
37 |
-
'module' => array(
|
38 |
-
'js/jquery.barrating.min.js' => array( 'jquery' ),
|
39 |
-
'js/nps.js' => array( 'bookly-jquery.barrating.min.js', 'bookly-alert.js', 'bookly-ladda.min.js', ),
|
40 |
-
),
|
41 |
-
) );
|
42 |
-
|
43 |
-
self::renderTemplate( 'nps', array( 'current_user' => wp_get_current_user() ) );
|
44 |
-
}
|
45 |
-
}
|
46 |
-
}
|
47 |
-
}
|
48 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Backend\Modules;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Nps
|
9 |
+
* @package Bookly\Backend\Components\Notices
|
10 |
+
*/
|
11 |
+
class Nps extends Lib\Base\Component
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Render Net Promoter Score notice.
|
15 |
+
*/
|
16 |
+
public static function render()
|
17 |
+
{
|
18 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() ) {
|
19 |
+
$dismiss_value = get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', true );
|
20 |
+
// Show notice 1 month after it was closed the last time.
|
21 |
+
if ( ! $dismiss_value || $dismiss_value > 1 && time() - $dismiss_value >= 30 * DAY_IN_SECONDS ) {
|
22 |
+
// Show notice 1 month after installation time.
|
23 |
+
if ( time() - Lib\Plugin::getInstallationTime() >= 30 * DAY_IN_SECONDS ) {
|
24 |
+
self::enqueueStyles( array(
|
25 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
26 |
+
'module' => array( 'css/bootstrap-stars.css', ),
|
27 |
+
) );
|
28 |
+
|
29 |
+
self::enqueueScripts( array(
|
30 |
+
'backend' => array(
|
31 |
+
'js/alert.js' => array( 'jquery' ),
|
32 |
+
),
|
33 |
+
'frontend' => array(
|
34 |
+
'js/spin.min.js' => array( 'jquery' ),
|
35 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
36 |
+
),
|
37 |
+
'module' => array(
|
38 |
+
'js/jquery.barrating.min.js' => array( 'jquery' ),
|
39 |
+
'js/nps.js' => array( 'bookly-jquery.barrating.min.js', 'bookly-alert.js', 'bookly-ladda.min.js', ),
|
40 |
+
),
|
41 |
+
) );
|
42 |
+
|
43 |
+
self::renderTemplate( 'nps', array( 'current_user' => wp_get_current_user() ) );
|
44 |
+
}
|
45 |
+
}
|
46 |
+
}
|
47 |
+
}
|
48 |
}
|
backend/components/notices/NpsAjax.php
CHANGED
@@ -1,40 +1,40 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Backend\Modules;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class NpsAjax
|
9 |
-
* @package Bookly\Backend\Components\Notices
|
10 |
-
*/
|
11 |
-
class NpsAjax extends Lib\Base\Ajax
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* Send Net Promoter Score.
|
15 |
-
*/
|
16 |
-
public static function npsSend()
|
17 |
-
{
|
18 |
-
$rate = self::parameter( 'rate' );
|
19 |
-
$msg = self::parameter( 'msg', '' );
|
20 |
-
$email = self::parameter( 'email', '' );
|
21 |
-
|
22 |
-
Lib\API::sendNps( $rate, $msg, $email );
|
23 |
-
|
24 |
-
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', 1 );
|
25 |
-
|
26 |
-
wp_send_json_success( array( 'message' => __( 'Sent successfully.', 'bookly' ) ) );
|
27 |
-
}
|
28 |
-
|
29 |
-
/**
|
30 |
-
* Dismiss NPS notice.
|
31 |
-
*/
|
32 |
-
public static function dismissNpsNotice()
|
33 |
-
{
|
34 |
-
if ( get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', true ) != 1 ) {
|
35 |
-
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', time() );
|
36 |
-
}
|
37 |
-
|
38 |
-
wp_send_json_success();
|
39 |
-
}
|
40 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Backend\Modules;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class NpsAjax
|
9 |
+
* @package Bookly\Backend\Components\Notices
|
10 |
+
*/
|
11 |
+
class NpsAjax extends Lib\Base\Ajax
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Send Net Promoter Score.
|
15 |
+
*/
|
16 |
+
public static function npsSend()
|
17 |
+
{
|
18 |
+
$rate = self::parameter( 'rate' );
|
19 |
+
$msg = self::parameter( 'msg', '' );
|
20 |
+
$email = self::parameter( 'email', '' );
|
21 |
+
|
22 |
+
Lib\API::sendNps( $rate, $msg, $email );
|
23 |
+
|
24 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', 1 );
|
25 |
+
|
26 |
+
wp_send_json_success( array( 'message' => __( 'Sent successfully.', 'bookly' ) ) );
|
27 |
+
}
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Dismiss NPS notice.
|
31 |
+
*/
|
32 |
+
public static function dismissNpsNotice()
|
33 |
+
{
|
34 |
+
if ( get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', true ) != 1 ) {
|
35 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_nps_notice', time() );
|
36 |
+
}
|
37 |
+
|
38 |
+
wp_send_json_success();
|
39 |
+
}
|
40 |
}
|
backend/components/notices/Subscribe.php
CHANGED
@@ -1,38 +1,38 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Subscribe
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class Subscribe extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render subscribe notice.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
if ( Lib\Utils\Common::isCurrentUserAdmin() &&
|
18 |
-
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_subscribe_notice', true ) ) {
|
19 |
-
|
20 |
-
// Show notice 1 day after installation time.
|
21 |
-
if ( time() - Lib\Plugin::getInstallationTime() >= DAY_IN_SECONDS ) {
|
22 |
-
self::enqueueStyles( array(
|
23 |
-
'frontend' => array( 'css/ladda.min.css', ),
|
24 |
-
) );
|
25 |
-
self::enqueueScripts( array(
|
26 |
-
'backend' => array( 'js/alert.js' => array( 'jquery' ), ),
|
27 |
-
'frontend' => array(
|
28 |
-
'js/spin.min.js' => array( 'jquery' ),
|
29 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
30 |
-
),
|
31 |
-
'module' => array( 'js/subscribe.js' => array( 'bookly-alert.js', 'bookly-ladda.min.js', ), ),
|
32 |
-
) );
|
33 |
-
|
34 |
-
self::renderTemplate( 'subscribe' );
|
35 |
-
}
|
36 |
-
}
|
37 |
-
}
|
38 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Subscribe
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class Subscribe extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render subscribe notice.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
if ( Lib\Utils\Common::isCurrentUserAdmin() &&
|
18 |
+
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_subscribe_notice', true ) ) {
|
19 |
+
|
20 |
+
// Show notice 1 day after installation time.
|
21 |
+
if ( time() - Lib\Plugin::getInstallationTime() >= DAY_IN_SECONDS ) {
|
22 |
+
self::enqueueStyles( array(
|
23 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
24 |
+
) );
|
25 |
+
self::enqueueScripts( array(
|
26 |
+
'backend' => array( 'js/alert.js' => array( 'jquery' ), ),
|
27 |
+
'frontend' => array(
|
28 |
+
'js/spin.min.js' => array( 'jquery' ),
|
29 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
30 |
+
),
|
31 |
+
'module' => array( 'js/subscribe.js' => array( 'bookly-alert.js', 'bookly-ladda.min.js', ), ),
|
32 |
+
) );
|
33 |
+
|
34 |
+
self::renderTemplate( 'subscribe' );
|
35 |
+
}
|
36 |
+
}
|
37 |
+
}
|
38 |
}
|
backend/components/notices/SubscribeAjax.php
CHANGED
@@ -1,36 +1,46 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class SubscribeAjax
|
8 |
-
* @package Bookly\Backend\Components\Notices
|
9 |
-
*/
|
10 |
-
class SubscribeAjax extends Lib\Base\Ajax
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Subscribe to monthly emails.
|
14 |
-
*/
|
15 |
-
public static function subscribe()
|
16 |
-
{
|
17 |
-
$email = self::parameter( 'email' );
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class SubscribeAjax
|
8 |
+
* @package Bookly\Backend\Components\Notices
|
9 |
+
*/
|
10 |
+
class SubscribeAjax extends Lib\Base\Ajax
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Subscribe to monthly emails.
|
14 |
+
*/
|
15 |
+
public static function subscribe()
|
16 |
+
{
|
17 |
+
$email = self::parameter( 'email' );
|
18 |
+
$state = 'invalid';
|
19 |
+
if ( is_email( $email ) ) {
|
20 |
+
$state = Lib\API::registerSubscriber( $email );
|
21 |
+
}
|
22 |
+
|
23 |
+
switch ( $state ) {
|
24 |
+
case 'success':
|
25 |
+
wp_send_json_success( array( 'message' => __( 'Please, check your email to confirm the subscription. Thank you!', 'bookly' ) ) );
|
26 |
+
break;
|
27 |
+
case 'exists':
|
28 |
+
wp_send_json_success( array( 'message' => __( 'Given email address is already subscribed, thank you!', 'bookly' ) ) );
|
29 |
+
break;
|
30 |
+
case 'invalid':
|
31 |
+
default:
|
32 |
+
wp_send_json_error( array( 'message' => __( 'This email address is not valid.', 'bookly' ) ) );
|
33 |
+
break;
|
34 |
+
}
|
35 |
+
}
|
36 |
+
|
37 |
+
/**
|
38 |
+
* Dismiss subscribe notice.
|
39 |
+
*/
|
40 |
+
public static function dismissSubscribeNotice()
|
41 |
+
{
|
42 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_subscribe_notice', 1 );
|
43 |
+
|
44 |
+
wp_send_json_success();
|
45 |
+
}
|
46 |
}
|
backend/components/notices/proxy/Pro.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Notices\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Components\Notices\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderWelcome()
|
11 |
-
*/
|
12 |
-
abstract class Pro extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Notices\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Components\Notices\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderWelcome()
|
11 |
+
*/
|
12 |
+
abstract class Pro extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/notices/resources/css/bootstrap-stars.css
CHANGED
@@ -1,38 +1,38 @@
|
|
1 |
-
.br-theme-bootstrap-stars .br-widget {
|
2 |
-
height: 28px;
|
3 |
-
white-space: nowrap;
|
4 |
-
}
|
5 |
-
.br-theme-bootstrap-stars .br-widget a {
|
6 |
-
font: normal normal normal 30px/1 'Glyphicons Halflings';
|
7 |
-
text-rendering: auto;
|
8 |
-
-webkit-font-smoothing: antialiased;
|
9 |
-
text-decoration: none;
|
10 |
-
margin-right: 2px;
|
11 |
-
}
|
12 |
-
.br-theme-bootstrap-stars .br-widget a:after {
|
13 |
-
content: '\e006';
|
14 |
-
color: #d2d2d2;
|
15 |
-
}
|
16 |
-
.br-theme-bootstrap-stars .br-widget a.br-active:after {
|
17 |
-
color: #EDB867;
|
18 |
-
}
|
19 |
-
.br-theme-bootstrap-stars .br-widget a.br-selected:after {
|
20 |
-
color: #EDB867;
|
21 |
-
}
|
22 |
-
.br-theme-bootstrap-stars .br-widget .br-current-rating {
|
23 |
-
display: none;
|
24 |
-
}
|
25 |
-
.br-theme-bootstrap-stars .br-readonly a {
|
26 |
-
cursor: default;
|
27 |
-
}
|
28 |
-
@media print {
|
29 |
-
.br-theme-bootstrap-stars .br-widget a:after {
|
30 |
-
content: '\e007';
|
31 |
-
color: black;
|
32 |
-
}
|
33 |
-
.br-theme-bootstrap-stars .br-widget a.br-active:after,
|
34 |
-
.br-theme-bootstrap-stars .br-widget a.br-selected:after {
|
35 |
-
content: '\e006';
|
36 |
-
color: black;
|
37 |
-
}
|
38 |
-
}
|
1 |
+
.br-theme-bootstrap-stars .br-widget {
|
2 |
+
height: 28px;
|
3 |
+
white-space: nowrap;
|
4 |
+
}
|
5 |
+
.br-theme-bootstrap-stars .br-widget a {
|
6 |
+
font: normal normal normal 30px/1 'Glyphicons Halflings';
|
7 |
+
text-rendering: auto;
|
8 |
+
-webkit-font-smoothing: antialiased;
|
9 |
+
text-decoration: none;
|
10 |
+
margin-right: 2px;
|
11 |
+
}
|
12 |
+
.br-theme-bootstrap-stars .br-widget a:after {
|
13 |
+
content: '\e006';
|
14 |
+
color: #d2d2d2;
|
15 |
+
}
|
16 |
+
.br-theme-bootstrap-stars .br-widget a.br-active:after {
|
17 |
+
color: #EDB867;
|
18 |
+
}
|
19 |
+
.br-theme-bootstrap-stars .br-widget a.br-selected:after {
|
20 |
+
color: #EDB867;
|
21 |
+
}
|
22 |
+
.br-theme-bootstrap-stars .br-widget .br-current-rating {
|
23 |
+
display: none;
|
24 |
+
}
|
25 |
+
.br-theme-bootstrap-stars .br-readonly a {
|
26 |
+
cursor: default;
|
27 |
+
}
|
28 |
+
@media print {
|
29 |
+
.br-theme-bootstrap-stars .br-widget a:after {
|
30 |
+
content: '\e007';
|
31 |
+
color: black;
|
32 |
+
}
|
33 |
+
.br-theme-bootstrap-stars .br-widget a.br-active:after,
|
34 |
+
.br-theme-bootstrap-stars .br-widget a.br-selected:after {
|
35 |
+
content: '\e006';
|
36 |
+
color: black;
|
37 |
+
}
|
38 |
+
}
|
backend/components/notices/resources/js/collect-stats.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1 |
-
jQuery(function ($) {
|
2 |
-
var $notice = $('#bookly-collect-stats-notice');
|
3 |
-
$notice.on('close.bs.alert', function () {
|
4 |
-
$.post(ajaxurl, {action: $notice.data('action'), csrf_token : SupportL10n.csrf_token});
|
5 |
-
});
|
6 |
-
$notice.find('#bookly-enable-collecting-stats-btn').on('click', function () {
|
7 |
-
$.post(ajaxurl, {action: 'bookly_enable_collecting_stats', csrf_token : SupportL10n.csrf_token});
|
8 |
-
});
|
9 |
});
|
1 |
+
jQuery(function ($) {
|
2 |
+
var $notice = $('#bookly-collect-stats-notice');
|
3 |
+
$notice.on('close.bs.alert', function () {
|
4 |
+
$.post(ajaxurl, {action: $notice.data('action'), csrf_token : SupportL10n.csrf_token});
|
5 |
+
});
|
6 |
+
$notice.find('#bookly-enable-collecting-stats-btn').on('click', function () {
|
7 |
+
$.post(ajaxurl, {action: 'bookly_enable_collecting_stats', csrf_token : SupportL10n.csrf_token});
|
8 |
+
});
|
9 |
});
|
backend/components/notices/resources/js/lite-rebranding.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1 |
-
jQuery(function ($) {
|
2 |
-
var $notice = $('#bookly-lite-rebranding-notice');
|
3 |
-
$notice.on('close.bs.alert', function () {
|
4 |
-
$.post(ajaxurl, {action: $notice.data('action'), csrf_token : SupportL10n.csrf_token});
|
5 |
-
});
|
6 |
});
|
1 |
+
jQuery(function ($) {
|
2 |
+
var $notice = $('#bookly-lite-rebranding-notice');
|
3 |
+
$notice.on('close.bs.alert', function () {
|
4 |
+
$.post(ajaxurl, {action: $notice.data('action'), csrf_token : SupportL10n.csrf_token});
|
5 |
+
});
|
6 |
});
|
backend/components/notices/resources/js/nps.js
CHANGED
@@ -1,60 +1,60 @@
|
|
1 |
-
jQuery(function ($) {
|
2 |
-
var $alert = $('#bookly-nps-notice'),
|
3 |
-
$quiz = $('#bookly-nps-quiz'),
|
4 |
-
$stars = $('#bookly-nps-stars'),
|
5 |
-
$msg = $('#bookly-nps-msg'),
|
6 |
-
$email = $('#bookly-nps-email'),
|
7 |
-
$form = $('#bookly-nps-form'),
|
8 |
-
$thanks = $('#bookly-nps-thanks')
|
9 |
-
;
|
10 |
-
|
11 |
-
// Init stars.
|
12 |
-
$stars.barrating({
|
13 |
-
theme: 'bootstrap-stars',
|
14 |
-
allowEmpty: false,
|
15 |
-
onSelect: function (value, text, event) {
|
16 |
-
if (value <= 7) {
|
17 |
-
$form.show();
|
18 |
-
} else {
|
19 |
-
$.post(ajaxurl, {action: 'bookly_nps_send', csrf_token : SupportL10n.csrf_token, rate: value});
|
20 |
-
$quiz.hide();
|
21 |
-
$form.hide();
|
22 |
-
$thanks.show();
|
23 |
-
}
|
24 |
-
}
|
25 |
-
});
|
26 |
-
|
27 |
-
$('#bookly-nps-btn').on('click', function () {
|
28 |
-
$alert.find('.form-group').removeClass('has-error');
|
29 |
-
if ($msg.val() == '') {
|
30 |
-
$msg.closest('.form-group').addClass('has-error');
|
31 |
-
} else {
|
32 |
-
var ladda = Ladda.create(this);
|
33 |
-
ladda.start();
|
34 |
-
$.post(
|
35 |
-
ajaxurl,
|
36 |
-
{
|
37 |
-
action : 'bookly_nps_send',
|
38 |
-
csrf_token : SupportL10n.csrf_token,
|
39 |
-
rate : $stars.val(),
|
40 |
-
msg : $msg.val(),
|
41 |
-
email : $email.val()
|
42 |
-
},
|
43 |
-
function (response) {
|
44 |
-
ladda.stop();
|
45 |
-
if (response.success) {
|
46 |
-
$alert.alert('close');
|
47 |
-
booklyAlert({success : [response.data.message]});
|
48 |
-
}
|
49 |
-
}
|
50 |
-
);
|
51 |
-
}
|
52 |
-
});
|
53 |
-
|
54 |
-
$alert.on('close.bs.alert', function () {
|
55 |
-
$.post(ajaxurl, {action: 'bookly_dismiss_nps_notice', csrf_token : SupportL10n.csrf_token}, function () {
|
56 |
-
// Indicator for Selenium that request has completed.
|
57 |
-
$('.bookly-js-nps-notice').remove();
|
58 |
-
});
|
59 |
-
});
|
60 |
});
|
1 |
+
jQuery(function ($) {
|
2 |
+
var $alert = $('#bookly-nps-notice'),
|
3 |
+
$quiz = $('#bookly-nps-quiz'),
|
4 |
+
$stars = $('#bookly-nps-stars'),
|
5 |
+
$msg = $('#bookly-nps-msg'),
|
6 |
+
$email = $('#bookly-nps-email'),
|
7 |
+
$form = $('#bookly-nps-form'),
|
8 |
+
$thanks = $('#bookly-nps-thanks')
|
9 |
+
;
|
10 |
+
|
11 |
+
// Init stars.
|
12 |
+
$stars.barrating({
|
13 |
+
theme: 'bootstrap-stars',
|
14 |
+
allowEmpty: false,
|
15 |
+
onSelect: function (value, text, event) {
|
16 |
+
if (value <= 7) {
|
17 |
+
$form.show();
|
18 |
+
} else {
|
19 |
+
$.post(ajaxurl, {action: 'bookly_nps_send', csrf_token : SupportL10n.csrf_token, rate: value});
|
20 |
+
$quiz.hide();
|
21 |
+
$form.hide();
|
22 |
+
$thanks.show();
|
23 |
+
}
|
24 |
+
}
|
25 |
+
});
|
26 |
+
|
27 |
+
$('#bookly-nps-btn').on('click', function () {
|
28 |
+
$alert.find('.form-group').removeClass('has-error');
|
29 |
+
if ($msg.val() == '') {
|
30 |
+
$msg.closest('.form-group').addClass('has-error');
|
31 |
+
} else {
|
32 |
+
var ladda = Ladda.create(this);
|
33 |
+
ladda.start();
|
34 |
+
$.post(
|
35 |
+
ajaxurl,
|
36 |
+
{
|
37 |
+
action : 'bookly_nps_send',
|
38 |
+
csrf_token : SupportL10n.csrf_token,
|
39 |
+
rate : $stars.val(),
|
40 |
+
msg : $msg.val(),
|
41 |
+
email : $email.val()
|
42 |
+
},
|
43 |
+
function (response) {
|
44 |
+
ladda.stop();
|
45 |
+
if (response.success) {
|
46 |
+
$alert.alert('close');
|
47 |
+
booklyAlert({success : [response.data.message]});
|
48 |
+
}
|
49 |
+
}
|
50 |
+
);
|
51 |
+
}
|
52 |
+
});
|
53 |
+
|
54 |
+
$alert.on('close.bs.alert', function () {
|
55 |
+
$.post(ajaxurl, {action: 'bookly_dismiss_nps_notice', csrf_token : SupportL10n.csrf_token}, function () {
|
56 |
+
// Indicator for Selenium that request has completed.
|
57 |
+
$('.bookly-js-nps-notice').remove();
|
58 |
+
});
|
59 |
+
});
|
60 |
});
|
backend/components/notices/resources/js/subscribe.js
CHANGED
@@ -1,24 +1,24 @@
|
|
1 |
-
jQuery(function ($) {
|
2 |
-
var $alert = $('#bookly-subscribe-notice');
|
3 |
-
$('#bookly-subscribe-btn').on('click', function () {
|
4 |
-
$alert.find('.input-group').removeClass('has-error');
|
5 |
-
var ladda = Ladda.create(this);
|
6 |
-
ladda.start();
|
7 |
-
$.post(ajaxurl, {action: 'bookly_subscribe', csrf_token : SupportL10n.csrf_token, email: $('#bookly-subscribe-email').val()}, function (response) {
|
8 |
-
ladda.stop();
|
9 |
-
if (response.success) {
|
10 |
-
$alert.alert('close');
|
11 |
-
booklyAlert({success
|
12 |
-
} else {
|
13 |
-
$alert.find('.input-group').addClass('has-error');
|
14 |
-
booklyAlert({error : [response.data.message]});
|
15 |
-
}
|
16 |
-
});
|
17 |
-
});
|
18 |
-
$alert.on('close.bs.alert', function () {
|
19 |
-
$.post(ajaxurl, {action: 'bookly_dismiss_subscribe_notice', csrf_token : SupportL10n.csrf_token}, function () {
|
20 |
-
// Indicator for Selenium that request has completed.
|
21 |
-
$
|
22 |
-
});
|
23 |
-
});
|
24 |
});
|
1 |
+
jQuery(function ($) {
|
2 |
+
var $alert = $('#bookly-subscribe-notice');
|
3 |
+
$('#bookly-subscribe-btn').on('click', function () {
|
4 |
+
$alert.find('.input-group').removeClass('has-error');
|
5 |
+
var ladda = Ladda.create(this);
|
6 |
+
ladda.start();
|
7 |
+
$.post(ajaxurl, {action: 'bookly_subscribe', csrf_token : SupportL10n.csrf_token, email: $('#bookly-subscribe-email').val()}, function (response) {
|
8 |
+
ladda.stop();
|
9 |
+
if (response.success) {
|
10 |
+
$alert.alert('close');
|
11 |
+
booklyAlert({success: [response.data.message]});
|
12 |
+
} else {
|
13 |
+
$alert.find('.input-group').addClass('has-error');
|
14 |
+
booklyAlert({error : [response.data.message]});
|
15 |
+
}
|
16 |
+
});
|
17 |
+
});
|
18 |
+
$alert.on('close.bs.alert', function () {
|
19 |
+
$.post(ajaxurl, {action: 'bookly_dismiss_subscribe_notice', csrf_token : SupportL10n.csrf_token}, function () {
|
20 |
+
// Indicator for Selenium that request has completed.
|
21 |
+
$alert.remove();
|
22 |
+
});
|
23 |
+
});
|
24 |
});
|
backend/components/notices/templates/collect_stats.php
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-tbs" class="wrap">
|
3 |
-
<div id="bookly-collect-stats-notice" class="alert alert-info bookly-tbs-body bookly-flexbox" data-action="bookly_dismiss_collect<?php if ( $enabled ): ?>ing<?php endif ?>_stats_notice">
|
4 |
-
<div class="bookly-flex-row">
|
5 |
-
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
6 |
-
<div class="bookly-flex-cell">
|
7 |
-
<button type="button" class="close" data-dismiss="alert">×</button>
|
8 |
-
<?php if ( $enabled ): ?>
|
9 |
-
<?php esc_html_e( 'To help us improve Bookly, the plugin anonymously collects usage information. You can opt out of sharing the information in Settings > General.', 'bookly' ) ?>
|
10 |
-
<div class="bookly-margin-top-md">
|
11 |
-
<button type="button" class="btn btn-primary" data-dismiss="alert"><?php esc_html_e( 'Close', 'bookly' ) ?></button>
|
12 |
-
</div>
|
13 |
-
<?php else: ?>
|
14 |
-
<?php esc_html_e( 'Let the plugin anonymously collect usage information to help Bookly team improve the product.', 'bookly' ) ?>
|
15 |
-
<div class="bookly-margin-top-md">
|
16 |
-
<button type="button" class="btn btn-default" data-dismiss="alert"><?php esc_html_e( 'Disagree', 'bookly' ) ?></button>
|
17 |
-
<button type="button" class="btn btn-success" id="bookly-enable-collecting-stats-btn" data-dismiss="alert"><?php esc_html_e( 'Agree', 'bookly' ) ?></button>
|
18 |
-
</div>
|
19 |
-
<?php endif ?>
|
20 |
-
</div>
|
21 |
-
</div>
|
22 |
-
</div>
|
23 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-tbs" class="wrap">
|
3 |
+
<div id="bookly-collect-stats-notice" class="alert alert-info bookly-tbs-body bookly-flexbox" data-action="bookly_dismiss_collect<?php if ( $enabled ): ?>ing<?php endif ?>_stats_notice">
|
4 |
+
<div class="bookly-flex-row">
|
5 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
6 |
+
<div class="bookly-flex-cell">
|
7 |
+
<button type="button" class="close" data-dismiss="alert">×</button>
|
8 |
+
<?php if ( $enabled ): ?>
|
9 |
+
<?php esc_html_e( 'To help us improve Bookly, the plugin anonymously collects usage information. You can opt out of sharing the information in Settings > General.', 'bookly' ) ?>
|
10 |
+
<div class="bookly-margin-top-md">
|
11 |
+
<button type="button" class="btn btn-primary" data-dismiss="alert"><?php esc_html_e( 'Close', 'bookly' ) ?></button>
|
12 |
+
</div>
|
13 |
+
<?php else: ?>
|
14 |
+
<?php esc_html_e( 'Let the plugin anonymously collect usage information to help Bookly team improve the product.', 'bookly' ) ?>
|
15 |
+
<div class="bookly-margin-top-md">
|
16 |
+
<button type="button" class="btn btn-default" data-dismiss="alert"><?php esc_html_e( 'Disagree', 'bookly' ) ?></button>
|
17 |
+
<button type="button" class="btn btn-success" id="bookly-enable-collecting-stats-btn" data-dismiss="alert"><?php esc_html_e( 'Agree', 'bookly' ) ?></button>
|
18 |
+
</div>
|
19 |
+
<?php endif ?>
|
20 |
+
</div>
|
21 |
+
</div>
|
22 |
+
</div>
|
23 |
</div>
|
backend/components/notices/templates/limitation.php
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<b class="h4"><?php _e( 'This function is not available in the Bookly.', 'bookly' ) ?></b>
|
3 |
<br><br><?php _e( 'To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Pro version of Bookly.<br>For more information visit', 'bookly' ) ?> <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://www.booking-wp-plugin.com</a>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<b class="h4"><?php _e( 'This function is not available in the Bookly.', 'bookly' ) ?></b>
|
3 |
<br><br><?php _e( 'To get access to all Bookly features, lifetime free updates and 24/7 support, please upgrade to the Pro version of Bookly.<br>For more information visit', 'bookly' ) ?> <a href="http://booking-wp-plugin.com" target="_blank" class="alert-link">http://www.booking-wp-plugin.com</a>
|
backend/components/notices/templates/lite_rebranding.php
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-tbs" class="wrap">
|
3 |
-
<div id="bookly-lite-rebranding-notice" class="alert alert-info bookly-tbs-body bookly-flexbox" data-action="bookly_dismiss_lite_rebranding_notice">
|
4 |
-
<div class="bookly-flex-row">
|
5 |
-
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
6 |
-
<div class="bookly-flex-cell">
|
7 |
-
<button type="button" class="close" data-dismiss="alert">×</button>
|
8 |
-
<?php printf( __( '<b>Bookly Lite rebrands into Bookly with more features available.</b><br/><br/>We have changed the architecture of Bookly Lite and Bookly to optimize the development of both plugin versions and add more features to the new free Bookly. To learn more about the major Bookly update, check our <a href="%s" target="_blank">blog post</a>.', 'bookly' ), 'https://www.booking-wp-plugin.com/bookly-major-update/?utm_source=bookly_admin&utm_medium=pro_not_active&utm_campaign=notification' ) ?>
|
9 |
-
</div>
|
10 |
-
</div>
|
11 |
-
</div>
|
12 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-tbs" class="wrap">
|
3 |
+
<div id="bookly-lite-rebranding-notice" class="alert alert-info bookly-tbs-body bookly-flexbox" data-action="bookly_dismiss_lite_rebranding_notice">
|
4 |
+
<div class="bookly-flex-row">
|
5 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
6 |
+
<div class="bookly-flex-cell">
|
7 |
+
<button type="button" class="close" data-dismiss="alert">×</button>
|
8 |
+
<?php printf( __( '<b>Bookly Lite rebrands into Bookly with more features available.</b><br/><br/>We have changed the architecture of Bookly Lite and Bookly to optimize the development of both plugin versions and add more features to the new free Bookly. To learn more about the major Bookly update, check our <a href="%s" target="_blank">blog post</a>.', 'bookly' ), 'https://www.booking-wp-plugin.com/bookly-major-update/?utm_source=bookly_admin&utm_medium=pro_not_active&utm_campaign=notification' ) ?>
|
9 |
+
</div>
|
10 |
+
</div>
|
11 |
+
</div>
|
12 |
</div>
|
backend/components/notices/templates/nps.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
use Bookly\Backend\Components\Support\Lib\Urls;
|
4 |
-
use Bookly\Lib\Utils\Common;
|
5 |
-
?>
|
6 |
-
<div id="bookly-tbs" class="wrap bookly-js-nps-notice">
|
7 |
-
<div id="bookly-nps-notice" class="alert alert-info bookly-tbs-body bookly-flexbox">
|
8 |
-
<div class="bookly-flex-row">
|
9 |
-
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
10 |
-
<div class="bookly-flex-cell">
|
11 |
-
<button type="button" class="close" data-dismiss="alert">×</button>
|
12 |
-
<div id="bookly-nps-quiz">
|
13 |
-
<label><?php
|
14 |
-
<select id="bookly-nps-stars" class="hidden">
|
15 |
-
<option value=""></option>
|
16 |
-
<?php for ( $i = 1; $i <= 10; ++ $i ): ?>
|
17 |
-
<option value="<?php echo $i ?>"><?php echo $i ?></option>
|
18 |
-
<?php endfor ?>
|
19 |
-
</select>
|
20 |
-
</div>
|
21 |
-
<div id="bookly-nps-form" class="bookly-margin-top-lg" style="max-width:400px;display:none;">
|
22 |
-
<div class="form-group">
|
23 |
-
<label for="bookly-nps-msg" class="control-label"><?php
|
24 |
-
<textarea id="bookly-nps-msg" class="form-control"></textarea>
|
25 |
-
</div>
|
26 |
-
<div class="form-group">
|
27 |
-
<label for="bookly-nps-email" class="control-label"><?php
|
28 |
-
<input type="text" id="bookly-nps-email" class="form-control" value="<?php echo esc_attr( $current_user->user_email ) ?>" />
|
29 |
-
</div>
|
30 |
-
<?php Buttons::renderCustom( 'bookly-nps-btn', 'btn-success', __( 'Send', 'bookly' ) ) ?>
|
31 |
-
</div>
|
32 |
-
<div id="bookly-nps-thanks" style="display:none;">
|
33 |
-
<?php printf(
|
34 |
-
__( 'Please leave your feedback <a href="%s" target="_blank">here</a>.', 'bookly' ),
|
35 |
-
Common::prepareUrlReferrers( Urls::
|
36 |
-
) ?>
|
37 |
-
</div>
|
38 |
-
</div>
|
39 |
-
</div>
|
40 |
-
</div>
|
41 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
use Bookly\Backend\Components\Support\Lib\Urls;
|
4 |
+
use Bookly\Lib\Utils\Common;
|
5 |
+
?>
|
6 |
+
<div id="bookly-tbs" class="wrap bookly-js-nps-notice">
|
7 |
+
<div id="bookly-nps-notice" class="alert alert-info bookly-tbs-body bookly-flexbox">
|
8 |
+
<div class="bookly-flex-row">
|
9 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
10 |
+
<div class="bookly-flex-cell">
|
11 |
+
<button type="button" class="close" data-dismiss="alert">×</button>
|
12 |
+
<div id="bookly-nps-quiz">
|
13 |
+
<label><?php esc_html_e( 'How likely is it that you would recommend Bookly to a friend or colleague?', 'bookly' ) ?></label>
|
14 |
+
<select id="bookly-nps-stars" class="hidden">
|
15 |
+
<option value=""></option>
|
16 |
+
<?php for ( $i = 1; $i <= 10; ++ $i ): ?>
|
17 |
+
<option value="<?php echo $i ?>"><?php echo $i ?></option>
|
18 |
+
<?php endfor ?>
|
19 |
+
</select>
|
20 |
+
</div>
|
21 |
+
<div id="bookly-nps-form" class="bookly-margin-top-lg" style="max-width:400px;display:none;">
|
22 |
+
<div class="form-group">
|
23 |
+
<label for="bookly-nps-msg" class="control-label"><?php esc_html_e( 'What do you think should be improved?', 'bookly' ) ?></label>
|
24 |
+
<textarea id="bookly-nps-msg" class="form-control"></textarea>
|
25 |
+
</div>
|
26 |
+
<div class="form-group">
|
27 |
+
<label for="bookly-nps-email" class="control-label"><?php esc_html_e( 'Please enter your email (optional)', 'bookly' ) ?></label>
|
28 |
+
<input type="text" id="bookly-nps-email" class="form-control" value="<?php echo esc_attr( $current_user->user_email ) ?>" />
|
29 |
+
</div>
|
30 |
+
<?php Buttons::renderCustom( 'bookly-nps-btn', 'btn-success', __( 'Send', 'bookly' ) ) ?>
|
31 |
+
</div>
|
32 |
+
<div id="bookly-nps-thanks" style="display:none;">
|
33 |
+
<?php printf(
|
34 |
+
__( 'Please leave your feedback <a href="%s" target="_blank">here</a>.', 'bookly' ),
|
35 |
+
Common::prepareUrlReferrers( Urls::REVIEWS_PAGE, 'nps' )
|
36 |
+
) ?>
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
</div>
|
40 |
+
</div>
|
41 |
</div>
|
backend/components/notices/templates/subscribe.php
CHANGED
@@ -1,21 +1,21 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-tbs" class="wrap bookly-js-subscribe-notice">
|
3 |
-
<div id="bookly-subscribe-notice" class="alert alert-info bookly-tbs-body bookly-flexbox">
|
4 |
-
<div class="bookly-flex-row">
|
5 |
-
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
6 |
-
<div class="bookly-flex-cell">
|
7 |
-
<button type="button" class="close" data-dismiss="alert">×</button>
|
8 |
-
<label for="bookly-subscribe-email"><?php _e( 'Subscribe to monthly emails about Bookly improvements and new releases.', 'bookly' ) ?></label>
|
9 |
-
<div class="input-group input-group-sm" style="max-width: 400px">
|
10 |
-
<span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
|
11 |
-
<input type="text" id="bookly-subscribe-email" class="form-control" />
|
12 |
-
<span class="input-group-btn">
|
13 |
-
<button type="button" id="bookly-subscribe-btn" class="btn btn-info ladda-button" data-spinner-size="30" data-style="zoom-in">
|
14 |
-
<span class="ladda-label"><?php _e( 'Send', 'bookly' ) ?></span>
|
15 |
-
</button>
|
16 |
-
</span>
|
17 |
-
</div>
|
18 |
-
</div>
|
19 |
-
</div>
|
20 |
-
</div>
|
21 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-tbs" class="wrap bookly-js-subscribe-notice">
|
3 |
+
<div id="bookly-subscribe-notice" class="alert alert-info bookly-tbs-body bookly-flexbox">
|
4 |
+
<div class="bookly-flex-row">
|
5 |
+
<div class="bookly-flex-cell" style="width:39px"><i class="alert-icon"></i></div>
|
6 |
+
<div class="bookly-flex-cell">
|
7 |
+
<button type="button" class="close" data-dismiss="alert">×</button>
|
8 |
+
<label for="bookly-subscribe-email"><?php _e( 'Subscribe to monthly emails about Bookly improvements and new releases.', 'bookly' ) ?></label>
|
9 |
+
<div class="input-group input-group-sm" style="max-width: 400px">
|
10 |
+
<span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
|
11 |
+
<input type="text" id="bookly-subscribe-email" class="form-control" />
|
12 |
+
<span class="input-group-btn">
|
13 |
+
<button type="button" id="bookly-subscribe-btn" class="btn btn-info ladda-button" data-spinner-size="30" data-style="zoom-in">
|
14 |
+
<span class="ladda-label"><?php _e( 'Send', 'bookly' ) ?></span>
|
15 |
+
</button>
|
16 |
+
</span>
|
17 |
+
</div>
|
18 |
+
</div>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
</div>
|
backend/components/settings/Image.php
CHANGED
@@ -1,30 +1,30 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Image
|
8 |
-
* @package Bookly\Backend\Components\Settings
|
9 |
-
*/
|
10 |
-
class Image extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render media image attachment.
|
14 |
-
*
|
15 |
-
* @param string $option_name
|
16 |
-
* @param string $class
|
17 |
-
*/
|
18 |
-
public static function render( $option_name, $class = 'lg' )
|
19 |
-
{
|
20 |
-
$img = wp_get_attachment_image_src( get_option( $option_name ), 'full' );
|
21 |
-
|
22 |
-
self::renderTemplate( 'image', array(
|
23 |
-
'option_name' => $option_name,
|
24 |
-
'option_value' => get_option( $option_name ),
|
25 |
-
'class' => $class,
|
26 |
-
'img_style' => $img ? 'background-image: url(' . $img[0] . '); background-size: contain;' : '',
|
27 |
-
'delete_style' => $img ? '' : 'display: none;',
|
28 |
-
) );
|
29 |
-
}
|
30 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Image
|
8 |
+
* @package Bookly\Backend\Components\Settings
|
9 |
+
*/
|
10 |
+
class Image extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render media image attachment.
|
14 |
+
*
|
15 |
+
* @param string $option_name
|
16 |
+
* @param string $class
|
17 |
+
*/
|
18 |
+
public static function render( $option_name, $class = 'lg' )
|
19 |
+
{
|
20 |
+
$img = wp_get_attachment_image_src( get_option( $option_name ), 'full' );
|
21 |
+
|
22 |
+
self::renderTemplate( 'image', array(
|
23 |
+
'option_name' => $option_name,
|
24 |
+
'option_value' => get_option( $option_name ),
|
25 |
+
'class' => $class,
|
26 |
+
'img_style' => $img ? 'background-image: url(' . $img[0] . '); background-size: contain;' : '',
|
27 |
+
'delete_style' => $img ? '' : 'display: none;',
|
28 |
+
) );
|
29 |
+
}
|
30 |
}
|
backend/components/settings/Inputs.php
CHANGED
@@ -1,76 +1,99 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class Inputs
|
6 |
-
* @package Bookly\Backend\Components\Settings
|
7 |
-
*/
|
8 |
-
class Inputs
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* Render numeric input.
|
12 |
-
*
|
13 |
-
* @param string $option_name
|
14 |
-
* @param string $label
|
15 |
-
* @param string $help
|
16 |
-
* @param int|null $min
|
17 |
-
* @param int|null $step
|
18 |
-
* @param int|null $max
|
19 |
-
*/
|
20 |
-
public static function renderNumber( $option_name, $label, $help, $min = null, $step = null, $max = null )
|
21 |
-
{
|
22 |
-
$control = strtr(
|
23 |
-
'<input type="number" id="{name}" class="form-control" name="{name}" value="{value}"{min}{max}{step} />',
|
24 |
-
array(
|
25 |
-
'{name}' => esc_attr( $option_name ),
|
26 |
-
'{value}' => esc_attr( get_option( $option_name ) ),
|
27 |
-
'{min}' => $min !== null ? ' min="' . $min . '"' : '',
|
28 |
-
'{max}' => $max !== null ? ' max="' . $max . '"' : '',
|
29 |
-
'{step}' => $step !== null ? ' step="' . $step . '"' : '',
|
30 |
-
)
|
31 |
-
);
|
32 |
-
|
33 |
-
echo self::buildControl( $option_name, $label, $help, $control );
|
34 |
-
}
|
35 |
-
|
36 |
-
/**
|
37 |
-
* Render text input.
|
38 |
-
*
|
39 |
-
* @param string $option_name
|
40 |
-
* @param string $label
|
41 |
-
* @param string|null $help
|
42 |
-
*/
|
43 |
-
public static function renderText( $option_name, $label, $help = null )
|
44 |
-
{
|
45 |
-
$control = strtr(
|
46 |
-
'<input type="text" id="{name}" class="form-control" name="{name}" value="{value}" />',
|
47 |
-
array(
|
48 |
-
'{name}' => esc_attr( $option_name ),
|
49 |
-
'{value}' => esc_attr( get_option( $option_name ) ),
|
50 |
-
)
|
51 |
-
);
|
52 |
-
|
53 |
-
echo self::buildControl( $option_name, $label, $help, $control );
|
54 |
-
}
|
55 |
-
|
56 |
-
/**
|
57 |
-
*
|
58 |
-
*
|
59 |
-
* @param string
|
60 |
-
* @param string
|
61 |
-
* @param string $help
|
62 |
-
* @param
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
'{
|
71 |
-
'{
|
72 |
-
'{
|
73 |
-
)
|
74 |
-
);
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
76 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class Inputs
|
6 |
+
* @package Bookly\Backend\Components\Settings
|
7 |
+
*/
|
8 |
+
class Inputs
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Render numeric input.
|
12 |
+
*
|
13 |
+
* @param string $option_name
|
14 |
+
* @param string $label
|
15 |
+
* @param string $help
|
16 |
+
* @param int|null $min
|
17 |
+
* @param int|null $step
|
18 |
+
* @param int|null $max
|
19 |
+
*/
|
20 |
+
public static function renderNumber( $option_name, $label, $help, $min = null, $step = null, $max = null )
|
21 |
+
{
|
22 |
+
$control = strtr(
|
23 |
+
'<input type="number" id="{name}" class="form-control" name="{name}" value="{value}"{min}{max}{step} />',
|
24 |
+
array(
|
25 |
+
'{name}' => esc_attr( $option_name ),
|
26 |
+
'{value}' => esc_attr( get_option( $option_name ) ),
|
27 |
+
'{min}' => $min !== null ? ' min="' . $min . '"' : '',
|
28 |
+
'{max}' => $max !== null ? ' max="' . $max . '"' : '',
|
29 |
+
'{step}' => $step !== null ? ' step="' . $step . '"' : '',
|
30 |
+
)
|
31 |
+
);
|
32 |
+
|
33 |
+
echo self::buildControl( $option_name, $label, $help, $control );
|
34 |
+
}
|
35 |
+
|
36 |
+
/**
|
37 |
+
* Render text input.
|
38 |
+
*
|
39 |
+
* @param string $option_name
|
40 |
+
* @param string $label
|
41 |
+
* @param string|null $help
|
42 |
+
*/
|
43 |
+
public static function renderText( $option_name, $label, $help = null )
|
44 |
+
{
|
45 |
+
$control = strtr(
|
46 |
+
'<input type="text" id="{name}" class="form-control" name="{name}" value="{value}" />',
|
47 |
+
array(
|
48 |
+
'{name}' => esc_attr( $option_name ),
|
49 |
+
'{value}' => esc_attr( get_option( $option_name ) ),
|
50 |
+
)
|
51 |
+
);
|
52 |
+
|
53 |
+
echo self::buildControl( $option_name, $label, $help, $control );
|
54 |
+
}
|
55 |
+
|
56 |
+
/**
|
57 |
+
* Render text area input.
|
58 |
+
*
|
59 |
+
* @param string $option_name
|
60 |
+
* @param string $label
|
61 |
+
* @param string|null $help
|
62 |
+
* @param int $rows
|
63 |
+
*/
|
64 |
+
public static function renderTextArea( $option_name, $label, $help = null, $rows = 9 )
|
65 |
+
{
|
66 |
+
$control = strtr(
|
67 |
+
'<textarea id="{name}" name="{name}" class="form-control" rows="{rows}" placeholder="{placeholder}">{value}</textarea>',
|
68 |
+
array(
|
69 |
+
'{name}' => esc_attr( $option_name ),
|
70 |
+
'{value}' => esc_textarea( get_option( $option_name ) ),
|
71 |
+
'{rows}' => $rows,
|
72 |
+
'{placeholder}' => esc_attr__( 'Enter a value', 'bookly' ),
|
73 |
+
)
|
74 |
+
);
|
75 |
+
|
76 |
+
echo self::buildControl( $option_name, $label, $help, $control );
|
77 |
+
}
|
78 |
+
|
79 |
+
/**
|
80 |
+
* Build setting control.
|
81 |
+
*
|
82 |
+
* @param string $option_name
|
83 |
+
* @param string $label
|
84 |
+
* @param string $help
|
85 |
+
* @param string $control_html
|
86 |
+
* @return string
|
87 |
+
*/
|
88 |
+
public static function buildControl( $option_name, $label, $help, $control_html )
|
89 |
+
{
|
90 |
+
return strtr(
|
91 |
+
'<div class="form-group">{label}{help}{control}</div>',
|
92 |
+
array(
|
93 |
+
'{label}' => $label != '' ? sprintf( '<label for="%s">%s</label>', $option_name, $label ) : '',
|
94 |
+
'{help}' => $help != '' ? sprintf( '<p class="help-block">%s</p>', $help ) : '',
|
95 |
+
'{control}' => $control_html,
|
96 |
+
)
|
97 |
+
);
|
98 |
+
}
|
99 |
}
|
backend/components/settings/Menu.php
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class Menu
|
6 |
-
* @package Bookly\Backend\Components\Settings
|
7 |
-
*/
|
8 |
-
class Menu
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* Render menu item on settings page.
|
12 |
-
*
|
13 |
-
* @param string $title
|
14 |
-
* @param string $tab
|
15 |
-
*/
|
16 |
-
public static function renderItem( $title, $tab )
|
17 |
-
{
|
18 |
-
printf( '<li class="bookly-nav-item" data-target="#bookly_settings_%s" data-toggle="tab">%s</li>',
|
19 |
-
$tab,
|
20 |
-
$title
|
21 |
-
);
|
22 |
-
}
|
23 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class Menu
|
6 |
+
* @package Bookly\Backend\Components\Settings
|
7 |
+
*/
|
8 |
+
class Menu
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Render menu item on settings page.
|
12 |
+
*
|
13 |
+
* @param string $title
|
14 |
+
* @param string $tab
|
15 |
+
*/
|
16 |
+
public static function renderItem( $title, $tab )
|
17 |
+
{
|
18 |
+
printf( '<li class="bookly-nav-item" data-target="#bookly_settings_%s" data-toggle="tab">%s</li>',
|
19 |
+
$tab,
|
20 |
+
$title
|
21 |
+
);
|
22 |
+
}
|
23 |
}
|
backend/components/settings/Payments.php
CHANGED
@@ -1,41 +1,41 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Payments
|
8 |
-
* @package Bookly\Backend\Components\Settings
|
9 |
-
*/
|
10 |
-
class Payments extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render discount and deduction for payment gateway.
|
14 |
-
*
|
15 |
-
* @param string $gateway
|
16 |
-
*/
|
17 |
-
public static function renderPriceCorrection( $gateway )
|
18 |
-
{
|
19 |
-
self::renderTemplate( 'price_correction', compact( 'gateway' ) );
|
20 |
-
}
|
21 |
-
|
22 |
-
/**
|
23 |
-
* Render tax settings for payment gateway.
|
24 |
-
*
|
25 |
-
* @param string $gateway
|
26 |
-
*/
|
27 |
-
public static function renderTax( $gateway )
|
28 |
-
{
|
29 |
-
if ( Lib\Config::taxesActive() ) {
|
30 |
-
Selects::renderSingle(
|
31 |
-
'bookly_' . $gateway . '_send_tax',
|
32 |
-
__( 'Send tax information', 'bookly' ),
|
33 |
-
null,
|
34 |
-
array(
|
35 |
-
array( 0, __( 'No', 'bookly' ) ),
|
36 |
-
array( 1, __( 'Yes', 'bookly' ) ),
|
37 |
-
)
|
38 |
-
);
|
39 |
-
}
|
40 |
-
}
|
41 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Payments
|
8 |
+
* @package Bookly\Backend\Components\Settings
|
9 |
+
*/
|
10 |
+
class Payments extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render discount and deduction for payment gateway.
|
14 |
+
*
|
15 |
+
* @param string $gateway
|
16 |
+
*/
|
17 |
+
public static function renderPriceCorrection( $gateway )
|
18 |
+
{
|
19 |
+
self::renderTemplate( 'price_correction', compact( 'gateway' ) );
|
20 |
+
}
|
21 |
+
|
22 |
+
/**
|
23 |
+
* Render tax settings for payment gateway.
|
24 |
+
*
|
25 |
+
* @param string $gateway
|
26 |
+
*/
|
27 |
+
public static function renderTax( $gateway )
|
28 |
+
{
|
29 |
+
if ( Lib\Config::taxesActive() ) {
|
30 |
+
Selects::renderSingle(
|
31 |
+
'bookly_' . $gateway . '_send_tax',
|
32 |
+
__( 'Send tax information', 'bookly' ),
|
33 |
+
null,
|
34 |
+
array(
|
35 |
+
array( 0, __( 'No', 'bookly' ) ),
|
36 |
+
array( 1, __( 'Yes', 'bookly' ) ),
|
37 |
+
)
|
38 |
+
);
|
39 |
+
}
|
40 |
+
}
|
41 |
}
|
backend/components/settings/Selects.php
CHANGED
@@ -1,80 +1,80 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class Selects
|
6 |
-
* @package Bookly\Backend\Components\Settings
|
7 |
-
*/
|
8 |
-
class Selects
|
9 |
-
{
|
10 |
-
/**
|
11 |
-
* Render multiple select (checkbox group).
|
12 |
-
*
|
13 |
-
* @param string $option_name
|
14 |
-
* @param string $label
|
15 |
-
* @param string $help
|
16 |
-
* @param array $options
|
17 |
-
*/
|
18 |
-
public static function renderMultiple( $option_name, $label = null, $help = null, array $options = array() )
|
19 |
-
{
|
20 |
-
$values = (array) get_option( $option_name );
|
21 |
-
$control = '';
|
22 |
-
foreach ( $options as $attr ) {
|
23 |
-
$control .= strtr(
|
24 |
-
'<div class="checkbox"><label><input type="checkbox" name="{name}[]" value="{value}"{checked} />{caption}</label></div>',
|
25 |
-
array(
|
26 |
-
'{name}' => $option_name,
|
27 |
-
'{value}' => esc_attr( $attr[0] ),
|
28 |
-
'{checked}' => checked( in_array( $attr[0], $values ), true, false ),
|
29 |
-
'{caption}' => esc_html( $attr[1] ),
|
30 |
-
)
|
31 |
-
);
|
32 |
-
}
|
33 |
-
$control = "<div class=\"bookly-flags\" id=\"$option_name\">$control</div>";
|
34 |
-
|
35 |
-
echo Inputs::buildControl( $option_name, $label, $help, $control );
|
36 |
-
}
|
37 |
-
|
38 |
-
/**
|
39 |
-
* Render drop-down select.
|
40 |
-
*
|
41 |
-
* @param string $option_name
|
42 |
-
* @param string $label
|
43 |
-
* @param array $options
|
44 |
-
* @param string $help
|
45 |
-
*/
|
46 |
-
public static function renderSingle( $option_name, $label = null, $help = null, array $options = array() )
|
47 |
-
{
|
48 |
-
if ( empty ( $options ) ) {
|
49 |
-
$options = array(
|
50 |
-
// value title disabled
|
51 |
-
array( 0, __( 'Disabled', 'bookly' ), 0 ),
|
52 |
-
array( 1, __( 'Enabled', 'bookly' ), 0 ),
|
53 |
-
);
|
54 |
-
}
|
55 |
-
|
56 |
-
$options_str = '';
|
57 |
-
foreach ( $options as $attr ) {
|
58 |
-
$options_str .= strtr(
|
59 |
-
'<option value="{value}"{attr}>{caption}</option>',
|
60 |
-
array(
|
61 |
-
'{value}' => esc_attr( $attr[ 0 ] ),
|
62 |
-
'{attr}' => empty ( $attr[ 2 ] )
|
63 |
-
? selected( get_option( $option_name ), $attr[0], false )
|
64 |
-
: disabled( true, true, false ),
|
65 |
-
'{caption}' => esc_html( $attr[1] ),
|
66 |
-
)
|
67 |
-
);
|
68 |
-
}
|
69 |
-
|
70 |
-
$control = strtr(
|
71 |
-
'<select id="{name}" class="form-control" name="{name}">{options}</select>',
|
72 |
-
array(
|
73 |
-
'{name}' => $option_name,
|
74 |
-
'{options}' => $options_str,
|
75 |
-
)
|
76 |
-
);
|
77 |
-
|
78 |
-
echo Inputs::buildControl( $option_name, $label, $help, $control );
|
79 |
-
}
|
80 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class Selects
|
6 |
+
* @package Bookly\Backend\Components\Settings
|
7 |
+
*/
|
8 |
+
class Selects
|
9 |
+
{
|
10 |
+
/**
|
11 |
+
* Render multiple select (checkbox group).
|
12 |
+
*
|
13 |
+
* @param string $option_name
|
14 |
+
* @param string $label
|
15 |
+
* @param string $help
|
16 |
+
* @param array $options
|
17 |
+
*/
|
18 |
+
public static function renderMultiple( $option_name, $label = null, $help = null, array $options = array() )
|
19 |
+
{
|
20 |
+
$values = (array) get_option( $option_name );
|
21 |
+
$control = '';
|
22 |
+
foreach ( $options as $attr ) {
|
23 |
+
$control .= strtr(
|
24 |
+
'<div class="checkbox"><label><input type="checkbox" name="{name}[]" value="{value}"{checked} />{caption}</label></div>',
|
25 |
+
array(
|
26 |
+
'{name}' => $option_name,
|
27 |
+
'{value}' => esc_attr( $attr[0] ),
|
28 |
+
'{checked}' => checked( in_array( $attr[0], $values ), true, false ),
|
29 |
+
'{caption}' => esc_html( $attr[1] ),
|
30 |
+
)
|
31 |
+
);
|
32 |
+
}
|
33 |
+
$control = "<div class=\"bookly-flags\" id=\"$option_name\">$control</div>";
|
34 |
+
|
35 |
+
echo Inputs::buildControl( $option_name, $label, $help, $control );
|
36 |
+
}
|
37 |
+
|
38 |
+
/**
|
39 |
+
* Render drop-down select.
|
40 |
+
*
|
41 |
+
* @param string $option_name
|
42 |
+
* @param string $label
|
43 |
+
* @param array $options
|
44 |
+
* @param string $help
|
45 |
+
*/
|
46 |
+
public static function renderSingle( $option_name, $label = null, $help = null, array $options = array() )
|
47 |
+
{
|
48 |
+
if ( empty ( $options ) ) {
|
49 |
+
$options = array(
|
50 |
+
// value title disabled
|
51 |
+
array( 0, __( 'Disabled', 'bookly' ), 0 ),
|
52 |
+
array( 1, __( 'Enabled', 'bookly' ), 0 ),
|
53 |
+
);
|
54 |
+
}
|
55 |
+
|
56 |
+
$options_str = '';
|
57 |
+
foreach ( $options as $attr ) {
|
58 |
+
$options_str .= strtr(
|
59 |
+
'<option value="{value}"{attr}>{caption}</option>',
|
60 |
+
array(
|
61 |
+
'{value}' => esc_attr( $attr[ 0 ] ),
|
62 |
+
'{attr}' => empty ( $attr[ 2 ] )
|
63 |
+
? selected( get_option( $option_name ), $attr[0], false )
|
64 |
+
: disabled( true, true, false ),
|
65 |
+
'{caption}' => esc_html( $attr[1] ),
|
66 |
+
)
|
67 |
+
);
|
68 |
+
}
|
69 |
+
|
70 |
+
$control = strtr(
|
71 |
+
'<select id="{name}" class="form-control" name="{name}">{options}</select>',
|
72 |
+
array(
|
73 |
+
'{name}' => $option_name,
|
74 |
+
'{options}' => $options_str,
|
75 |
+
)
|
76 |
+
);
|
77 |
+
|
78 |
+
echo Inputs::buildControl( $option_name, $label, $help, $control );
|
79 |
+
}
|
80 |
}
|
backend/components/settings/proxy/Pro.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Components\Settings\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderPurchaseCode( $blog_id = null ) Render purchase code
|
11 |
-
*/
|
12 |
-
abstract class Pro extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Components\Settings\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderPurchaseCode( $blog_id = null ) Render purchase code
|
11 |
+
*/
|
12 |
+
abstract class Pro extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/settings/proxy/Taxes.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Settings\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Taxes
|
8 |
-
* @package Bookly\Backend\Components\Settings\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderHelpMessage() Render tax help message.
|
11 |
-
*/
|
12 |
-
abstract class Taxes extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Settings\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Taxes
|
8 |
+
* @package Bookly\Backend\Components\Settings\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderHelpMessage() Render tax help message.
|
11 |
+
*/
|
12 |
+
abstract class Taxes extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/settings/templates/image.php
CHANGED
@@ -1,48 +1,48 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<div id="bookly-js-<?php echo esc_attr( $option_name ) ?>" class="bookly-thumb bookly-thumb-<?php echo $class ?> bookly-margin-right-lg">
|
3 |
-
<input type="hidden" name="<?php echo $option_name ?>" data-default="<?php echo esc_attr( $option_value ) ?>" value="<?php echo esc_attr( $option_value ) ?>">
|
4 |
-
<div class="bookly-flex-cell">
|
5 |
-
<div class="form-group">
|
6 |
-
<div class="bookly-js-image bookly-thumb bookly-thumb-<?php echo esc_attr( $class ) ?> bookly-margin-right-lg" style="<?php echo esc_attr( $img_style ) ?>" data-style="<?php echo esc_attr( $img_style ) ?>">
|
7 |
-
<a class="dashicons dashicons-trash text-danger bookly-thumb-delete" href="javascript:void(0)" style="<?php echo esc_attr( $delete_style ) ?>" title="<?php esc_attr_e( 'Delete', 'bookly' ) ?>"></a>
|
8 |
-
<div class="bookly-thumb-edit">
|
9 |
-
<div class="bookly-pretty"><label class="bookly-pretty-indicator bookly-thumb-edit-btn"><?php esc_html_e( 'Image', 'bookly' ) ?></label></div>
|
10 |
-
</div>
|
11 |
-
</div>
|
12 |
-
</div>
|
13 |
-
</div>
|
14 |
-
</div>
|
15 |
-
<script type="text/javascript">
|
16 |
-
jQuery(function ($) {
|
17 |
-
$('#bookly-js-<?php echo $option_name ?> .bookly-pretty-indicator').on('click', function(){
|
18 |
-
var frame = wp.media({
|
19 |
-
library: {type: 'image'},
|
20 |
-
multiple: false
|
21 |
-
});
|
22 |
-
frame.on('select', function () {
|
23 |
-
var selection = frame.state().get('selection').toJSON(),
|
24 |
-
img_src
|
25 |
-
;
|
26 |
-
if (selection.length) {
|
27 |
-
if (selection[0].sizes['full'] !== undefined) {
|
28 |
-
img_src = selection[0].sizes['full'].url;
|
29 |
-
} else {
|
30 |
-
img_src = selection[0].url;
|
31 |
-
}
|
32 |
-
$('[name=<?php echo $option_name ?>]').val(selection[0].id);
|
33 |
-
$('#bookly-js-<?php echo $option_name ?> .bookly-js-image').css({'background-image': 'url(' + img_src + ')', 'background-size': 'contain'});
|
34 |
-
$('#bookly-js-<?php echo $option_name ?> .bookly-thumb-delete').show();
|
35 |
-
$(this).hide();
|
36 |
-
}
|
37 |
-
});
|
38 |
-
frame.open();
|
39 |
-
});
|
40 |
-
|
41 |
-
$('#bookly-js-<?php echo $option_name ?>')
|
42 |
-
.on('click', '.bookly-thumb-delete', function () {
|
43 |
-
var $thumb = $(this).closest('.bookly-js-image');
|
44 |
-
$thumb.attr('style', '');
|
45 |
-
$('[name=<?php echo $option_name ?>]').val('');
|
46 |
-
});
|
47 |
-
});
|
48 |
</script>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<div id="bookly-js-<?php echo esc_attr( $option_name ) ?>" class="bookly-thumb bookly-thumb-<?php echo $class ?> bookly-margin-right-lg">
|
3 |
+
<input type="hidden" name="<?php echo $option_name ?>" data-default="<?php echo esc_attr( $option_value ) ?>" value="<?php echo esc_attr( $option_value ) ?>">
|
4 |
+
<div class="bookly-flex-cell">
|
5 |
+
<div class="form-group">
|
6 |
+
<div class="bookly-js-image bookly-thumb bookly-thumb-<?php echo esc_attr( $class ) ?> bookly-margin-right-lg" style="<?php echo esc_attr( $img_style ) ?>" data-style="<?php echo esc_attr( $img_style ) ?>">
|
7 |
+
<a class="dashicons dashicons-trash text-danger bookly-thumb-delete" href="javascript:void(0)" style="<?php echo esc_attr( $delete_style ) ?>" title="<?php esc_attr_e( 'Delete', 'bookly' ) ?>"></a>
|
8 |
+
<div class="bookly-thumb-edit">
|
9 |
+
<div class="bookly-pretty"><label class="bookly-pretty-indicator bookly-thumb-edit-btn"><?php esc_html_e( 'Image', 'bookly' ) ?></label></div>
|
10 |
+
</div>
|
11 |
+
</div>
|
12 |
+
</div>
|
13 |
+
</div>
|
14 |
+
</div>
|
15 |
+
<script type="text/javascript">
|
16 |
+
jQuery(function ($) {
|
17 |
+
$('#bookly-js-<?php echo $option_name ?> .bookly-pretty-indicator').on('click', function(){
|
18 |
+
var frame = wp.media({
|
19 |
+
library: {type: 'image'},
|
20 |
+
multiple: false
|
21 |
+
});
|
22 |
+
frame.on('select', function () {
|
23 |
+
var selection = frame.state().get('selection').toJSON(),
|
24 |
+
img_src
|
25 |
+
;
|
26 |
+
if (selection.length) {
|
27 |
+
if (selection[0].sizes['full'] !== undefined) {
|
28 |
+
img_src = selection[0].sizes['full'].url;
|
29 |
+
} else {
|
30 |
+
img_src = selection[0].url;
|
31 |
+
}
|
32 |
+
$('[name=<?php echo $option_name ?>]').val(selection[0].id);
|
33 |
+
$('#bookly-js-<?php echo $option_name ?> .bookly-js-image').css({'background-image': 'url(' + img_src + ')', 'background-size': 'contain'});
|
34 |
+
$('#bookly-js-<?php echo $option_name ?> .bookly-thumb-delete').show();
|
35 |
+
$(this).hide();
|
36 |
+
}
|
37 |
+
});
|
38 |
+
frame.open();
|
39 |
+
});
|
40 |
+
|
41 |
+
$('#bookly-js-<?php echo $option_name ?>')
|
42 |
+
.on('click', '.bookly-thumb-delete', function () {
|
43 |
+
var $thumb = $(this).closest('.bookly-js-image');
|
44 |
+
$thumb.attr('style', '');
|
45 |
+
$('[name=<?php echo $option_name ?>]').val('');
|
46 |
+
});
|
47 |
+
});
|
48 |
</script>
|
backend/components/settings/templates/price_correction.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Settings;
|
3 |
-
use Bookly\Lib\Entities\Payment;
|
4 |
-
?>
|
5 |
-
<label for="bookly_<?php echo $gateway ?>_discount"><?php _e( 'Price correction', 'bookly' ) ?></label>
|
6 |
-
<?php if ( ! in_array( $gateway, array( Payment::TYPE_MOLLIE, Payment::TYPE_PAYSON, Payment::TYPE_STRIPE, Payment::TYPE_PAYUBIZ ) ) ) :
|
7 |
-
Settings\Proxy\Taxes::renderHelpMessage();
|
8 |
-
endif ?>
|
9 |
-
<div class="form-group">
|
10 |
-
<div class="row">
|
11 |
-
<div class="col-md-6">
|
12 |
-
<?php Settings\Inputs::renderNumber( 'bookly_' . $gateway . '_increase', __( 'Increase/Discount (%)', 'bookly' ), '', -100, 'any', 100 ) ?>
|
13 |
-
</div>
|
14 |
-
<div class="col-md-6">
|
15 |
-
<?php Settings\Inputs::renderNumber( 'bookly_' . $gateway . '_addition', __( 'Addition/Deduction', 'bookly' ), '', null, 'any' ) ?>
|
16 |
-
</div>
|
17 |
-
</div>
|
18 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Settings;
|
3 |
+
use Bookly\Lib\Entities\Payment;
|
4 |
+
?>
|
5 |
+
<label for="bookly_<?php echo $gateway ?>_discount"><?php _e( 'Price correction', 'bookly' ) ?></label>
|
6 |
+
<?php if ( ! in_array( $gateway, array( Payment::TYPE_MOLLIE, Payment::TYPE_PAYSON, Payment::TYPE_STRIPE, Payment::TYPE_PAYUBIZ ) ) ) :
|
7 |
+
Settings\Proxy\Taxes::renderHelpMessage();
|
8 |
+
endif ?>
|
9 |
+
<div class="form-group">
|
10 |
+
<div class="row">
|
11 |
+
<div class="col-md-6">
|
12 |
+
<?php Settings\Inputs::renderNumber( 'bookly_' . $gateway . '_increase', __( 'Increase/Discount (%)', 'bookly' ), '', -100, 'any', 100 ) ?>
|
13 |
+
</div>
|
14 |
+
<div class="col-md-6">
|
15 |
+
<?php Settings\Inputs::renderNumber( 'bookly_' . $gateway . '_addition', __( 'Addition/Deduction', 'bookly' ), '', null, 'any' ) ?>
|
16 |
+
</div>
|
17 |
+
</div>
|
18 |
</div>
|
backend/components/sms/custom/Notification.php
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Sms\Custom;
|
3 |
+
|
4 |
+
use Bookly\Lib as BooklyLib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Notification
|
8 |
+
* @package Bookly\Backend\Components\Sms\Custom
|
9 |
+
*/
|
10 |
+
class Notification extends BooklyLib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render custom notification
|
14 |
+
*
|
15 |
+
* @param \Bookly\Backend\Modules\Notifications\Forms\Notifications $form
|
16 |
+
* @param array $notification
|
17 |
+
* @param bool $echo
|
18 |
+
* @return string|void
|
19 |
+
*/
|
20 |
+
public static function render( $form, $notification, $echo = true )
|
21 |
+
{
|
22 |
+
$unique = self::getFromCache( 'unique', 1 );
|
23 |
+
|
24 |
+
return self::renderTemplate( 'layout', compact( 'form', 'notification', 'unique' ), $echo );
|
25 |
+
}
|
26 |
+
|
27 |
+
/**
|
28 |
+
* Render settings for notification.
|
29 |
+
*
|
30 |
+
* @param string $set
|
31 |
+
* @param integer $id
|
32 |
+
* @param array $settings
|
33 |
+
*/
|
34 |
+
public static function renderSet( $set, $id, $settings )
|
35 |
+
{
|
36 |
+
$statuses = BooklyLib\Entities\CustomerAppointment::getStatuses();
|
37 |
+
if ( ! self::hasInCache( 'service_dropdown_data' ) ) {
|
38 |
+
$service_dropdown_data = BooklyLib\Utils\Common::getServiceDataForDropDown( 's.type <> "package"' );
|
39 |
+
self::putInCache( 'service_dropdown_data', $service_dropdown_data );
|
40 |
+
}
|
41 |
+
|
42 |
+
$service_dropdown_data = self::getFromCache( 'service_dropdown_data' );
|
43 |
+
$unique = self::getFromCache( 'unique', 2 );
|
44 |
+
self::renderTemplate( $set, compact( 'id', 'settings', 'statuses', 'service_dropdown_data', 'unique' ) );
|
45 |
+
}
|
46 |
+
}
|
backend/components/sms/custom/templates/after_event.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Lib\Entities\CustomerAppointment;
|
3 |
+
use Bookly\Lib\DataHolders\Notification\Settings;
|
4 |
+
|
5 |
+
$set = Settings::SET_AFTER_EVENT;
|
6 |
+
$name = 'notification[' . $id . '][settings][' . $set . ']';
|
7 |
+
?>
|
8 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
9 |
+
<div class="row">
|
10 |
+
<div class="col-md-3">
|
11 |
+
<div class="form-group">
|
12 |
+
<label for="notification_<?php echo ++ $unique ?>_status_1" class="bookly-js-with"><?php esc_attr_e( 'With status', 'bookly' ) ?></label>
|
13 |
+
<label for="notification_<?php echo $unique ?>_status_1" class="bookly-js-to"><?php esc_attr_e( 'To', 'bookly' ) ?></label>
|
14 |
+
<select class="form-control" name="<?php echo $name ?>[status]" id="notification_<?php echo $unique ?>_status_1">
|
15 |
+
<option value="any"><?php esc_attr_e( 'Any', 'bookly' ) ?></option>
|
16 |
+
<?php foreach ( $statuses as $status ) : ?>
|
17 |
+
<option value="<?php echo $status ?>" <?php selected( $settings['status'] == $status ) ?>><?php echo CustomerAppointment::statusToString( $status ) ?></option>
|
18 |
+
<?php endforeach ?>
|
19 |
+
</select>
|
20 |
+
</div>
|
21 |
+
</div>
|
22 |
+
<div class="col-md-5">
|
23 |
+
<label><?php esc_attr_e( 'For service', 'bookly' ) ?></label>
|
24 |
+
<div class="form-inline">
|
25 |
+
<input type="hidden" name="<?php echo $name ?>[services][any]" value="0">
|
26 |
+
<input type="checkbox" name="<?php echo $name ?>[services][any]" value="1" <?php checked( @$settings['services']['any'] ) ?>> <span class="bookly-checkbox-text"><?php esc_html_e( 'Any', 'bookly' ) ?></span>
|
27 |
+
<ul class="bookly-js-services"
|
28 |
+
data-icon-class="glyphicon glyphicon-tag"
|
29 |
+
data-txt-select-all="<?php esc_attr_e( 'All services', 'bookly' ) ?>"
|
30 |
+
data-txt-all-selected="<?php esc_attr_e( 'All services', 'bookly' ) ?>"
|
31 |
+
data-txt-nothing-selected="<?php esc_attr_e( 'No service selected', 'bookly' ) ?>"
|
32 |
+
>
|
33 |
+
<?php foreach ( $service_dropdown_data as $category_id => $category ): ?>
|
34 |
+
<li<?php if ( ! $category_id ) : ?> data-flatten-if-single<?php endif ?>><?php echo esc_html( $category['name'] ) ?>
|
35 |
+
<ul>
|
36 |
+
<?php foreach ( $category['items'] as $service ) : ?>
|
37 |
+
<li
|
38 |
+
data-input-name="<?php echo $name ?>[services][ids][]"
|
39 |
+
data-value="<?php echo $service['id'] ?>"
|
40 |
+
data-selected="<?php echo (int) isset( $settings['services']['ids'] ) && in_array( $service['id'], @$settings['services']['ids'] ) ?>"
|
41 |
+
>
|
42 |
+
<?php echo esc_html( $service['title'] ) ?>
|
43 |
+
</li>
|
44 |
+
<?php endforeach ?>
|
45 |
+
</ul>
|
46 |
+
</li>
|
47 |
+
<?php endforeach ?>
|
48 |
+
</ul>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
<div class="row">
|
53 |
+
<div class="col-md-6 bookly-margin-left-sm bookly-margin-bottom-sm">
|
54 |
+
<label for="notification_<?php echo ++ $unique ?>_send_1"><?php esc_attr_e( 'Send', 'bookly' ) ?></label>
|
55 |
+
<div class="form-inline bookly-margin-bottom-sm">
|
56 |
+
<div class="form-group">
|
57 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="1" checked></label> <?php esc_attr_e( 'Instantly', 'bookly' ) ?>
|
58 |
+
</div>
|
59 |
+
</div>
|
60 |
+
|
61 |
+
<div class="form-inline bookly-margin-bottom-sm">
|
62 |
+
<div class="form-group">
|
63 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="2" <?php checked( @$settings['option'] == 2 ) ?>></label>
|
64 |
+
<select class="form-control" name="<?php echo $name ?>[offset_hours]">
|
65 |
+
<?php foreach ( array_merge( range( 1, 24 ), range( 48, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
66 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'after', 'bookly' ) ?></option>
|
67 |
+
<?php endforeach ?>
|
68 |
+
</select>
|
69 |
+
<input type="hidden" name="<?php echo $name ?>[perform]" value="after">
|
70 |
+
</div>
|
71 |
+
</div>
|
72 |
+
|
73 |
+
<div class="form-inline">
|
74 |
+
<div class="form-group">
|
75 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="3" <?php checked( @$settings['option'] == 3 ) ?>></label>
|
76 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]">
|
77 |
+
<option value="0"><?php esc_attr_e( 'on the same day', 'bookly' ) ?></option>
|
78 |
+
<?php foreach ( array_merge( range( 24, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
79 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'after', 'bookly' ) ?></option>
|
80 |
+
<?php endforeach ?>
|
81 |
+
</select>
|
82 |
+
<?php esc_attr_e( 'at', 'bookly' ) ?>
|
83 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
84 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
85 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
86 |
+
<?php endforeach ?>
|
87 |
+
</select>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
</div>
|
93 |
+
<?php $self::putInCache( 'unique', ++$unique ) ?>
|
backend/components/sms/custom/templates/existing_event_with_date.php
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Lib\DataHolders\Notification\Settings;
|
3 |
+
|
4 |
+
$set = Settings::SET_EXISTING_EVENT_WITH_DATE;
|
5 |
+
$name = 'notification[' . $id . '][settings][' . $set . ']';
|
6 |
+
?>
|
7 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
8 |
+
<div class="col-md-6">
|
9 |
+
<label for="notification_<?php echo ++$unique ?>_send_2"><?php esc_attr_e( 'Send', 'bookly' ) ?></label>
|
10 |
+
<div class="form-inline">
|
11 |
+
<div class="form-group">
|
12 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]" id="notification_<?php echo $unique ?>_send_2">
|
13 |
+
<?php foreach ( array_merge( array( -672, -504 ), range( -336, -24, 24 ) ) as $hour ) : ?>
|
14 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( abs( $hour ) * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'before', 'bookly' ) ?></option>
|
15 |
+
<?php endforeach ?>
|
16 |
+
<option value="0" <?php selected( @$settings['offset_bidirectional_hours'], 0 ) ?>><?php esc_attr_e( 'on the same day', 'bookly' ) ?></option>
|
17 |
+
<?php foreach ( array_merge( range( 24, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
18 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'after', 'bookly' ) ?></option>
|
19 |
+
<?php endforeach ?>
|
20 |
+
</select>
|
21 |
+
<?php esc_attr_e( 'at', 'bookly' ) ?>
|
22 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
23 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
24 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
25 |
+
<?php endforeach ?>
|
26 |
+
</select>
|
27 |
+
</div>
|
28 |
+
</div>
|
29 |
+
</div>
|
30 |
+
</div>
|
31 |
+
<?php $self::putInCache( 'unique', ++$unique ) ?>
|
backend/components/sms/custom/templates/existing_event_with_date_and_time.php
ADDED
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Lib\Entities\CustomerAppointment;
|
3 |
+
use Bookly\Lib\DataHolders\Notification\Settings;
|
4 |
+
|
5 |
+
$set = Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME;
|
6 |
+
$name = 'notification[' . $id . '][settings][' . $set . ']';
|
7 |
+
?>
|
8 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
9 |
+
<div class="row">
|
10 |
+
<div class="col-md-3">
|
11 |
+
<div class="form-group">
|
12 |
+
<label for="notification_<?php echo ++ $unique ?>_status_1"><?php esc_attr_e( 'With status', 'bookly' ) ?></label>
|
13 |
+
<select class="form-control" name="<?php echo $name ?>[status]" id="notification_<?php echo $unique ?>_status_1">
|
14 |
+
<option value="any"><?php esc_attr_e( 'Any', 'bookly' ) ?></option>
|
15 |
+
<?php foreach ( $statuses as $status ) : ?>
|
16 |
+
<option value="<?php echo $status ?>" <?php selected( $settings['status'] == $status ) ?>><?php echo CustomerAppointment::statusToString( $status ) ?></option>
|
17 |
+
<?php endforeach ?>
|
18 |
+
</select>
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
<div class="col-md-5">
|
22 |
+
<label><?php esc_attr_e( 'For service', 'bookly' ) ?></label>
|
23 |
+
<div class="form-inline">
|
24 |
+
<input type="hidden" name="<?php echo $name ?>[services][any]" value="0">
|
25 |
+
<input type="checkbox" name="<?php echo $name ?>[services][any]" value="1" <?php checked( @$settings['services']['any'] ) ?>> <span class="bookly-checkbox-text"><?php esc_html_e( 'Any', 'bookly' ) ?></span>
|
26 |
+
<ul class="bookly-js-services"
|
27 |
+
data-icon-class="glyphicon glyphicon-tag"
|
28 |
+
data-txt-select-all="<?php esc_attr_e( 'All services', 'bookly' ) ?>"
|
29 |
+
data-txt-all-selected="<?php esc_attr_e( 'All services', 'bookly' ) ?>"
|
30 |
+
data-txt-nothing-selected="<?php esc_attr_e( 'No service selected', 'bookly' ) ?>"
|
31 |
+
>
|
32 |
+
<?php foreach ( $service_dropdown_data as $category_id => $category ): ?>
|
33 |
+
<li<?php if ( ! $category_id ) : ?> data-flatten-if-single<?php endif ?>><?php echo esc_html( $category['name'] ) ?>
|
34 |
+
<ul>
|
35 |
+
<?php foreach ( $category['items'] as $service ) : ?>
|
36 |
+
<li
|
37 |
+
data-input-name="<?php echo $name ?>[services][ids][]"
|
38 |
+
data-value="<?php echo $service['id'] ?>"
|
39 |
+
data-selected="<?php echo (int) isset( $settings['services']['ids'] ) && in_array( $service['id'], @$settings['services']['ids'] ) ?>"
|
40 |
+
>
|
41 |
+
<?php echo esc_html( $service['title'] ) ?>
|
42 |
+
</li>
|
43 |
+
<?php endforeach ?>
|
44 |
+
</ul>
|
45 |
+
</li>
|
46 |
+
<?php endforeach ?>
|
47 |
+
</ul>
|
48 |
+
</div>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
<div class="row">
|
52 |
+
<div class="col-md-6 bookly-margin-left-sm bookly-margin-bottom-sm">
|
53 |
+
<label for="notification_<?php echo ++ $unique ?>_send_1"><?php esc_attr_e( 'Send', 'bookly' ) ?></label>
|
54 |
+
<div class="form-inline bookly-margin-bottom-sm">
|
55 |
+
<div class="form-group">
|
56 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="1" checked id="notification_<?php echo $unique ?>_send_1"></label>
|
57 |
+
<select class="form-control" name="<?php echo $name ?>[offset_hours]">
|
58 |
+
<?php foreach ( array_merge( range( 1, 24 ), range( 48, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
59 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?></option>
|
60 |
+
<?php endforeach ?>
|
61 |
+
<option value="43200" <?php selected( @$settings['offset_hours'], 43200 ) ?>>30 <?php esc_attr_e( 'days', 'bookly' ) ?></option>
|
62 |
+
</select>
|
63 |
+
<select class="form-control" name="<?php echo $name ?>[perform]">
|
64 |
+
<option value="before"><?php esc_attr_e( 'before', 'bookly' ) ?></option>
|
65 |
+
<option value="after"<?php selected( @$settings['perform'] == 'after' ) ?>><?php esc_attr_e( 'after', 'bookly' ) ?></option>
|
66 |
+
</select>
|
67 |
+
</div>
|
68 |
+
</div>
|
69 |
+
|
70 |
+
<div class="form-inline">
|
71 |
+
<div class="form-group">
|
72 |
+
<label><input type="radio" name="<?php echo $name ?>[option]" value="2" <?php checked( @$settings['option'] == 2 ) ?>></label>
|
73 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]">
|
74 |
+
<?php foreach ( array_merge( array( - 672, - 504 ), range( - 336, - 24, 24 ) ) as $hour ) : ?>
|
75 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( abs( $hour ) * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'before', 'bookly' ) ?></option>
|
76 |
+
<?php endforeach ?>
|
77 |
+
<option value="0" <?php selected( @$settings['offset_bidirectional_hours'], 0 ) ?>><?php esc_attr_e( 'on the same day', 'bookly' ) ?></option>
|
78 |
+
<?php foreach ( array_merge( range( 24, 336, 24 ), array( 504, 672 ) ) as $hour ) : ?>
|
79 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( $hour * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'after', 'bookly' ) ?></option>
|
80 |
+
<?php endforeach ?>
|
81 |
+
</select>
|
82 |
+
<?php esc_attr_e( 'at', 'bookly' ) ?>
|
83 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
84 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
85 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
86 |
+
<?php endforeach ?>
|
87 |
+
</select>
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
</div>
|
92 |
+
</div>
|
93 |
+
<?php $self::putInCache( 'unique', ++$unique ) ?>
|
backend/components/sms/custom/templates/existing_event_with_date_before.php
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Lib\DataHolders\Notification\Settings;
|
3 |
+
|
4 |
+
$set = Settings::SET_EXISTING_EVENT_WITH_DATE_BEFORE;
|
5 |
+
$name = 'notification[' . $id . '][settings][' . $set . ']';
|
6 |
+
?>
|
7 |
+
<div class="bookly-js-settings bookly-js-<?php echo $set ?>">
|
8 |
+
<div class="col-md-6">
|
9 |
+
<label for="notification_<?php echo ++$unique ?>_send_2"><?php esc_attr_e( 'Send', 'bookly' ) ?></label>
|
10 |
+
<div class="form-inline">
|
11 |
+
<div class="form-group">
|
12 |
+
<select class="form-control" name="<?php echo $name ?>[offset_bidirectional_hours]" id="notification_<?php echo $unique ?>_send_2">
|
13 |
+
<?php foreach ( array_merge( array( -672, -504 ), range( -336, -24, 24 ) ) as $hour ) : ?>
|
14 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['offset_bidirectional_hours'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::secondsToInterval( abs( $hour ) * HOUR_IN_SECONDS ) ?> <?php esc_attr_e( 'before', 'bookly' ) ?></option>
|
15 |
+
<?php endforeach ?>
|
16 |
+
<option value="0" <?php selected( @$settings['offset_bidirectional_hours'], 0 ) ?>><?php esc_attr_e( 'on the same day', 'bookly' ) ?></option>
|
17 |
+
</select>
|
18 |
+
<?php esc_attr_e( 'at', 'bookly' ) ?>
|
19 |
+
<select class="form-control" name="<?php echo $name ?>[at_hour]">
|
20 |
+
<?php foreach ( range( 0, 23 ) as $hour ) : ?>
|
21 |
+
<option value="<?php echo $hour ?>" <?php selected( @$settings['at_hour'], $hour ) ?>><?php echo \Bookly\Lib\Utils\DateTime::buildTimeString( $hour * HOUR_IN_SECONDS, false ) ?></option>
|
22 |
+
<?php endforeach ?>
|
23 |
+
</select>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
</div>
|
27 |
+
</div>
|
28 |
+
<?php $self::putInCache( 'unique', ++$unique ) ?>
|
backend/components/sms/custom/templates/layout.php
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
/** @var Bookly\Backend\Modules\Notifications\Forms\Notifications $form */
|
3 |
+
use Bookly\Lib\DataHolders\Notification\Settings;
|
4 |
+
use Bookly\Lib\Entities\Notification;
|
5 |
+
use Bookly\Backend\Modules\Notifications\Proxy as NotificationProxy;
|
6 |
+
use Bookly\Backend\Components\Sms\Custom;
|
7 |
+
|
8 |
+
$id = $notification['id'];
|
9 |
+
$notification_settings = (array) json_decode( $notification['settings'], true );
|
10 |
+
?>
|
11 |
+
<div class="panel panel-default bookly-js-collapse">
|
12 |
+
<div class="panel-heading" role="tab">
|
13 |
+
<div class="checkbox bookly-margin-remove">
|
14 |
+
<label>
|
15 |
+
<input name="notification[<?php echo $id ?>][active]" value="0" type="checkbox" checked="checked" class="hidden">
|
16 |
+
<input id="<?php echo $id ?>_active" name="notification[<?php echo $id ?>][active]" value="1" type="checkbox" <?php checked( $notification['active'] ) ?>>
|
17 |
+
<a href="#collapse_<?php echo $id ?>" class="collapsed panel-title" role="button" data-toggle="collapse" data-parent="#bookly-js-custom-notifications">
|
18 |
+
<?php echo $notification['subject'] ?: __( 'Custom notification', 'bookly' ) ?>
|
19 |
+
</a>
|
20 |
+
</label>
|
21 |
+
<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' ) ?>" data-style="zoom-in" data-spinner-size="20" data-spinner-color="#333">
|
22 |
+
<span class="ladda-label"><i class="glyphicon glyphicon-trash text-danger"></i></span>
|
23 |
+
</button>
|
24 |
+
</div>
|
25 |
+
</div>
|
26 |
+
<div id="collapse_<?php echo $id ?>" class="panel-collapse collapse">
|
27 |
+
<div class="panel-body">
|
28 |
+
<div class="row">
|
29 |
+
<div class="col-md-3">
|
30 |
+
<div class="form-group">
|
31 |
+
<label for="notification_<?php echo $unique ?>_type"><?php esc_attr_e( 'Type', 'bookly' ) ?></label>
|
32 |
+
<select class="form-control" name="notification[<?php echo $id ?>][type]" id="notification_<?php echo $unique ?>_type">
|
33 |
+
<optgroup label="<?php esc_attr_e( 'Event notification', 'bookly' ) ?>">
|
34 |
+
<option
|
35 |
+
value="<?php echo Notification::TYPE_CUSTOMER_APPOINTMENT_STATUS_CHANGED ?>"
|
36 |
+
data-set="<?php echo Settings::SET_AFTER_EVENT ?>"
|
37 |
+
data-to='["customer","staff","admin"]'
|
38 |
+
data-attach-show='["ics","invoice"]'
|
39 |
+
<?php selected( $notification['type'], Notification::TYPE_CUSTOMER_APPOINTMENT_STATUS_CHANGED ) ?>><?php esc_attr_e( 'Status changed', 'bookly' ) ?></option>
|
40 |
+
<option
|
41 |
+
value="<?php echo Notification::TYPE_CUSTOMER_APPOINTMENT_CREATED ?>"
|
42 |
+
data-set="<?php echo Settings::SET_AFTER_EVENT ?>"
|
43 |
+
data-to='["customer","staff","admin"]'
|
44 |
+
data-attach-show='["ics","invoice"]'
|
45 |
+
<?php selected( $notification['type'], Notification::TYPE_CUSTOMER_APPOINTMENT_CREATED ) ?> ><?php esc_attr_e( 'New booking', 'bookly' ) ?></option>
|
46 |
+
</optgroup>
|
47 |
+
<optgroup label="<?php esc_attr_e( 'Reminder notification', 'bookly' ) ?>">
|
48 |
+
<option
|
49 |
+
value="<?php echo Notification::TYPE_APPOINTMENT_START_TIME ?>"
|
50 |
+
data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME ?>"
|
51 |
+
data-to='["customer","staff","admin"]'
|
52 |
+
data-attach-show='["ics"]'
|
53 |
+
<?php selected( $notification['type'], Notification::TYPE_APPOINTMENT_START_TIME ) ?>><?php esc_attr_e( 'Appointment date and time', 'bookly' ) ?></option>
|
54 |
+
<option
|
55 |
+
value="<?php echo Notification::TYPE_CUSTOMER_BIRTHDAY ?>"
|
56 |
+
data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE ?>"
|
57 |
+
data-to='["customer"]'
|
58 |
+
data-attach-show='[]'
|
59 |
+
<?php selected( $notification['type'], Notification::TYPE_CUSTOMER_BIRTHDAY ) ?>><?php esc_attr_e( 'Customer\'s birthday', 'bookly' ) ?></option>
|
60 |
+
<option
|
61 |
+
value="<?php echo Notification::TYPE_LAST_CUSTOMER_APPOINTMENT ?>"
|
62 |
+
data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME ?>"
|
63 |
+
data-to='["customer","staff","admin"]'
|
64 |
+
data-attach-show='["ics"]'
|
65 |
+
<?php selected( $notification['type'], Notification::TYPE_LAST_CUSTOMER_APPOINTMENT ) ?>><?php esc_attr_e( 'Last client\'s appointment', 'bookly' ) ?></option>
|
66 |
+
<option
|
67 |
+
value="<?php echo Notification::TYPE_STAFF_DAY_AGENDA ?>"
|
68 |
+
data-set="<?php echo Settings::SET_EXISTING_EVENT_WITH_DATE_BEFORE ?>"
|
69 |
+
data-to='["staff","admin"]'
|
70 |
+
data-attach-show='[]'
|
71 |
+
<?php selected( $notification['type'], Notification::TYPE_STAFF_DAY_AGENDA ) ?>><?php esc_attr_e( 'Full day agenda', 'bookly' ) ?></option>
|
72 |
+
</optgroup>
|
73 |
+
</select>
|
74 |
+
</div>
|
75 |
+
</div>
|
76 |
+
<?php foreach ( array( Settings::SET_EXISTING_EVENT_WITH_DATE_AND_TIME, Settings::SET_EXISTING_EVENT_WITH_DATE, Settings::SET_EXISTING_EVENT_WITH_DATE_BEFORE, Settings::SET_AFTER_EVENT ) as $set ) {
|
77 |
+
$settings = array_key_exists( $set, $notification_settings ) ? $notification_settings[ $set ] : array();
|
78 |
+
Custom\Notification::renderSet( $set, $id, $settings );
|
79 |
+
}
|
80 |
+
$unique = $self::getFromCache( 'unique' ) ?>
|
81 |
+
</div>
|
82 |
+
|
83 |
+
<div class="row">
|
84 |
+
<div class="col-md-6">
|
85 |
+
<div class="form-group">
|
86 |
+
<label for="notification_<?php echo ++$unique ?>_subject"><?php esc_attr_e( 'Subject', 'bookly' ) ?></label>
|
87 |
+
<input type="text" class="form-control" id="notification_<?php echo $unique ?>_subject" name="notification[<?php echo $id ?>][subject]" value="<?php echo esc_attr( $notification['subject'] ) ?>" />
|
88 |
+
</div>
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<div class="row">
|
93 |
+
<div class="col-md-4">
|
94 |
+
<div class="form-group">
|
95 |
+
<label><?php esc_attr_e( 'Recipient', 'bookly' ) ?></label>
|
96 |
+
<br>
|
97 |
+
<label class="checkbox-inline">
|
98 |
+
<input type="hidden" name="notification[<?php echo $id ?>][to_customer]" value="0">
|
99 |
+
<input type="checkbox" name="notification[<?php echo $id ?>][to_customer]" value="1"<?php checked( $notification['to_customer'] ) ?> /> <?php esc_attr_e( 'Client', 'bookly' ) ?>
|
100 |
+
</label>
|
101 |
+
<label class="checkbox-inline">
|
102 |
+
<input type="hidden" name="notification[<?php echo $id ?>][to_staff]" value="0">
|
103 |
+
<input type="checkbox" name="notification[<?php echo $id ?>][to_staff]" value="1"<?php checked( $notification['to_staff'] ) ?> /> <?php esc_attr_e( 'Staff', 'bookly' ) ?>
|
104 |
+
</label>
|
105 |
+
<label class="checkbox-inline">
|
106 |
+
<input type="hidden" name="notification[<?php echo $id ?>][to_admin]" value="0">
|
107 |
+
<input type="checkbox" name="notification[<?php echo $id ?>][to_admin]" value="1"<?php checked( $notification['to_admin'] ) ?> /> <?php esc_attr_e( 'Administrators', 'bookly' ) ?>
|
108 |
+
</label>
|
109 |
+
</div>
|
110 |
+
</div>
|
111 |
+
</div>
|
112 |
+
|
113 |
+
<?php $form->renderEditor( $id ) ?>
|
114 |
+
|
115 |
+
<?php NotificationProxy\Invoices::renderAttach( $notification ) ?>
|
116 |
+
<div class="form-group">
|
117 |
+
<label><?php esc_attr_e( 'Codes', 'bookly' ) ?></label>
|
118 |
+
<?php foreach ( Notification::getCustomNotificationTypes() as $notification_type ) :
|
119 |
+
$form->renderCodes( $notification_type );
|
120 |
+
endforeach ?>
|
121 |
+
</div>
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
</div>
|
125 |
+
<?php $self::putInCache( 'unique', ++$unique ) ?>
|
backend/components/support/Buttons.php
CHANGED
@@ -1,74 +1,75 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Support;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Backend\Modules;
|
6 |
-
use Bookly\Backend\Components\Notices;
|
7 |
-
|
8 |
-
/**
|
9 |
-
* Class Buttons
|
10 |
-
* @package Bookly\Backend\Components\Support
|
11 |
-
*/
|
12 |
-
class Buttons extends Lib\Base\Component
|
13 |
-
{
|
14 |
-
/**
|
15 |
-
* Render support buttons.
|
16 |
-
*
|
17 |
-
* @param string $page_slug
|
18 |
-
*/
|
19 |
-
public static function render( $page_slug )
|
20 |
-
{
|
21 |
-
|
22 |
-
'
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
'
|
28 |
-
|
29 |
-
'js/
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
!
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . '
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
->
|
58 |
-
->
|
59 |
-
->
|
60 |
-
->
|
61 |
-
|
62 |
-
$
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
'
|
67 |
-
'
|
68 |
-
'
|
69 |
-
'
|
70 |
-
'
|
71 |
-
'
|
72 |
-
|
73 |
-
|
|
|
74 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Support;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Backend\Modules;
|
6 |
+
use Bookly\Backend\Components\Notices;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class Buttons
|
10 |
+
* @package Bookly\Backend\Components\Support
|
11 |
+
*/
|
12 |
+
class Buttons extends Lib\Base\Component
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Render support buttons.
|
16 |
+
*
|
17 |
+
* @param string $page_slug
|
18 |
+
*/
|
19 |
+
public static function render( $page_slug )
|
20 |
+
{
|
21 |
+
self::enqueueStyles( array(
|
22 |
+
'backend' => array( 'css/fontawesome-all.min.css' ),
|
23 |
+
'frontend' => array( 'css/ladda.min.css', ),
|
24 |
+
) );
|
25 |
+
|
26 |
+
self::enqueueScripts( array(
|
27 |
+
'backend' => array( 'js/alert.js' => array( 'jquery' ), ),
|
28 |
+
'frontend' => array(
|
29 |
+
'js/spin.min.js' => array( 'jquery' ),
|
30 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
31 |
+
),
|
32 |
+
'module' => array( 'js/support.js' => array( 'bookly-alert.js', 'bookly-ladda.min.js', ), ),
|
33 |
+
) );
|
34 |
+
|
35 |
+
wp_localize_script( 'bookly-support.js', 'SupportL10n', array(
|
36 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken()
|
37 |
+
) );
|
38 |
+
|
39 |
+
// Documentation link.
|
40 |
+
$doc_link = 'http://api.booking-wp-plugin.com/go/' . $page_slug;
|
41 |
+
|
42 |
+
$days_in_use = (int) ( ( time() - Lib\Plugin::getInstallationTime() ) / DAY_IN_SECONDS );
|
43 |
+
|
44 |
+
// Whether to show contact us notice or not.
|
45 |
+
$show_contact_us_notice = $days_in_use < 7 &&
|
46 |
+
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_contact_us_notice', true ) &&
|
47 |
+
! Notices\CollectStats::needShowCollectStatNotice();
|
48 |
+
|
49 |
+
// Whether to show feedback notice.
|
50 |
+
$show_feedback_notice = $days_in_use >= 7 &&
|
51 |
+
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_feedback_notice', true ) &&
|
52 |
+
! get_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'contact_us_btn_clicked', true );
|
53 |
+
|
54 |
+
$current_user = wp_get_current_user();
|
55 |
+
|
56 |
+
$messages = Lib\Entities\Message::query( 'm' )
|
57 |
+
->select( 'm.created, m.subject, m.seen' )
|
58 |
+
->sortBy( 'm.seen, m.message_id' )
|
59 |
+
->order( 'DESC' )
|
60 |
+
->limit( 10 )
|
61 |
+
->fetchArray();
|
62 |
+
$messages_new = Lib\Entities\Message::query( 'm' )->where( 'm.seen', '0' )->count();
|
63 |
+
$messages_link = Lib\Utils\Common::escAdminUrl( Modules\Messages\Ajax::pageSlug() );
|
64 |
+
|
65 |
+
static::renderTemplate( 'buttons', compact(
|
66 |
+
'doc_link',
|
67 |
+
'show_contact_us_notice',
|
68 |
+
'show_feedback_notice',
|
69 |
+
'current_user',
|
70 |
+
'messages',
|
71 |
+
'messages_new',
|
72 |
+
'messages_link'
|
73 |
+
) );
|
74 |
+
}
|
75 |
}
|
backend/components/support/ButtonsAjax.php
CHANGED
@@ -1,78 +1,88 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Support;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Backend\Modules;
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
*
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
$
|
20 |
-
$
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
'
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
$
|
35 |
-
$
|
36 |
-
|
37 |
-
'
|
38 |
-
'
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
update_user_meta( get_current_user_id(),
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
78 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Support;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Backend\Modules;
|
6 |
+
use Bookly\Backend\Components\Support\Lib\Urls;
|
7 |
+
|
8 |
+
/**
|
9 |
+
* Class ButtonsAjax
|
10 |
+
* @package Bookly\Backend\Components\Support
|
11 |
+
*/
|
12 |
+
class ButtonsAjax extends Lib\Base\Ajax
|
13 |
+
{
|
14 |
+
/**
|
15 |
+
* Send support request.
|
16 |
+
*/
|
17 |
+
public static function sendSupportRequest()
|
18 |
+
{
|
19 |
+
$name = trim( self::parameter( 'name' ) );
|
20 |
+
$email = trim( self::parameter( 'email' ) );
|
21 |
+
$msg = trim( self::parameter( 'msg' ) );
|
22 |
+
|
23 |
+
// Validation.
|
24 |
+
if ( $email == '' || $msg == '' ) {
|
25 |
+
wp_send_json_error( array( 'message' => __( 'All fields marked with an asterisk (*) are required.', 'bookly' ) ) );
|
26 |
+
}
|
27 |
+
if ( ! is_email( $email ) ) {
|
28 |
+
wp_send_json_error( array(
|
29 |
+
'invalid_email' => true,
|
30 |
+
'message' => __( 'Invalid email.', 'bookly' ),
|
31 |
+
) );
|
32 |
+
}
|
33 |
+
|
34 |
+
$plugins = apply_filters( 'bookly_plugins', array() );
|
35 |
+
$message = self::renderTemplate( '_email_to_support', compact( 'name', 'email', 'msg', 'plugins' ), false );
|
36 |
+
$headers = array(
|
37 |
+
'Content-Type: text/html; charset=utf-8',
|
38 |
+
'From: ' . get_option( 'bookly_email_sender_name' ) . ' <' . get_option( 'bookly_email_sender' ) . '>',
|
39 |
+
'Reply-To: ' . $name . ' <' . $email . '>'
|
40 |
+
);
|
41 |
+
|
42 |
+
if ( wp_mail( 'support@bookly.info', 'Support Request ' . site_url(), $message, $headers ) ) {
|
43 |
+
wp_send_json_success( array( 'message' => __( 'Sent successfully.', 'bookly' ) ) );
|
44 |
+
} else {
|
45 |
+
wp_send_json_error( array( 'message' => __( 'Error sending support request.', 'bookly' ) ) );
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
/**
|
50 |
+
* Dismiss notice for 'Contact Us' button.
|
51 |
+
*/
|
52 |
+
public static function dismissContactUsNotice()
|
53 |
+
{
|
54 |
+
update_user_meta( get_current_user_id(), 'bookly_dismiss_contact_us_notice', 1 );
|
55 |
+
|
56 |
+
wp_send_json_success();
|
57 |
+
}
|
58 |
+
|
59 |
+
/**
|
60 |
+
* Record click on 'Contact Us' button.
|
61 |
+
*/
|
62 |
+
public static function contactUsBtnClicked()
|
63 |
+
{
|
64 |
+
update_user_meta( get_current_user_id(), 'bookly_dismiss_contact_us_notice', 1 );
|
65 |
+
update_user_meta( get_current_user_id(), 'bookly_contact_us_btn_clicked', 1 );
|
66 |
+
|
67 |
+
wp_send_json_success();
|
68 |
+
}
|
69 |
+
|
70 |
+
/**
|
71 |
+
* Dismiss notice for 'Feedback' button.
|
72 |
+
*/
|
73 |
+
public static function dismissFeedbackNotice()
|
74 |
+
{
|
75 |
+
update_user_meta( get_current_user_id(), 'bookly_dismiss_feedback_notice', 1 );
|
76 |
+
|
77 |
+
wp_send_json_success();
|
78 |
+
}
|
79 |
+
|
80 |
+
/**
|
81 |
+
* Proceed to feature requests.
|
82 |
+
*/
|
83 |
+
public static function proceedToFeatureRequests()
|
84 |
+
{
|
85 |
+
update_user_meta( get_current_user_id(), 'bookly_feature_requests_rules_hide', self::parameter( 'hide', 0 ) );
|
86 |
+
wp_send_json_success( array( 'target' => Lib\Utils\Common::prepareUrlReferrers( Urls::FEATURES_REQUEST_PAGE, 'notification_bar' ) ) );
|
87 |
+
}
|
88 |
}
|
backend/components/support/lib/Urls.php
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\Support\Lib;
|
3 |
-
|
4 |
-
/**
|
5 |
-
* Class Urls
|
6 |
-
* @package Bookly\Backend\Components\Support\Lib
|
7 |
-
*/
|
8 |
-
abstract class Urls
|
9 |
-
{
|
10 |
-
const
|
|
|
11 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\Support\Lib;
|
3 |
+
|
4 |
+
/**
|
5 |
+
* Class Urls
|
6 |
+
* @package Bookly\Backend\Components\Support\Lib
|
7 |
+
*/
|
8 |
+
abstract class Urls
|
9 |
+
{
|
10 |
+
const REVIEWS_PAGE = 'https://wordpress.org/plugins/bookly-responsive-appointment-booking-tool/#reviews';
|
11 |
+
const FEATURES_REQUEST_PAGE = 'https://support.booking-wp-plugin.com/hc/en-us/community/topics/200189331-Feature-Requests';
|
12 |
}
|
backend/components/support/resources/js/support.js
CHANGED
@@ -1,136 +1,174 @@
|
|
1 |
-
jQuery(function ($) {
|
2 |
-
var $modal = $('#bookly-support-modal'),
|
3 |
-
$btnContactUs = $('#bookly-contact-us-btn'),
|
4 |
-
$btnFeedback = $('#bookly-feedback-btn')
|
5 |
-
;
|
6 |
-
|
7 |
-
if ($btnContactUs.data('trigger')) {
|
8 |
-
$btnContactUs
|
9 |
-
.popover().popover('show')
|
10 |
-
.next('.popover')
|
11 |
-
.css({right:22+$btnFeedback.outerWidth()+'px',left:'auto'})
|
12 |
-
.find('.arrow').removeClass().addClass('popover-arrow').css({right:($btnContactUs.outerWidth()/2)+'px',left:'auto'}).end()
|
13 |
-
.find('.popover-content button').on('click', function () {
|
14 |
-
$btnContactUs.popover('hide');
|
15 |
-
$.ajax({
|
16 |
-
url : ajaxurl,
|
17 |
-
type : 'POST',
|
18 |
-
data : { action : 'bookly_dismiss_contact_us_notice', csrf_token : SupportL10n.csrf_token },
|
19 |
-
success : function(response) {
|
20 |
-
$btnContactUs.attr("data-processed", true);
|
21 |
-
}
|
22 |
-
});
|
23 |
-
}).end()
|
24 |
-
.end()
|
25 |
-
.on('click', function () {
|
26 |
-
$btnContactUs.popover('hide');
|
27 |
-
$.ajax({
|
28 |
-
url : ajaxurl,
|
29 |
-
type : 'POST',
|
30 |
-
data : { action : 'bookly_contact_us_btn_clicked', csrf_token : SupportL10n.csrf_token }
|
31 |
-
});
|
32 |
-
});
|
33 |
-
}
|
34 |
-
|
35 |
-
if ($btnFeedback.data('trigger')) {
|
36 |
-
$btnFeedback
|
37 |
-
.popover().popover('show')
|
38 |
-
.next('.popover')
|
39 |
-
.css({right:'10px',left:'auto'})
|
40 |
-
.find('.arrow').removeClass().addClass('popover-arrow').css({right:($btnFeedback.outerWidth()/2)+'px',left:'auto'}).end()
|
41 |
-
.find('.popover-content').css({overflow:'hidden'})
|
42 |
-
.find('button').on('click', function () {
|
43 |
-
$btnFeedback.popover('hide');
|
44 |
-
$.ajax({
|
45 |
-
url : ajaxurl,
|
46 |
-
type : 'POST',
|
47 |
-
data : { action : 'bookly_dismiss_feedback_notice', csrf_token : SupportL10n.csrf_token }
|
48 |
-
});
|
49 |
-
}).end()
|
50 |
-
.end()
|
51 |
-
.end()
|
52 |
-
.on('click', function () {
|
53 |
-
$btnFeedback.popover('hide');
|
54 |
-
$.ajax({
|
55 |
-
url : ajaxurl,
|
56 |
-
type : 'POST',
|
57 |
-
data : { action : 'bookly_dismiss_feedback_notice', csrf_token : SupportL10n.csrf_token }
|
58 |
-
});
|
59 |
-
});
|
60 |
-
}
|
61 |
-
|
62 |
-
$('#bookly-support-send').on('click', function (e) {
|
63 |
-
var $name = $('#bookly-support-name'),
|
64 |
-
$email = $('#bookly-support-email'),
|
65 |
-
$msg = $('#bookly-support-msg')
|
66 |
-
;
|
67 |
-
|
68 |
-
// Validation.
|
69 |
-
$email.closest('.form-group').toggleClass('has-error', $email.val() == '');
|
70 |
-
$msg.closest('.form-group').toggleClass('has-error', $msg.val() == '');
|
71 |
-
|
72 |
-
// Send request.
|
73 |
-
if ($modal.find('.has-error').length == 0) {
|
74 |
-
var ladda = Ladda.create(this);
|
75 |
-
ladda.start();
|
76 |
-
$.ajax({
|
77 |
-
url : ajaxurl,
|
78 |
-
type : 'POST',
|
79 |
-
data : {
|
80 |
-
action : 'bookly_send_support_request',
|
81 |
-
csrf_token : SupportL10n.csrf_token,
|
82 |
-
name : $name.val(),
|
83 |
-
email : $email.val(),
|
84 |
-
msg : $msg.val()
|
85 |
-
},
|
86 |
-
dataType : 'json',
|
87 |
-
success : function (response) {
|
88 |
-
if (response.success) {
|
89 |
-
$msg.val('');
|
90 |
-
$modal.modal('hide');
|
91 |
-
booklyAlert({success : [response.data.message]});
|
92 |
-
} else {
|
93 |
-
booklyAlert({error : [response.data.message]});
|
94 |
-
if (response.data.invalid_email) {
|
95 |
-
$email.closest('.form-group').addClass('has-error');
|
96 |
-
}
|
97 |
-
}
|
98 |
-
},
|
99 |
-
complete : function () {
|
100 |
-
ladda.stop();
|
101 |
-
}
|
102 |
-
});
|
103 |
-
}
|
104 |
-
});
|
105 |
-
|
106 |
-
$('#bookly-js-mark-read-all-messages').on('click', function (e) {
|
107 |
-
e.preventDefault();
|
108 |
-
var $link = $(this),
|
109 |
-
ladda = Ladda.create($('#bookly-bell').get(0)),
|
110 |
-
$dropdown = $link.closest(".dropdown-menu");
|
111 |
-
|
112 |
-
$dropdown.prev().dropdown("toggle");
|
113 |
-
ladda.start();
|
114 |
-
$.ajax({
|
115 |
-
url : ajaxurl,
|
116 |
-
type : 'POST',
|
117 |
-
data : {
|
118 |
-
action: 'bookly_mark_read_all_messages',
|
119 |
-
csrf_token: SupportL10n.csrf_token
|
120 |
-
},
|
121 |
-
dataType : 'json',
|
122 |
-
success : function (response) {
|
123 |
-
if (response.success) {
|
124 |
-
$('.bookly-js-new-messages-count').remove();
|
125 |
-
$link.closest('li').remove();
|
126 |
-
$('a', $dropdown).each(function () {
|
127 |
-
$(this).html($(this).text());
|
128 |
-
});
|
129 |
-
}
|
130 |
-
},
|
131 |
-
complete : function () {
|
132 |
-
ladda.stop();
|
133 |
-
}
|
134 |
-
});
|
135 |
-
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
136 |
});
|
1 |
+
jQuery(function ($) {
|
2 |
+
var $modal = $('#bookly-support-modal'),
|
3 |
+
$btnContactUs = $('#bookly-contact-us-btn'),
|
4 |
+
$btnFeedback = $('#bookly-feedback-btn')
|
5 |
+
;
|
6 |
+
|
7 |
+
if ($btnContactUs.data('trigger')) {
|
8 |
+
$btnContactUs
|
9 |
+
.popover().popover('show')
|
10 |
+
.next('.popover')
|
11 |
+
.css({right:22+$btnFeedback.outerWidth()+'px',left:'auto'})
|
12 |
+
.find('.arrow').removeClass().addClass('popover-arrow').css({right:($btnContactUs.outerWidth()/2)+'px',left:'auto'}).end()
|
13 |
+
.find('.popover-content button').on('click', function () {
|
14 |
+
$btnContactUs.popover('hide');
|
15 |
+
$.ajax({
|
16 |
+
url : ajaxurl,
|
17 |
+
type : 'POST',
|
18 |
+
data : { action : 'bookly_dismiss_contact_us_notice', csrf_token : SupportL10n.csrf_token },
|
19 |
+
success : function(response) {
|
20 |
+
$btnContactUs.attr("data-processed", true);
|
21 |
+
}
|
22 |
+
});
|
23 |
+
}).end()
|
24 |
+
.end()
|
25 |
+
.on('click', function () {
|
26 |
+
$btnContactUs.popover('hide');
|
27 |
+
$.ajax({
|
28 |
+
url : ajaxurl,
|
29 |
+
type : 'POST',
|
30 |
+
data : { action : 'bookly_contact_us_btn_clicked', csrf_token : SupportL10n.csrf_token }
|
31 |
+
});
|
32 |
+
});
|
33 |
+
}
|
34 |
+
|
35 |
+
if ($btnFeedback.data('trigger')) {
|
36 |
+
$btnFeedback
|
37 |
+
.popover().popover('show')
|
38 |
+
.next('.popover')
|
39 |
+
.css({right:'10px',left:'auto'})
|
40 |
+
.find('.arrow').removeClass().addClass('popover-arrow').css({right:($btnFeedback.outerWidth()/2)+'px',left:'auto'}).end()
|
41 |
+
.find('.popover-content').css({overflow:'hidden'})
|
42 |
+
.find('button').on('click', function () {
|
43 |
+
$btnFeedback.popover('hide');
|
44 |
+
$.ajax({
|
45 |
+
url : ajaxurl,
|
46 |
+
type : 'POST',
|
47 |
+
data : { action : 'bookly_dismiss_feedback_notice', csrf_token : SupportL10n.csrf_token }
|
48 |
+
});
|
49 |
+
}).end()
|
50 |
+
.end()
|
51 |
+
.end()
|
52 |
+
.on('click', function () {
|
53 |
+
$btnFeedback.popover('hide');
|
54 |
+
$.ajax({
|
55 |
+
url : ajaxurl,
|
56 |
+
type : 'POST',
|
57 |
+
data : { action : 'bookly_dismiss_feedback_notice', csrf_token : SupportL10n.csrf_token }
|
58 |
+
});
|
59 |
+
});
|
60 |
+
}
|
61 |
+
|
62 |
+
$('#bookly-support-send').on('click', function (e) {
|
63 |
+
var $name = $('#bookly-support-name'),
|
64 |
+
$email = $('#bookly-support-email'),
|
65 |
+
$msg = $('#bookly-support-msg')
|
66 |
+
;
|
67 |
+
|
68 |
+
// Validation.
|
69 |
+
$email.closest('.form-group').toggleClass('has-error', $email.val() == '');
|
70 |
+
$msg.closest('.form-group').toggleClass('has-error', $msg.val() == '');
|
71 |
+
|
72 |
+
// Send request.
|
73 |
+
if ($modal.find('.has-error').length == 0) {
|
74 |
+
var ladda = Ladda.create(this);
|
75 |
+
ladda.start();
|
76 |
+
$.ajax({
|
77 |
+
url : ajaxurl,
|
78 |
+
type : 'POST',
|
79 |
+
data : {
|
80 |
+
action : 'bookly_send_support_request',
|
81 |
+
csrf_token : SupportL10n.csrf_token,
|
82 |
+
name : $name.val(),
|
83 |
+
email : $email.val(),
|
84 |
+
msg : $msg.val()
|
85 |
+
},
|
86 |
+
dataType : 'json',
|
87 |
+
success : function (response) {
|
88 |
+
if (response.success) {
|
89 |
+
$msg.val('');
|
90 |
+
$modal.modal('hide');
|
91 |
+
booklyAlert({success : [response.data.message]});
|
92 |
+
} else {
|
93 |
+
booklyAlert({error : [response.data.message]});
|
94 |
+
if (response.data.invalid_email) {
|
95 |
+
$email.closest('.form-group').addClass('has-error');
|
96 |
+
}
|
97 |
+
}
|
98 |
+
},
|
99 |
+
complete : function () {
|
100 |
+
ladda.stop();
|
101 |
+
}
|
102 |
+
});
|
103 |
+
}
|
104 |
+
});
|
105 |
+
|
106 |
+
$('#bookly-js-mark-read-all-messages').on('click', function (e) {
|
107 |
+
e.preventDefault();
|
108 |
+
var $link = $(this),
|
109 |
+
ladda = Ladda.create($('#bookly-bell').get(0)),
|
110 |
+
$dropdown = $link.closest(".dropdown-menu");
|
111 |
+
|
112 |
+
$dropdown.prev().dropdown("toggle");
|
113 |
+
ladda.start();
|
114 |
+
$.ajax({
|
115 |
+
url : ajaxurl,
|
116 |
+
type : 'POST',
|
117 |
+
data : {
|
118 |
+
action: 'bookly_mark_read_all_messages',
|
119 |
+
csrf_token: SupportL10n.csrf_token
|
120 |
+
},
|
121 |
+
dataType : 'json',
|
122 |
+
success : function (response) {
|
123 |
+
if (response.success) {
|
124 |
+
$('.bookly-js-new-messages-count').remove();
|
125 |
+
$link.closest('li').remove();
|
126 |
+
$('a', $dropdown).each(function () {
|
127 |
+
$(this).html($(this).text());
|
128 |
+
});
|
129 |
+
}
|
130 |
+
},
|
131 |
+
complete : function () {
|
132 |
+
ladda.stop();
|
133 |
+
}
|
134 |
+
});
|
135 |
+
});
|
136 |
+
|
137 |
+
$('[data-action=feature-request]')
|
138 |
+
.on('click', function () {
|
139 |
+
if ($(this).data('target')) {
|
140 |
+
window.open($(this).data('target'), '_blank');
|
141 |
+
} else {
|
142 |
+
$('#bookly-feature-requests-modal').modal('show');
|
143 |
+
}
|
144 |
+
});
|
145 |
+
|
146 |
+
$('.bookly-js-proceed-requests').on('click', function () {
|
147 |
+
var $modal = $('#bookly-feature-requests-modal'),
|
148 |
+
hide = $('#bookly-js-dont-show-again', $modal).prop('checked')||0,
|
149 |
+
ladda = Ladda.create(this);
|
150 |
+
ladda.start();
|
151 |
+
$.ajax({
|
152 |
+
url : ajaxurl,
|
153 |
+
type: 'POST',
|
154 |
+
data: {
|
155 |
+
action : 'bookly_proceed_to_feature_requests',
|
156 |
+
csrf_token: SupportL10n.csrf_token,
|
157 |
+
hide : hide
|
158 |
+
},
|
159 |
+
dataType: 'json',
|
160 |
+
success : function (response) {
|
161 |
+
if (response.success) {
|
162 |
+
$modal.modal('hide');
|
163 |
+
if (hide) {
|
164 |
+
$('[data-action=feature-request]').data('target', response.data.target);
|
165 |
+
}
|
166 |
+
window.open(response.data.target, '_blank');
|
167 |
+
}
|
168 |
+
},
|
169 |
+
complete: function () {
|
170 |
+
ladda.stop();
|
171 |
+
}
|
172 |
+
});
|
173 |
+
});
|
174 |
});
|
backend/components/support/templates/_email_to_support.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
-
<!doctype html>
|
3 |
-
<html>
|
4 |
-
<head>
|
5 |
-
<meta name="viewport" content="width=device-width" />
|
6 |
-
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7 |
-
<title>Support Request <?php echo site_url() ?></title>
|
8 |
-
</head>
|
9 |
-
<body>
|
10 |
-
<p><?php echo esc_html( $name ) ?><br /><?php echo esc_html( $email ) ?></p>
|
11 |
-
<p><?php echo nl2br( esc_html( $msg ) ) ?></p>
|
12 |
-
<ol>
|
13 |
-
<?php foreach ( $plugins as $plugin ): ?>
|
14 |
-
<li><?php echo $plugin::getTitle() ?> v<?php echo $plugin::getVersion() ?>: <b><?php echo $plugin::getPurchaseCode() ?></b></li>
|
15 |
-
<?php endforeach ?>
|
16 |
-
</ol>
|
17 |
-
<p><?php echo esc_html( $_SERVER['HTTP_REFERER'] ) ?></p>
|
18 |
-
</body>
|
19 |
</html>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly ?>
|
2 |
+
<!doctype html>
|
3 |
+
<html>
|
4 |
+
<head>
|
5 |
+
<meta name="viewport" content="width=device-width" />
|
6 |
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
7 |
+
<title>Support Request <?php echo site_url() ?></title>
|
8 |
+
</head>
|
9 |
+
<body>
|
10 |
+
<p><?php echo esc_html( $name ) ?><br /><?php echo esc_html( $email ) ?></p>
|
11 |
+
<p><?php echo nl2br( esc_html( $msg ) ) ?></p>
|
12 |
+
<ol>
|
13 |
+
<?php foreach ( $plugins as $plugin ): ?>
|
14 |
+
<li><?php echo $plugin::getTitle() ?> v<?php echo $plugin::getVersion() ?>: <b><?php echo $plugin::getPurchaseCode() ?></b></li>
|
15 |
+
<?php endforeach ?>
|
16 |
+
</ol>
|
17 |
+
<p><?php echo esc_html( $_SERVER['HTTP_REFERER'] ) ?></p>
|
18 |
+
</body>
|
19 |
</html>
|
backend/components/support/templates/buttons.php
CHANGED
@@ -1,86 +1,127 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
-
use Bookly\Backend\Components\Controls\Inputs;
|
4 |
-
use Bookly\Backend\Components\Support\Lib\Urls;
|
5 |
-
use Bookly\Lib\Utils;
|
6 |
-
?>
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
<
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
<li
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
<
|
36 |
-
|
37 |
-
|
38 |
-
<a href="#bookly-support-modal" id="bookly-contact-us-btn" class="btn btn-default-outline"
|
39 |
-
data-
|
40 |
-
|
41 |
-
|
42 |
-
data-trigger="manual" data-placement="bottom" data-html="1"
|
43 |
-
data-content="<?php echo esc_attr( '<button type="button" class="close pull-right bookly-margin-left-sm"><span>×</span></button>' .
|
44 |
-
<?php endif ?>
|
45 |
-
>
|
46 |
-
<i class="bookly-icon bookly-icon-contact-us"></i><?php
|
47 |
-
</a>
|
48 |
-
|
49 |
-
|
50 |
-
<?php
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
>
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
<
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
<
|
69 |
-
|
70 |
-
|
71 |
-
<
|
72 |
-
<
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
</div>
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
</div>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\Controls\Buttons;
|
3 |
+
use Bookly\Backend\Components\Controls\Inputs;
|
4 |
+
use Bookly\Backend\Components\Support\Lib\Urls;
|
5 |
+
use Bookly\Lib\Utils;
|
6 |
+
?>
|
7 |
+
<style type="text/css">
|
8 |
+
#bookly-tbs .page-header > .popover {
|
9 |
+
z-index: 1039;
|
10 |
+
}
|
11 |
+
</style>
|
12 |
+
<span class="dropdown">
|
13 |
+
<button type="button" class="btn btn-default-outline dropdown-toggle ladda-button" data-toggle="dropdown" id="bookly-bell" aria-haspopup="true" aria-expanded="true" data-spinner-size="40" data-style="zoom-in" data-spinner-color="#DDDDDD"><span class="ladda-label"><i class="bookly-icon glyphicon glyphicon-bell"></i></span></button>
|
14 |
+
<?php if ( $messages_new ) : ?>
|
15 |
+
<span class="badge bookly-js-new-messages-count"><?php echo $messages_new ?></span>
|
16 |
+
<?php endif ?>
|
17 |
+
<ul class="dropdown-menu dropdown-menu-right" aria-labelledby="bookly-bell">
|
18 |
+
<?php foreach ( $messages as $message ) : ?>
|
19 |
+
<li><a href="<?php echo $messages_link ?>"><?php echo Utils\DateTime::formatDate( $message['created'] ) . ': ';
|
20 |
+
if ( $message['seen'] ) :
|
21 |
+
echo esc_html( $message['subject'] );
|
22 |
+
else:
|
23 |
+
echo '<b>' . esc_html( $message['subject'] ) . '</b>';
|
24 |
+
endif ?>
|
25 |
+
</a></li>
|
26 |
+
<?php endforeach ?>
|
27 |
+
<li role="separator" class="divider"></li>
|
28 |
+
<li><a href="<?php echo $messages_link ?>"><?php esc_html_e( 'Show all notifications', 'bookly' ) ?></a></li>
|
29 |
+
<?php if ( $messages_new ) : ?>
|
30 |
+
<li><a href="#" id="bookly-js-mark-read-all-messages"><?php esc_html_e( 'Mark all notifications as read', 'bookly' ) ?></a></li>
|
31 |
+
<?php endif ?>
|
32 |
+
</ul>
|
33 |
+
</span>
|
34 |
+
<a href="<?php echo esc_url( $doc_link ) ?>" target="_blank" id="bookly-help-btn" class="btn btn-default-outline">
|
35 |
+
<i class="bookly-icon bookly-icon-help"></i><?php esc_html_e( 'Documentation', 'bookly' ) ?>
|
36 |
+
</a>
|
37 |
+
|
38 |
+
<a href="#bookly-support-modal" id="bookly-contact-us-btn" class="btn btn-default-outline"
|
39 |
+
data-toggle="modal"
|
40 |
+
<?php if ( $show_contact_us_notice ) : ?>
|
41 |
+
data-processed="false"
|
42 |
+
data-trigger="manual" data-placement="bottom" data-html="1"
|
43 |
+
data-content="<?php echo esc_attr( '<button type="button" class="close pull-right bookly-margin-left-sm"><span>×</span></button>' . esc_html__( 'Need help? Contact us here.', 'bookly' ) ) ?>"
|
44 |
+
<?php endif ?>
|
45 |
+
>
|
46 |
+
<i class="bookly-icon bookly-icon-contact-us"></i><?php esc_html_e( 'Contact Us', 'bookly' ) ?>
|
47 |
+
</a>
|
48 |
+
|
49 |
+
<?php if ( get_user_meta( get_current_user_id(), 'bookly_feature_requests_rules_hide', true ) ) : ?>
|
50 |
+
<a href="<?php echo Utils\Common::prepareUrlReferrers( Urls::FEATURES_REQUEST_PAGE, 'notification_bar' ) ?>" target="_blank" class="btn btn-default-outline bookly-margin-left-sm">
|
51 |
+
<i class="bookly-icon"><i class="fas fa-lightbulb"></i></i><?php esc_html_e( 'Feature requests', 'bookly' ) ?>
|
52 |
+
</a>
|
53 |
+
<?php else : ?>
|
54 |
+
<div id="bookly-feature-requests-modal" class="modal fade text-left" tabindex=-1>
|
55 |
+
<div class="modal-dialog">
|
56 |
+
<div class="modal-content">
|
57 |
+
<div class="modal-header">
|
58 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
59 |
+
<h4 class="modal-title"><?php esc_html_e( 'Feature requests', 'bookly' ) ?></h4>
|
60 |
+
</div>
|
61 |
+
<div class="modal-body">
|
62 |
+
<p>
|
63 |
+
<?php esc_html_e( 'In the Feature Requests section of our Community, you can make suggestions about what you\'d like to see in our future releases.', 'bookly' ) ?>
|
64 |
+
</p>
|
65 |
+
<p>
|
66 |
+
<?php esc_html_e( 'Before you post, please check if the same suggestion has already been made. If so, vote for ideas you like and add a comment with the details about your situation.', 'bookly' ) ?>
|
67 |
+
</p>
|
68 |
+
<p>
|
69 |
+
<?php esc_html_e( 'It\'s much easier for us to address a suggestion if we clearly understand the context of the issue, the problem, and why it matters to you. When commenting or posting, please consider these questions so we can get a better idea of the problem you\'re facing:', 'bookly' ) ?>
|
70 |
+
<div>● <?php esc_html_e( 'What is the issue you\'re struggling with?', 'bookly' ) ?></div>
|
71 |
+
<div>● <?php esc_html_e( 'Where in your workflow do you encounter this issue?', 'bookly' ) ?></div>
|
72 |
+
<div>● <?php esc_html_e( 'Is this something that impacts just you, your whole team, or your customers?', 'bookly' ) ?></div>
|
73 |
+
</p>
|
74 |
+
<div class="form-inline">
|
75 |
+
<input type="checkbox" id="bookly-js-dont-show-again" /> <label class="bookly-checkbox-text" for="bookly-js-dont-show-again"><?php esc_html_e( 'don\'t show this notification again', 'bookly' ) ?></label>
|
76 |
+
</div>
|
77 |
+
</div>
|
78 |
+
<div class="modal-footer">
|
79 |
+
<?php Buttons::renderCustom( null, 'bookly-js-proceed-requests btn-success btn-lg', esc_html__( 'Proceed to Feature requests', 'bookly' ) ) ?>
|
80 |
+
<?php Buttons::renderCustom( null, 'btn-default btn-lg', esc_html__( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
81 |
+
</div>
|
82 |
+
</div>
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
<button data-action="feature-request" class="btn btn-default-outline bookly-margin-left-sm">
|
86 |
+
<i class="bookly-icon"><i class="fas fa-lightbulb"></i></i><?php esc_html_e( 'Feature requests', 'bookly' ) ?>
|
87 |
+
</button>
|
88 |
+
<?php endif ?>
|
89 |
+
|
90 |
+
<a href="<?php echo Utils\Common::prepareUrlReferrers( Urls::REVIEWS_PAGE, 'feedback' ) ?>" id="bookly-feedback-btn" target="_blank" class="btn btn-default-outline"
|
91 |
+
<?php if ( $show_feedback_notice ) : ?>
|
92 |
+
data-trigger="manual" data-placement="bottom" data-html="1"
|
93 |
+
data-content="<?php echo esc_attr( '<button type="button" class="close pull-right bookly-margin-left-sm"><span>×</span></button><div class="pull-left">' . esc_html__( 'We care about your experience of using Bookly!<br/>Leave a review and tell others what you think.', 'bookly' ) . '</div>' ) ?>"
|
94 |
+
<?php endif ?>
|
95 |
+
>
|
96 |
+
<i class="bookly-icon bookly-icon-feedback"></i><?php esc_html_e( 'Feedback', 'bookly' ) ?>
|
97 |
+
</a>
|
98 |
+
|
99 |
+
<div id="bookly-support-modal" class="modal fade text-left" tabindex=-1>
|
100 |
+
<div class="modal-dialog">
|
101 |
+
<div class="modal-content">
|
102 |
+
<div class="modal-header">
|
103 |
+
<button type="button" class="close" data-dismiss="modal"><span>×</span></button>
|
104 |
+
<h4 class="modal-title"><?php esc_html_e( 'Leave us a message', 'bookly' ) ?></h4>
|
105 |
+
</div>
|
106 |
+
<div class="modal-body">
|
107 |
+
<div class="form-group">
|
108 |
+
<label for="bookly-support-name" class="control-label"><?php esc_html_e( 'Your name', 'bookly' ) ?></label>
|
109 |
+
<input type="text" id="bookly-support-name" class="form-control" value="<?php echo esc_attr( $current_user->user_firstname . ' ' . $current_user->user_lastname ) ?>" />
|
110 |
+
</div>
|
111 |
+
<div class="form-group">
|
112 |
+
<label for="bookly-support-email" class="control-label"><?php esc_html_e( 'Email address', 'bookly' ) ?> <span class="bookly-color-brand-danger">*</span></label>
|
113 |
+
<input type="text" id="bookly-support-email" class="form-control" value="<?php echo esc_attr( $current_user->user_email ) ?>" />
|
114 |
+
</div>
|
115 |
+
<div class="form-group">
|
116 |
+
<label for="bookly-support-msg" class="control-label"><?php esc_html_e( 'How can we help you?', 'bookly' ) ?> <span class="bookly-color-brand-danger">*</span></label>
|
117 |
+
<textarea id="bookly-support-msg" class="form-control" rows="10"></textarea>
|
118 |
+
</div>
|
119 |
+
</div>
|
120 |
+
<div class="modal-footer">
|
121 |
+
<?php Inputs::renderCsrf() ?>
|
122 |
+
<?php Buttons::renderCustom( 'bookly-support-send', 'btn-success btn-lg', esc_html__( 'Send', 'bookly' ) ) ?>
|
123 |
+
<?php Buttons::renderCustom( null, 'btn-default btn-lg', esc_html__( 'Cancel', 'bookly' ), array( 'data-dismiss' => 'modal' ) ) ?>
|
124 |
+
</div>
|
125 |
+
</div>
|
126 |
+
</div>
|
127 |
</div>
|
backend/components/tiny_mce/Tools.php
CHANGED
@@ -1,58 +1,58 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\TinyMce;
|
3 |
-
|
4 |
-
use Bookly\Backend\Components\TinyMce\Proxy;
|
5 |
-
use Bookly\Lib;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Tools
|
9 |
-
* @package Bookly\Backend\Modules\TinyMce
|
10 |
-
*/
|
11 |
-
class Tools extends Lib\Base\Component
|
12 |
-
{
|
13 |
-
public static function init()
|
14 |
-
{
|
15 |
-
global $PHP_SELF;
|
16 |
-
if ( // check if we are in admin area and current page is adding/editing the post
|
17 |
-
is_admin() && ( strpos( $PHP_SELF, 'post-new.php' ) !== false || strpos( $PHP_SELF, 'post.php' ) !== false || strpos( $PHP_SELF, 'admin-ajax.php' ) )
|
18 |
-
) {
|
19 |
-
add_action( 'admin_footer', array( '\Bookly\Backend\Components\TinyMce\Tools', 'renderPopup' ), 10, 0 );
|
20 |
-
add_filter( 'media_buttons', array( '\Bookly\Backend\Components\TinyMce\Tools', 'addButton' ), 50, 1 );
|
21 |
-
}
|
22 |
-
}
|
23 |
-
|
24 |
-
public static function addButton( $editor_id )
|
25 |
-
{
|
26 |
-
// don't show on dashboard (QuickPress)
|
27 |
-
$current_screen = get_current_screen();
|
28 |
-
if ( $current_screen && 'dashboard' == $current_screen->base ) {
|
29 |
-
return;
|
30 |
-
}
|
31 |
-
|
32 |
-
// don't display button for users who don't have access
|
33 |
-
if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
|
34 |
-
return;
|
35 |
-
}
|
36 |
-
|
37 |
-
// do a version check for the new 3.5 UI
|
38 |
-
$version = get_bloginfo( 'version' );
|
39 |
-
|
40 |
-
if ( $version < 3.5 ) {
|
41 |
-
// show button for v 3.4 and below
|
42 |
-
echo '<a href="#TB_inline?width=640&inlineId=bookly-tinymce-popup&height=650" id="add-bookly-form" title="' . esc_attr__( 'Add Bookly booking form', 'bookly' ) . '">' . __( 'Add Bookly booking form', 'bookly' ) . '</a>';
|
43 |
-
} else {
|
44 |
-
// display button matching new UI
|
45 |
-
$img = '<span class="bookly-media-icon"></span> ';
|
46 |
-
echo '<a href="#TB_inline?width=640&inlineId=bookly-tinymce-popup&height=650" id="add-bookly-form" class="thickbox button bookly-media-button" title="' . esc_attr__( 'Add Bookly booking form', 'bookly' ) . '">' . $img . __( 'Add Bookly booking form', 'bookly' ) . '</a>';
|
47 |
-
}
|
48 |
-
Proxy\Shared::renderMediaButtons( $version );
|
49 |
-
}
|
50 |
-
|
51 |
-
public static function renderPopup()
|
52 |
-
{
|
53 |
-
$casest = Lib\Config::getCaSeSt();
|
54 |
-
self::renderTemplate( 'bookly_form', compact( 'casest' ) );
|
55 |
-
|
56 |
-
Proxy\Shared::renderPopup();
|
57 |
-
}
|
58 |
-
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\TinyMce;
|
3 |
+
|
4 |
+
use Bookly\Backend\Components\TinyMce\Proxy;
|
5 |
+
use Bookly\Lib;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Tools
|
9 |
+
* @package Bookly\Backend\Modules\TinyMce
|
10 |
+
*/
|
11 |
+
class Tools extends Lib\Base\Component
|
12 |
+
{
|
13 |
+
public static function init()
|
14 |
+
{
|
15 |
+
global $PHP_SELF;
|
16 |
+
if ( // check if we are in admin area and current page is adding/editing the post
|
17 |
+
is_admin() && ( strpos( $PHP_SELF, 'post-new.php' ) !== false || strpos( $PHP_SELF, 'post.php' ) !== false || strpos( $PHP_SELF, 'admin-ajax.php' ) )
|
18 |
+
) {
|
19 |
+
add_action( 'admin_footer', array( '\Bookly\Backend\Components\TinyMce\Tools', 'renderPopup' ), 10, 0 );
|
20 |
+
add_filter( 'media_buttons', array( '\Bookly\Backend\Components\TinyMce\Tools', 'addButton' ), 50, 1 );
|
21 |
+
}
|
22 |
+
}
|
23 |
+
|
24 |
+
public static function addButton( $editor_id )
|
25 |
+
{
|
26 |
+
// don't show on dashboard (QuickPress)
|
27 |
+
$current_screen = get_current_screen();
|
28 |
+
if ( $current_screen && 'dashboard' == $current_screen->base ) {
|
29 |
+
return;
|
30 |
+
}
|
31 |
+
|
32 |
+
// don't display button for users who don't have access
|
33 |
+
if ( ! current_user_can( 'edit_posts' ) && ! current_user_can( 'edit_pages' ) ) {
|
34 |
+
return;
|
35 |
+
}
|
36 |
+
|
37 |
+
// do a version check for the new 3.5 UI
|
38 |
+
$version = get_bloginfo( 'version' );
|
39 |
+
|
40 |
+
if ( $version < 3.5 ) {
|
41 |
+
// show button for v 3.4 and below
|
42 |
+
echo '<a href="#TB_inline?width=640&inlineId=bookly-tinymce-popup&height=650" id="add-bookly-form" title="' . esc_attr__( 'Add Bookly booking form', 'bookly' ) . '">' . __( 'Add Bookly booking form', 'bookly' ) . '</a>';
|
43 |
+
} else {
|
44 |
+
// display button matching new UI
|
45 |
+
$img = '<span class="bookly-media-icon"></span> ';
|
46 |
+
echo '<a href="#TB_inline?width=640&inlineId=bookly-tinymce-popup&height=650" id="add-bookly-form" class="thickbox button bookly-media-button" title="' . esc_attr__( 'Add Bookly booking form', 'bookly' ) . '">' . $img . __( 'Add Bookly booking form', 'bookly' ) . '</a>';
|
47 |
+
}
|
48 |
+
Proxy\Shared::renderMediaButtons( $version );
|
49 |
+
}
|
50 |
+
|
51 |
+
public static function renderPopup()
|
52 |
+
{
|
53 |
+
$casest = Lib\Config::getCaSeSt();
|
54 |
+
self::renderTemplate( 'bookly_form', compact( 'casest' ) );
|
55 |
+
|
56 |
+
Proxy\Shared::renderPopup();
|
57 |
+
}
|
58 |
+
}
|
backend/components/tiny_mce/proxy/DepositPayments.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class DepositPayments
|
8 |
-
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
-
*/
|
12 |
-
abstract class DepositPayments extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class DepositPayments
|
8 |
+
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
+
*/
|
12 |
+
abstract class DepositPayments extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/tiny_mce/proxy/GroupBooking.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class GroupBooking
|
8 |
-
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
-
*/
|
12 |
-
abstract class GroupBooking extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class GroupBooking
|
8 |
+
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
+
*/
|
12 |
+
abstract class GroupBooking extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/tiny_mce/proxy/Shared.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Shared
|
8 |
-
* @package Bookly\Backend\Components\TinyMce\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderMediaButtons( string $version ) Add buttons to WordPress editor.
|
11 |
-
* @method static void renderBooklyFormFields() Render controls in popup for bookly-form (build shortcode).
|
12 |
-
* @method static void renderBooklyFormHead() Render controls in header of popup for bookly-form (build shortcode).
|
13 |
-
* @method static void renderPopup() Render popup windows for WordPress editor.
|
14 |
-
*/
|
15 |
-
abstract class Shared extends Lib\Base\Proxy
|
16 |
-
{
|
17 |
-
|
18 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Shared
|
8 |
+
* @package Bookly\Backend\Components\TinyMce\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderMediaButtons( string $version ) Add buttons to WordPress editor.
|
11 |
+
* @method static void renderBooklyFormFields() Render controls in popup for bookly-form (build shortcode).
|
12 |
+
* @method static void renderBooklyFormHead() Render controls in header of popup for bookly-form (build shortcode).
|
13 |
+
* @method static void renderPopup() Render popup windows for WordPress editor.
|
14 |
+
*/
|
15 |
+
abstract class Shared extends Lib\Base\Proxy
|
16 |
+
{
|
17 |
+
|
18 |
}
|
backend/components/tiny_mce/proxy/SpecialDays.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class SpecialDays
|
8 |
-
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
-
*/
|
12 |
-
abstract class SpecialDays extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class SpecialDays
|
8 |
+
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
+
*/
|
12 |
+
abstract class SpecialDays extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/tiny_mce/proxy/SpecialHours.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class SpecialHours
|
8 |
-
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
-
*/
|
12 |
-
abstract class SpecialHours extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class SpecialHours
|
8 |
+
* @package Bookly\Backend\Components\TinyMce\Proxy\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderStaffCabinetSettings() Render settings in Staff Cabinet shortcode.
|
11 |
+
*/
|
12 |
+
abstract class SpecialHours extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/components/tiny_mce/templates/bookly_form.php
CHANGED
@@ -1,424 +1,425 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
-
?>
|
4 |
-
|
5 |
-
<div id="bookly-tinymce-popup" style="display: none">
|
6 |
-
<form id="bookly-shortcode-form">
|
7 |
-
<table>
|
8 |
-
<?php Proxy\Shared::renderBooklyFormHead() ?>
|
9 |
-
<tr>
|
10 |
-
<td>
|
11 |
-
<label for="bookly-select-category"><?php
|
12 |
-
</td>
|
13 |
-
<td>
|
14 |
-
<select id="bookly-select-category">
|
15 |
-
<option value=""><?php
|
16 |
-
</select>
|
17 |
-
<div><label><input type="checkbox" id="bookly-hide-categories" /><?php
|
18 |
-
</td>
|
19 |
-
</tr>
|
20 |
-
<tr>
|
21 |
-
<td>
|
22 |
-
<label for="bookly-select-service"><?php
|
23 |
-
</td>
|
24 |
-
<td>
|
25 |
-
<select id="bookly-select-service">
|
26 |
-
<option value=""><?php
|
27 |
-
</select>
|
28 |
-
<div><label><input type="checkbox" id="bookly-hide-services" /><?php
|
29 |
-
<i><?php
|
30 |
-
</td>
|
31 |
-
</tr>
|
32 |
-
<tr>
|
33 |
-
<td>
|
34 |
-
<label for="bookly-select-employee"><?php
|
35 |
-
</td>
|
36 |
-
<td>
|
37 |
-
<select class="bookly-select-mobile" id="bookly-select-employee">
|
38 |
-
<option value=""><?php
|
39 |
-
</select>
|
40 |
-
<div><label><input type="checkbox" id="bookly-hide-employee" /><?php
|
41 |
-
</td>
|
42 |
-
</tr>
|
43 |
-
<?php Proxy\Shared::renderBooklyFormFields() ?>
|
44 |
-
<tr>
|
45 |
-
<td>
|
46 |
-
<label for="bookly-hide-date"><?php
|
47 |
-
</td>
|
48 |
-
<td>
|
49 |
-
<label><input type="checkbox" id="bookly-hide-date" /><?php
|
50 |
-
</td>
|
51 |
-
</tr>
|
52 |
-
<tr>
|
53 |
-
<td>
|
54 |
-
<label for="bookly-hide-week-days"><?php
|
55 |
-
</td>
|
56 |
-
<td>
|
57 |
-
<label><input type="checkbox" id="bookly-hide-week-days" /><?php
|
58 |
-
</td>
|
59 |
-
</tr>
|
60 |
-
<tr>
|
61 |
-
<td>
|
62 |
-
<label for="bookly-hide-time-range"><?php
|
63 |
-
</td>
|
64 |
-
<td>
|
65 |
-
<label><input type="checkbox" id="bookly-hide-time-range" /><?php
|
66 |
-
</td>
|
67 |
-
</tr>
|
68 |
-
<tr>
|
69 |
-
<td></td>
|
70 |
-
<td>
|
71 |
-
<
|
72 |
-
</td>
|
73 |
-
</tr>
|
74 |
-
</table>
|
75 |
-
</form>
|
76 |
-
</div>
|
77 |
-
<style type="text/css">
|
78 |
-
#bookly-shortcode-form { margin-top: 15px; }
|
79 |
-
#bookly-shortcode-form table { width: 100%; }
|
80 |
-
#bookly-shortcode-form table td select { width: 100%; margin-bottom: 5px; }
|
81 |
-
.bookly-media-icon {
|
82 |
-
display: inline-block;
|
83 |
-
width: 16px;
|
84 |
-
height: 16px;
|
85 |
-
vertical-align: text-top;
|
86 |
-
margin: 0 2px;
|
87 |
-
background: url("<?php echo plugins_url( 'resources/images/calendar.png', __DIR__ ) ?>") 0 0 no-repeat;
|
88 |
-
}
|
89 |
-
#TB_overlay { z-index: 100001 !important; }
|
90 |
-
#TB_window { z-index: 100002 !important; }
|
91 |
-
</style>
|
92 |
-
<script type="text/javascript">
|
93 |
-
jQuery(function ($) {
|
94 |
-
var $
|
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 |
-
window.
|
120 |
-
|
121 |
-
|
122 |
-
'overflow-
|
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 |
-
option
|
151 |
-
option.
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
var
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
setSelect($
|
235 |
-
setSelect($
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
setSelect($
|
349 |
-
setSelect($
|
350 |
-
setSelect($
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
var
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
$
|
408 |
-
$
|
409 |
-
$
|
410 |
-
$
|
411 |
-
$
|
412 |
-
$
|
413 |
-
$
|
414 |
-
$
|
415 |
-
$
|
416 |
-
$
|
417 |
-
$
|
418 |
-
$
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
|
|
424 |
</script>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Backend\Components\TinyMce\Proxy;
|
3 |
+
?>
|
4 |
+
|
5 |
+
<div id="bookly-tinymce-popup" style="display: none">
|
6 |
+
<form id="bookly-shortcode-form">
|
7 |
+
<table>
|
8 |
+
<?php Proxy\Shared::renderBooklyFormHead() ?>
|
9 |
+
<tr>
|
10 |
+
<td>
|
11 |
+
<label for="bookly-select-category"><?php esc_html_e( 'Default value for category select', 'bookly' ) ?></label>
|
12 |
+
</td>
|
13 |
+
<td>
|
14 |
+
<select id="bookly-select-category">
|
15 |
+
<option value=""><?php esc_html_e( 'Select category', 'bookly' ) ?></option>
|
16 |
+
</select>
|
17 |
+
<div><label><input type="checkbox" id="bookly-hide-categories" /><?php esc_html_e( 'Hide this field', 'bookly' ) ?></label></div>
|
18 |
+
</td>
|
19 |
+
</tr>
|
20 |
+
<tr>
|
21 |
+
<td>
|
22 |
+
<label for="bookly-select-service"><?php esc_html_e( 'Default value for service select', 'bookly' ) ?></label>
|
23 |
+
</td>
|
24 |
+
<td>
|
25 |
+
<select id="bookly-select-service">
|
26 |
+
<option value=""><?php esc_html_e( 'Select service', 'bookly' ) ?></option>
|
27 |
+
</select>
|
28 |
+
<div><label><input type="checkbox" id="bookly-hide-services" /><?php esc_html_e( 'Hide this field', 'bookly' ) ?></label></div>
|
29 |
+
<i><?php esc_html_e( 'Please be aware that a value in this field is required in the frontend. If you choose to hide this field, please be sure to select a default value for it', 'bookly' ) ?></i>
|
30 |
+
</td>
|
31 |
+
</tr>
|
32 |
+
<tr>
|
33 |
+
<td>
|
34 |
+
<label for="bookly-select-employee"><?php esc_html_e( 'Default value for employee select', 'bookly' ) ?></label>
|
35 |
+
</td>
|
36 |
+
<td>
|
37 |
+
<select class="bookly-select-mobile" id="bookly-select-employee">
|
38 |
+
<option value=""><?php esc_html_e( 'Any', 'bookly' ) ?></option>
|
39 |
+
</select>
|
40 |
+
<div><label><input type="checkbox" id="bookly-hide-employee" /><?php esc_html_e( 'Hide this field', 'bookly' ) ?></label></div>
|
41 |
+
</td>
|
42 |
+
</tr>
|
43 |
+
<?php Proxy\Shared::renderBooklyFormFields() ?>
|
44 |
+
<tr>
|
45 |
+
<td>
|
46 |
+
<label for="bookly-hide-date"><?php esc_html_e( 'Date', 'bookly' ) ?></label>
|
47 |
+
</td>
|
48 |
+
<td>
|
49 |
+
<label><input type="checkbox" id="bookly-hide-date" /><?php esc_html_e( 'Hide this block', 'bookly' ) ?></label>
|
50 |
+
</td>
|
51 |
+
</tr>
|
52 |
+
<tr>
|
53 |
+
<td>
|
54 |
+
<label for="bookly-hide-week-days"><?php esc_html_e( 'Week days', 'bookly' ) ?></label>
|
55 |
+
</td>
|
56 |
+
<td>
|
57 |
+
<label><input type="checkbox" id="bookly-hide-week-days" /><?php esc_html_e( 'Hide this block', 'bookly' ) ?></label>
|
58 |
+
</td>
|
59 |
+
</tr>
|
60 |
+
<tr>
|
61 |
+
<td>
|
62 |
+
<label for="bookly-hide-time-range"><?php esc_html_e( 'Time range', 'bookly' ) ?></label>
|
63 |
+
</td>
|
64 |
+
<td>
|
65 |
+
<label><input type="checkbox" id="bookly-hide-time-range" /><?php esc_html_e( 'Hide this block', 'bookly' ) ?></label>
|
66 |
+
</td>
|
67 |
+
</tr>
|
68 |
+
<tr>
|
69 |
+
<td></td>
|
70 |
+
<td>
|
71 |
+
<button class="button button-primary bookly-js-insert-shortcode" type="button"><?php esc_html_e( 'Insert', 'bookly' ) ?></button>
|
72 |
+
</td>
|
73 |
+
</tr>
|
74 |
+
</table>
|
75 |
+
</form>
|
76 |
+
</div>
|
77 |
+
<style type="text/css">
|
78 |
+
#bookly-shortcode-form { margin-top: 15px; }
|
79 |
+
#bookly-shortcode-form table { width: 100%; }
|
80 |
+
#bookly-shortcode-form table td select { width: 100%; margin-bottom: 5px; }
|
81 |
+
.bookly-media-icon {
|
82 |
+
display: inline-block;
|
83 |
+
width: 16px;
|
84 |
+
height: 16px;
|
85 |
+
vertical-align: text-top;
|
86 |
+
margin: 0 2px;
|
87 |
+
background: url("<?php echo plugins_url( 'resources/images/calendar.png', __DIR__ ) ?>") 0 0 no-repeat;
|
88 |
+
}
|
89 |
+
#TB_overlay { z-index: 100001 !important; }
|
90 |
+
#TB_window { z-index: 100002 !important; }
|
91 |
+
</style>
|
92 |
+
<script type="text/javascript">
|
93 |
+
jQuery(function ($) {
|
94 |
+
var $form = $('#bookly-shortcode-form'),
|
95 |
+
$select_location = $('#bookly-select-location',$form),
|
96 |
+
$select_category = $('#bookly-select-category',$form),
|
97 |
+
$select_service = $('#bookly-select-service',$form),
|
98 |
+
$select_employee = $('#bookly-select-employee',$form),
|
99 |
+
$hide_locations = $('#bookly-hide-locations',$form),
|
100 |
+
$hide_categories = $('#bookly-hide-categories',$form),
|
101 |
+
$hide_services = $('#bookly-hide-services',$form),
|
102 |
+
$hide_staff = $('#bookly-hide-employee',$form),
|
103 |
+
$hide_service_duration = $('#bookly-hide-service-duration',$form),
|
104 |
+
$hide_number_of_persons = $('#bookly-hide-number-of-persons',$form),
|
105 |
+
$hide_quantity = $('#bookly-hide-quantity',$form),
|
106 |
+
$hide_date = $('#bookly-hide-date',$form),
|
107 |
+
$hide_week_days = $('#bookly-hide-week-days',$form),
|
108 |
+
$hide_time_range = $('#bookly-hide-time-range',$form),
|
109 |
+
$add_button = $('#add-bookly-form'),
|
110 |
+
$insert = $('button.bookly-js-insert-shortcode', $form),
|
111 |
+
location_custom = <?php echo (int) Bookly\Lib\Proxy\Locations::servicesPerLocationAllowed() ?>,
|
112 |
+
locations = <?php echo json_encode( $casest['locations'] ) ?>,
|
113 |
+
categories = <?php echo json_encode( $casest['categories'] ) ?>,
|
114 |
+
services = <?php echo json_encode( $casest['services'] ) ?>,
|
115 |
+
staff = <?php echo json_encode( $casest['staff'] ) ?>
|
116 |
+
;
|
117 |
+
|
118 |
+
$add_button.on('click', function () {
|
119 |
+
window.parent.tb_show(<?php echo json_encode( __( 'Insert Appointment Booking Form', 'bookly' ) ) ?>, this.href);
|
120 |
+
window.setTimeout(function(){
|
121 |
+
$('#TB_window').css({
|
122 |
+
'overflow-x': 'auto',
|
123 |
+
'overflow-y': 'hidden'
|
124 |
+
});
|
125 |
+
},100);
|
126 |
+
});
|
127 |
+
// insert data into select
|
128 |
+
function setSelect($select, data, value) {
|
129 |
+
// reset select
|
130 |
+
$('option:not([value=""])', $select).remove();
|
131 |
+
// and fill the new data
|
132 |
+
var docFragment = document.createDocumentFragment();
|
133 |
+
|
134 |
+
function valuesToArray(obj) {
|
135 |
+
return Object.keys(obj).map(function (key) { return obj[key]; });
|
136 |
+
}
|
137 |
+
|
138 |
+
function compare(a, b) {
|
139 |
+
if (parseInt(a.pos) < parseInt(b.pos))
|
140 |
+
return -1;
|
141 |
+
if (parseInt(a.pos) > parseInt(b.pos))
|
142 |
+
return 1;
|
143 |
+
return 0;
|
144 |
+
}
|
145 |
+
|
146 |
+
// sort select by position
|
147 |
+
data = valuesToArray(data).sort(compare);
|
148 |
+
|
149 |
+
$.each(data, function(key, object) {
|
150 |
+
var option = document.createElement('option');
|
151 |
+
option.value = object.id;
|
152 |
+
option.text = object.name;
|
153 |
+
docFragment.appendChild(option);
|
154 |
+
});
|
155 |
+
$select.append(docFragment);
|
156 |
+
// set default value of select
|
157 |
+
$select.val(value);
|
158 |
+
}
|
159 |
+
|
160 |
+
function setSelects(location_id, category_id, service_id, staff_id) {
|
161 |
+
var _location_id = (location_custom && location_id) ? location_id : 0
|
162 |
+
var _staff = {}, _services = {}, _categories = {}, _nop = {}, _max_capacity = null, _min_capacity = null;
|
163 |
+
$.each(staff, function(id, staff_member) {
|
164 |
+
if (!location_id || locations[location_id].staff.hasOwnProperty(id)) {
|
165 |
+
if (!service_id) {
|
166 |
+
if (!category_id) {
|
167 |
+
_staff[id] = staff_member;
|
168 |
+
} else {
|
169 |
+
$.each(staff_member.services, function(s_id) {
|
170 |
+
if (services[s_id].category_id == category_id) {
|
171 |
+
_staff[id] = staff_member;
|
172 |
+
return false;
|
173 |
+
}
|
174 |
+
});
|
175 |
+
}
|
176 |
+
} else if (staff_member.services.hasOwnProperty(service_id)) {
|
177 |
+
// var _location_id = staff_member.services[service_id].locations.hasOwnProperty(location_id) ? location_id : 0;
|
178 |
+
if (staff_member.services[service_id].locations.hasOwnProperty(_location_id)) {
|
179 |
+
if ( staff_member.services[service_id].locations[_location_id].price != null) {
|
180 |
+
_min_capacity = _min_capacity ? Math.min(_min_capacity, staff_member.services[service_id].locations[_location_id].min_capacity) : staff_member.services[service_id].locations[_location_id].min_capacity;
|
181 |
+
_max_capacity = _max_capacity ? Math.max(_max_capacity, staff_member.services[service_id].locations[_location_id].max_capacity) : staff_member.services[service_id].locations[_location_id].max_capacity;
|
182 |
+
_staff[id] = {
|
183 |
+
id : id,
|
184 |
+
name : staff_member.name + ' (' + staff_member.services[service_id].locations[_location_id].price + ')',
|
185 |
+
pos : staff_member.pos
|
186 |
+
};
|
187 |
+
} else {
|
188 |
+
_staff[id] = {
|
189 |
+
id : id,
|
190 |
+
name : staff_member.name,
|
191 |
+
pos : staff_member.pos
|
192 |
+
};
|
193 |
+
}
|
194 |
+
}
|
195 |
+
}
|
196 |
+
}
|
197 |
+
});
|
198 |
+
if (!location_id) {
|
199 |
+
_categories = categories;
|
200 |
+
$.each(services, function(id, service) {
|
201 |
+
if (!category_id || service.category_id == category_id) {
|
202 |
+
if (!staff_id || staff[staff_id].services.hasOwnProperty(id)) {
|
203 |
+
_services[id] = service;
|
204 |
+
}
|
205 |
+
}
|
206 |
+
});
|
207 |
+
} else {
|
208 |
+
var category_ids = [],
|
209 |
+
service_ids = [];
|
210 |
+
$.each(staff, function (st_id) {
|
211 |
+
$.each(staff[st_id].services, function (s_id) {
|
212 |
+
if (staff[st_id].services[s_id].locations.hasOwnProperty(_location_id)) {
|
213 |
+
category_ids.push(services[s_id].category_id);
|
214 |
+
service_ids.push(s_id);
|
215 |
+
}
|
216 |
+
});
|
217 |
+
});
|
218 |
+
$.each(categories, function(id, category) {
|
219 |
+
if ($.inArray(parseInt(id), category_ids) > -1) {
|
220 |
+
_categories[id] = category;
|
221 |
+
}
|
222 |
+
});
|
223 |
+
$.each(services, function(id, service) {
|
224 |
+
if ($.inArray(id, service_ids) > -1) {
|
225 |
+
if (!category_id || service.category_id == category_id) {
|
226 |
+
if (!staff_id || staff[staff_id].services.hasOwnProperty(id)) {
|
227 |
+
_services[id] = service;
|
228 |
+
}
|
229 |
+
}
|
230 |
+
}
|
231 |
+
});
|
232 |
+
}
|
233 |
+
|
234 |
+
setSelect($select_category, _categories, category_id);
|
235 |
+
setSelect($select_service, _services, service_id);
|
236 |
+
setSelect($select_employee, _staff, staff_id);
|
237 |
+
}
|
238 |
+
|
239 |
+
// Location select change
|
240 |
+
$select_location.on('change', function () {
|
241 |
+
var location_id = this.value,
|
242 |
+
category_id = $select_category.val(),
|
243 |
+
service_id = $select_service.val(),
|
244 |
+
staff_id = $select_employee.val()
|
245 |
+
;
|
246 |
+
|
247 |
+
// Validate selected values.
|
248 |
+
if (location_id != '') {
|
249 |
+
if (staff_id != '' && !locations[location_id].staff.hasOwnProperty(staff_id)) {
|
250 |
+
staff_id = '';
|
251 |
+
}
|
252 |
+
if (service_id != '') {
|
253 |
+
var valid = false;
|
254 |
+
$.each(locations[location_id].staff, function(id) {
|
255 |
+
if (staff[id].services.hasOwnProperty(service_id)) {
|
256 |
+
valid = true;
|
257 |
+
return false;
|
258 |
+
}
|
259 |
+
});
|
260 |
+
if (!valid) {
|
261 |
+
service_id = '';
|
262 |
+
}
|
263 |
+
}
|
264 |
+
if (category_id != '') {
|
265 |
+
var valid = false;
|
266 |
+
$.each(locations[location_id].staff, function(id) {
|
267 |
+
$.each(staff[id].services, function(s_id) {
|
268 |
+
if (services[s_id].category_id == category_id) {
|
269 |
+
valid = true;
|
270 |
+
return false;
|
271 |
+
}
|
272 |
+
});
|
273 |
+
if (valid) {
|
274 |
+
return false;
|
275 |
+
}
|
276 |
+
});
|
277 |
+
if (!valid) {
|
278 |
+
category_id = '';
|
279 |
+
}
|
280 |
+
}
|
281 |
+
}
|
282 |
+
setSelects(location_id, category_id, service_id, staff_id);
|
283 |
+
});
|
284 |
+
|
285 |
+
// Category select change
|
286 |
+
$select_category.on('change', function () {
|
287 |
+
var location_id = $select_location.val(),
|
288 |
+
category_id = this.value,
|
289 |
+
service_id = $select_service.val(),
|
290 |
+
staff_id = $select_employee.val()
|
291 |
+
;
|
292 |
+
|
293 |
+
// Validate selected values.
|
294 |
+
if (category_id != '') {
|
295 |
+
if (service_id != '') {
|
296 |
+
if (services[service_id].category_id != category_id) {
|
297 |
+
service_id = '';
|
298 |
+
}
|
299 |
+
}
|
300 |
+
if (staff_id != '') {
|
301 |
+
var valid = false;
|
302 |
+
$.each(staff[staff_id].services, function(id) {
|
303 |
+
if (services[id].category_id == category_id) {
|
304 |
+
valid = true;
|
305 |
+
return false;
|
306 |
+
}
|
307 |
+
});
|
308 |
+
if (!valid) {
|
309 |
+
staff_id = '';
|
310 |
+
}
|
311 |
+
}
|
312 |
+
}
|
313 |
+
setSelects(location_id, category_id, service_id, staff_id);
|
314 |
+
});
|
315 |
+
|
316 |
+
// Service select change
|
317 |
+
$select_service.on('change', function () {
|
318 |
+
var location_id = $select_location.val(),
|
319 |
+
category_id = '',
|
320 |
+
service_id = this.value,
|
321 |
+
staff_id = $select_employee.val()
|
322 |
+
;
|
323 |
+
|
324 |
+
// Validate selected values.
|
325 |
+
if (service_id != '') {
|
326 |
+
if (staff_id != '' && !staff[staff_id].services.hasOwnProperty(service_id)) {
|
327 |
+
staff_id = '';
|
328 |
+
}
|
329 |
+
}
|
330 |
+
setSelects(location_id, category_id, service_id, staff_id);
|
331 |
+
if (service_id) {
|
332 |
+
$select_category.val(services[service_id].category_id);
|
333 |
+
}
|
334 |
+
});
|
335 |
+
|
336 |
+
// Staff select change
|
337 |
+
$select_employee.on('change', function() {
|
338 |
+
var location_id = $select_location.val(),
|
339 |
+
category_id = $select_category.val(),
|
340 |
+
service_id = $select_service.val(),
|
341 |
+
staff_id = this.value
|
342 |
+
;
|
343 |
+
|
344 |
+
setSelects(location_id, category_id, service_id, staff_id);
|
345 |
+
});
|
346 |
+
|
347 |
+
// Set up draft selects.
|
348 |
+
setSelect($select_location, locations);
|
349 |
+
setSelect($select_category, categories);
|
350 |
+
setSelect($select_service, services);
|
351 |
+
setSelect($select_employee, staff);
|
352 |
+
|
353 |
+
$insert.on('click', function (e) {
|
354 |
+
e.preventDefault();
|
355 |
+
|
356 |
+
var insert = '[bookly-form';
|
357 |
+
var hide = [];
|
358 |
+
if ($select_location.val()) {
|
359 |
+
insert += ' location_id="' + $select_location.val() + '"';
|
360 |
+
}
|
361 |
+
if ($select_category.val()) {
|
362 |
+
insert += ' category_id="' + $select_category.val() + '"';
|
363 |
+
}
|
364 |
+
if ($hide_locations.is(':checked')) {
|
365 |
+
hide.push('locations');
|
366 |
+
}
|
367 |
+
if ($hide_categories.is(':checked')) {
|
368 |
+
hide.push('categories');
|
369 |
+
}
|
370 |
+
if ($select_service.val()) {
|
371 |
+
insert += ' service_id="' + $select_service.val() + '"';
|
372 |
+
}
|
373 |
+
if ($hide_services.is(':checked')) {
|
374 |
+
hide.push('services');
|
375 |
+
}
|
376 |
+
if ($hide_service_duration.is(':checked')) {
|
377 |
+
hide.push('service_duration');
|
378 |
+
}
|
379 |
+
if ($select_employee.val()) {
|
380 |
+
insert += ' staff_member_id="' + $select_employee.val() + '"';
|
381 |
+
}
|
382 |
+
if ($hide_number_of_persons.is(':not(:checked)')) {
|
383 |
+
insert += ' show_number_of_persons="1"';
|
384 |
+
}
|
385 |
+
if ($hide_quantity.is(':checked')) {
|
386 |
+
hide.push('quantity');
|
387 |
+
}
|
388 |
+
if ($hide_staff.is(':checked')) {
|
389 |
+
hide.push('staff_members');
|
390 |
+
}
|
391 |
+
if ($hide_date.is(':checked')) {
|
392 |
+
hide.push('date')
|
393 |
+
}
|
394 |
+
if ($hide_week_days.is(':checked')) {
|
395 |
+
hide.push('week_days')
|
396 |
+
}
|
397 |
+
if ($hide_time_range.is(':checked')) {
|
398 |
+
hide.push('time_range');
|
399 |
+
}
|
400 |
+
if (hide.length > 0) {
|
401 |
+
insert += ' hide="' + hide.join() + '"';
|
402 |
+
}
|
403 |
+
insert += ']';
|
404 |
+
|
405 |
+
window.send_to_editor(insert);
|
406 |
+
|
407 |
+
$select_location.val('');
|
408 |
+
$select_category.val('');
|
409 |
+
$select_service.val('');
|
410 |
+
$select_employee.val('');
|
411 |
+
$hide_locations.prop('checked', false);
|
412 |
+
$hide_categories.prop('checked', false);
|
413 |
+
$hide_services.prop('checked', false);
|
414 |
+
$hide_service_duration.prop('checked', false);
|
415 |
+
$hide_staff.prop('checked', false);
|
416 |
+
$hide_date.prop('checked', false);
|
417 |
+
$hide_week_days.prop('checked', false);
|
418 |
+
$hide_time_range.prop('checked', false);
|
419 |
+
$hide_number_of_persons.prop('checked', true);
|
420 |
+
|
421 |
+
window.parent.tb_remove();
|
422 |
+
return false;
|
423 |
+
});
|
424 |
+
});
|
425 |
</script>
|
backend/modules/appearance/Ajax.php
CHANGED
@@ -1,132 +1,136 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
use Bookly\Backend\Modules\Appearance\Proxy;
|
6 |
-
|
7 |
-
/**
|
8 |
-
* Class Ajax
|
9 |
-
* @package Bookly\Backend\Modules\Appearance
|
10 |
-
*/
|
11 |
-
class Ajax extends Lib\Base\Ajax
|
12 |
-
{
|
13 |
-
/**
|
14 |
-
* Update options.
|
15 |
-
*/
|
16 |
-
public static function updateAppearanceOptions()
|
17 |
-
{
|
18 |
-
$options = self::parameter( 'options', array() );
|
19 |
-
|
20 |
-
// Make sure that we save only allowed options.
|
21 |
-
$options_to_save = array_intersect_key( $options, array_flip( array(
|
22 |
-
// Info text.
|
23 |
-
'bookly_l10n_info_complete_step',
|
24 |
-
'bookly_l10n_info_complete_step_limit_error',
|
25 |
-
'bookly_l10n_info_complete_step_processing',
|
26 |
-
'bookly_l10n_info_details_step',
|
27 |
-
'bookly_l10n_info_details_step_guest',
|
28 |
-
'bookly_l10n_info_payment_step_single_app',
|
29 |
-
'bookly_l10n_info_payment_step_several_apps',
|
30 |
-
'bookly_l10n_info_service_step',
|
31 |
-
'bookly_l10n_info_time_step',
|
32 |
-
// Step, label and option texts.
|
33 |
-
'bookly_l10n_button_apply',
|
34 |
-
'bookly_l10n_button_back',
|
35 |
-
'bookly_l10n_label_category',
|
36 |
-
'bookly_l10n_label_ccard_code',
|
37 |
-
'bookly_l10n_label_ccard_expire',
|
38 |
-
'bookly_l10n_label_ccard_number',
|
39 |
-
'bookly_l10n_label_email',
|
40 |
-
'
|
41 |
-
'
|
42 |
-
'
|
43 |
-
'
|
44 |
-
'
|
45 |
-
'
|
46 |
-
'
|
47 |
-
'
|
48 |
-
'
|
49 |
-
'
|
50 |
-
'
|
51 |
-
'
|
52 |
-
'
|
53 |
-
'
|
54 |
-
'
|
55 |
-
'
|
56 |
-
'
|
57 |
-
'
|
58 |
-
'
|
59 |
-
'
|
60 |
-
'
|
61 |
-
'
|
62 |
-
'
|
63 |
-
'
|
64 |
-
'
|
65 |
-
'
|
66 |
-
'
|
67 |
-
'
|
68 |
-
'
|
69 |
-
'
|
70 |
-
'
|
71 |
-
|
72 |
-
|
73 |
-
'
|
74 |
-
'
|
75 |
-
'
|
76 |
-
'
|
77 |
-
'
|
78 |
-
'
|
79 |
-
|
80 |
-
'
|
81 |
-
//
|
82 |
-
'
|
83 |
-
|
84 |
-
'
|
85 |
-
'
|
86 |
-
'
|
87 |
-
'
|
88 |
-
'
|
89 |
-
'
|
90 |
-
'
|
91 |
-
'
|
92 |
-
'
|
93 |
-
'
|
94 |
-
'
|
95 |
-
'
|
96 |
-
|
97 |
-
'
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
|
|
|
|
|
|
|
|
132 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
use Bookly\Backend\Modules\Appearance\Proxy;
|
6 |
+
|
7 |
+
/**
|
8 |
+
* Class Ajax
|
9 |
+
* @package Bookly\Backend\Modules\Appearance
|
10 |
+
*/
|
11 |
+
class Ajax extends Lib\Base\Ajax
|
12 |
+
{
|
13 |
+
/**
|
14 |
+
* Update options.
|
15 |
+
*/
|
16 |
+
public static function updateAppearanceOptions()
|
17 |
+
{
|
18 |
+
$options = self::parameter( 'options', array() );
|
19 |
+
|
20 |
+
// Make sure that we save only allowed options.
|
21 |
+
$options_to_save = array_intersect_key( $options, array_flip( array(
|
22 |
+
// Info text.
|
23 |
+
'bookly_l10n_info_complete_step',
|
24 |
+
'bookly_l10n_info_complete_step_limit_error',
|
25 |
+
'bookly_l10n_info_complete_step_processing',
|
26 |
+
'bookly_l10n_info_details_step',
|
27 |
+
'bookly_l10n_info_details_step_guest',
|
28 |
+
'bookly_l10n_info_payment_step_single_app',
|
29 |
+
'bookly_l10n_info_payment_step_several_apps',
|
30 |
+
'bookly_l10n_info_service_step',
|
31 |
+
'bookly_l10n_info_time_step',
|
32 |
+
// Step, label and option texts.
|
33 |
+
'bookly_l10n_button_apply',
|
34 |
+
'bookly_l10n_button_back',
|
35 |
+
'bookly_l10n_label_category',
|
36 |
+
'bookly_l10n_label_ccard_code',
|
37 |
+
'bookly_l10n_label_ccard_expire',
|
38 |
+
'bookly_l10n_label_ccard_number',
|
39 |
+
'bookly_l10n_label_email',
|
40 |
+
'bookly_l10n_label_email_confirm',
|
41 |
+
'bookly_l10n_label_employee',
|
42 |
+
'bookly_l10n_label_service_duration',
|
43 |
+
'bookly_l10n_label_finish_by',
|
44 |
+
'bookly_l10n_label_name',
|
45 |
+
'bookly_l10n_label_first_name',
|
46 |
+
'bookly_l10n_label_last_name',
|
47 |
+
'bookly_l10n_label_notes',
|
48 |
+
'bookly_l10n_label_number_of_persons',
|
49 |
+
'bookly_l10n_label_pay_ccard',
|
50 |
+
'bookly_l10n_label_pay_locally',
|
51 |
+
'bookly_l10n_label_phone',
|
52 |
+
'bookly_l10n_label_select_date',
|
53 |
+
'bookly_l10n_label_service',
|
54 |
+
'bookly_l10n_label_start_from',
|
55 |
+
'bookly_l10n_option_category',
|
56 |
+
'bookly_l10n_option_employee',
|
57 |
+
'bookly_l10n_option_service',
|
58 |
+
'bookly_l10n_option_day',
|
59 |
+
'bookly_l10n_option_month',
|
60 |
+
'bookly_l10n_option_year',
|
61 |
+
'bookly_l10n_step_service',
|
62 |
+
'bookly_l10n_step_service_mobile_button_next',
|
63 |
+
'bookly_l10n_step_service_button_next',
|
64 |
+
'bookly_l10n_step_time',
|
65 |
+
'bookly_l10n_step_time_slot_not_available',
|
66 |
+
'bookly_l10n_step_details',
|
67 |
+
'bookly_l10n_step_details_button_next',
|
68 |
+
'bookly_l10n_step_details_button_login',
|
69 |
+
'bookly_l10n_step_payment',
|
70 |
+
'bookly_l10n_step_payment_button_next',
|
71 |
+
'bookly_l10n_step_done',
|
72 |
+
// Validator errors.
|
73 |
+
'bookly_l10n_required_email',
|
74 |
+
'bookly_l10n_email_confirm_not_match',
|
75 |
+
'bookly_l10n_required_employee',
|
76 |
+
'bookly_l10n_required_name',
|
77 |
+
'bookly_l10n_required_first_name',
|
78 |
+
'bookly_l10n_required_last_name',
|
79 |
+
'bookly_l10n_required_phone',
|
80 |
+
'bookly_l10n_required_service',
|
81 |
+
// Color.
|
82 |
+
'bookly_app_color',
|
83 |
+
// Checkboxes.
|
84 |
+
'bookly_app_required_employee',
|
85 |
+
'bookly_app_service_name_with_duration',
|
86 |
+
'bookly_app_show_blocked_timeslots',
|
87 |
+
'bookly_app_show_calendar',
|
88 |
+
'bookly_app_show_day_one_column',
|
89 |
+
'bookly_app_show_time_zone_switcher',
|
90 |
+
'bookly_app_show_login_button',
|
91 |
+
'bookly_app_show_facebook_login_button',
|
92 |
+
'bookly_app_show_notes',
|
93 |
+
'bookly_app_show_progress_tracker',
|
94 |
+
'bookly_app_align_buttons_left',
|
95 |
+
'bookly_app_staff_name_with_price',
|
96 |
+
'bookly_cst_required_details',
|
97 |
+
'bookly_app_service_duration_with_price',
|
98 |
+
'bookly_cst_first_last_name',
|
99 |
+
'bookly_app_show_email_confirm',
|
100 |
+
// Options.
|
101 |
+
'bookly_multiply_appointments_quantity_max',
|
102 |
+
) ) );
|
103 |
+
|
104 |
+
// Allow add-ons to add their options.
|
105 |
+
$options_to_save = Proxy\Shared::prepareOptions( $options_to_save, $options );
|
106 |
+
|
107 |
+
// Save options.
|
108 |
+
foreach ( $options_to_save as $option_name => $option_value ) {
|
109 |
+
update_option( $option_name, $option_value );
|
110 |
+
// Register string for translate in WPML.
|
111 |
+
if ( strpos( $option_name, 'bookly_l10n_' ) === 0 ) {
|
112 |
+
do_action( 'wpml_register_single_string', 'bookly', $option_name, $option_value );
|
113 |
+
}
|
114 |
+
}
|
115 |
+
|
116 |
+
wp_send_json_success();
|
117 |
+
}
|
118 |
+
|
119 |
+
/**
|
120 |
+
* Ajax request to dismiss appearance notice for current user.
|
121 |
+
*/
|
122 |
+
public static function dismissAppearanceNotice()
|
123 |
+
{
|
124 |
+
update_user_meta( get_current_user_id(), Lib\Plugin::getPrefix() . 'dismiss_appearance_notice', 1 );
|
125 |
+
}
|
126 |
+
|
127 |
+
/**
|
128 |
+
* Process ajax request to save custom css
|
129 |
+
*/
|
130 |
+
public static function saveCustomCss()
|
131 |
+
{
|
132 |
+
update_option( 'bookly_app_custom_styles', self::parameter( 'custom_css' ) );
|
133 |
+
|
134 |
+
wp_send_json_success( array( 'message' => __( 'Your custom CSS was saved. Please refresh the page to see your changes.', 'bookly') ) );
|
135 |
+
}
|
136 |
}
|
backend/modules/appearance/Page.php
CHANGED
@@ -1,103 +1,108 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Page
|
8 |
-
* @package Bookly\Backend\Modules\Appearance
|
9 |
-
*/
|
10 |
-
class Page extends Lib\Base\Component
|
11 |
-
{
|
12 |
-
/**
|
13 |
-
* Render page.
|
14 |
-
*/
|
15 |
-
public static function render()
|
16 |
-
{
|
17 |
-
/** @var \WP_Locale $wp_locale */
|
18 |
-
global $wp_locale;
|
19 |
-
|
20 |
-
self::enqueueStyles( array(
|
21 |
-
'frontend' => array_merge(
|
22 |
-
( get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
23 |
-
? array()
|
24 |
-
: array( 'css/intlTelInput.css' ) ),
|
25 |
-
array(
|
26 |
-
'css/ladda.min.css',
|
27 |
-
'css/picker.classic.css',
|
28 |
-
'css/picker.classic.date.css',
|
29 |
-
'css/bookly-main.css',
|
30 |
-
)
|
31 |
-
),
|
32 |
-
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
33 |
-
'wp' => array( 'wp-color-picker', ),
|
34 |
-
'module' => array( 'css/bootstrap-editable.css', )
|
35 |
-
) );
|
36 |
-
|
37 |
-
self::enqueueScripts( array(
|
38 |
-
'backend' => array(
|
39 |
-
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
40 |
-
'js/alert.js' => array( 'jquery' ),
|
41 |
-
),
|
42 |
-
'frontend' => array_merge(
|
43 |
-
array(
|
44 |
-
'js/picker.js' => array( 'jquery' ),
|
45 |
-
'js/picker.date.js' => array( 'jquery' ),
|
46 |
-
'js/spin.min.js' => array( 'jquery' ),
|
47 |
-
'js/ladda.min.js' => array( 'jquery' ),
|
48 |
-
),
|
49 |
-
get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
50 |
-
? array()
|
51 |
-
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
52 |
-
),
|
53 |
-
'wp' => array( 'wp-color-picker' ),
|
54 |
-
'module' => array(
|
55 |
-
'js/bootstrap-editable.min.js' => array( 'bookly-bootstrap.min.js' ),
|
56 |
-
'js/bootstrap-editable.bookly.js' => array( 'bookly-bootstrap-editable.min.js' ),
|
57 |
-
'js/appearance.js' => array( 'bookly-bootstrap-editable.bookly.js' )
|
58 |
-
)
|
59 |
-
) );
|
60 |
-
|
61 |
-
wp_localize_script( 'bookly-picker.date.js', 'BooklyL10n', array(
|
62 |
-
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
63 |
-
'nop_format' => get_option( 'bookly_group_booking_nop_format' ),
|
64 |
-
'today' => __( 'Today', 'bookly' ),
|
65 |
-
'months' => array_values( $wp_locale->month ),
|
66 |
-
'days' => array_values( $wp_locale->weekday_abbrev ),
|
67 |
-
'nextMonth' => __( 'Next month', 'bookly' ),
|
68 |
-
'prevMonth' => __( 'Previous month', 'bookly' ),
|
69 |
-
'date_format' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_PICKADATE ),
|
70 |
-
'start_of_week' => (int) get_option( 'start_of_week' ),
|
71 |
-
'saved' => __( 'Settings saved.', 'bookly' ),
|
72 |
-
'intlTelInput' => array(
|
73 |
-
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
74 |
-
'utils' => is_rtl() ? '' : plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
75 |
-
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
76 |
-
),
|
77 |
-
) );
|
78 |
-
|
79 |
-
// Initialize steps (tabs).
|
80 |
-
$steps = array(
|
81 |
-
1 => array( 'show' => true, 'title' => get_option( 'bookly_l10n_step_service' ) ),
|
82 |
-
3 => array( 'show' => true, 'title' => get_option( 'bookly_l10n_step_time' ) ),
|
83 |
-
6 => array( 'show' => true, 'title' => get_option( 'bookly_l10n_step_details' ) ),
|
84 |
-
7 => array( 'show' => true, 'title' => get_option( 'bookly_l10n_step_payment' ) ),
|
85 |
-
8 => array( 'show' => true, 'title' => get_option( 'bookly_l10n_step_done' ) ),
|
86 |
-
);
|
87 |
-
if ( Lib\Config::serviceExtrasActive() ) {
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
103 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Page
|
8 |
+
* @package Bookly\Backend\Modules\Appearance
|
9 |
+
*/
|
10 |
+
class Page extends Lib\Base\Component
|
11 |
+
{
|
12 |
+
/**
|
13 |
+
* Render page.
|
14 |
+
*/
|
15 |
+
public static function render()
|
16 |
+
{
|
17 |
+
/** @var \WP_Locale $wp_locale */
|
18 |
+
global $wp_locale;
|
19 |
+
|
20 |
+
self::enqueueStyles( array(
|
21 |
+
'frontend' => array_merge(
|
22 |
+
( get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
23 |
+
? array()
|
24 |
+
: array( 'css/intlTelInput.css' ) ),
|
25 |
+
array(
|
26 |
+
'css/ladda.min.css',
|
27 |
+
'css/picker.classic.css',
|
28 |
+
'css/picker.classic.date.css',
|
29 |
+
'css/bookly-main.css',
|
30 |
+
)
|
31 |
+
),
|
32 |
+
'backend' => array( 'bootstrap/css/bootstrap-theme.min.css', ),
|
33 |
+
'wp' => array( 'wp-color-picker', ),
|
34 |
+
'module' => array( 'css/bootstrap-editable.css', )
|
35 |
+
) );
|
36 |
+
|
37 |
+
self::enqueueScripts( array(
|
38 |
+
'backend' => array(
|
39 |
+
'bootstrap/js/bootstrap.min.js' => array( 'jquery' ),
|
40 |
+
'js/alert.js' => array( 'jquery' ),
|
41 |
+
),
|
42 |
+
'frontend' => array_merge(
|
43 |
+
array(
|
44 |
+
'js/picker.js' => array( 'jquery' ),
|
45 |
+
'js/picker.date.js' => array( 'jquery' ),
|
46 |
+
'js/spin.min.js' => array( 'jquery' ),
|
47 |
+
'js/ladda.min.js' => array( 'jquery' ),
|
48 |
+
),
|
49 |
+
get_option( 'bookly_cst_phone_default_country' ) == 'disabled'
|
50 |
+
? array()
|
51 |
+
: array( 'js/intlTelInput.min.js' => array( 'jquery' ) )
|
52 |
+
),
|
53 |
+
'wp' => array( 'wp-color-picker' ),
|
54 |
+
'module' => array(
|
55 |
+
'js/bootstrap-editable.min.js' => array( 'bookly-bootstrap.min.js' ),
|
56 |
+
'js/bootstrap-editable.bookly.js' => array( 'bookly-bootstrap-editable.min.js' ),
|
57 |
+
'js/appearance.js' => array( 'bookly-bootstrap-editable.bookly.js' )
|
58 |
+
)
|
59 |
+
) );
|
60 |
+
|
61 |
+
wp_localize_script( 'bookly-picker.date.js', 'BooklyL10n', array(
|
62 |
+
'csrf_token' => Lib\Utils\Common::getCsrfToken(),
|
63 |
+
'nop_format' => get_option( 'bookly_group_booking_nop_format' ),
|
64 |
+
'today' => __( 'Today', 'bookly' ),
|
65 |
+
'months' => array_values( $wp_locale->month ),
|
66 |
+
'days' => array_values( $wp_locale->weekday_abbrev ),
|
67 |
+
'nextMonth' => __( 'Next month', 'bookly' ),
|
68 |
+
'prevMonth' => __( 'Previous month', 'bookly' ),
|
69 |
+
'date_format' => Lib\Utils\DateTime::convertFormat( 'date', Lib\Utils\DateTime::FORMAT_PICKADATE ),
|
70 |
+
'start_of_week' => (int) get_option( 'start_of_week' ),
|
71 |
+
'saved' => __( 'Settings saved.', 'bookly' ),
|
72 |
+
'intlTelInput' => array(
|
73 |
+
'enabled' => get_option( 'bookly_cst_phone_default_country' ) != 'disabled',
|
74 |
+
'utils' => is_rtl() ? '' : plugins_url( 'intlTelInput.utils.js', Lib\Plugin::getDirectory() . '/frontend/resources/js/intlTelInput.utils.js' ),
|
75 |
+
'country' => get_option( 'bookly_cst_phone_default_country' ),
|
76 |
+
),
|
77 |
+
) );
|
78 |
+
|
79 |
+
// Initialize steps (tabs).
|
80 |
+
$steps = array(
|
81 |
+
1 => array( 'step' => 1, 'show' => true, 'title' => get_option( 'bookly_l10n_step_service' ) ),
|
82 |
+
3 => array( 'step' => 3, 'show' => true, 'title' => get_option( 'bookly_l10n_step_time' ) ),
|
83 |
+
6 => array( 'step' => 6, 'show' => true, 'title' => get_option( 'bookly_l10n_step_details' ) ),
|
84 |
+
7 => array( 'step' => 7, 'show' => true, 'title' => get_option( 'bookly_l10n_step_payment' ) ),
|
85 |
+
8 => array( 'step' => 8, 'show' => true, 'title' => get_option( 'bookly_l10n_step_done' ) ),
|
86 |
+
);
|
87 |
+
if ( Lib\Config::serviceExtrasActive() ) {
|
88 |
+
if ( get_option( 'bookly_service_extras_after_step_time' ) ) {
|
89 |
+
$steps[2] = $steps[3];
|
90 |
+
$steps[3] = array( 'step' => 2, 'show' => get_option( 'bookly_service_extras_enabled' ), 'title' => get_option( 'bookly_l10n_step_extras' ) );
|
91 |
+
} else {
|
92 |
+
$steps[2] = array( 'step' => 2, 'show' => get_option( 'bookly_service_extras_enabled' ), 'title' => get_option( 'bookly_l10n_step_extras' ) );
|
93 |
+
}
|
94 |
+
}
|
95 |
+
if ( Lib\Config::recurringAppointmentsActive() ) {
|
96 |
+
$steps[4] = array( 'step' => 4, 'show' => get_option( 'bookly_recurring_appointments_enabled' ), 'title' => get_option( 'bookly_l10n_step_repeat' ) );
|
97 |
+
}
|
98 |
+
if ( Lib\Config::cartActive() ) {
|
99 |
+
$steps[5] = array( 'step' => 5, 'show' => get_option( 'bookly_cart_enabled' ), 'title' => get_option( 'bookly_l10n_step_cart' ) );
|
100 |
+
}
|
101 |
+
ksort( $steps );
|
102 |
+
|
103 |
+
$custom_css = get_option( 'bookly_app_custom_styles' );
|
104 |
+
|
105 |
+
// Render general layout.
|
106 |
+
self::renderTemplate( 'index', compact( 'steps', 'custom_css' ) );
|
107 |
+
}
|
108 |
}
|
backend/modules/appearance/proxy/Cart.php
CHANGED
@@ -1,17 +1,17 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Cart
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderCartStepSettings() Render settings on Cart step.
|
11 |
-
* @method static void renderShowStep() Render "Show Cart step".
|
12 |
-
* @method static void renderStep( string $progress_tracker ) Render Cart step.
|
13 |
-
*/
|
14 |
-
abstract class Cart extends Lib\Base\Proxy
|
15 |
-
{
|
16 |
-
|
17 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Cart
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCartStepSettings() Render settings on Cart step.
|
11 |
+
* @method static void renderShowStep() Render "Show Cart step".
|
12 |
+
* @method static void renderStep( string $progress_tracker ) Render Cart step.
|
13 |
+
*/
|
14 |
+
abstract class Cart extends Lib\Base\Proxy
|
15 |
+
{
|
16 |
+
|
17 |
}
|
backend/modules/appearance/proxy/ChainAppointments.php
CHANGED
@@ -1,14 +1,14 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class ChainAppointments
|
8 |
-
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderChain() render a 'plus' for chain appointments on service step
|
11 |
-
*/
|
12 |
-
abstract class ChainAppointments extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class ChainAppointments
|
8 |
+
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderChain() render a 'plus' for chain appointments on service step
|
11 |
+
*/
|
12 |
+
abstract class ChainAppointments extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
}
|
backend/modules/appearance/proxy/Coupons.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Coupons
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderCouponBlock() Render coupon block in Payments step.
|
11 |
-
* @method static void renderShowCoupons() Render coupon block in Payments step.
|
12 |
-
*/
|
13 |
-
abstract class Coupons extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Coupons
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCouponBlock() Render coupon block in Payments step.
|
11 |
+
* @method static void renderShowCoupons() Render coupon block in Payments step.
|
12 |
+
*/
|
13 |
+
abstract class Coupons extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
}
|
backend/modules/appearance/proxy/CustomDuration.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class GoogleMapsAddress
|
8 |
-
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderServiceDuration() render a select with service durations
|
11 |
-
* @method static void renderShowCustomDuration() Render "Show custom duration" checkbox on Service step settings.
|
12 |
-
*/
|
13 |
-
abstract class CustomDuration extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class GoogleMapsAddress
|
8 |
+
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderServiceDuration() render a select with service durations
|
11 |
+
* @method static void renderShowCustomDuration() Render "Show custom duration" checkbox on Service step settings.
|
12 |
+
*/
|
13 |
+
abstract class CustomDuration extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
}
|
backend/modules/appearance/proxy/CustomFields.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class CustomFields
|
8 |
-
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderCustomFields() render "custom fields" input
|
11 |
-
* @method static void renderShowCustomFields() render a checkbox "Show custom fields"
|
12 |
-
*/
|
13 |
-
abstract class CustomFields extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CustomFields
|
8 |
+
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCustomFields() render "custom fields" input
|
11 |
+
* @method static void renderShowCustomFields() render a checkbox "Show custom fields"
|
12 |
+
*/
|
13 |
+
abstract class CustomFields extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
}
|
backend/modules/appearance/proxy/CustomerInformation.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class CustomerInformation
|
8 |
-
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderCustomerInformation() render "customer information" input
|
11 |
-
* @method static void renderShowCustomerInformation() render a checkbox "Show customer information"
|
12 |
-
*/
|
13 |
-
abstract class CustomerInformation extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class CustomerInformation
|
8 |
+
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCustomerInformation() render "customer information" input
|
11 |
+
* @method static void renderShowCustomerInformation() render a checkbox "Show customer information"
|
12 |
+
*/
|
13 |
+
abstract class CustomerInformation extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
}
|
backend/modules/appearance/proxy/DepositPayments.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class DepositPayments
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderAppearance() Render editable selector for deposit/full payment
|
11 |
-
*/
|
12 |
-
abstract class DepositPayments extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class DepositPayments
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderAppearance() Render editable selector for deposit/full payment
|
11 |
+
*/
|
12 |
+
abstract class DepositPayments extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/modules/appearance/proxy/Files.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Files
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderAppearance() Render button browse in Appearance
|
11 |
-
* @method static void renderShowFiles() Render 'Show files' on details step
|
12 |
-
*/
|
13 |
-
abstract class Files extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Files
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderAppearance() Render button browse in Appearance
|
11 |
+
* @method static void renderShowFiles() Render 'Show files' on details step
|
12 |
+
*/
|
13 |
+
abstract class Files extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
}
|
backend/modules/appearance/proxy/GoogleMapsAddress.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class GoogleMapsAddress
|
8 |
-
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderGoogleMaps() Render google maps input.
|
11 |
-
* @method static void renderShowGoogleMaps() Render show google maps fields checkbox.
|
12 |
-
*/
|
13 |
-
abstract class GoogleMapsAddress extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class GoogleMapsAddress
|
8 |
+
* @package Bookly\Backend\Modules\Frontend\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderGoogleMaps() Render google maps input.
|
11 |
+
* @method static void renderShowGoogleMaps() Render show google maps fields checkbox.
|
12 |
+
*/
|
13 |
+
abstract class GoogleMapsAddress extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
}
|
backend/modules/appearance/proxy/GroupBooking.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class GroupBooking
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderNOP() Render number of persons select in Service step.
|
11 |
-
* @method static void renderShowNOP() Render "Show number of persons" checkbox on Service step settings.
|
12 |
-
*/
|
13 |
-
abstract class GroupBooking extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class GroupBooking
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderNOP() Render number of persons select in Service step.
|
11 |
+
* @method static void renderShowNOP() Render "Show number of persons" checkbox on Service step settings.
|
12 |
+
*/
|
13 |
+
abstract class GroupBooking extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
}
|
backend/modules/appearance/proxy/Locations.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Locations
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderLocation() Render location select in Service step.
|
11 |
-
* @method static void renderShowLocation() Render "Show location" checkbox on Service step settings.
|
12 |
-
*/
|
13 |
-
abstract class Locations extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Locations
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderLocation() Render location select in Service step.
|
11 |
+
* @method static void renderShowLocation() Render "Show location" checkbox on Service step settings.
|
12 |
+
*/
|
13 |
+
abstract class Locations extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
}
|
backend/modules/appearance/proxy/MultiplyAppointments.php
CHANGED
@@ -1,16 +1,16 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class MultiplyAppointments
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderQuantity() Render Multiply (quantity) control in Service step.
|
11 |
-
* @method static void renderShowQuantity() Render "Show quantity" checkbox on Service step settings.
|
12 |
-
*/
|
13 |
-
abstract class MultiplyAppointments extends Lib\Base\Proxy
|
14 |
-
{
|
15 |
-
|
16 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class MultiplyAppointments
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderQuantity() Render Multiply (quantity) control in Service step.
|
11 |
+
* @method static void renderShowQuantity() Render "Show quantity" checkbox on Service step settings.
|
12 |
+
*/
|
13 |
+
abstract class MultiplyAppointments extends Lib\Base\Proxy
|
14 |
+
{
|
15 |
+
|
16 |
}
|
backend/modules/appearance/proxy/Pro.php
CHANGED
@@ -1,23 +1,23 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Pro
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderFacebookButton() Render facebook login button on Time step.
|
11 |
-
* @method static void renderMultipleBookingSelector() Render single/multiple booking selector on Payment step.
|
12 |
-
* @method static void renderMultipleBookingText() Render multiple booking text option on Payment step.
|
13 |
-
* @method static void renderPayPalPaymentOption() Render Cart step.
|
14 |
-
* @method static void renderShowFacebookButton() Render 'Show facebook login button switcher' on Time step.
|
15 |
-
* @method static void renderTimeZoneSwitcher() Render timezone switcher on Time step.
|
16 |
-
* @method static void renderTimeZoneSwitcherCheckbox() Render 'Show time zone switcher' on Time step.
|
17 |
-
* @method static void renderShowAddress() render 'Show Address Fields' on Details Step.
|
18 |
-
* @method static void renderShowBirthday() render 'Show Birthday Fields' on Details Step.
|
19 |
-
*/
|
20 |
-
abstract class Pro extends Lib\Base\Proxy
|
21 |
-
{
|
22 |
-
|
23 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Pro
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderFacebookButton() Render facebook login button on Time step.
|
11 |
+
* @method static void renderMultipleBookingSelector() Render single/multiple booking selector on Payment step.
|
12 |
+
* @method static void renderMultipleBookingText() Render multiple booking text option on Payment step.
|
13 |
+
* @method static void renderPayPalPaymentOption() Render Cart step.
|
14 |
+
* @method static void renderShowFacebookButton() Render 'Show facebook login button switcher' on Time step.
|
15 |
+
* @method static void renderTimeZoneSwitcher() Render timezone switcher on Time step.
|
16 |
+
* @method static void renderTimeZoneSwitcherCheckbox() Render 'Show time zone switcher' on Time step.
|
17 |
+
* @method static void renderShowAddress() render 'Show Address Fields' on Details Step.
|
18 |
+
* @method static void renderShowBirthday() render 'Show Birthday Fields' on Details Step.
|
19 |
+
*/
|
20 |
+
abstract class Pro extends Lib\Base\Proxy
|
21 |
+
{
|
22 |
+
|
23 |
}
|
backend/modules/appearance/proxy/RecurringAppointments.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class RecurringAppointments
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderInfoMessage() Render editable info message in appearance.
|
11 |
-
* @method static void renderShowStep() Render "Show Repeat step".
|
12 |
-
* @method static void renderStep( string $progress_tracker ) Render Repeat step.
|
13 |
-
*
|
14 |
-
*/
|
15 |
-
abstract class RecurringAppointments extends Lib\Base\Proxy
|
16 |
-
{
|
17 |
-
|
18 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class RecurringAppointments
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderInfoMessage() Render editable info message in appearance.
|
11 |
+
* @method static void renderShowStep() Render "Show Repeat step".
|
12 |
+
* @method static void renderStep( string $progress_tracker ) Render Repeat step.
|
13 |
+
*
|
14 |
+
*/
|
15 |
+
abstract class RecurringAppointments extends Lib\Base\Proxy
|
16 |
+
{
|
17 |
+
|
18 |
}
|
backend/modules/appearance/proxy/ServiceExtras.php
CHANGED
@@ -1,18 +1,18 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class ServiceExtras
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderCartExtras() Render extras on Cart step.
|
11 |
-
* @method static void renderShowCartExtras() Render "Show extras" on Cart step.
|
12 |
-
* @method static void renderShowStep() Render "Show Extras step".
|
13 |
-
* @method static void renderStep( string $progress_tracker ) Render Extras step.
|
14 |
-
*/
|
15 |
-
abstract class ServiceExtras extends Lib\Base\Proxy
|
16 |
-
{
|
17 |
-
|
18 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class ServiceExtras
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderCartExtras() Render extras on Cart step.
|
11 |
+
* @method static void renderShowCartExtras() Render "Show extras" on Cart step.
|
12 |
+
* @method static void renderShowStep() Render "Show Extras step".
|
13 |
+
* @method static void renderStep( string $progress_tracker ) Render Extras step.
|
14 |
+
*/
|
15 |
+
abstract class ServiceExtras extends Lib\Base\Proxy
|
16 |
+
{
|
17 |
+
|
18 |
}
|
backend/modules/appearance/proxy/Shared.php
CHANGED
@@ -1,19 +1,19 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class Shared
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static array prepareOptions( array $options_to_save, array $options ) Alter array of options to be saved in Bookly Appearance.
|
11 |
-
* @method static void renderPaymentGatewaySelector() Render gateway selector.
|
12 |
-
* @method static int renderServiceStepSettings() Render checkbox settings.
|
13 |
-
* @method static int renderTimeStepSettings() Render checkbox settings.
|
14 |
-
* @method static bool showCreditCard() In case there are payment systems that request credit card information in the Details step, it will return true.
|
15 |
-
*/
|
16 |
-
abstract class Shared extends Lib\Base\Proxy
|
17 |
-
{
|
18 |
-
|
19 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Shared
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static array prepareOptions( array $options_to_save, array $options ) Alter array of options to be saved in Bookly Appearance.
|
11 |
+
* @method static void renderPaymentGatewaySelector() Render gateway selector.
|
12 |
+
* @method static int renderServiceStepSettings() Render checkbox settings.
|
13 |
+
* @method static int renderTimeStepSettings() Render checkbox settings.
|
14 |
+
* @method static bool showCreditCard() In case there are payment systems that request credit card information in the Details step, it will return true.
|
15 |
+
*/
|
16 |
+
abstract class Shared extends Lib\Base\Proxy
|
17 |
+
{
|
18 |
+
|
19 |
}
|
backend/modules/appearance/proxy/Tasks.php
ADDED
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class Tasks
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderSkipButton() Render 'Skip' button on time step.
|
11 |
+
*/
|
12 |
+
abstract class Tasks extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
+
}
|
backend/modules/appearance/proxy/WaitingList.php
CHANGED
@@ -1,15 +1,15 @@
|
|
1 |
-
<?php
|
2 |
-
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
-
|
4 |
-
use Bookly\Lib;
|
5 |
-
|
6 |
-
/**
|
7 |
-
* Class WaitingList
|
8 |
-
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
-
*
|
10 |
-
* @method static void renderInfoText() Render WL info text in Time step.
|
11 |
-
*/
|
12 |
-
abstract class WaitingList extends Lib\Base\Proxy
|
13 |
-
{
|
14 |
-
|
15 |
}
|
1 |
+
<?php
|
2 |
+
namespace Bookly\Backend\Modules\Appearance\Proxy;
|
3 |
+
|
4 |
+
use Bookly\Lib;
|
5 |
+
|
6 |
+
/**
|
7 |
+
* Class WaitingList
|
8 |
+
* @package Bookly\Backend\Modules\Appearance\Proxy
|
9 |
+
*
|
10 |
+
* @method static void renderInfoText() Render WL info text in Time step.
|
11 |
+
*/
|
12 |
+
abstract class WaitingList extends Lib\Base\Proxy
|
13 |
+
{
|
14 |
+
|
15 |
}
|
backend/modules/appearance/resources/css/bootstrap-editable.css
CHANGED
@@ -1,663 +1,663 @@
|
|
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 */
|
5 |
-
.editableform {
|
6 |
-
margin-bottom: 0; /* overwrites bootstrap margin */
|
7 |
-
}
|
8 |
-
|
9 |
-
.editableform .control-group {
|
10 |
-
margin-bottom: 0; /* overwrites bootstrap margin */
|
11 |
-
white-space: nowrap; /* prevent wrapping buttons on new line */
|
12 |
-
line-height: 20px; /* overwriting bootstrap line-height. See #133 */
|
13 |
-
}
|
14 |
-
|
15 |
-
/*
|
16 |
-
BS3 width:1005 for inputs breaks editable form in popup
|
17 |
-
See: https://github.com/vitalets/x-editable/issues/393
|
18 |
-
*/
|
19 |
-
.editableform .form-control {
|
20 |
-
width: auto;
|
21 |
-
}
|
22 |
-
|
23 |
-
.editable-buttons {
|
24 |
-
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
25 |
-
vertical-align: top;
|
26 |
-
margin-left: 7px;
|
27 |
-
/* inline-block emulation for IE7*/
|
28 |
-
zoom: 1;
|
29 |
-
*display: inline;
|
30 |
-
}
|
31 |
-
|
32 |
-
.editable-buttons.editable-buttons-bottom {
|
33 |
-
display: block;
|
34 |
-
margin-top: 7px;
|
35 |
-
margin-left: 0;
|
36 |
-
}
|
37 |
-
|
38 |
-
.editable-input {
|
39 |
-
vertical-align: top;
|
40 |
-
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
41 |
-
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
|
42 |
-
white-space: normal; /* reset white-space decalred in parent*/
|
43 |
-
/* display-inline emulation for IE7*/
|
44 |
-
zoom: 1;
|
45 |
-
*display: inline;
|
46 |
-
}
|
47 |
-
|
48 |
-
.editable-buttons .editable-cancel {
|
49 |
-
margin-left: 7px;
|
50 |
-
}
|
51 |
-
|
52 |
-
/*for jquery-ui buttons need set height to look more pretty*/
|
53 |
-
.editable-buttons button.ui-button-icon-only {
|
54 |
-
height: 24px;
|
55 |
-
width: 30px;
|
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;
|
63 |
-
}
|
64 |
-
|
65 |
-
.editable-inline .editableform-loading {
|
66 |
-
background-position: left 5px;
|
67 |
-
}
|
68 |
-
|
69 |
-
.editable-error-block {
|
70 |
-
max-width: 300px;
|
71 |
-
margin: 5px 0 0 0;
|
72 |
-
width: auto;
|
73 |
-
white-space: normal;
|
74 |
-
}
|
75 |
-
|
76 |
-
/*add padding for jquery ui*/
|
77 |
-
.editable-error-block.ui-state-error {
|
78 |
-
padding: 3px;
|
79 |
-
}
|
80 |
-
|
81 |
-
.editable-error {
|
82 |
-
color: red;
|
83 |
-
}
|
84 |
-
|
85 |
-
/* ---- For specific types ---- */
|
86 |
-
|
87 |
-
.editableform .editable-date {
|
88 |
-
padding: 0;
|
89 |
-
margin: 0;
|
90 |
-
float: left;
|
91 |
-
}
|
92 |
-
|
93 |
-
/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
|
94 |
-
.editable-inline .add-on .icon-th {
|
95 |
-
margin-top: 3px;
|
96 |
-
margin-left: 1px;
|
97 |
-
}
|
98 |
-
|
99 |
-
|
100 |
-
/* checklist vertical alignment */
|
101 |
-
.editable-checklist label input[type="checkbox"],
|
102 |
-
.editable-checklist label span {
|
103 |
-
vertical-align: middle;
|
104 |
-
margin: 0;
|
105 |
-
}
|
106 |
-
|
107 |
-
.editable-checklist label {
|
108 |
-
white-space: nowrap;
|
109 |
-
}
|
110 |
-
|
111 |
-
/* set exact width of textarea to fit buttons toolbar */
|
112 |
-
.editable-wysihtml5 {
|
113 |
-
width: 566px;
|
114 |
-
height: 250px;
|
115 |
-
}
|
116 |
-
|
117 |
-
/* clear button shown as link in date inputs */
|
118 |
-
.editable-clear {
|
119 |
-
clear: both;
|
120 |
-
font-size: 0.9em;
|
121 |
-
text-decoration: none;
|
122 |
-
text-align: right;
|
123 |
-
}
|
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;
|
131 |
-
position: absolute;
|
132 |
-
opacity: 0.6;
|
133 |
-
z-index: 100;
|
134 |
-
|
135 |
-
top: 50%;
|
136 |
-
right: 6px;
|
137 |
-
margin-top: -6px;
|
138 |
-
|
139 |
-
}
|
140 |
-
|
141 |
-
.editable-clear-x:hover {
|
142 |
-
opacity: 1;
|
143 |
-
}
|
144 |
-
|
145 |
-
.editable-pre-wrapped {
|
146 |
-
white-space: pre-wrap;
|
147 |
-
}
|
148 |
-
.editable-container.editable-popup {
|
149 |
-
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
|
150 |
-
}
|
151 |
-
|
152 |
-
.editable-container.popover {
|
153 |
-
width: auto; /* without this rule popover does not stretch */
|
154 |
-
}
|
155 |
-
|
156 |
-
.editable-container.editable-inline {
|
157 |
-
display: inline-block;
|
158 |
-
vertical-align: middle;
|
159 |
-
width: auto;
|
160 |
-
/* inline-block emulation for IE7*/
|
161 |
-
zoom: 1;
|
162 |
-
*display: inline;
|
163 |
-
}
|
164 |
-
|
165 |
-
.editable-container.ui-widget {
|
166 |
-
font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
|
167 |
-
z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
|
168 |
-
}
|
169 |
-
.editable-click,
|
170 |
-
a.editable-click,
|
171 |
-
a.editable-click:hover {
|
172 |
-
text-decoration: none;
|
173 |
-
border-bottom: dashed 1px #0088cc;
|
174 |
-
}
|
175 |
-
|
176 |
-
.editable-click.editable-disabled,
|
177 |
-
a.editable-click.editable-disabled,
|
178 |
-
a.editable-click.editable-disabled:hover {
|
179 |
-
color: #585858;
|
180 |
-
cursor: default;
|
181 |
-
border-bottom: none;
|
182 |
-
}
|
183 |
-
|
184 |
-
.editable-empty, .editable-empty:hover, .editable-empty:focus{
|
185 |
-
font-style: italic;
|
186 |
-
color: #DD1144;
|
187 |
-
/* border-bottom: none; */
|
188 |
-
text-decoration: none;
|
189 |
-
}
|
190 |
-
|
191 |
-
.editable-unsaved {
|
192 |
-
font-weight: bold;
|
193 |
-
}
|
194 |
-
|
195 |
-
.editable-unsaved:after {
|
196 |
-
/* content: '*'*/
|
197 |
-
}
|
198 |
-
|
199 |
-
.editable-bg-transition {
|
200 |
-
-webkit-transition: background-color 1400ms ease-out;
|
201 |
-
-moz-transition: background-color 1400ms ease-out;
|
202 |
-
-o-transition: background-color 1400ms ease-out;
|
203 |
-
-ms-transition: background-color 1400ms ease-out;
|
204 |
-
transition: background-color 1400ms ease-out;
|
205 |
-
}
|
206 |
-
|
207 |
-
/*see https://github.com/vitalets/x-editable/issues/139 */
|
208 |
-
.form-horizontal .editable
|
209 |
-
{
|
210 |
-
padding-top: 5px;
|
211 |
-
display:inline-block;
|
212 |
-
}
|
213 |
-
|
214 |
-
|
215 |
-
/*!
|
216 |
-
* Datepicker for Bootstrap
|
217 |
-
*
|
218 |
-
* Copyright 2012 Stefan Petre
|
219 |
-
* Improvements by Andrew Rowls
|
220 |
-
* Licensed under the Apache License v2.0
|
221 |
-
* http://www.apache.org/licenses/LICENSE-2.0
|
222 |
-
*
|
223 |
-
*/
|
224 |
-
.datepicker {
|
225 |
-
padding: 4px;
|
226 |
-
-webkit-border-radius: 4px;
|
227 |
-
-moz-border-radius: 4px;
|
228 |
-
border-radius: 4px;
|
229 |
-
direction: ltr;
|
230 |
-
/*.dow {
|
231 |
-
border-top: 1px solid #ddd !important;
|
232 |
-
}*/
|
233 |
-
|
234 |
-
}
|
235 |
-
.datepicker-inline {
|
236 |
-
width: 220px;
|
237 |
-
}
|
238 |
-
.datepicker.datepicker-rtl {
|
239 |
-
direction: rtl;
|
240 |
-
}
|
241 |
-
.datepicker.datepicker-rtl table tr td span {
|
242 |
-
float: right;
|
243 |
-
}
|
244 |
-
.datepicker-dropdown {
|
245 |
-
top: 0;
|
246 |
-
left: 0;
|
247 |
-
}
|
248 |
-
.datepicker-dropdown:before {
|
249 |
-
content: '';
|
250 |
-
display: inline-block;
|
251 |
-
border-left: 7px solid transparent;
|
252 |
-
border-right: 7px solid transparent;
|
253 |
-
border-bottom: 7px solid #ccc;
|
254 |
-
border-bottom-color: rgba(0, 0, 0, 0.2);
|
255 |
-
position: absolute;
|
256 |
-
top: -7px;
|
257 |
-
left: 6px;
|
258 |
-
}
|
259 |
-
.datepicker-dropdown:after {
|
260 |
-
content: '';
|
261 |
-
display: inline-block;
|
262 |
-
border-left: 6px solid transparent;
|
263 |
-
border-right: 6px solid transparent;
|
264 |
-
border-bottom: 6px solid #ffffff;
|
265 |
-
position: absolute;
|
266 |
-
top: -6px;
|
267 |
-
left: 7px;
|
268 |
-
}
|
269 |
-
.datepicker > div {
|
270 |
-
display: none;
|
271 |
-
}
|
272 |
-
.datepicker.days div.datepicker-days {
|
273 |
-
display: block;
|
274 |
-
}
|
275 |
-
.datepicker.months div.datepicker-months {
|
276 |
-
display: block;
|
277 |
-
}
|
278 |
-
.datepicker.years div.datepicker-years {
|
279 |
-
display: block;
|
280 |
-
}
|
281 |
-
.datepicker table {
|
282 |
-
margin: 0;
|
283 |
-
}
|
284 |
-
.datepicker td,
|
285 |
-
.datepicker th {
|
286 |
-
text-align: center;
|
287 |
-
width: 20px;
|
288 |
-
height: 20px;
|
289 |
-
-webkit-border-radius: 4px;
|
290 |
-
-moz-border-radius: 4px;
|
291 |
-
border-radius: 4px;
|
292 |
-
border: none;
|
293 |
-
}
|
294 |
-
.table-striped .datepicker table tr td,
|
295 |
-
.table-striped .datepicker table tr th {
|
296 |
-
background-color: transparent;
|
297 |
-
}
|
298 |
-
.datepicker table tr td.day:hover {
|
299 |
-
background: #eeeeee;
|
300 |
-
cursor: pointer;
|
301 |
-
}
|
302 |
-
.datepicker table tr td.old,
|
303 |
-
.datepicker table tr td.new {
|
304 |
-
color: #999999;
|
305 |
-
}
|
306 |
-
.datepicker table tr td.disabled,
|
307 |
-
.datepicker table tr td.disabled:hover {
|
308 |
-
background: none;
|
309 |
-
color: #999999;
|
310 |
-
cursor: default;
|
311 |
-
}
|
312 |
-
.datepicker table tr td.today,
|
313 |
-
.datepicker table tr td.today:hover,
|
314 |
-
.datepicker table tr td.today.disabled,
|
315 |
-
.datepicker table tr td.today.disabled:hover {
|
316 |
-
background-color: #fde19a;
|
317 |
-
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
318 |
-
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
319 |
-
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
320 |
-
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
321 |
-
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
322 |
-
background-image: linear-gradient(top, #fdd49a, #fdf59a);
|
323 |
-
background-repeat: repeat-x;
|
324 |
-
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
325 |
-
border-color: #fdf59a #fdf59a #fbed50;
|
326 |
-
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
327 |
-
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
328 |
-
color: #000;
|
329 |
-
}
|
330 |
-
.datepicker table tr td.today:hover,
|
331 |
-
.datepicker table tr td.today:hover:hover,
|
332 |
-
.datepicker table tr td.today.disabled:hover,
|
333 |
-
.datepicker table tr td.today.disabled:hover:hover,
|
334 |
-
.datepicker table tr td.today:active,
|
335 |
-
.datepicker table tr td.today:hover:active,
|
336 |
-
.datepicker table tr td.today.disabled:active,
|
337 |
-
.datepicker table tr td.today.disabled:hover:active,
|
338 |
-
.datepicker table tr td.today.active,
|
339 |
-
.datepicker table tr td.today:hover.active,
|
340 |
-
.datepicker table tr td.today.disabled.active,
|
341 |
-
.datepicker table tr td.today.disabled:hover.active,
|
342 |
-
.datepicker table tr td.today.disabled,
|
343 |
-
.datepicker table tr td.today:hover.disabled,
|
344 |
-
.datepicker table tr td.today.disabled.disabled,
|
345 |
-
.datepicker table tr td.today.disabled:hover.disabled,
|
346 |
-
.datepicker table tr td.today[disabled],
|
347 |
-
.datepicker table tr td.today:hover[disabled],
|
348 |
-
.datepicker table tr td.today.disabled[disabled],
|
349 |
-
.datepicker table tr td.today.disabled:hover[disabled] {
|
350 |
-
background-color: #fdf59a;
|
351 |
-
}
|
352 |
-
.datepicker table tr td.today:active,
|
353 |
-
.datepicker table tr td.today:hover:active,
|
354 |
-
.datepicker table tr td.today.disabled:active,
|
355 |
-
.datepicker table tr td.today.disabled:hover:active,
|
356 |
-
.datepicker table tr td.today.active,
|
357 |
-
.datepicker table tr td.today:hover.active,
|
358 |
-
.datepicker table tr td.today.disabled.active,
|
359 |
-
.datepicker table tr td.today.disabled:hover.active {
|
360 |
-
background-color: #fbf069 \9;
|
361 |
-
}
|
362 |
-
.datepicker table tr td.today:hover:hover {
|
363 |
-
color: #000;
|
364 |
-
}
|
365 |
-
.datepicker table tr td.today.active:hover {
|
366 |
-
color: #fff;
|
367 |
-
}
|
368 |
-
.datepicker table tr td.range,
|
369 |
-
.datepicker table tr td.range:hover,
|
370 |
-
.datepicker table tr td.range.disabled,
|
371 |
-
.datepicker table tr td.range.disabled:hover {
|
372 |
-
background: #eeeeee;
|
373 |
-
-webkit-border-radius: 0;
|
374 |
-
-moz-border-radius: 0;
|
375 |
-
border-radius: 0;
|
376 |
-
}
|
377 |
-
.datepicker table tr td.range.today,
|
378 |
-
.datepicker table tr td.range.today:hover,
|
379 |
-
.datepicker table tr td.range.today.disabled,
|
380 |
-
.datepicker table tr td.range.today.disabled:hover {
|
381 |
-
background-color: #f3d17a;
|
382 |
-
background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
|
383 |
-
background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
|
384 |
-
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
385 |
-
background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
|
386 |
-
background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
|
387 |
-
background-image: linear-gradient(top, #f3c17a, #f3e97a);
|
388 |
-
background-repeat: repeat-x;
|
389 |
-
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
390 |
-
border-color: #f3e97a #f3e97a #edde34;
|
391 |
-
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
392 |
-
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
393 |
-
-webkit-border-radius: 0;
|
394 |
-
-moz-border-radius: 0;
|
395 |
-
border-radius: 0;
|
396 |
-
}
|
397 |
-
.datepicker table tr td.range.today:hover,
|
398 |
-
.datepicker table tr td.range.today:hover:hover,
|
399 |
-
.datepicker table tr td.range.today.disabled:hover,
|
400 |
-
.datepicker table tr td.range.today.disabled:hover:hover,
|
401 |
-
.datepicker table tr td.range.today:active,
|
402 |
-
.datepicker table tr td.range.today:hover:active,
|
403 |
-
.datepicker table tr td.range.today.disabled:active,
|
404 |
-
.datepicker table tr td.range.today.disabled:hover:active,
|
405 |
-
.datepicker table tr td.range.today.active,
|
406 |
-
.datepicker table tr td.range.today:hover.active,
|
407 |
-
.datepicker table tr td.range.today.disabled.active,
|
408 |
-
.datepicker table tr td.range.today.disabled:hover.active,
|
409 |
-
.datepicker table tr td.range.today.disabled,
|
410 |
-
.datepicker table tr td.range.today:hover.disabled,
|
411 |
-
.datepicker table tr td.range.today.disabled.disabled,
|
412 |
-
.datepicker table tr td.range.today.disabled:hover.disabled,
|
413 |
-
.datepicker table tr td.range.today[disabled],
|
414 |
-
.datepicker table tr td.range.today:hover[disabled],
|
415 |
-
.datepicker table tr td.range.today.disabled[disabled],
|
416 |
-
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
417 |
-
background-color: #f3e97a;
|
418 |
-
}
|
419 |
-
.datepicker table tr td.range.today:active,
|
420 |
-
.datepicker table tr td.range.today:hover:active,
|
421 |
-
.datepicker table tr td.range.today.disabled:active,
|
422 |
-
.datepicker table tr td.range.today.disabled:hover:active,
|
423 |
-
.datepicker table tr td.range.today.active,
|
424 |
-
.datepicker table tr td.range.today:hover.active,
|
425 |
-
.datepicker table tr td.range.today.disabled.active,
|
426 |
-
.datepicker table tr td.range.today.disabled:hover.active {
|
427 |
-
background-color: #efe24b \9;
|
428 |
-
}
|
429 |
-
.datepicker table tr td.selected,
|
430 |
-
.datepicker table tr td.selected:hover,
|
431 |
-
.datepicker table tr td.selected.disabled,
|
432 |
-
.datepicker table tr td.selected.disabled:hover {
|
433 |
-
background-color: #9e9e9e;
|
434 |
-
background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
|
435 |
-
background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
|
436 |
-
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
437 |
-
background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
|
438 |
-
background-image: -o-linear-gradient(top, #b3b3b3, #808080);
|
439 |
-
background-image: linear-gradient(top, #b3b3b3, #808080);
|
440 |
-
background-repeat: repeat-x;
|
441 |
-
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
442 |
-
border-color: #808080 #808080 #595959;
|
443 |
-
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
444 |
-
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
445 |
-
color: #fff;
|
446 |
-
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
447 |
-
}
|
448 |
-
.datepicker table tr td.selected:hover,
|
449 |
-
.datepicker table tr td.selected:hover:hover,
|
450 |
-
.datepicker table tr td.selected.disabled:hover,
|
451 |
-
.datepicker table tr td.selected.disabled:hover:hover,
|
452 |
-
.datepicker table tr td.selected:active,
|
453 |
-
.datepicker table tr td.selected:hover:active,
|
454 |
-
.datepicker table tr td.selected.disabled:active,
|
455 |
-
.datepicker table tr td.selected.disabled:hover:active,
|
456 |
-
.datepicker table tr td.selected.active,
|
457 |
-
.datepicker table tr td.selected:hover.active,
|
458 |
-
.datepicker table tr td.selected.disabled.active,
|
459 |
-
.datepicker table tr td.selected.disabled:hover.active,
|
460 |
-
.datepicker table tr td.selected.disabled,
|
461 |
-
.datepicker table tr td.selected:hover.disabled,
|
462 |
-
.datepicker table tr td.selected.disabled.disabled,
|
463 |
-
.datepicker table tr td.selected.disabled:hover.disabled,
|
464 |
-
.datepicker table tr td.selected[disabled],
|
465 |
-
.datepicker table tr td.selected:hover[disabled],
|
466 |
-
.datepicker table tr td.selected.disabled[disabled],
|
467 |
-
.datepicker table tr td.selected.disabled:hover[disabled] {
|
468 |
-
background-color: #808080;
|
469 |
-
}
|
470 |
-
.datepicker table tr td.selected:active,
|
471 |
-
.datepicker table tr td.selected:hover:active,
|
472 |
-
.datepicker table tr td.selected.disabled:active,
|
473 |
-
.datepicker table tr td.selected.disabled:hover:active,
|
474 |
-
.datepicker table tr td.selected.active,
|
475 |
-
.datepicker table tr td.selected:hover.active,
|
476 |
-
.datepicker table tr td.selected.disabled.active,
|
477 |
-
.datepicker table tr td.selected.disabled:hover.active {
|
478 |
-
background-color: #666666 \9;
|
479 |
-
}
|
480 |
-
.datepicker table tr td.active,
|
481 |
-
.datepicker table tr td.active:hover,
|
482 |
-
.datepicker table tr td.active.disabled,
|
483 |
-
.datepicker table tr td.active.disabled:hover {
|
484 |
-
background-color: #006dcc;
|
485 |
-
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
486 |
-
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
487 |
-
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
488 |
-
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
489 |
-
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
490 |
-
background-image: linear-gradient(top, #0088cc, #0044cc);
|
491 |
-
background-repeat: repeat-x;
|
492 |
-
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
493 |
-
border-color: #0044cc #0044cc #002a80;
|
494 |
-
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
495 |
-
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
496 |
-
color: #fff;
|
497 |
-
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
498 |
-
}
|
499 |
-
.datepicker table tr td.active:hover,
|
500 |
-
.datepicker table tr td.active:hover:hover,
|
501 |
-
.datepicker table tr td.active.disabled:hover,
|
502 |
-
.datepicker table tr td.active.disabled:hover:hover,
|
503 |
-
.datepicker table tr td.active:active,
|
504 |
-
.datepicker table tr td.active:hover:active,
|
505 |
-
.datepicker table tr td.active.disabled:active,
|
506 |
-
.datepicker table tr td.active.disabled:hover:active,
|
507 |
-
.datepicker table tr td.active.active,
|
508 |
-
.datepicker table tr td.active:hover.active,
|
509 |
-
.datepicker table tr td.active.disabled.active,
|
510 |
-
.datepicker table tr td.active.disabled:hover.active,
|
511 |
-
.datepicker table tr td.active.disabled,
|
512 |
-
.datepicker table tr td.active:hover.disabled,
|
513 |
-
.datepicker table tr td.active.disabled.disabled,
|
514 |
-
.datepicker table tr td.active.disabled:hover.disabled,
|
515 |
-
.datepicker table tr td.active[disabled],
|
516 |
-
.datepicker table tr td.active:hover[disabled],
|
517 |
-
.datepicker table tr td.active.disabled[disabled],
|
518 |
-
.datepicker table tr td.active.disabled:hover[disabled] {
|
519 |
-
background-color: #0044cc;
|
520 |
-
}
|
521 |
-
.datepicker table tr td.active:active,
|
522 |
-
.datepicker table tr td.active:hover:active,
|
523 |
-
.datepicker table tr td.active.disabled:active,
|
524 |
-
.datepicker table tr td.active.disabled:hover:active,
|
525 |
-
.datepicker table tr td.active.active,
|
526 |
-
.datepicker table tr td.active:hover.active,
|
527 |
-
.datepicker table tr td.active.disabled.active,
|
528 |
-
.datepicker table tr td.active.disabled:hover.active {
|
529 |
-
background-color: #003399 \9;
|
530 |
-
}
|
531 |
-
.datepicker table tr td span {
|
532 |
-
display: block;
|
533 |
-
width: 23%;
|
534 |
-
height: 54px;
|
535 |
-
line-height: 54px;
|
536 |
-
float: left;
|
537 |
-
margin: 1%;
|
538 |
-
cursor: pointer;
|
539 |
-
-webkit-border-radius: 4px;
|
540 |
-
-moz-border-radius: 4px;
|
541 |
-
border-radius: 4px;
|
542 |
-
}
|
543 |
-
.datepicker table tr td span:hover {
|
544 |
-
background: #eeeeee;
|
545 |
-
}
|
546 |
-
.datepicker table tr td span.disabled,
|
547 |
-
.datepicker table tr td span.disabled:hover {
|
548 |
-
background: none;
|
549 |
-
color: #999999;
|
550 |
-
cursor: default;
|
551 |
-
}
|
552 |
-
.datepicker table tr td span.active,
|
553 |
-
.datepicker table tr td span.active:hover,
|
554 |
-
.datepicker table tr td span.active.disabled,
|
555 |
-
.datepicker table tr td span.active.disabled:hover {
|
556 |
-
background-color: #006dcc;
|
557 |
-
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
558 |
-
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
559 |
-
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
560 |
-
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
561 |
-
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
562 |
-
background-image: linear-gradient(top, #0088cc, #0044cc);
|
563 |
-
background-repeat: repeat-x;
|
564 |
-
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
565 |
-
border-color: #0044cc #0044cc #002a80;
|
566 |
-
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
567 |
-
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
568 |
-
color: #fff;
|
569 |
-
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
570 |
-
}
|
571 |
-
.datepicker table tr td span.active:hover,
|
572 |
-
.datepicker table tr td span.active:hover:hover,
|
573 |
-
.datepicker table tr td span.active.disabled:hover,
|
574 |
-
.datepicker table tr td span.active.disabled:hover:hover,
|
575 |
-
.datepicker table tr td span.active:active,
|
576 |
-
.datepicker table tr td span.active:hover:active,
|
577 |
-
.datepicker table tr td span.active.disabled:active,
|
578 |
-
.datepicker table tr td span.active.disabled:hover:active,
|
579 |
-
.datepicker table tr td span.active.active,
|
580 |
-
.datepicker table tr td span.active:hover.active,
|
581 |
-
.datepicker table tr td span.active.disabled.active,
|
582 |
-
.datepicker table tr td span.active.disabled:hover.active,
|
583 |
-
.datepicker table tr td span.active.disabled,
|
584 |
-
.datepicker table tr td span.active:hover.disabled,
|
585 |
-
.datepicker table tr td span.active.disabled.disabled,
|
586 |
-
.datepicker table tr td span.active.disabled:hover.disabled,
|
587 |
-
.datepicker table tr td span.active[disabled],
|
588 |
-
.datepicker table tr td span.active:hover[disabled],
|
589 |
-
.datepicker table tr td span.active.disabled[disabled],
|
590 |
-
.datepicker table tr td span.active.disabled:hover[disabled] {
|
591 |
-
background-color: #0044cc;
|
592 |
-
}
|
593 |
-
.datepicker table tr td span.active:active,
|
594 |
-
.datepicker table tr td span.active:hover:active,
|
595 |
-
.datepicker table tr td span.active.disabled:active,
|
596 |
-
.datepicker table tr td span.active.disabled:hover:active,
|
597 |
-
.datepicker table tr td span.active.active,
|
598 |
-
.datepicker table tr td span.active:hover.active,
|
599 |
-
.datepicker table tr td span.active.disabled.active,
|
600 |
-
.datepicker table tr td span.active.disabled:hover.active {
|
601 |
-
background-color: #003399 \9;
|
602 |
-
}
|
603 |
-
.datepicker table tr td span.old,
|
604 |
-
.datepicker table tr td span.new {
|
605 |
-
color: #999999;
|
606 |
-
}
|
607 |
-
.datepicker th.datepicker-switch {
|
608 |
-
width: 145px;
|
609 |
-
}
|
610 |
-
.datepicker thead tr:first-child th,
|
611 |
-
.datepicker tfoot tr th {
|
612 |
-
cursor: pointer;
|
613 |
-
}
|
614 |
-
.datepicker thead tr:first-child th:hover,
|
615 |
-
.datepicker tfoot tr th:hover {
|
616 |
-
background: #eeeeee;
|
617 |
-
}
|
618 |
-
.datepicker .cw {
|
619 |
-
font-size: 10px;
|
620 |
-
width: 12px;
|
621 |
-
padding: 0 2px 0 5px;
|
622 |
-
vertical-align: middle;
|
623 |
-
}
|
624 |
-
.datepicker thead tr:first-child th.cw {
|
625 |
-
cursor: default;
|
626 |
-
background-color: transparent;
|
627 |
-
}
|
628 |
-
.input-append.date .add-on i,
|
629 |
-
.input-prepend.date .add-on i {
|
630 |
-
display: block;
|
631 |
-
cursor: pointer;
|
632 |
-
width: 16px;
|
633 |
-
height: 16px;
|
634 |
-
}
|
635 |
-
.input-daterange input {
|
636 |
-
text-align: center;
|
637 |
-
}
|
638 |
-
.input-daterange input:first-child {
|
639 |
-
-webkit-border-radius: 3px 0 0 3px;
|
640 |
-
-moz-border-radius: 3px 0 0 3px;
|
641 |
-
border-radius: 3px 0 0 3px;
|
642 |
-
}
|
643 |
-
.input-daterange input:last-child {
|
644 |
-
-webkit-border-radius: 0 3px 3px 0;
|
645 |
-
-moz-border-radius: 0 3px 3px 0;
|
646 |
-
border-radius: 0 3px 3px 0;
|
647 |
-
}
|
648 |
-
.input-daterange .add-on {
|
649 |
-
display: inline-block;
|
650 |
-
width: auto;
|
651 |
-
min-width: 16px;
|
652 |
-
height: 18px;
|
653 |
-
padding: 4px 5px;
|
654 |
-
font-weight: normal;
|
655 |
-
line-height: 18px;
|
656 |
-
text-align: center;
|
657 |
-
text-shadow: 0 1px 0 #ffffff;
|
658 |
-
vertical-align: middle;
|
659 |
-
background-color: #eeeeee;
|
660 |
-
border: 1px solid #ccc;
|
661 |
-
margin-left: -5px;
|
662 |
-
margin-right: -5px;
|
663 |
-
}
|
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 */
|
5 |
+
.editableform {
|
6 |
+
margin-bottom: 0; /* overwrites bootstrap margin */
|
7 |
+
}
|
8 |
+
|
9 |
+
.editableform .control-group {
|
10 |
+
margin-bottom: 0; /* overwrites bootstrap margin */
|
11 |
+
white-space: nowrap; /* prevent wrapping buttons on new line */
|
12 |
+
line-height: 20px; /* overwriting bootstrap line-height. See #133 */
|
13 |
+
}
|
14 |
+
|
15 |
+
/*
|
16 |
+
BS3 width:1005 for inputs breaks editable form in popup
|
17 |
+
See: https://github.com/vitalets/x-editable/issues/393
|
18 |
+
*/
|
19 |
+
.editableform .form-control {
|
20 |
+
width: auto;
|
21 |
+
}
|
22 |
+
|
23 |
+
.editable-buttons {
|
24 |
+
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
25 |
+
vertical-align: top;
|
26 |
+
margin-left: 7px;
|
27 |
+
/* inline-block emulation for IE7*/
|
28 |
+
zoom: 1;
|
29 |
+
*display: inline;
|
30 |
+
}
|
31 |
+
|
32 |
+
.editable-buttons.editable-buttons-bottom {
|
33 |
+
display: block;
|
34 |
+
margin-top: 7px;
|
35 |
+
margin-left: 0;
|
36 |
+
}
|
37 |
+
|
38 |
+
.editable-input {
|
39 |
+
vertical-align: top;
|
40 |
+
display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */
|
41 |
+
width: auto; /* bootstrap-responsive has width: 100% that breakes layout */
|
42 |
+
white-space: normal; /* reset white-space decalred in parent*/
|
43 |
+
/* display-inline emulation for IE7*/
|
44 |
+
zoom: 1;
|
45 |
+
*display: inline;
|
46 |
+
}
|
47 |
+
|
48 |
+
.editable-buttons .editable-cancel {
|
49 |
+
margin-left: 7px;
|
50 |
+
}
|
51 |
+
|
52 |
+
/*for jquery-ui buttons need set height to look more pretty*/
|
53 |
+
.editable-buttons button.ui-button-icon-only {
|
54 |
+
height: 24px;
|
55 |
+
width: 30px;
|
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;
|
63 |
+
}
|
64 |
+
|
65 |
+
.editable-inline .editableform-loading {
|
66 |
+
background-position: left 5px;
|
67 |
+
}
|
68 |
+
|
69 |
+
.editable-error-block {
|
70 |
+
max-width: 300px;
|
71 |
+
margin: 5px 0 0 0;
|
72 |
+
width: auto;
|
73 |
+
white-space: normal;
|
74 |
+
}
|
75 |
+
|
76 |
+
/*add padding for jquery ui*/
|
77 |
+
.editable-error-block.ui-state-error {
|
78 |
+
padding: 3px;
|
79 |
+
}
|
80 |
+
|
81 |
+
.editable-error {
|
82 |
+
color: red;
|
83 |
+
}
|
84 |
+
|
85 |
+
/* ---- For specific types ---- */
|
86 |
+
|
87 |
+
.editableform .editable-date {
|
88 |
+
padding: 0;
|
89 |
+
margin: 0;
|
90 |
+
float: left;
|
91 |
+
}
|
92 |
+
|
93 |
+
/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */
|
94 |
+
.editable-inline .add-on .icon-th {
|
95 |
+
margin-top: 3px;
|
96 |
+
margin-left: 1px;
|
97 |
+
}
|
98 |
+
|
99 |
+
|
100 |
+
/* checklist vertical alignment */
|
101 |
+
.editable-checklist label input[type="checkbox"],
|
102 |
+
.editable-checklist label span {
|
103 |
+
vertical-align: middle;
|
104 |
+
margin: 0;
|
105 |
+
}
|
106 |
+
|
107 |
+
.editable-checklist label {
|
108 |
+
white-space: nowrap;
|
109 |
+
}
|
110 |
+
|
111 |
+
/* set exact width of textarea to fit buttons toolbar */
|
112 |
+
.editable-wysihtml5 {
|
113 |
+
width: 566px;
|
114 |
+
height: 250px;
|
115 |
+
}
|
116 |
+
|
117 |
+
/* clear button shown as link in date inputs */
|
118 |
+
.editable-clear {
|
119 |
+
clear: both;
|
120 |
+
font-size: 0.9em;
|
121 |
+
text-decoration: none;
|
122 |
+
text-align: right;
|
123 |
+
}
|
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;
|
131 |
+
position: absolute;
|
132 |
+
opacity: 0.6;
|
133 |
+
z-index: 100;
|
134 |
+
|
135 |
+
top: 50%;
|
136 |
+
right: 6px;
|
137 |
+
margin-top: -6px;
|
138 |
+
|
139 |
+
}
|
140 |
+
|
141 |
+
.editable-clear-x:hover {
|
142 |
+
opacity: 1;
|
143 |
+
}
|
144 |
+
|
145 |
+
.editable-pre-wrapped {
|
146 |
+
white-space: pre-wrap;
|
147 |
+
}
|
148 |
+
.editable-container.editable-popup {
|
149 |
+
max-width: none !important; /* without this rule poshytip/tooltip does not stretch */
|
150 |
+
}
|
151 |
+
|
152 |
+
.editable-container.popover {
|
153 |
+
width: auto; /* without this rule popover does not stretch */
|
154 |
+
}
|
155 |
+
|
156 |
+
.editable-container.editable-inline {
|
157 |
+
display: inline-block;
|
158 |
+
vertical-align: middle;
|
159 |
+
width: auto;
|
160 |
+
/* inline-block emulation for IE7*/
|
161 |
+
zoom: 1;
|
162 |
+
*display: inline;
|
163 |
+
}
|
164 |
+
|
165 |
+
.editable-container.ui-widget {
|
166 |
+
font-size: inherit; /* jqueryui widget font 1.1em too big, overwrite it */
|
167 |
+
z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */
|
168 |
+
}
|
169 |
+
.editable-click,
|
170 |
+
a.editable-click,
|
171 |
+
a.editable-click:hover {
|
172 |
+
text-decoration: none;
|
173 |
+
border-bottom: dashed 1px #0088cc;
|
174 |
+
}
|
175 |
+
|
176 |
+
.editable-click.editable-disabled,
|
177 |
+
a.editable-click.editable-disabled,
|
178 |
+
a.editable-click.editable-disabled:hover {
|
179 |
+
color: #585858;
|
180 |
+
cursor: default;
|
181 |
+
border-bottom: none;
|
182 |
+
}
|
183 |
+
|
184 |
+
.editable-empty, .editable-empty:hover, .editable-empty:focus{
|
185 |
+
font-style: italic;
|
186 |
+
color: #DD1144;
|
187 |
+
/* border-bottom: none; */
|
188 |
+
text-decoration: none;
|
189 |
+
}
|
190 |
+
|
191 |
+
.editable-unsaved {
|
192 |
+
font-weight: bold;
|
193 |
+
}
|
194 |
+
|
195 |
+
.editable-unsaved:after {
|
196 |
+
/* content: '*'*/
|
197 |
+
}
|
198 |
+
|
199 |
+
.editable-bg-transition {
|
200 |
+
-webkit-transition: background-color 1400ms ease-out;
|
201 |
+
-moz-transition: background-color 1400ms ease-out;
|
202 |
+
-o-transition: background-color 1400ms ease-out;
|
203 |
+
-ms-transition: background-color 1400ms ease-out;
|
204 |
+
transition: background-color 1400ms ease-out;
|
205 |
+
}
|
206 |
+
|
207 |
+
/*see https://github.com/vitalets/x-editable/issues/139 */
|
208 |
+
.form-horizontal .editable
|
209 |
+
{
|
210 |
+
padding-top: 5px;
|
211 |
+
display:inline-block;
|
212 |
+
}
|
213 |
+
|
214 |
+
|
215 |
+
/*!
|
216 |
+
* Datepicker for Bootstrap
|
217 |
+
*
|
218 |
+
* Copyright 2012 Stefan Petre
|
219 |
+
* Improvements by Andrew Rowls
|
220 |
+
* Licensed under the Apache License v2.0
|
221 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
222 |
+
*
|
223 |
+
*/
|
224 |
+
.datepicker {
|
225 |
+
padding: 4px;
|
226 |
+
-webkit-border-radius: 4px;
|
227 |
+
-moz-border-radius: 4px;
|
228 |
+
border-radius: 4px;
|
229 |
+
direction: ltr;
|
230 |
+
/*.dow {
|
231 |
+
border-top: 1px solid #ddd !important;
|
232 |
+
}*/
|
233 |
+
|
234 |
+
}
|
235 |
+
.datepicker-inline {
|
236 |
+
width: 220px;
|
237 |
+
}
|
238 |
+
.datepicker.datepicker-rtl {
|
239 |
+
direction: rtl;
|
240 |
+
}
|
241 |
+
.datepicker.datepicker-rtl table tr td span {
|
242 |
+
float: right;
|
243 |
+
}
|
244 |
+
.datepicker-dropdown {
|
245 |
+
top: 0;
|
246 |
+
left: 0;
|
247 |
+
}
|
248 |
+
.datepicker-dropdown:before {
|
249 |
+
content: '';
|
250 |
+
display: inline-block;
|
251 |
+
border-left: 7px solid transparent;
|
252 |
+
border-right: 7px solid transparent;
|
253 |
+
border-bottom: 7px solid #ccc;
|
254 |
+
border-bottom-color: rgba(0, 0, 0, 0.2);
|
255 |
+
position: absolute;
|
256 |
+
top: -7px;
|
257 |
+
left: 6px;
|
258 |
+
}
|
259 |
+
.datepicker-dropdown:after {
|
260 |
+
content: '';
|
261 |
+
display: inline-block;
|
262 |
+
border-left: 6px solid transparent;
|
263 |
+
border-right: 6px solid transparent;
|
264 |
+
border-bottom: 6px solid #ffffff;
|
265 |
+
position: absolute;
|
266 |
+
top: -6px;
|
267 |
+
left: 7px;
|
268 |
+
}
|
269 |
+
.datepicker > div {
|
270 |
+
display: none;
|
271 |
+
}
|
272 |
+
.datepicker.days div.datepicker-days {
|
273 |
+
display: block;
|
274 |
+
}
|
275 |
+
.datepicker.months div.datepicker-months {
|
276 |
+
display: block;
|
277 |
+
}
|
278 |
+
.datepicker.years div.datepicker-years {
|
279 |
+
display: block;
|
280 |
+
}
|
281 |
+
.datepicker table {
|
282 |
+
margin: 0;
|
283 |
+
}
|
284 |
+
.datepicker td,
|
285 |
+
.datepicker th {
|
286 |
+
text-align: center;
|
287 |
+
width: 20px;
|
288 |
+
height: 20px;
|
289 |
+
-webkit-border-radius: 4px;
|
290 |
+
-moz-border-radius: 4px;
|
291 |
+
border-radius: 4px;
|
292 |
+
border: none;
|
293 |
+
}
|
294 |
+
.table-striped .datepicker table tr td,
|
295 |
+
.table-striped .datepicker table tr th {
|
296 |
+
background-color: transparent;
|
297 |
+
}
|
298 |
+
.datepicker table tr td.day:hover {
|
299 |
+
background: #eeeeee;
|
300 |
+
cursor: pointer;
|
301 |
+
}
|
302 |
+
.datepicker table tr td.old,
|
303 |
+
.datepicker table tr td.new {
|
304 |
+
color: #999999;
|
305 |
+
}
|
306 |
+
.datepicker table tr td.disabled,
|
307 |
+
.datepicker table tr td.disabled:hover {
|
308 |
+
background: none;
|
309 |
+
color: #999999;
|
310 |
+
cursor: default;
|
311 |
+
}
|
312 |
+
.datepicker table tr td.today,
|
313 |
+
.datepicker table tr td.today:hover,
|
314 |
+
.datepicker table tr td.today.disabled,
|
315 |
+
.datepicker table tr td.today.disabled:hover {
|
316 |
+
background-color: #fde19a;
|
317 |
+
background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);
|
318 |
+
background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);
|
319 |
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));
|
320 |
+
background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);
|
321 |
+
background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);
|
322 |
+
background-image: linear-gradient(top, #fdd49a, #fdf59a);
|
323 |
+
background-repeat: repeat-x;
|
324 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);
|
325 |
+
border-color: #fdf59a #fdf59a #fbed50;
|
326 |
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
327 |
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
328 |
+
color: #000;
|
329 |
+
}
|
330 |
+
.datepicker table tr td.today:hover,
|
331 |
+
.datepicker table tr td.today:hover:hover,
|
332 |
+
.datepicker table tr td.today.disabled:hover,
|
333 |
+
.datepicker table tr td.today.disabled:hover:hover,
|
334 |
+
.datepicker table tr td.today:active,
|
335 |
+
.datepicker table tr td.today:hover:active,
|
336 |
+
.datepicker table tr td.today.disabled:active,
|
337 |
+
.datepicker table tr td.today.disabled:hover:active,
|
338 |
+
.datepicker table tr td.today.active,
|
339 |
+
.datepicker table tr td.today:hover.active,
|
340 |
+
.datepicker table tr td.today.disabled.active,
|
341 |
+
.datepicker table tr td.today.disabled:hover.active,
|
342 |
+
.datepicker table tr td.today.disabled,
|
343 |
+
.datepicker table tr td.today:hover.disabled,
|
344 |
+
.datepicker table tr td.today.disabled.disabled,
|
345 |
+
.datepicker table tr td.today.disabled:hover.disabled,
|
346 |
+
.datepicker table tr td.today[disabled],
|
347 |
+
.datepicker table tr td.today:hover[disabled],
|
348 |
+
.datepicker table tr td.today.disabled[disabled],
|
349 |
+
.datepicker table tr td.today.disabled:hover[disabled] {
|
350 |
+
background-color: #fdf59a;
|
351 |
+
}
|
352 |
+
.datepicker table tr td.today:active,
|
353 |
+
.datepicker table tr td.today:hover:active,
|
354 |
+
.datepicker table tr td.today.disabled:active,
|
355 |
+
.datepicker table tr td.today.disabled:hover:active,
|
356 |
+
.datepicker table tr td.today.active,
|
357 |
+
.datepicker table tr td.today:hover.active,
|
358 |
+
.datepicker table tr td.today.disabled.active,
|
359 |
+
.datepicker table tr td.today.disabled:hover.active {
|
360 |
+
background-color: #fbf069 \9;
|
361 |
+
}
|
362 |
+
.datepicker table tr td.today:hover:hover {
|
363 |
+
color: #000;
|
364 |
+
}
|
365 |
+
.datepicker table tr td.today.active:hover {
|
366 |
+
color: #fff;
|
367 |
+
}
|
368 |
+
.datepicker table tr td.range,
|
369 |
+
.datepicker table tr td.range:hover,
|
370 |
+
.datepicker table tr td.range.disabled,
|
371 |
+
.datepicker table tr td.range.disabled:hover {
|
372 |
+
background: #eeeeee;
|
373 |
+
-webkit-border-radius: 0;
|
374 |
+
-moz-border-radius: 0;
|
375 |
+
border-radius: 0;
|
376 |
+
}
|
377 |
+
.datepicker table tr td.range.today,
|
378 |
+
.datepicker table tr td.range.today:hover,
|
379 |
+
.datepicker table tr td.range.today.disabled,
|
380 |
+
.datepicker table tr td.range.today.disabled:hover {
|
381 |
+
background-color: #f3d17a;
|
382 |
+
background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);
|
383 |
+
background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);
|
384 |
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));
|
385 |
+
background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);
|
386 |
+
background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);
|
387 |
+
background-image: linear-gradient(top, #f3c17a, #f3e97a);
|
388 |
+
background-repeat: repeat-x;
|
389 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);
|
390 |
+
border-color: #f3e97a #f3e97a #edde34;
|
391 |
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
392 |
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
393 |
+
-webkit-border-radius: 0;
|
394 |
+
-moz-border-radius: 0;
|
395 |
+
border-radius: 0;
|
396 |
+
}
|
397 |
+
.datepicker table tr td.range.today:hover,
|
398 |
+
.datepicker table tr td.range.today:hover:hover,
|
399 |
+
.datepicker table tr td.range.today.disabled:hover,
|
400 |
+
.datepicker table tr td.range.today.disabled:hover:hover,
|
401 |
+
.datepicker table tr td.range.today:active,
|
402 |
+
.datepicker table tr td.range.today:hover:active,
|
403 |
+
.datepicker table tr td.range.today.disabled:active,
|
404 |
+
.datepicker table tr td.range.today.disabled:hover:active,
|
405 |
+
.datepicker table tr td.range.today.active,
|
406 |
+
.datepicker table tr td.range.today:hover.active,
|
407 |
+
.datepicker table tr td.range.today.disabled.active,
|
408 |
+
.datepicker table tr td.range.today.disabled:hover.active,
|
409 |
+
.datepicker table tr td.range.today.disabled,
|
410 |
+
.datepicker table tr td.range.today:hover.disabled,
|
411 |
+
.datepicker table tr td.range.today.disabled.disabled,
|
412 |
+
.datepicker table tr td.range.today.disabled:hover.disabled,
|
413 |
+
.datepicker table tr td.range.today[disabled],
|
414 |
+
.datepicker table tr td.range.today:hover[disabled],
|
415 |
+
.datepicker table tr td.range.today.disabled[disabled],
|
416 |
+
.datepicker table tr td.range.today.disabled:hover[disabled] {
|
417 |
+
background-color: #f3e97a;
|
418 |
+
}
|
419 |
+
.datepicker table tr td.range.today:active,
|
420 |
+
.datepicker table tr td.range.today:hover:active,
|
421 |
+
.datepicker table tr td.range.today.disabled:active,
|
422 |
+
.datepicker table tr td.range.today.disabled:hover:active,
|
423 |
+
.datepicker table tr td.range.today.active,
|
424 |
+
.datepicker table tr td.range.today:hover.active,
|
425 |
+
.datepicker table tr td.range.today.disabled.active,
|
426 |
+
.datepicker table tr td.range.today.disabled:hover.active {
|
427 |
+
background-color: #efe24b \9;
|
428 |
+
}
|
429 |
+
.datepicker table tr td.selected,
|
430 |
+
.datepicker table tr td.selected:hover,
|
431 |
+
.datepicker table tr td.selected.disabled,
|
432 |
+
.datepicker table tr td.selected.disabled:hover {
|
433 |
+
background-color: #9e9e9e;
|
434 |
+
background-image: -moz-linear-gradient(top, #b3b3b3, #808080);
|
435 |
+
background-image: -ms-linear-gradient(top, #b3b3b3, #808080);
|
436 |
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));
|
437 |
+
background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);
|
438 |
+
background-image: -o-linear-gradient(top, #b3b3b3, #808080);
|
439 |
+
background-image: linear-gradient(top, #b3b3b3, #808080);
|
440 |
+
background-repeat: repeat-x;
|
441 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);
|
442 |
+
border-color: #808080 #808080 #595959;
|
443 |
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
444 |
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
445 |
+
color: #fff;
|
446 |
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
447 |
+
}
|
448 |
+
.datepicker table tr td.selected:hover,
|
449 |
+
.datepicker table tr td.selected:hover:hover,
|
450 |
+
.datepicker table tr td.selected.disabled:hover,
|
451 |
+
.datepicker table tr td.selected.disabled:hover:hover,
|
452 |
+
.datepicker table tr td.selected:active,
|
453 |
+
.datepicker table tr td.selected:hover:active,
|
454 |
+
.datepicker table tr td.selected.disabled:active,
|
455 |
+
.datepicker table tr td.selected.disabled:hover:active,
|
456 |
+
.datepicker table tr td.selected.active,
|
457 |
+
.datepicker table tr td.selected:hover.active,
|
458 |
+
.datepicker table tr td.selected.disabled.active,
|
459 |
+
.datepicker table tr td.selected.disabled:hover.active,
|
460 |
+
.datepicker table tr td.selected.disabled,
|
461 |
+
.datepicker table tr td.selected:hover.disabled,
|
462 |
+
.datepicker table tr td.selected.disabled.disabled,
|
463 |
+
.datepicker table tr td.selected.disabled:hover.disabled,
|
464 |
+
.datepicker table tr td.selected[disabled],
|
465 |
+
.datepicker table tr td.selected:hover[disabled],
|
466 |
+
.datepicker table tr td.selected.disabled[disabled],
|
467 |
+
.datepicker table tr td.selected.disabled:hover[disabled] {
|
468 |
+
background-color: #808080;
|
469 |
+
}
|
470 |
+
.datepicker table tr td.selected:active,
|
471 |
+
.datepicker table tr td.selected:hover:active,
|
472 |
+
.datepicker table tr td.selected.disabled:active,
|
473 |
+
.datepicker table tr td.selected.disabled:hover:active,
|
474 |
+
.datepicker table tr td.selected.active,
|
475 |
+
.datepicker table tr td.selected:hover.active,
|
476 |
+
.datepicker table tr td.selected.disabled.active,
|
477 |
+
.datepicker table tr td.selected.disabled:hover.active {
|
478 |
+
background-color: #666666 \9;
|
479 |
+
}
|
480 |
+
.datepicker table tr td.active,
|
481 |
+
.datepicker table tr td.active:hover,
|
482 |
+
.datepicker table tr td.active.disabled,
|
483 |
+
.datepicker table tr td.active.disabled:hover {
|
484 |
+
background-color: #006dcc;
|
485 |
+
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
486 |
+
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
487 |
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
488 |
+
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
489 |
+
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
490 |
+
background-image: linear-gradient(top, #0088cc, #0044cc);
|
491 |
+
background-repeat: repeat-x;
|
492 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
493 |
+
border-color: #0044cc #0044cc #002a80;
|
494 |
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
495 |
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
496 |
+
color: #fff;
|
497 |
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
498 |
+
}
|
499 |
+
.datepicker table tr td.active:hover,
|
500 |
+
.datepicker table tr td.active:hover:hover,
|
501 |
+
.datepicker table tr td.active.disabled:hover,
|
502 |
+
.datepicker table tr td.active.disabled:hover:hover,
|
503 |
+
.datepicker table tr td.active:active,
|
504 |
+
.datepicker table tr td.active:hover:active,
|
505 |
+
.datepicker table tr td.active.disabled:active,
|
506 |
+
.datepicker table tr td.active.disabled:hover:active,
|
507 |
+
.datepicker table tr td.active.active,
|
508 |
+
.datepicker table tr td.active:hover.active,
|
509 |
+
.datepicker table tr td.active.disabled.active,
|
510 |
+
.datepicker table tr td.active.disabled:hover.active,
|
511 |
+
.datepicker table tr td.active.disabled,
|
512 |
+
.datepicker table tr td.active:hover.disabled,
|
513 |
+
.datepicker table tr td.active.disabled.disabled,
|
514 |
+
.datepicker table tr td.active.disabled:hover.disabled,
|
515 |
+
.datepicker table tr td.active[disabled],
|
516 |
+
.datepicker table tr td.active:hover[disabled],
|
517 |
+
.datepicker table tr td.active.disabled[disabled],
|
518 |
+
.datepicker table tr td.active.disabled:hover[disabled] {
|
519 |
+
background-color: #0044cc;
|
520 |
+
}
|
521 |
+
.datepicker table tr td.active:active,
|
522 |
+
.datepicker table tr td.active:hover:active,
|
523 |
+
.datepicker table tr td.active.disabled:active,
|
524 |
+
.datepicker table tr td.active.disabled:hover:active,
|
525 |
+
.datepicker table tr td.active.active,
|
526 |
+
.datepicker table tr td.active:hover.active,
|
527 |
+
.datepicker table tr td.active.disabled.active,
|
528 |
+
.datepicker table tr td.active.disabled:hover.active {
|
529 |
+
background-color: #003399 \9;
|
530 |
+
}
|
531 |
+
.datepicker table tr td span {
|
532 |
+
display: block;
|
533 |
+
width: 23%;
|
534 |
+
height: 54px;
|
535 |
+
line-height: 54px;
|
536 |
+
float: left;
|
537 |
+
margin: 1%;
|
538 |
+
cursor: pointer;
|
539 |
+
-webkit-border-radius: 4px;
|
540 |
+
-moz-border-radius: 4px;
|
541 |
+
border-radius: 4px;
|
542 |
+
}
|
543 |
+
.datepicker table tr td span:hover {
|
544 |
+
background: #eeeeee;
|
545 |
+
}
|
546 |
+
.datepicker table tr td span.disabled,
|
547 |
+
.datepicker table tr td span.disabled:hover {
|
548 |
+
background: none;
|
549 |
+
color: #999999;
|
550 |
+
cursor: default;
|
551 |
+
}
|
552 |
+
.datepicker table tr td span.active,
|
553 |
+
.datepicker table tr td span.active:hover,
|
554 |
+
.datepicker table tr td span.active.disabled,
|
555 |
+
.datepicker table tr td span.active.disabled:hover {
|
556 |
+
background-color: #006dcc;
|
557 |
+
background-image: -moz-linear-gradient(top, #0088cc, #0044cc);
|
558 |
+
background-image: -ms-linear-gradient(top, #0088cc, #0044cc);
|
559 |
+
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));
|
560 |
+
background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);
|
561 |
+
background-image: -o-linear-gradient(top, #0088cc, #0044cc);
|
562 |
+
background-image: linear-gradient(top, #0088cc, #0044cc);
|
563 |
+
background-repeat: repeat-x;
|
564 |
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);
|
565 |
+
border-color: #0044cc #0044cc #002a80;
|
566 |
+
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
567 |
+
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
|
568 |
+
color: #fff;
|
569 |
+
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
570 |
+
}
|
571 |
+
.datepicker table tr td span.active:hover,
|
572 |
+
.datepicker table tr td span.active:hover:hover,
|
573 |
+
.datepicker table tr td span.active.disabled:hover,
|
574 |
+
.datepicker table tr td span.active.disabled:hover:hover,
|
575 |
+
.datepicker table tr td span.active:active,
|
576 |
+
.datepicker table tr td span.active:hover:active,
|
577 |
+
.datepicker table tr td span.active.disabled:active,
|
578 |
+
.datepicker table tr td span.active.disabled:hover:active,
|
579 |
+
.datepicker table tr td span.active.active,
|
580 |
+
.datepicker table tr td span.active:hover.active,
|
581 |
+
.datepicker table tr td span.active.disabled.active,
|
582 |
+
.datepicker table tr td span.active.disabled:hover.active,
|
583 |
+
.datepicker table tr td span.active.disabled,
|
584 |
+
.datepicker table tr td span.active:hover.disabled,
|
585 |
+
.datepicker table tr td span.active.disabled.disabled,
|
586 |
+
.datepicker table tr td span.active.disabled:hover.disabled,
|
587 |
+
.datepicker table tr td span.active[disabled],
|
588 |
+
.datepicker table tr td span.active:hover[disabled],
|
589 |
+
.datepicker table tr td span.active.disabled[disabled],
|
590 |
+
.datepicker table tr td span.active.disabled:hover[disabled] {
|
591 |
+
background-color: #0044cc;
|
592 |
+
}
|
593 |
+
.datepicker table tr td span.active:active,
|
594 |
+
.datepicker table tr td span.active:hover:active,
|
595 |
+
.datepicker table tr td span.active.disabled:active,
|
596 |
+
.datepicker table tr td span.active.disabled:hover:active,
|
597 |
+
.datepicker table tr td span.active.active,
|
598 |
+
.datepicker table tr td span.active:hover.active,
|
599 |
+
.datepicker table tr td span.active.disabled.active,
|
600 |
+
.datepicker table tr td span.active.disabled:hover.active {
|
601 |
+
background-color: #003399 \9;
|
602 |
+
}
|
603 |
+
.datepicker table tr td span.old,
|
604 |
+
.datepicker table tr td span.new {
|
605 |
+
color: #999999;
|
606 |
+
}
|
607 |
+
.datepicker th.datepicker-switch {
|
608 |
+
width: 145px;
|
609 |
+
}
|
610 |
+
.datepicker thead tr:first-child th,
|
611 |
+
.datepicker tfoot tr th {
|
612 |
+
cursor: pointer;
|
613 |
+
}
|
614 |
+
.datepicker thead tr:first-child th:hover,
|
615 |
+
.datepicker tfoot tr th:hover {
|
616 |
+
background: #eeeeee;
|
617 |
+
}
|
618 |
+
.datepicker .cw {
|
619 |
+
font-size: 10px;
|
620 |
+
width: 12px;
|
621 |
+
padding: 0 2px 0 5px;
|
622 |
+
vertical-align: middle;
|
623 |
+
}
|
624 |
+
.datepicker thead tr:first-child th.cw {
|
625 |
+
cursor: default;
|
626 |
+
background-color: transparent;
|
627 |
+
}
|
628 |
+
.input-append.date .add-on i,
|
629 |
+
.input-prepend.date .add-on i {
|
630 |
+
display: block;
|
631 |
+
cursor: pointer;
|
632 |
+
width: 16px;
|
633 |
+
height: 16px;
|
634 |
+
}
|
635 |
+
.input-daterange input {
|
636 |
+
text-align: center;
|
637 |
+
}
|
638 |
+
.input-daterange input:first-child {
|
639 |
+
-webkit-border-radius: 3px 0 0 3px;
|
640 |
+
-moz-border-radius: 3px 0 0 3px;
|
641 |
+
border-radius: 3px 0 0 3px;
|
642 |
+
}
|
643 |
+
.input-daterange input:last-child {
|
644 |
+
-webkit-border-radius: 0 3px 3px 0;
|
645 |
+
-moz-border-radius: 0 3px 3px 0;
|
646 |
+
border-radius: 0 3px 3px 0;
|
647 |
+
}
|
648 |
+
.input-daterange .add-on {
|
649 |
+
display: inline-block;
|
650 |
+
width: auto;
|
651 |
+
min-width: 16px;
|
652 |
+
height: 18px;
|
653 |
+
padding: 4px 5px;
|
654 |
+
font-weight: normal;
|
655 |
+
line-height: 18px;
|
656 |
+
text-align: center;
|
657 |
+
text-shadow: 0 1px 0 #ffffff;
|
658 |
+
vertical-align: middle;
|
659 |
+
background-color: #eeeeee;
|
660 |
+
border: 1px solid #ccc;
|
661 |
+
margin-left: -5px;
|
662 |
+
margin-right: -5px;
|
663 |
+
}
|
backend/modules/appearance/resources/js/appearance.js
CHANGED
@@ -1,782 +1,838 @@
|
|
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 |
-
$
|
7 |
-
$
|
8 |
-
$
|
9 |
-
$
|
10 |
-
|
11 |
-
|
12 |
-
$
|
13 |
-
$
|
14 |
-
$
|
15 |
-
$
|
16 |
-
$
|
17 |
-
$
|
18 |
-
$
|
19 |
-
$
|
20 |
-
$
|
21 |
-
$
|
22 |
-
|
23 |
-
|
24 |
-
$
|
25 |
-
$
|
26 |
-
$
|
27 |
-
$
|
28 |
-
$
|
29 |
-
$
|
30 |
-
$
|
31 |
-
$
|
32 |
-
$
|
33 |
-
$
|
34 |
-
|
35 |
-
|
36 |
-
$
|
37 |
-
$
|
38 |
-
$
|
39 |
-
$
|
40 |
-
$
|
41 |
-
$
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
$
|
47 |
-
$
|
48 |
-
$
|
49 |
-
$
|
50 |
-
$
|
51 |
-
$
|
52 |
-
$
|
53 |
-
$
|
54 |
-
$
|
55 |
-
$
|
56 |
-
|
57 |
-
$
|
58 |
-
//
|
59 |
-
$
|
60 |
-
|
61 |
-
$
|
62 |
-
$
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
$
|
76 |
-
|
77 |
-
$('.bookly-
|
78 |
-
$('.bookly-js-
|
79 |
-
$('.bookly-
|
80 |
-
$('.bookly-js-
|
81 |
-
$('.
|
82 |
-
$('.
|
83 |
-
$('.
|
84 |
-
|
85 |
-
|
86 |
-
$(this).attr('style',
|
87 |
-
})
|
88 |
-
|
89 |
-
|
90 |
-
$('.
|
91 |
-
$('.
|
92 |
-
$('.
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
$('.bookly-
|
127 |
-
$('.bookly-
|
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 |
-
if (
|
161 |
-
$
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
$
|
169 |
-
}
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
$
|
291 |
-
|
292 |
-
|
293 |
-
$
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
}
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
}
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
$
|
389 |
-
$('.
|
390 |
-
|
391 |
-
$('.
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
}
|
414 |
-
});
|
415 |
-
|
416 |
-
// Show
|
417 |
-
$
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
$('.bookly-column
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
}
|
454 |
-
}).trigger('change');
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
$
|
575 |
-
|
576 |
-
$
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
|
626 |
-
|
627 |
-
|
628 |
-
|
629 |
-
|
630 |
-
|
631 |
-
|
632 |
-
|
633 |
-
});
|
634 |
-
|
635 |
-
|
636 |
-
|
637 |
-
|
638 |
-
|
639 |
-
|
640 |
-
|
641 |
-
|
642 |
-
|
643 |
-
|
644 |
-
$
|
645 |
-
|
646 |
-
|
647 |
-
|
648 |
-
|
649 |
-
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
|
735 |
-
|
736 |
-
|
737 |
-
|
738 |
-
|
739 |
-
|
740 |
-
|
741 |
-
|
742 |
-
|
743 |
-
|
744 |
-
|
745 |
-
|
746 |
-
|
747 |
-
|
748 |
-
|
749 |
-
|
750 |
-
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
-
|
766 |
-
|
767 |
-
|
768 |
-
|
769 |
-
|
770 |
-
|
771 |
-
|
772 |
-
|
773 |
-
|
774 |
-
|
775 |
-
|
776 |
-
|
777 |
-
|
778 |
-
|
779 |
-
|
780 |
-
|
781 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
782 |
});
|
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 |
+
$align_buttons_left = $('#bookly-align-buttons-left'),
|
7 |
+
$step_settings = $('#bookly-step-settings'),
|
8 |
+
$bookly_show_step_extras = $('#bookly-show-step-extras'),
|
9 |
+
$bookly_show_step_repeat = $('#bookly-show-step-repeat'),
|
10 |
+
$bookly_show_step_cart = $('#bookly-show-step-cart'),
|
11 |
+
// Service step.
|
12 |
+
$staff_name_with_price = $('#bookly-staff-name-with-price'),
|
13 |
+
$service_duration_with_price = $('#bookly-service-duration-with-price'),
|
14 |
+
$service_name_with_duration = $('#bookly-service-name-with-duration'),
|
15 |
+
$required_employee = $('#bookly-required-employee'),
|
16 |
+
$required_location = $('#bookly-required-location'),
|
17 |
+
$show_ratings = $('#bookly-show-ratings'),
|
18 |
+
$show_chain_appointments = $('#bookly-show-chain-appointments'),
|
19 |
+
$show_location = $('#bookly-show-location'),
|
20 |
+
$show_custom_duration = $('#bookly-show-custom-duration'),
|
21 |
+
$show_nop = $('#bookly-show-nop'),
|
22 |
+
$show_quantity = $('#bookly-show-quantity'),
|
23 |
+
// Time step.
|
24 |
+
$time_step_nop = $('#bookly-show-nop-on-time-step'),
|
25 |
+
$time_step_calendar = $('.bookly-js-selected-date'),
|
26 |
+
$time_step_calendar_wrap = $('.bookly-js-slot-calendar'),
|
27 |
+
$show_blocked_timeslots = $('#bookly-show-blocked-timeslots'),
|
28 |
+
$show_waiting_list = $('#bookly-show-waiting-list'),
|
29 |
+
$show_day_one_column = $('#bookly-show-day-one-column'),
|
30 |
+
$show_time_zone_switcher = $('#bookly-show-time-zone-switcher'),
|
31 |
+
$show_calendar = $('#bookly-show-calendar'),
|
32 |
+
$day_one_column = $('#bookly-day-one-column'),
|
33 |
+
$day_multi_columns = $('#bookly-day-multi-columns'),
|
34 |
+
$columnizer = $('.bookly-time-step .bookly-columnizer-wrap'),
|
35 |
+
// Step repeat.
|
36 |
+
$repeat_step_calendar = $('.bookly-js-repeat-until'),
|
37 |
+
$repeat_variants = $('[class^="bookly-js-variant"]'),
|
38 |
+
$repeat_variant = $('.bookly-js-repeat-variant'),
|
39 |
+
$repeat_variant_monthly = $('.bookly-js-repeat-variant-monthly'),
|
40 |
+
$repeat_weekly_week_day = $('.bookly-js-week-day'),
|
41 |
+
$repeat_monthly_specific_day = $('.bookly-js-monthly-specific-day'),
|
42 |
+
$repeat_monthly_week_day = $('.bookly-js-monthly-week-day'),
|
43 |
+
// Step Cart.
|
44 |
+
$show_cart_extras = $('#bookly-show-cart-extras'),
|
45 |
+
// Step details.
|
46 |
+
$required_details = $('#bookly-cst-required-details'),
|
47 |
+
$show_login_button = $('#bookly-show-login-button'),
|
48 |
+
$show_facebook_login_button = $('#bookly-show-facebook-login-button'),
|
49 |
+
$first_last_name = $('#bookly-cst-first-last-name'),
|
50 |
+
$confirm_email = $('#bookly-cst-show-email-confirm'),
|
51 |
+
$show_notes_field = $('#bookly-show-notes'),
|
52 |
+
$show_birthday_fields = $('#bookly-show-birthday'),
|
53 |
+
$show_address_fields = $('#bookly-show-address'),
|
54 |
+
$show_google_maps = $('#bookly-show-google-maps'),
|
55 |
+
$show_custom_fields = $('#bookly-show-custom-fields'),
|
56 |
+
$show_customer_information = $('#bookly-show-customer-information'),
|
57 |
+
$show_files = $('#bookly-show-files'),
|
58 |
+
// Step payment.
|
59 |
+
$show_coupons = $('#bookly-show-coupons'),
|
60 |
+
// Buttons.
|
61 |
+
$save_button = $('#ajax-send-appearance'),
|
62 |
+
$reset_button = $('button[type=reset]'),
|
63 |
+
$checkboxes = $('#bookly-appearance').find('input[type="checkbox"]'),
|
64 |
+
$selects = $('#bookly-appearance').find('select[data-default]')
|
65 |
+
;
|
66 |
+
|
67 |
+
$checkboxes.each(function () {
|
68 |
+
$(this).data('default', $(this).prop('checked'));
|
69 |
+
});
|
70 |
+
// Menu fix for WP 3.8.1
|
71 |
+
$('#toplevel_page_ab-system > ul').css('margin-left', '0px');
|
72 |
+
|
73 |
+
// Apply color from color picker.
|
74 |
+
var applyColor = function() {
|
75 |
+
var color = $color_picker.wpColorPicker('color'),
|
76 |
+
color_important = color + '!important;';
|
77 |
+
$('.bookly-progress-tracker').find('.active').css('color', color).find('.step').css('background', color);
|
78 |
+
$('.bookly-js-mobile-step-1 label').css('color', color);
|
79 |
+
$('.bookly-label-error').css('color', color);
|
80 |
+
$('.bookly-js-actions > a').css('background-color', color);
|
81 |
+
$('.bookly-js-mobile-next-step').css('background', color);
|
82 |
+
$('.bookly-js-week-days label').css('background-color', color);
|
83 |
+
$('.picker__frame').attr('style', 'background: ' + color_important);
|
84 |
+
$('.picker__header').attr('style', 'border-bottom: ' + '1px solid ' + color_important);
|
85 |
+
$('.picker__day').off().mouseenter(function() {
|
86 |
+
$(this).attr('style', 'color: ' + color_important);
|
87 |
+
}).mouseleave(function(){
|
88 |
+
$(this).attr('style', $(this).hasClass('picker__day--selected') ? 'color: ' + color_important : '')
|
89 |
+
});
|
90 |
+
$('.picker__day--selected').attr('style', 'color: ' + color_important);
|
91 |
+
$('.picker__button--clear').attr('style', 'color: ' + color_important);
|
92 |
+
$('.picker__button--today').attr('style', 'color: ' + color_important);
|
93 |
+
$('.bookly-extra-step .bookly-extras-thumb.bookly-extras-selected').css('border-color', color);
|
94 |
+
$('.bookly-columnizer .bookly-day, .bookly-schedule-date,.bookly-pagination li.active').css({
|
95 |
+
'background': color,
|
96 |
+
'border-color': color
|
97 |
+
});
|
98 |
+
$('.bookly-columnizer .bookly-hour').off().hover(
|
99 |
+
function() { // mouse-on
|
100 |
+
$(this).css({
|
101 |
+
'color': color,
|
102 |
+
'border': '2px solid ' + color
|
103 |
+
});
|
104 |
+
$(this).find('.bookly-hour-icon').css({
|
105 |
+
'border-color': color,
|
106 |
+
'color': color
|
107 |
+
});
|
108 |
+
$(this).find('.bookly-hour-icon > span').css({
|
109 |
+
'background': color
|
110 |
+
});
|
111 |
+
},
|
112 |
+
function() { // mouse-out
|
113 |
+
$(this).css({
|
114 |
+
'color': '#333333',
|
115 |
+
'border': '1px solid #cccccc'
|
116 |
+
});
|
117 |
+
$(this).find('.bookly-hour-icon').css({
|
118 |
+
'border-color': '#333333',
|
119 |
+
'color': '#cccccc'
|
120 |
+
});
|
121 |
+
$(this).find('.bookly-hour-icon > span').css({
|
122 |
+
'background': '#cccccc'
|
123 |
+
});
|
124 |
+
}
|
125 |
+
);
|
126 |
+
$('.bookly-details-step label').css('color', color);
|
127 |
+
$('.bookly-card-form label').css('color', color);
|
128 |
+
$('.bookly-nav-tabs .ladda-button, .bookly-nav-steps .ladda-button, .bookly-btn, .bookly-round, .bookly-square').css('background-color', color);
|
129 |
+
$('.bookly-triangle').css('border-bottom-color', color);
|
130 |
+
$('#bookly-pickadate-style').html('.picker__nav--next:before { border-left: 6px solid ' + color_important + ' } .picker__nav--prev:before { border-right: 6px solid ' + color_important + ' }');
|
131 |
+
};
|
132 |
+
|
133 |
+
// Init color picker.
|
134 |
+
$color_picker.wpColorPicker({
|
135 |
+
change : applyColor
|
136 |
+
});
|
137 |
+
|
138 |
+
// Init editable elements.
|
139 |
+
$editableElements.editable();
|
140 |
+
|
141 |
+
// Show progress tracker.
|
142 |
+
$show_progress_tracker.on('change', function() {
|
143 |
+
$('.bookly-progress-tracker').toggle(this.checked);
|
144 |
+
}).trigger('change');
|
145 |
+
|
146 |
+
// Align buttons to the left
|
147 |
+
$align_buttons_left.on('change', function () {
|
148 |
+
if (this.checked) {
|
149 |
+
$('.bookly-nav-steps > div.bookly-right').removeClass('bookly-right').addClass('bookly-left');
|
150 |
+
} else {
|
151 |
+
$('.bookly-nav-steps > div.bookly-left').removeClass('bookly-left').addClass('bookly-right');
|
152 |
+
}
|
153 |
+
});
|
154 |
+
|
155 |
+
// Show steps.
|
156 |
+
$('.bookly-js-show-step').on('change', function () {
|
157 |
+
var target = $(this).data('target'),
|
158 |
+
$button = $('li.bookly-nav-item[data-target="#' + target + '"]'),
|
159 |
+
$step = $('div[data-step="' + target + '"]');
|
160 |
+
if ($(this).prop('checked')) {
|
161 |
+
$button.show();
|
162 |
+
$step.show();
|
163 |
+
} else {
|
164 |
+
if ($button.hasClass('active')) {
|
165 |
+
$('li.bookly-nav-item[data-target="#bookly-step-1"]').trigger('click');
|
166 |
+
}
|
167 |
+
$button.hide();
|
168 |
+
$step.hide();
|
169 |
+
}
|
170 |
+
// Hide/show cart buttons
|
171 |
+
if ( target == 'bookly-step-5') {
|
172 |
+
$('.bookly-js-go-to-cart').toggle( $(this).prop('checked') );
|
173 |
+
}
|
174 |
+
|
175 |
+
$('.bookly-progress-tracker > div:visible').each(function (num) {
|
176 |
+
$(this).find('.bookly-js-step-number').html(num + 1);
|
177 |
+
});
|
178 |
+
$('.bookly-js-appearance-steps > li:visible').each(function (num) {
|
179 |
+
$(this).find('.bookly-js-step-number').html(num + 1);
|
180 |
+
});
|
181 |
+
}).trigger('change');
|
182 |
+
|
183 |
+
// Show step specific settings.
|
184 |
+
$('li.bookly-nav-item').on('shown.bs.tab', function (e) {
|
185 |
+
$step_settings.children().hide();
|
186 |
+
switch (e.target.getAttribute('data-target')) {
|
187 |
+
case '#bookly-step-1': $step_settings.find('.bookly-js-service-settings').show(); break;
|
188 |
+
case '#bookly-step-3': $step_settings.find('.bookly-js-time-settings').show(); break;
|
189 |
+
case '#bookly-step-5': $step_settings.find('.bookly-js-cart-settings').show(); break;
|
190 |
+
case '#bookly-step-6': $step_settings.find('.bookly-js-details-settings').show(); break;
|
191 |
+
case '#bookly-step-7': $step_settings.find('.bookly-js-payment-settings').show(); break;
|
192 |
+
case '#bookly-step-8': $step_settings.find('.bookly-js-done-settings').show(); break;
|
193 |
+
}
|
194 |
+
});
|
195 |
+
|
196 |
+
// Dismiss help notice.
|
197 |
+
$('#bookly-js-hint-alert').on('closed.bs.alert', function () {
|
198 |
+
$.ajax({
|
199 |
+
url: ajaxurl,
|
200 |
+
data: { action: 'bookly_dismiss_appearance_notice', csrf_token : BooklyL10n.csrf_token }
|
201 |
+
});
|
202 |
+
});
|
203 |
+
|
204 |
+
/**
|
205 |
+
* Step Service
|
206 |
+
*/
|
207 |
+
|
208 |
+
// Init calendar.
|
209 |
+
$('.bookly-js-date-from').pickadate({
|
210 |
+
formatSubmit : 'yyyy-mm-dd',
|
211 |
+
format : BooklyL10n.date_format,
|
212 |
+
min : true,
|
213 |
+
clear : false,
|
214 |
+
close : false,
|
215 |
+
today : BooklyL10n.today,
|
216 |
+
weekdaysShort : BooklyL10n.days,
|
217 |
+
monthsFull : BooklyL10n.months,
|
218 |
+
labelMonthNext : BooklyL10n.nextMonth,
|
219 |
+
labelMonthPrev : BooklyL10n.prevMonth,
|
220 |
+
onRender : applyColor,
|
221 |
+
firstDay : BooklyL10n.start_of_week == 1
|
222 |
+
});
|
223 |
+
|
224 |
+
// Show price next to staff member name.
|
225 |
+
$staff_name_with_price.on('change', function () {
|
226 |
+
var staff = $('.bookly-js-select-employee').val();
|
227 |
+
if (staff) {
|
228 |
+
$('.bookly-js-select-employee').val(staff * -1);
|
229 |
+
}
|
230 |
+
$('.employee-name-price').toggle($staff_name_with_price.prop("checked"));
|
231 |
+
$('.employee-name').toggle(!$staff_name_with_price.prop("checked"));
|
232 |
+
}).trigger('change');
|
233 |
+
|
234 |
+
if ($service_duration_with_price.prop("checked")) {
|
235 |
+
$('.bookly-js-select-duration').val(-1);
|
236 |
+
}
|
237 |
+
|
238 |
+
// Show price next to service duration.
|
239 |
+
$service_duration_with_price.on('change', function () {
|
240 |
+
var duration = $('.bookly-js-select-duration').val();
|
241 |
+
if (duration) {
|
242 |
+
$('.bookly-js-select-duration').val(duration * -1);
|
243 |
+
}
|
244 |
+
$('.bookly-js-duration-price').toggle($service_duration_with_price.prop("checked"));
|
245 |
+
$('.bookly-js-duration').toggle(!$service_duration_with_price.prop("checked"));
|
246 |
+
}).trigger('change');
|
247 |
+
|
248 |
+
$show_ratings.on('change', function () {
|
249 |
+
var state = $(this).prop('checked');
|
250 |
+
$('.bookly-js-select-employee option').each(function () {
|
251 |
+
if ($(this).val() != '0') {
|
252 |
+
if (!state) {
|
253 |
+
if ($(this).text().charAt(0) == '★') {
|
254 |
+
$(this).text($(this).text().substring(5));
|
255 |
+
}
|
256 |
+
} else {
|
257 |
+
var rating = Math.round(10 * (Math.random() * 6 + 1)) / 10;
|
258 |
+
if (rating <= 5) {
|
259 |
+
$(this).text('★' + rating.toFixed(1) + ' ' + $(this).text());
|
260 |
+
}
|
261 |
+
}
|
262 |
+
}
|
263 |
+
});
|
264 |
+
}).trigger('change');
|
265 |
+
|
266 |
+
// Show chain appointments
|
267 |
+
$show_chain_appointments.on('change', function () {
|
268 |
+
$('.bookly-js-chain-appointments').toggle( this.checked );
|
269 |
+
});
|
270 |
+
|
271 |
+
// Show location
|
272 |
+
$show_location.on('change', function () {
|
273 |
+
$('.bookly-js-location').toggle( this.checked );
|
274 |
+
if (!this.disabled) {
|
275 |
+
if (this.checked) {
|
276 |
+
$required_location.closest('[data-toggle="popover"]').popover('destroy');
|
277 |
+
$required_location.prop('disabled', false);
|
278 |
+
} else {
|
279 |
+
$required_location.closest('[data-toggle="popover"]').popover();
|
280 |
+
$required_location.prop('checked', false).prop('disabled', true).trigger('change');
|
281 |
+
}
|
282 |
+
}
|
283 |
+
}).trigger('change');
|
284 |
+
|
285 |
+
// Show custom duration
|
286 |
+
$show_custom_duration.on('change', function () {
|
287 |
+
$('.bookly-js-custom-duration').toggle( this.checked );
|
288 |
+
if (this.checked) {
|
289 |
+
$service_duration_with_price.closest('[data-toggle="popover"]').popover('destroy');
|
290 |
+
$service_duration_with_price.prop('disabled', false);
|
291 |
+
} else {
|
292 |
+
$service_duration_with_price.closest('[data-toggle="popover"]').popover();
|
293 |
+
$service_duration_with_price.prop('checked', false).prop('disabled', true).trigger('change');
|
294 |
+
}
|
295 |
+
}).trigger('change');
|
296 |
+
|
297 |
+
// Show number of persons
|
298 |
+
$show_nop.on('change', function () {
|
299 |
+
$('.bookly-js-nop').toggle( this.checked );
|
300 |
+
if (this.checked) {
|
301 |
+
$time_step_nop.closest('[data-toggle="popover"]').popover('destroy');
|
302 |
+
$time_step_nop.prop('disabled', false);
|
303 |
+
} else {
|
304 |
+
$time_step_nop.closest('[data-toggle="popover"]').popover();
|
305 |
+
$time_step_nop.prop('checked', false).prop('disabled', true).trigger('change');
|
306 |
+
}
|
307 |
+
}).trigger('change');
|
308 |
+
|
309 |
+
// Show quantity
|
310 |
+
$show_quantity.on('change', function () {
|
311 |
+
$('.bookly-js-quantity').toggle( this.checked );
|
312 |
+
});
|
313 |
+
|
314 |
+
// Set max quantity
|
315 |
+
$('.bookly_multiply_appointments_quantity_max').on('save', function (e, params) {
|
316 |
+
var $options = '';
|
317 |
+
for (var x = 1; x <= params.newValue['bookly_multiply_appointments_quantity_max']; x++) {
|
318 |
+
$options += "<option>" + x + "</option>";
|
319 |
+
}
|
320 |
+
$('.bookly-js-select-quantity').html($options);
|
321 |
+
});
|
322 |
+
|
323 |
+
// Show duration next to service name.
|
324 |
+
$service_name_with_duration.on('change', function () {
|
325 |
+
var service = $('.bookly-js-select-service').val();
|
326 |
+
if (service) {
|
327 |
+
$('.bookly-js-select-service').val(service * -1);
|
328 |
+
}
|
329 |
+
$('.service-name-duration').toggle($service_name_with_duration.prop("checked"));
|
330 |
+
$('.service-name').toggle(!$service_name_with_duration.prop("checked"));
|
331 |
+
}).trigger('change');
|
332 |
+
|
333 |
+
// Show price next to service duration.
|
334 |
+
$service_duration_with_price.on('change', function () {
|
335 |
+
if ($(this).prop('checked')) {
|
336 |
+
$('.bookly-js-select-duration option[value="1"]').each(function () {
|
337 |
+
$(this).text($(this).attr('data-text-1'));
|
338 |
+
});
|
339 |
+
} else {
|
340 |
+
$('.bookly-js-select-duration option[value="1"]').each(function () {
|
341 |
+
$(this).text($(this).attr('data-text-0'));
|
342 |
+
});
|
343 |
+
}
|
344 |
+
}).trigger('change');
|
345 |
+
|
346 |
+
// Clickable week-days.
|
347 |
+
$repeat_weekly_week_day.on('change', function () {
|
348 |
+
$(this).parent().toggleClass('active', this.checked);
|
349 |
+
});
|
350 |
+
|
351 |
+
|
352 |
+
/**
|
353 |
+
* Step Time
|
354 |
+
*/
|
355 |
+
|
356 |
+
// Init calendar.
|
357 |
+
$time_step_calendar.pickadate({
|
358 |
+
formatSubmit : 'yyyy-mm-dd',
|
359 |
+
format : BooklyL10n.date_format,
|
360 |
+
min : true,
|
361 |
+
weekdaysShort : BooklyL10n.days,
|
362 |
+
monthsFull : BooklyL10n.months,
|
363 |
+
labelMonthNext : BooklyL10n.nextMonth,
|
364 |
+
labelMonthPrev : BooklyL10n.prevMonth,
|
365 |
+
close : false,
|
366 |
+
clear : false,
|
367 |
+
today : false,
|
368 |
+
closeOnSelect : false,
|
369 |
+
onRender : applyColor,
|
370 |
+
firstDay : BooklyL10n.start_of_week == 1,
|
371 |
+
klass : {
|
372 |
+
picker: 'picker picker--opened picker--focused'
|
373 |
+
},
|
374 |
+
onClose : function() {
|
375 |
+
this.open(false);
|
376 |
+
}
|
377 |
+
});
|
378 |
+
$time_step_calendar_wrap.find('.picker__holder').css({ top : '0px', left : '0px' });
|
379 |
+
|
380 |
+
// Show calendar.
|
381 |
+
$show_calendar.on('change', function() {
|
382 |
+
if (this.checked) {
|
383 |
+
$time_step_calendar_wrap.show();
|
384 |
+
$day_multi_columns.find('.col3,.col4,.col5,.col6,.col7').hide();
|
385 |
+
$day_multi_columns.find('.col2 button:gt(0)').attr('style', 'display: none !important');
|
386 |
+
$day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').hide();
|
387 |
+
} else {
|
388 |
+
$time_step_calendar_wrap.hide();
|
389 |
+
$day_multi_columns.find('.col2 button:gt(0)').attr('style', 'display: block !important');
|
390 |
+
$day_multi_columns.find('.col2 button.bookly-js-first-child').attr('style', 'background: ' + $color_picker.wpColorPicker('color') + '!important;display: block !important');
|
391 |
+
$day_multi_columns.find('.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
392 |
+
$day_one_column.find('.col2,.col3,.col4,.col5,.col6,.col7').css('display','inline-block');
|
393 |
+
}
|
394 |
+
}).trigger('change');
|
395 |
+
|
396 |
+
// Show blocked time slots.
|
397 |
+
$show_blocked_timeslots.on('change', function () {
|
398 |
+
if (this.checked) {
|
399 |
+
$('.bookly-hour.no-booked').removeClass('no-booked').addClass('booked');
|
400 |
+
$('.bookly-column .bookly-hour.booked .bookly-time-additional', $columnizer).text('');
|
401 |
+
} else {
|
402 |
+
$('.bookly-hour.booked').removeClass('booked').addClass('no-booked');
|
403 |
+
if ($time_step_nop.prop('checked')) {
|
404 |
+
$('.bookly-column .bookly-hour:not(.booked):not(.bookly-slot-in-waiting-list) .bookly-time-additional', $columnizer).each(function () {
|
405 |
+
var nop = Math.ceil(Math.random() * 9);
|
406 |
+
if (BooklyL10n.nop_format == 'busy') {
|
407 |
+
$(this).text('[' + nop + '/10]');
|
408 |
+
} else {
|
409 |
+
$(this).text('[' + nop + ']');
|
410 |
+
}
|
411 |
+
});
|
412 |
+
}
|
413 |
+
}
|
414 |
+
});
|
415 |
+
|
416 |
+
// Show day as one column.
|
417 |
+
$show_day_one_column.change(function() {
|
418 |
+
if (this.checked) {
|
419 |
+
$day_one_column.show();
|
420 |
+
$day_multi_columns.hide();
|
421 |
+
} else {
|
422 |
+
$day_one_column.hide();
|
423 |
+
$day_multi_columns.show();
|
424 |
+
}
|
425 |
+
});
|
426 |
+
|
427 |
+
// Show time zone switcher
|
428 |
+
$show_time_zone_switcher.on('change', function() {
|
429 |
+
$('.bookly-js-time-zone-switcher').toggle(this.checked);
|
430 |
+
}).trigger('change');
|
431 |
+
|
432 |
+
// Show nop/capacity
|
433 |
+
$time_step_nop.on('change', function () {
|
434 |
+
if (this.checked) {
|
435 |
+
$('.bookly-column', $columnizer).addClass('bookly-column-wide');
|
436 |
+
$('.bookly-column .bookly-hour:not(.booked):not(.bookly-slot-in-waiting-list) .bookly-time-additional', $columnizer).each(function () {
|
437 |
+
var nop = Math.ceil(Math.random() * 9);
|
438 |
+
if (BooklyL10n.nop_format == 'busy') {
|
439 |
+
$(this).text('[' + nop + '/10]');
|
440 |
+
} else {
|
441 |
+
$(this).text('[' + nop + ']');
|
442 |
+
}
|
443 |
+
});
|
444 |
+
$('.bookly-column.col5', $columnizer).hide();
|
445 |
+
$('.bookly-column.col6', $columnizer).hide();
|
446 |
+
$('.bookly-column.col7', $columnizer).hide();
|
447 |
+
} else {
|
448 |
+
$('.bookly-column', $columnizer).removeClass('bookly-column-wide');
|
449 |
+
$('.bookly-column .bookly-hour:not(.bookly-slot-in-waiting-list) .bookly-time-additional', $columnizer).text('');
|
450 |
+
if (!$show_calendar.prop('checked')) {
|
451 |
+
$('.bookly-column', $columnizer).removeClass('bookly-column-wide').show();
|
452 |
+
}
|
453 |
+
}
|
454 |
+
}).trigger('change');
|
455 |
+
|
456 |
+
$show_waiting_list.on('change', function () {
|
457 |
+
if (this.checked) {
|
458 |
+
$('.bookly-column .bookly-hour.no-waiting-list, .bookly-column .bookly-hour.bookly-slot-in-waiting-list').each(function () {
|
459 |
+
$(this).removeClass('no-waiting-list').addClass('bookly-slot-in-waiting-list').find('.bookly-time-additional').text('(' + Math.floor(Math.random() * 10) + ')');
|
460 |
+
})
|
461 |
+
} else {
|
462 |
+
$('.bookly-column .bookly-hour.bookly-slot-in-waiting-list').removeClass('bookly-slot-in-waiting-list').addClass('no-waiting-list').find('.bookly-time-additional').text('');
|
463 |
+
$time_step_nop.trigger('change');
|
464 |
+
}
|
465 |
+
}).trigger('change');
|
466 |
+
|
467 |
+
/**
|
468 |
+
* Step repeat.
|
469 |
+
*/
|
470 |
+
|
471 |
+
// Init calendar.
|
472 |
+
$repeat_step_calendar.pickadate({
|
473 |
+
formatSubmit : 'yyyy-mm-dd',
|
474 |
+
format : BooklyL10n.date_format,
|
475 |
+
min : true,
|
476 |
+
clear : false,
|
477 |
+
close : false,
|
478 |
+
today : BooklyL10n.today,
|
479 |
+
weekdaysShort : BooklyL10n.days,
|
480 |
+
monthsFull : BooklyL10n.months,
|
481 |
+
labelMonthNext : BooklyL10n.nextMonth,
|
482 |
+
labelMonthPrev : BooklyL10n.prevMonth,
|
483 |
+
onRender : applyColor,
|
484 |
+
firstDay : BooklyL10n.start_of_week == 1
|
485 |
+
});
|
486 |
+
$repeat_variant.on('change', function () {
|
487 |
+
$repeat_variants.hide();
|
488 |
+
$('.bookly-js-variant-' + this.value).show()
|
489 |
+
}).trigger('change');
|
490 |
+
|
491 |
+
$repeat_variant_monthly.on('change', function () {
|
492 |
+
$repeat_monthly_week_day.toggle(this.value != 'specific');
|
493 |
+
$repeat_monthly_specific_day.toggle(this.value == 'specific');
|
494 |
+
}).trigger('change');
|
495 |
+
|
496 |
+
$repeat_weekly_week_day.on('change', function () {
|
497 |
+
var $this = $(this);
|
498 |
+
if ($this.is(':checked')) {
|
499 |
+
$this.parent().not("[class*='active']").addClass('active');
|
500 |
+
} else {
|
501 |
+
$this.parent().removeClass('active');
|
502 |
+
}
|
503 |
+
});
|
504 |
+
|
505 |
+
|
506 |
+
/**
|
507 |
+
* Step Repeat.
|
508 |
+
*/
|
509 |
+
$bookly_show_step_repeat.change(function () {
|
510 |
+
$('.bookly-js-repeat-enabled').toggle(this.checked);
|
511 |
+
}).trigger('change');
|
512 |
+
|
513 |
+
/**
|
514 |
+
* Step Cart
|
515 |
+
*/
|
516 |
+
$show_cart_extras.change(function () {
|
517 |
+
$('.bookly-js-extras-cart').toggle(this.checked);
|
518 |
+
}).trigger('change');
|
519 |
+
|
520 |
+
/**
|
521 |
+
* Step Details
|
522 |
+
*/
|
523 |
+
|
524 |
+
// Init phone field.
|
525 |
+
if (BooklyL10n.intlTelInput.enabled) {
|
526 |
+
$('.bookly-user-phone').intlTelInput({
|
527 |
+
preferredCountries: [BooklyL10n.intlTelInput.country],
|
528 |
+
initialCountry: BooklyL10n.intlTelInput.country,
|
529 |
+
geoIpLookup: function (callback) {
|
530 |
+
$.get('https://ipinfo.io', function() {}, 'jsonp').always(function(resp) {
|
531 |
+
var countryCode = (resp && resp.country) ? resp.country : '';
|
532 |
+
callback(countryCode);
|
533 |
+
});
|
534 |
+
},
|
535 |
+
utilsScript: BooklyL10n.intlTelInput.utils
|
536 |
+
});
|
537 |
+
}
|
538 |
+
|
539 |
+
// Show login button.
|
540 |
+
$show_login_button.change(function () {
|
541 |
+
$('#bookly-login-button').toggle(this.checked);
|
542 |
+
}).trigger('change');
|
543 |
+
|
544 |
+
// Show Facebook login button.
|
545 |
+
$show_facebook_login_button.change(function () {
|
546 |
+
if ($(this).data('appid') == '') {
|
547 |
+
$('#bookly-facebook-warning').modal('show');
|
548 |
+
this.checked = false;
|
549 |
+
} else {
|
550 |
+
$('#bookly-facebook-login-button').toggle(this.checked);
|
551 |
+
}
|
552 |
+
});
|
553 |
+
|
554 |
+
if ($show_facebook_login_button.prop('checked')) {
|
555 |
+
$show_facebook_login_button.trigger('change');
|
556 |
+
}
|
557 |
+
|
558 |
+
// Show first and last name.
|
559 |
+
$first_last_name.on('change', function () {
|
560 |
+
$first_last_name.popover('toggle');
|
561 |
+
if (this.checked) {
|
562 |
+
$('.bookly-js-details-full-name').addClass('collapse');
|
563 |
+
$('.bookly-js-details-first-last-name').removeClass('collapse');
|
564 |
+
if ($confirm_email.is(':checked')) {
|
565 |
+
$('.bookly-js-details-email').removeClass('collapse');
|
566 |
+
$('.bookly-js-details-confirm').removeClass('collapse');
|
567 |
+
$('.bookly-js-details-email-confirm').addClass('collapse');
|
568 |
+
} else {
|
569 |
+
$('.bookly-js-details-email').removeClass('collapse');
|
570 |
+
$('.bookly-js-details-confirm').addClass('collapse');
|
571 |
+
$('.bookly-js-details-email-confirm').addClass('collapse');
|
572 |
+
}
|
573 |
+
} else {
|
574 |
+
$('.bookly-js-details-full-name').removeClass('collapse');
|
575 |
+
$('.bookly-js-details-first-last-name').addClass('collapse');
|
576 |
+
if ($confirm_email.is(':checked')) {
|
577 |
+
$('.bookly-js-details-email').addClass('collapse');
|
578 |
+
$('.bookly-js-details-confirm').addClass('collapse');
|
579 |
+
$('.bookly-js-details-email-confirm').removeClass('collapse');
|
580 |
+
} else {
|
581 |
+
$('.bookly-js-details-email').removeClass('collapse');
|
582 |
+
$('.bookly-js-details-confirm').addClass('collapse');
|
583 |
+
$('.bookly-js-details-email-confirm').addClass('collapse');
|
584 |
+
}
|
585 |
+
}
|
586 |
+
});
|
587 |
+
|
588 |
+
// Show first and last name.
|
589 |
+
$confirm_email.on('change', function () {
|
590 |
+
if (this.checked) {
|
591 |
+
if ($first_last_name.is(':checked')) {
|
592 |
+
$('.bookly-js-details-email').removeClass('collapse');
|
593 |
+
$('.bookly-js-details-confirm').removeClass('collapse');
|
594 |
+
$('.bookly-js-details-email-confirm').addClass('collapse');
|
595 |
+
} else {
|
596 |
+
$('.bookly-js-details-email').addClass('collapse');
|
597 |
+
$('.bookly-js-details-confirm').addClass('collapse');
|
598 |
+
$('.bookly-js-details-email-confirm').removeClass('collapse');
|
599 |
+
}
|
600 |
+
} else {
|
601 |
+
if ($first_last_name.is(':checked')) {
|
602 |
+
$('.bookly-js-details-email').removeClass('collapse');
|
603 |
+
$('.bookly-js-details-confirm').addClass('collapse');
|
604 |
+
$('.bookly-js-details-email-confirm').addClass('collapse');
|
605 |
+
} else {
|
606 |
+
$('.bookly-js-details-email').removeClass('collapse');
|
607 |
+
$('.bookly-js-details-confirm').addClass('collapse');
|
608 |
+
$('.bookly-js-details-email-confirm').addClass('collapse');
|
609 |
+
}
|
610 |
+
}
|
611 |
+
});
|
612 |
+
|
613 |
+
// Show notes field.
|
614 |
+
$show_notes_field.change(function () {
|
615 |
+
$('#bookly-js-notes').toggle(this.checked);
|
616 |
+
}).trigger('change');
|
617 |
+
|
618 |
+
// Show birthday fields
|
619 |
+
$show_birthday_fields.change(function () {
|
620 |
+
$('#bookly-js-birthday').toggle(this.checked);
|
621 |
+
}).trigger('change');
|
622 |
+
|
623 |
+
// Show address fields
|
624 |
+
$show_address_fields.change(function () {
|
625 |
+
$('#bookly-js-address').toggle(this.checked);
|
626 |
+
if (this.checked) {
|
627 |
+
$show_google_maps.closest('[data-toggle="popover"]').popover('destroy');
|
628 |
+
$show_google_maps.prop('disabled', false);
|
629 |
+
} else {
|
630 |
+
$show_google_maps.closest('[data-toggle="popover"]').popover();
|
631 |
+
$show_google_maps.prop('checked', false).prop('disabled', true).trigger('change');
|
632 |
+
}
|
633 |
+
}).trigger('change');
|
634 |
+
|
635 |
+
// Show address fields
|
636 |
+
$show_google_maps.change(function () {
|
637 |
+
$('.bookly-js-google-maps').toggle(this.checked);
|
638 |
+
}).trigger('change');
|
639 |
+
|
640 |
+
$show_custom_fields.change(function () {
|
641 |
+
$('.bookly-js-custom-fields').toggle(this.checked);
|
642 |
+
if (this.checked) {
|
643 |
+
$show_files.closest('[data-toggle="popover"]').popover('destroy');
|
644 |
+
$show_files.prop('disabled', false);
|
645 |
+
} else {
|
646 |
+
$show_files.closest('[data-toggle="popover"]').popover();
|
647 |
+
$show_files.prop('checked', false).prop('disabled', true).trigger('change');
|
648 |
+
}
|
649 |
+
}).trigger('change');
|
650 |
+
|
651 |
+
$show_files.change(function () {
|
652 |
+
$('.bookly-js-files').toggle(this.checked);
|
653 |
+
}).trigger('change');
|
654 |
+
|
655 |
+
$show_customer_information.change(function () {
|
656 |
+
$('.bookly-js-customer-information').toggle(this.checked);
|
657 |
+
}).trigger('change');
|
658 |
+
|
659 |
+
/**
|
660 |
+
* Step Payment.
|
661 |
+
*/
|
662 |
+
|
663 |
+
// Switch payment step view (single/several services).
|
664 |
+
$('#bookly-payment-step-view').on('change', function () {
|
665 |
+
$('.bookly-js-payment-single-app').toggle(this.value == 'single-app');
|
666 |
+
$('.bookly-js-payment-several-apps').toggle(this.value == 'several-apps');
|
667 |
+
});
|
668 |
+
|
669 |
+
// Show credit card form.
|
670 |
+
$('.bookly-payment-nav :radio').on('change', function () {
|
671 |
+
$('form.bookly-card-form').toggle(this.id == 'bookly-card-payment');
|
672 |
+
});
|
673 |
+
|
674 |
+
$show_coupons.on('change', function () {
|
675 |
+
$('.bookly-js-payment-coupons').toggle( this.checked );
|
676 |
+
});
|
677 |
+
|
678 |
+
/**
|
679 |
+
* Step Done.
|
680 |
+
*/
|
681 |
+
|
682 |
+
// Switch done step view (success/error).
|
683 |
+
$('#bookly-done-step-view').on('change', function () {
|
684 |
+
$('.bookly-js-done-success').toggle(this.value == 'booking-success');
|
685 |
+
$('.bookly-js-done-limit-error').toggle(this.value == 'booking-limit-error');
|
686 |
+
$('.bookly-js-done-processing').toggle(this.value == 'booking-processing');
|
687 |
+
});
|
688 |
+
|
689 |
+
|
690 |
+
/**
|
691 |
+
* Misc.
|
692 |
+
*/
|
693 |
+
$('.bookly-js-simple-popover').popover();
|
694 |
+
|
695 |
+
// Custom CSS.
|
696 |
+
$('#bookly-custom-css-save').on('click', function (e) {
|
697 |
+
var $custom_css = $('#bookly-custom-css'),
|
698 |
+
$modal = $('#bookly-custom-css-dialog');
|
699 |
+
|
700 |
+
saved_css = $custom_css.val();
|
701 |
+
|
702 |
+
var ladda = Ladda.create(this);
|
703 |
+
ladda.start();
|
704 |
+
|
705 |
+
$.ajax({
|
706 |
+
url : ajaxurl,
|
707 |
+
type : 'POST',
|
708 |
+
data : {
|
709 |
+
action : 'bookly_save_custom_css',
|
710 |
+
csrf_token : BooklyL10n.csrf_token,
|
711 |
+
custom_css : $custom_css.val()
|
712 |
+
},
|
713 |
+
dataType : 'json',
|
714 |
+
success : function (response) {
|
715 |
+
if (response.success) {
|
716 |
+
$modal.modal('hide');
|
717 |
+
booklyAlert({success : [response.data.message]});
|
718 |
+
}
|
719 |
+
},
|
720 |
+
complete : function () {
|
721 |
+
ladda.stop();
|
722 |
+
}
|
723 |
+
});
|
724 |
+
});
|
725 |
+
|
726 |
+
$('#bookly-custom-css-cancel').on('click', function (e) {
|
727 |
+
var $custom_css = $('#bookly-custom-css'),
|
728 |
+
$modal = $('#bookly-custom-css-dialog');
|
729 |
+
|
730 |
+
$modal.modal('hide');
|
731 |
+
|
732 |
+
$custom_css.val(saved_css);
|
733 |
+
});
|
734 |
+
|
735 |
+
$('#bookly-custom-css').keydown(function(e) {
|
736 |
+
if(e.keyCode === 9) { //tab button
|
737 |
+
var start = this.selectionStart;
|
738 |
+
var end = this.selectionEnd;
|
739 |
+
|
740 |
+
var $this = $(this);
|
741 |
+
var value = $this.val();
|
742 |
+
|
743 |
+
$this.val(value.substring(0, start)
|
744 |
+
+ "\t"
|
745 |
+
+ value.substring(end));
|
746 |
+
|
747 |
+
this.selectionStart = this.selectionEnd = start + 1;
|
748 |
+
|
749 |
+
e.preventDefault();
|
750 |
+
}
|
751 |
+
});
|
752 |
+
|
753 |
+
// Save options.
|
754 |
+
$save_button.on('click', function (e) {
|
755 |
+
e.preventDefault();
|
756 |
+
// Prepare data.
|
757 |
+
var data = {
|
758 |
+
action : 'bookly_update_appearance_options',
|
759 |
+
csrf_token: BooklyL10n.csrf_token,
|
760 |
+
options : {
|
761 |
+
// Color.
|
762 |
+
'bookly_app_color' : $color_picker.wpColorPicker('color'),
|
763 |
+
// Checkboxes.
|
764 |
+
'bookly_app_service_name_with_duration' : Number($service_name_with_duration.prop('checked')),
|
765 |
+
'bookly_app_show_blocked_timeslots' : Number($show_blocked_timeslots.prop('checked')),
|
766 |
+
'bookly_app_show_calendar' : Number($show_calendar.prop('checked')),
|
767 |
+
'bookly_app_show_day_one_column' : Number($show_day_one_column.prop('checked')),
|
768 |
+
'bookly_app_show_time_zone_switcher' : Number($show_time_zone_switcher.prop('checked')),
|
769 |
+
'bookly_app_show_login_button' : Number($show_login_button.prop('checked')),
|
770 |
+
'bookly_app_show_facebook_login_button' : Number($show_facebook_login_button.prop('checked')),
|
771 |
+
'bookly_app_show_notes' : Number($show_notes_field.prop('checked')),
|
772 |
+
'bookly_app_show_birthday' : Number($show_birthday_fields.prop('checked')),
|
773 |
+
'bookly_app_show_address' : Number($show_address_fields.prop('checked')),
|
774 |
+
'bookly_app_show_progress_tracker' : Number($show_progress_tracker.prop('checked')),
|
775 |
+
'bookly_app_align_buttons_left' : Number($align_buttons_left.prop('checked')),
|
776 |
+
'bookly_app_staff_name_with_price' : Number($staff_name_with_price.prop('checked')),
|
777 |
+
'bookly_app_service_duration_with_price': Number($service_duration_with_price.prop('checked')),
|
778 |
+
'bookly_app_required_employee' : Number($required_employee.prop('checked')),
|
779 |
+
'bookly_app_required_location' : Number($required_location.prop('checked')),
|
780 |
+
'bookly_group_booking_app_show_nop' : Number($time_step_nop.prop('checked')),
|
781 |
+
'bookly_ratings_app_show_on_frontend' : Number($show_ratings.prop('checked')),
|
782 |
+
'bookly_cst_required_details' : $required_details.val() == 'both' ? ['phone', 'email'] : [$required_details.val()],
|
783 |
+
'bookly_cst_first_last_name' : Number($first_last_name.prop('checked')),
|
784 |
+
'bookly_app_show_email_confirm' : Number($confirm_email.prop('checked')),
|
785 |
+
'bookly_service_extras_enabled' : Number($bookly_show_step_extras.prop('checked')),
|
786 |
+
'bookly_recurring_appointments_enabled' : Number($bookly_show_step_repeat.prop('checked')),
|
787 |
+
'bookly_cart_enabled' : Number($bookly_show_step_cart.prop('checked')),
|
788 |
+
'bookly_chain_appointments_enabled' : Number($show_chain_appointments.prop('checked')),
|
789 |
+
'bookly_coupons_enabled' : Number($show_coupons.prop('checked')),
|
790 |
+
'bookly_custom_fields_enabled' : Number($show_custom_fields.prop('checked')),
|
791 |
+
'bookly_customer_information_enabled' : Number($show_customer_information.prop('checked')),
|
792 |
+
'bookly_files_enabled' : Number($show_files.prop('checked')),
|
793 |
+
'bookly_waiting_list_enabled' : Number($show_waiting_list.prop('checked')),
|
794 |
+
'bookly_google_maps_address_enabled' : Number($show_google_maps.prop('checked')),
|
795 |
+
'bookly_service_extras_show_in_cart' : Number($show_cart_extras.prop('checked')),
|
796 |
+
'bookly_locations_enabled' : Number($show_location.prop('checked')),
|
797 |
+
'bookly_custom_duration_enabled' : Number($show_custom_duration.prop('checked')),
|
798 |
+
'bookly_group_booking_enabled' : Number($show_nop.prop('checked')),
|
799 |
+
'bookly_multiply_appointments_enabled' : Number($show_quantity.prop('checked'))
|
800 |
+
}
|
801 |
+
};
|
802 |
+
// Add data from editable elements.
|
803 |
+
$editableElements.each(function () {
|
804 |
+
$.extend(data.options, $(this).editable('getValue', true));
|
805 |
+
});
|
806 |
+
|
807 |
+
// Update data and show spinner while updating.
|
808 |
+
var ladda = Ladda.create(this);
|
809 |
+
ladda.start();
|
810 |
+
$.post(ajaxurl, data, function (response) {
|
811 |
+
ladda.stop();
|
812 |
+
booklyAlert({success : [BooklyL10n.saved]});
|
813 |
+
});
|
814 |
+
});
|
815 |
+
|
816 |
+
// Reset options to defaults.
|
817 |
+
$reset_button.on('click', function() {
|
818 |
+
// Reset color.
|
819 |
+
$color_picker.wpColorPicker('color', $color_picker.data('selected'));
|
820 |
+
|
821 |
+
// Reset editable texts.
|
822 |
+
$editableElements.each(function () {
|
823 |
+
$(this).editable('setValue', $.extend({}, $(this).data('values')));
|
824 |
+
});
|
825 |
+
|
826 |
+
$checkboxes.each(function () {
|
827 |
+
if ($(this).prop('checked') != $(this).data('default')) {
|
828 |
+
$(this).prop('checked', $(this).data('default')).trigger('change');
|
829 |
+
}
|
830 |
+
});
|
831 |
+
$selects.each(function () {
|
832 |
+
if ($(this).val() != $(this).data('default')) {
|
833 |
+
$(this).val($(this).data('default')).trigger('change');
|
834 |
+
}
|
835 |
+
});
|
836 |
+
$first_last_name.popover('hide');
|
837 |
+
});
|
838 |
});
|
backend/modules/appearance/resources/js/bootstrap-editable.bookly.js
CHANGED
@@ -1,125 +1,125 @@
|
|
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
|
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 |
-
switch (_this.options.fieldType) {
|
36 |
-
case 'input':
|
37 |
-
// Create input with "x" button.
|
38 |
-
var $clear = $('<span class="editable-clear-x"></span>');
|
39 |
-
var $input = $('<input/>', {
|
40 |
-
type : 'text',
|
41 |
-
class: 'form-control',
|
42 |
-
name : option_name,
|
43 |
-
value: option_value
|
44 |
-
});
|
45 |
-
$input.keyup(function(e) {
|
46 |
-
// arrows, enter, tab, etc
|
47 |
-
if (~$.inArray(e.keyCode, [40,38,9,13,27])) {
|
48 |
-
return;
|
49 |
-
}
|
50 |
-
clearTimeout(this.t);
|
51 |
-
this.t = setTimeout(function() {
|
52 |
-
var len = $input.val().length,
|
53 |
-
visible = $clear.is(':visible');
|
54 |
-
if (len && !visible) {
|
55 |
-
$clear.show();
|
56 |
-
}
|
57 |
-
if (!len && visible) {
|
58 |
-
$clear.hide();
|
59 |
-
}
|
60 |
-
}, 100);
|
61 |
-
});
|
62 |
-
$clear.click(function () {
|
63 |
-
$clear.hide();
|
64 |
-
$input.val('').focus();
|
65 |
-
});
|
66 |
-
$row.append($input).append($clear);
|
67 |
-
break;
|
68 |
-
case 'number':
|
69 |
-
// Create input[type="number"]
|
70 |
-
$('<input/>', {
|
71 |
-
type : 'number',
|
72 |
-
class: 'form-control',
|
73 |
-
name : option_name,
|
74 |
-
min : $(_this.options.scope).data('min'),
|
75 |
-
step : $(_this.options.scope).data('step')
|
76 |
-
}).val(option_value).appendTo($row);
|
77 |
-
break;
|
78 |
-
default :
|
79 |
-
// Create textarea.
|
80 |
-
$('<textarea/>', {
|
81 |
-
class: 'form-control',
|
82 |
-
name : option_name,
|
83 |
-
rows : 7
|
84 |
-
}).val(option_value).appendTo($row);
|
85 |
-
break;
|
86 |
-
}
|
87 |
-
});
|
88 |
-
// Set codes.
|
89 |
-
this.$tpl.closest('form').find('.bookly-js-codes').html($(this.options.scope).data('codes'));
|
90 |
-
},
|
91 |
-
input2value: function () {
|
92 |
-
var _this = this;
|
93 |
-
var values = {};
|
94 |
-
this.$tpl.find(':input').each(function () {
|
95 |
-
values[this.name] = this.value;
|
96 |
-
// Find all elements which display option value.
|
97 |
-
var option_name = this.name;
|
98 |
-
var option_value = this.value;
|
99 |
-
$('.bookly-js-option.' + option_name).each(function () {
|
100 |
-
var $this = $(this);
|
101 |
-
if ($this.hasClass('editable') && !$this.is(_this.$tpl)) {
|
102 |
-
// Update editable value.
|
103 |
-
var val = $this.editable('getValue', true);
|
104 |
-
val[option_name] = option_value;
|
105 |
-
$this.editable('setValue', val);
|
106 |
-
}
|
107 |
-
});
|
108 |
-
});
|
109 |
-
|
110 |
-
return values;
|
111 |
-
}
|
112 |
-
});
|
113 |
-
|
114 |
-
Bookly.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
115 |
-
tpl: '<div/>',
|
116 |
-
fieldType: 'input'
|
117 |
-
});
|
118 |
-
|
119 |
-
$.fn.editabletypes.bookly = Bookly;
|
120 |
-
|
121 |
-
// Set template for popovers and editable form.
|
122 |
-
$.fn.popover.Constructor.DEFAULTS.template = '<div class="popover"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>';
|
123 |
-
$.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>';
|
124 |
-
$.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>';
|
125 |
});
|
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[data-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 |
+
switch (_this.options.fieldType) {
|
36 |
+
case 'input':
|
37 |
+
// Create input with "x" button.
|
38 |
+
var $clear = $('<span class="editable-clear-x"></span>');
|
39 |
+
var $input = $('<input/>', {
|
40 |
+
type : 'text',
|
41 |
+
class: 'form-control',
|
42 |
+
name : option_name,
|
43 |
+
value: option_value
|
44 |
+
});
|
45 |
+
$input.keyup(function(e) {
|
46 |
+
// arrows, enter, tab, etc
|
47 |
+
if (~$.inArray(e.keyCode, [40,38,9,13,27])) {
|
48 |
+
return;
|
49 |
+
}
|
50 |
+
clearTimeout(this.t);
|
51 |
+
this.t = setTimeout(function() {
|
52 |
+
var len = $input.val().length,
|
53 |
+
visible = $clear.is(':visible');
|
54 |
+
if (len && !visible) {
|
55 |
+
$clear.show();
|
56 |
+
}
|
57 |
+
if (!len && visible) {
|
58 |
+
$clear.hide();
|
59 |
+
}
|
60 |
+
}, 100);
|
61 |
+
});
|
62 |
+
$clear.click(function () {
|
63 |
+
$clear.hide();
|
64 |
+
$input.val('').focus();
|
65 |
+
});
|
66 |
+
$row.append($input).append($clear);
|
67 |
+
break;
|
68 |
+
case 'number':
|
69 |
+
// Create input[type="number"]
|
70 |
+
$('<input/>', {
|
71 |
+
type : 'number',
|
72 |
+
class: 'form-control',
|
73 |
+
name : option_name,
|
74 |
+
min : $(_this.options.scope).data('min'),
|
75 |
+
step : $(_this.options.scope).data('step')
|
76 |
+
}).val(option_value).appendTo($row);
|
77 |
+
break;
|
78 |
+
default :
|
79 |
+
// Create textarea.
|
80 |
+
$('<textarea/>', {
|
81 |
+
class: 'form-control',
|
82 |
+
name : option_name,
|
83 |
+
rows : 7
|
84 |
+
}).val(option_value).appendTo($row);
|
85 |
+
break;
|
86 |
+
}
|
87 |
+
});
|
88 |
+
// Set codes.
|
89 |
+
this.$tpl.closest('form').find('.bookly-js-codes').html($(this.options.scope).data('codes'));
|
90 |
+
},
|
91 |
+
input2value: function () {
|
92 |
+
var _this = this;
|
93 |
+
var values = {};
|
94 |
+
this.$tpl.find(':input').each(function () {
|
95 |
+
values[this.name] = this.value;
|
96 |
+
// Find all elements which display option value.
|
97 |
+
var option_name = this.name;
|
98 |
+
var option_value = this.value;
|
99 |
+
$('.bookly-js-option.' + option_name).each(function () {
|
100 |
+
var $this = $(this);
|
101 |
+
if ($this.hasClass('editable') && !$this.is(_this.$tpl)) {
|
102 |
+
// Update editable value.
|
103 |
+
var val = $this.editable('getValue', true);
|
104 |
+
val[option_name] = option_value;
|
105 |
+
$this.editable('setValue', val);
|
106 |
+
}
|
107 |
+
});
|
108 |
+
});
|
109 |
+
|
110 |
+
return values;
|
111 |
+
}
|
112 |
+
});
|
113 |
+
|
114 |
+
Bookly.defaults = $.extend({}, $.fn.editabletypes.abstractinput.defaults, {
|
115 |
+
tpl: '<div/>',
|
116 |
+
fieldType: 'input'
|
117 |
+
});
|
118 |
+
|
119 |
+
$.fn.editabletypes.bookly = Bookly;
|
120 |
+
|
121 |
+
// Set template for popovers and editable form.
|
122 |
+
$.fn.popover.Constructor.DEFAULTS.template = '<div class="popover"><div class="popover-arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>';
|
123 |
+
$.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>';
|
124 |
+
$.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>';
|
125 |
});
|
backend/modules/appearance/resources/js/bootstrap-editable.min.js
CHANGED
@@ -1,7 +1,7 @@
|
|
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 */
|
5 |
-
!function(a){"use strict";var b=function(b,c){this.options=a.extend({},a.fn.editableform.defaults,c),this.$div=a(b),this.options.scope||(this.options.scope=this)};b.prototype={constructor:b,initInput:function(){this.input=this.options.input,this.value=this.input.str2value(this.options.value),this.input.prerender()},initTemplate:function(){this.$form=a(a.fn.editableform.template)},initButtons:function(){var b=this.$form.find(".editable-buttons");b.append(a.fn.editableform.buttons),"bottom"===this.options.showbuttons&&b.addClass("editable-buttons-bottom")},render:function(){this.$loading=a(a.fn.editableform.loading),this.$div.empty().append(this.$loading),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.showLoading(),this.isSaving=!1,this.$div.triggerHandler("rendering"),this.initInput(),this.$form.find("div.editable-input").append(this.input.$tpl),this.$div.append(this.$form),a.when(this.input.render()).then(a.proxy(function(){if(this.options.showbuttons||this.input.autosubmit(),this.$form.find(".editable-cancel").click(a.proxy(this.cancel,this)),this.input.error)this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(a){a.preventDefault()});else{this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled");var b=null===this.value||void 0===this.value||""===this.value?this.options.defaultValue:this.value;this.input.value2input(b),this.$form.submit(a.proxy(this.submit,this))}this.$div.triggerHandler("rendered"),this.showForm(),this.input.postrender&&this.input.postrender()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var a,b;this.$form?(a=this.$form.outerWidth(),b=this.$form.outerHeight(),a&&this.$loading.width(a),b&&this.$loading.height(b),this.$form.hide()):(a=this.$loading.parent().width(),a&&this.$loading.width(a)),this.$loading.show()},showForm:function(a){this.$loading.hide(),this.$form.show(),a!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(b){var c,d=this.$form.find(".control-group"),e=this.$form.find(".editable-error-block");if(b===!1)d.removeClass(a.fn.editableform.errorGroupClass),e.removeClass(a.fn.editableform.errorBlockClass).empty().hide();else{if(b){c=(""+b).split("\n");for(var f=0;f<c.length;f++)c[f]=a("<div>").text(c[f]).html();b=c.join("<br>")}d.addClass(a.fn.editableform.errorGroupClass),e.addClass(a.fn.editableform.errorBlockClass).html(b).show()}},submit:function(b){b.stopPropagation(),b.preventDefault();var c=this.input.input2value(),d=this.validate(c);if("object"===a.type(d)&&void 0!==d.newValue){if(c=d.newValue,this.input.value2input(c),"string"==typeof d.msg)return this.error(d.msg),this.showForm(),void 0}else if(d)return this.error(d),this.showForm(),void 0;if(!this.options.savenochange&&this.input.value2str(c)==this.input.value2str(this.value))return this.$div.triggerHandler("nochange"),void 0;var e=this.input.value2submit(c);this.isSaving=!0,a.when(this.save(e)).done(a.proxy(function(a){this.isSaving=!1;var b="function"==typeof this.options.success?this.options.success.call(this.options.scope,a,c):null;return b===!1?(this.error(!1),this.showForm(!1),void 0):"string"==typeof b?(this.error(b),this.showForm(),void 0):(b&&"object"==typeof b&&b.hasOwnProperty("newValue")&&(c=b.newValue),this.error(!1),this.value=c,this.$div.triggerHandler("save",{newValue:c,submitValue:e,response:a}),void 0)},this)).fail(a.proxy(function(a){this.isSaving=!1;var b;b="function"==typeof this.options.error?this.options.error.call(this.options.scope,a,c):"string"==typeof a?a:a.responseText||a.statusText||"Unknown error!",this.error(b),this.showForm()},this))},save:function(b){this.options.pk=a.fn.editableutils.tryParseJson(this.options.pk,!0);var c,d="function"==typeof this.options.pk?this.options.pk.call(this.options.scope):this.options.pk,e=!!("function"==typeof this.options.url||this.options.url&&("always"===this.options.send||"auto"===this.options.send&&null!==d&&void 0!==d));return e?(this.showLoading(),c={name:this.options.name||"",value:b,pk:d},"function"==typeof this.options.params?c=this.options.params.call(this.options.scope,c):(this.options.params=a.fn.editableutils.tryParseJson(this.options.params,!0),a.extend(c,this.options.params)),"function"==typeof this.options.url?this.options.url.call(this.options.scope,c):a.ajax(a.extend({url:this.options.url,data:c,type:"POST"},this.options.ajaxOptions))):void 0},validate:function(a){return void 0===a&&(a=this.value),"function"==typeof this.options.validate?this.options.validate.call(this.options.scope,a):void 0},option:function(a,b){a in this.options&&(this.options[a]=b),"value"===a&&this.setValue(b)},setValue:function(a,b){this.value=b?this.input.str2value(a):a,this.$form&&this.$form.is(":visible")&&this.input.value2input(this.value)}},a.fn.editableform=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("editableform"),g="object"==typeof c&&c;f||e.data("editableform",f=new b(this,g)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.editableform.Constructor=b,a.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,defaultValue:null,send:"auto",validate:null,success:null,error:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},a.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',a.fn.editableform.loading='<div class="editableform-loading"></div>',a.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',a.fn.editableform.errorGroupClass=null,a.fn.editableform.errorBlockClass="editable-error",a.fn.editableform.engine="jquery"}(window.jQuery),function(a){"use strict";a.fn.editableutils={inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a,a.superclass=b.prototype},setCursorPosition:function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",b),c.select()}},tryParseJson:function(a,b){if("string"==typeof a&&a.length&&a.match(/^[\{\[].*[\}\]]$/))if(b)try{a=new Function("return "+a)()}catch(c){}finally{return a}else a=new Function("return "+a)();return a},sliceObj:function(b,c,d){var e,f,g={};if(!a.isArray(c)||!c.length)return g;for(var h=0;h<c.length;h++)e=c[h],b.hasOwnProperty(e)&&(g[e]=b[e]),d!==!0&&(f=e.toLowerCase(),b.hasOwnProperty(f)&&(g[e]=b[f]));return g},getConfigData:function(b){var c={};return a.each(b.data(),function(a,b){("object"!=typeof b||b&&"object"==typeof b&&(b.constructor===Object||b.constructor===Array))&&(c[a]=b)}),c},objectKeys:function(a){if(Object.keys)return Object.keys(a);if(a!==Object(a))throw new TypeError("Object.keys called on a non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c},escape:function(b){return a("<div>").text(b).html()},itemsByValue:function(b,c,d){if(!c||null===b)return[];if("function"!=typeof d){var e=d||"value";d=function(a){return a[e]}}var f=a.isArray(b),g=[],h=this;return a.each(c,function(c,e){if(e.children)g=g.concat(h.itemsByValue(b,e.children,d));else if(f)a.grep(b,function(a){return a==(e&&"object"==typeof e?d(e):e)}).length&&g.push(e);else{var i=e&&"object"==typeof e?d(e):e;b==i&&g.push(e)}}),g},createInput:function(b){var c,d,e,f=b.type;return"date"===f&&("inline"===b.mode?a.fn.editabletypes.datefield?f="datefield":a.fn.editabletypes.dateuifield&&(f="dateuifield"):a.fn.editabletypes.date?f="date":a.fn.editabletypes.dateui&&(f="dateui"),"date"!==f||a.fn.editabletypes.date||(f="combodate")),"datetime"===f&&"inline"===b.mode&&(f="datetimefield"),"wysihtml5"!==f||a.fn.editabletypes[f]||(f="textarea"),"function"==typeof a.fn.editabletypes[f]?(c=a.fn.editabletypes[f],d=this.sliceObj(b,this.objectKeys(c.defaults)),e=new c(d)):(a.error("Unknown type: "+f),!1)},supportsTransitions:function(){var a=document.body||document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e<d.length;e++)if("string"==typeof b[d[e]+c])return!0;return!1}}}(window.jQuery),function(a){"use strict";var b=function(a,b){this.init(a,b)},c=function(a,b){this.init(a,b)};b.prototype={containerName:null,containerDataName:null,innerCss:null,containerClass:"editable-container editable-popup",defaults:{},init:function(c,d){this.$element=a(c),this.options=a.extend({},a.fn.editableContainer.defaults,d),this.splitOptions(),this.formOptions.scope=this.$element[0],this.initContainer(),this.delayedHide=!1,this.$element.on("destroyed",a.proxy(function(){this.destroy()},this)),a(document).data("editable-handlers-attached")||(a(document).on("keyup.editable",function(b){27===b.which&&a(".editable-open").editableContainer("hide")}),a(document).on("click.editable",function(c){var d,e=a(c.target),f=[".editable-container",".ui-datepicker-header",".datepicker",".modal-backdrop",".bootstrap-wysihtml5-insert-image-modal",".bootstrap-wysihtml5-insert-link-modal"];if(a.contains(document.documentElement,c.target)&&!e.is(document)){for(d=0;d<f.length;d++)if(e.is(f[d])||e.parents(f[d]).length)return;b.prototype.closeOthers(c.target)}}),a(document).data("editable-handlers-attached",!0))},splitOptions:function(){if(this.containerOptions={},this.formOptions={},!a.fn[this.containerName])throw new Error(this.containerName+" not found. Have you included corresponding js file?");for(var b in this.options)b in this.defaults?this.containerOptions[b]=this.options[b]:this.formOptions[b]=this.options[b]},tip:function(){return this.container()?this.container().$tip:null},container:function(){var a;return this.containerDataName&&(a=this.$element.data(this.containerDataName))?a:a=this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},initContainer:function(){this.call(this.containerOptions)},renderForm:function(){this.$form.editableform(this.formOptions).on({save:a.proxy(this.save,this),nochange:a.proxy(function(){this.hide("nochange")},this),cancel:a.proxy(function(){this.hide("cancel")},this),show:a.proxy(function(){this.delayedHide?(this.hide(this.delayedHide.reason),this.delayedHide=!1):this.setPosition()},this),rendering:a.proxy(this.setPosition,this),resize:a.proxy(this.setPosition,this),rendered:a.proxy(function(){this.$element.triggerHandler("shown",a(this.options.scope).data("editable"))},this)}).editableform("render")},show:function(b){this.$element.addClass("editable-open"),b!==!1&&this.closeOthers(this.$element[0]),this.innerShow(),this.tip().addClass(this.containerClass),this.$form,this.$form=a("<div>"),this.tip().is(this.innerCss)?this.tip().append(this.$form):this.tip().find(this.innerCss).append(this.$form),this.renderForm()},hide:function(a){if(this.tip()&&this.tip().is(":visible")&&this.$element.hasClass("editable-open")){if(this.$form.data("editableform").isSaving)return this.delayedHide={reason:a},void 0;this.delayedHide=!1,this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",a||"manual")}},innerShow:function(){},innerHide:function(){},toggle:function(a){this.container()&&this.tip()&&this.tip().is(":visible")?this.hide():this.show(a)},setPosition:function(){},save:function(a,b){this.$element.triggerHandler("save",b),this.hide("save")},option:function(a,b){this.options[a]=b,a in this.containerOptions?(this.containerOptions[a]=b,this.setContainerOption(a,b)):(this.formOptions[a]=b,this.$form&&this.$form.editableform("option",a,b))},setContainerOption:function(a,b){this.call("option",a,b)},destroy:function(){this.hide(),this.innerDestroy(),this.$element.off("destroyed"),this.$element.removeData("editableContainer")},innerDestroy:function(){},closeOthers:function(b){a(".editable-open").each(function(c,d){if(d!==b&&!a(d).find(b).length){var e=a(d),f=e.data("editableContainer");f&&("cancel"===f.options.onblur?e.data("editableContainer").hide("onblur"):"submit"===f.options.onblur&&e.data("editableContainer").tip().find("form").submit())}})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},a.fn.editableContainer=function(d){var e=arguments;return this.each(function(){var f=a(this),g="editableContainer",h=f.data(g),i="object"==typeof d&&d,j="inline"===i.mode?c:b;h||f.data(g,h=new j(this,i)),"string"==typeof d&&h[d].apply(h,Array.prototype.slice.call(e,1))})},a.fn.editableContainer.Popup=b,a.fn.editableContainer.Inline=c,a.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel",anim:!1,mode:"popup"},jQuery.event.special.destroyed={remove:function(a){a.handler&&a.handler()}}}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Inline.prototype,a.fn.editableContainer.Popup.prototype,{containerName:"editableform",innerCss:".editable-inline",containerClass:"editable-container editable-inline",initContainer:function(){this.$tip=a("<span></span>"),this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$tip},innerShow:function(){this.$element.hide(),this.tip().insertAfter(this.$element).show()},innerHide:function(){this.$tip.hide(this.options.anim,a.proxy(function(){this.$element.show(),this.innerDestroy()},this))},innerDestroy:function(){this.tip()&&this.tip().empty().remove()}})}(window.jQuery),function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.editable.defaults,c,a.fn.editableutils.getConfigData(this.$element)),this.options.selector?this.initLive():this.init(),this.options.highlight&&!a.fn.editableutils.supportsTransitions()&&(this.options.highlight=!1)};b.prototype={constructor:b,init:function(){var b,c=!1;if(this.options.name=this.options.name||this.$element.attr("id"),this.options.scope=this.$element[0],this.input=a.fn.editableutils.createInput(this.options),this.input){switch(void 0===this.options.value||null===this.options.value?(this.value=this.input.html2value(a.trim(this.$element.html())),c=!0):(this.options.value=a.fn.editableutils.tryParseJson(this.options.value,!0),this.value="string"==typeof this.options.value?this.input.str2value(this.options.value):this.options.value),this.$element.addClass("editable"),"textarea"===this.input.type&&this.$element.addClass("editable-pre-wrapped"),"manual"!==this.options.toggle?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",a.proxy(function(a){if(this.options.disabled||a.preventDefault(),"mouseenter"===this.options.toggle)this.show();else{var b="click"!==this.options.toggle;this.toggle(b)}},this))):this.$element.attr("tabindex",-1),"function"==typeof this.options.display&&(this.options.autotext="always"),this.options.autotext){case"always":b=!0;break;case"auto":b=!a.trim(this.$element.text()).length&&null!==this.value&&void 0!==this.value&&!c;break;default:b=!1}a.when(b?this.render():!0).then(a.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))}},initLive:function(){var b=this.options.selector;this.options.selector=!1,this.options.autotext="never",this.$element.on(this.options.toggle+".editable",b,a.proxy(function(b){var c=a(b.target);c.data("editable")||(c.hasClass(this.options.emptyclass)&&c.empty(),c.editable(this.options).trigger(b))},this))},render:function(a){return this.options.display!==!1?this.input.value2htmlFinal?this.input.value2html(this.value,this.$element[0],this.options.display,a):"function"==typeof this.options.display?this.options.display.call(this.$element[0],this.value,a):this.input.value2html(this.value,this.$element[0]):void 0},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(this.isEmpty),"manual"!==this.options.toggle&&"-1"===this.$element.attr("tabindex")&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(this.isEmpty),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(b,c){return b&&"object"==typeof b?(a.each(b,a.proxy(function(b,c){this.option(a.trim(b),c)},this)),void 0):(this.options[b]=c,"disabled"===b?c?this.disable():this.enable():("value"===b&&this.setValue(c),this.container&&this.container.option(b,c),this.input.option&&this.input.option(b,c),void 0))},handleEmpty:function(b){this.options.display!==!1&&(this.isEmpty=void 0!==b?b:"function"==typeof this.input.isEmpty?this.input.isEmpty(this.$element):""===a.trim(this.$element.html()),this.options.disabled?this.isEmpty&&(this.$element.empty(),this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass)):this.isEmpty?(this.$element.html(this.options.emptytext),this.options.emptyclass&&this.$element.addClass(this.options.emptyclass)):this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass))},show:function(b){if(!this.options.disabled){if(this.container){if(this.container.tip().is(":visible"))return}else{var c=a.extend({},this.options,{value:this.value,input:this.input});this.$element.editableContainer(c),this.$element.on("save.internal",a.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}this.container.show(b)}},hide:function(){this.container&&this.container.hide()},toggle:function(a){this.container&&this.container.tip().is(":visible")?this.hide():this.show(a)},save:function(a,b){if(this.options.unsavedclass){var c=!1;c=c||"function"==typeof this.options.url,c=c||this.options.display===!1,c=c||void 0!==b.response,c=c||this.options.savenochange&&this.input.value2str(this.value)!==this.input.value2str(b.newValue),c?this.$element.removeClass(this.options.unsavedclass):this.$element.addClass(this.options.unsavedclass)}if(this.options.highlight){var d=this.$element,e=d.css("background-color");d.css("background-color",this.options.highlight),setTimeout(function(){"transparent"===e&&(e=""),d.css("background-color",e),d.addClass("editable-bg-transition"),setTimeout(function(){d.removeClass("editable-bg-transition")},1700)},10)}this.setValue(b.newValue,!1,b.response)},validate:function(){return"function"==typeof this.options.validate?this.options.validate.call(this,this.value):void 0},setValue:function(b,c,d){this.value=c?this.input.str2value(b):b,this.container&&this.container.option("value",this.value),a.when(this.render(d)).then(a.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()},destroy:function(){this.disable(),this.container&&this.container.destroy(),this.input.destroy(),"manual"!==this.options.toggle&&(this.$element.removeClass("editable-click"),this.$element.off(this.options.toggle+".editable")),this.$element.off("save.internal"),this.$element.removeClass("editable editable-open editable-disabled"),this.$element.removeData("editable")}},a.fn.editable=function(c){var d={},e=arguments,f="editable";switch(c){case"validate":return this.each(function(){var b,c=a(this),e=c.data(f);e&&(b=e.validate())&&(d[e.options.name]=b)}),d;case"getValue":return 2===arguments.length&&arguments[1]===!0?d=this.eq(0).data(f).value:this.each(function(){var b=a(this),c=b.data(f);c&&void 0!==c.value&&null!==c.value&&(d[c.options.name]=c.input.value2submit(c.value))}),d;case"submit":var g=arguments[1]||{},h=this,i=this.editable("validate");if(a.isEmptyObject(i)){var j={};if(1===h.length){var k=h.data("editable"),l={name:k.options.name||"",value:k.input.value2submit(k.value),pk:"function"==typeof k.options.pk?k.options.pk.call(k.options.scope):k.options.pk};"function"==typeof k.options.params?l=k.options.params.call(k.options.scope,l):(k.options.params=a.fn.editableutils.tryParseJson(k.options.params,!0),a.extend(l,k.options.params)),j={url:k.options.url,data:l,type:"POST"},g.success=g.success||k.options.success,g.error=g.error||k.options.error}else{var m=this.editable("getValue");j={url:g.url,data:m,type:"POST"}}j.success="function"==typeof g.success?function(a){g.success.call(h,a,g)}:a.noop,j.error="function"==typeof g.error?function(){g.error.apply(h,arguments)}:a.noop,g.ajaxOptions&&a.extend(j,g.ajaxOptions),g.data&&a.extend(j.data,g.data),a.ajax(j)}else"function"==typeof g.error&&g.error.call(h,i);return this}return this.each(function(){var d=a(this),g=d.data(f),h="object"==typeof c&&c;return h&&h.selector?(g=new b(this,h),void 0):(g||d.data(f,g=new b(this,h)),"string"==typeof c&&g[c].apply(g,Array.prototype.slice.call(e,1)),void 0)})},a.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null,emptyclass:"editable-empty",unsavedclass:"editable-unsaved",selector:null,highlight:"#FFFF80"}}(window.jQuery),function(a){"use strict";a.fn.editabletypes={};var b=function(){};b.prototype={init:function(b,c,d){this.type=b,this.options=a.extend({},d,c)},prerender:function(){this.$tpl=a(this.options.tpl),this.$input=this.$tpl,this.$clear=null,this.error=null},render:function(){},value2html:function(b,c){a(c)[this.options.escape?"text":"html"](a.trim(b))},html2value:function(b){return a("<div>").html(b).text()},value2str:function(a){return a},str2value:function(a){return a},value2submit:function(a){return a},value2input:function(a){this.$input.val(a)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(b){return a("<div>").text(b).html()},autosubmit:function(){},destroy:function(){},setClass:function(){this.options.inputclass&&this.$input.addClass(this.options.inputclass)},setAttr:function(a){void 0!==this.options[a]&&null!==this.options[a]&&this.$input.attr(a,this.options[a])},option:function(a,b){this.options[a]=b}},b.defaults={tpl:"",inputclass:null,escape:!0,scope:null,showbuttons:!0},a.extend(a.fn.editabletypes,{abstractinput:b})}(window.jQuery),function(a){"use strict";var b=function(){};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){var b=a.Deferred();return this.error=null,this.onSourceReady(function(){this.renderList(),b.resolve()},function(){this.error=this.options.sourceError,b.resolve()}),b.promise()},html2value:function(){return null},value2html:function(b,c,d,e){var f=a.Deferred(),g=function(){"function"==typeof d?d.call(c,b,this.sourceData,e):this.value2htmlFinal(b,c),f.resolve()};return null===b?g.call(this):this.onSourceReady(g,function(){f.resolve()}),f.promise()},onSourceReady:function(b,c){var d;if(a.isFunction(this.options.source)?(d=this.options.source.call(this.options.scope),this.sourceData=null):d=this.options.source,this.options.sourceCache&&a.isArray(this.sourceData))return b.call(this),void 0;try{d=a.fn.editableutils.tryParseJson(d,!1)}catch(e){return c.call(this),void 0}if("string"==typeof d){if(this.options.sourceCache){var f,g=d;if(a(document).data(g)||a(document).data(g,{}),f=a(document).data(g),f.loading===!1&&f.sourceData)return this.sourceData=f.sourceData,this.doPrepend(),b.call(this),void 0;if(f.loading===!0)return f.callbacks.push(a.proxy(function(){this.sourceData=f.sourceData,this.doPrepend(),b.call(this)},this)),f.err_callbacks.push(a.proxy(c,this)),void 0;f.loading=!0,f.callbacks=[],f.err_callbacks=[]}var h=a.extend({url:d,type:"get",cache:!1,dataType:"json",success:a.proxy(function(d){f&&(f.loading=!1),this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(f&&(f.sourceData=this.sourceData,a.each(f.callbacks,function(){this.call()})),this.doPrepend(),b.call(this)):(c.call(this),f&&a.each(f.err_callbacks,function(){this.call()}))},this),error:a.proxy(function(){c.call(this),f&&(f.loading=!1,a.each(f.err_callbacks,function(){this.call()}))},this)},this.options.sourceOptions);a.ajax(h)}else this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(this.doPrepend(),b.call(this)):c.call(this)},doPrepend:function(){null!==this.options.prepend&&void 0!==this.options.prepend&&(a.isArray(this.prependData)||(a.isFunction(this.options.prepend)&&(this.options.prepend=this.options.prepend.call(this.options.scope)),this.options.prepend=a.fn.editableutils.tryParseJson(this.options.prepend,!0),"string"==typeof this.options.prepend&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),a.isArray(this.prependData)&&a.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData)))},renderList:function(){},value2htmlFinal:function(){},makeArray:function(b){var c,d,e,f,g=[];if(!b||"string"==typeof b)return null;if(a.isArray(b)){f=function(a,b){return d={value:a,text:b},c++>=2?!1:void 0};for(var h=0;h<b.length;h++)e=b[h],"object"==typeof e?(c=0,a.each(e,f),1===c?g.push(d):c>1&&(e.children&&(e.children=this.makeArray(e.children)),g.push(e))):g.push({value:e,text:e})}else a.each(b,function(a,b){g.push({value:a,text:b})});return g},option:function(a,b){this.options[a]=b,"source"===a&&(this.sourceData=null),"prepend"===a&&(this.prependData=null)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0,sourceOptions:null}),a.fn.editabletypes.list=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("text",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.renderClear(),this.setClass(),this.setAttr("placeholder")},activate:function(){this.$input.is(":visible")&&(this.$input.focus(),a.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.toggleClear&&this.toggleClear())},renderClear:function(){this.options.clear&&(this.$clear=a('<span class="editable-clear-x"></span>'),this.$input.after(this.$clear).css("padding-right",24).keyup(a.proxy(function(b){if(!~a.inArray(b.keyCode,[40,38,9,13,27])){clearTimeout(this.t);var c=this;this.t=setTimeout(function(){c.toggleClear(b)},100)}},this)).parent().css("position","relative"),this.$clear.click(a.proxy(this.clear,this)))},postrender:function(){},toggleClear:function(){if(this.$clear){var a=this.$input.val().length,b=this.$clear.is(":visible");a&&!b&&this.$clear.show(),!a&&b&&this.$clear.hide()}},clear:function(){this.$clear.hide(),this.$input.val("").focus()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null,clear:!0}),a.fn.editabletypes.text=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("textarea",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.setAttr("placeholder"),this.setAttr("rows"),this.$input.keydown(function(b){b.ctrlKey&&13===b.which&&a(this).closest("form").submit()})},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null,rows:7}),a.fn.editabletypes.textarea=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("select",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input.empty();var b=function(c,d){var e;if(a.isArray(d))for(var f=0;f<d.length;f++)e={},d[f].children?(e.label=d[f].text,c.append(b(a("<optgroup>",e),d[f].children))):(e.value=d[f].value,d[f].disabled&&(e.disabled=!0),c.append(a("<option>",e).text(d[f].text)));return c};b(this.$input,this.sourceData),this.setClass(),this.$input.on("keydown.editable",function(b){13===b.which&&a(this).closest("form").submit()})},value2htmlFinal:function(b,c){var d="",e=a.fn.editableutils.itemsByValue(b,this.sourceData);e.length&&(d=e[0].text),a.fn.editabletypes.abstractinput.prototype.value2html.call(this,d,c)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),a.fn.editabletypes.select=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("checklist",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){var b;if(this.$tpl.empty(),a.isArray(this.sourceData)){for(var c=0;c<this.sourceData.length;c++)b=a("<label>").append(a("<input>",{type:"checkbox",value:this.sourceData[c].value})).append(a("<span>").text(" "+this.sourceData[c].text)),a("<div>").append(b).appendTo(this.$tpl);this.$input=this.$tpl.find('input[type="checkbox"]'),this.setClass()}},value2str:function(b){return a.isArray(b)?b.sort().join(a.trim(this.options.separator)):""},str2value:function(b){var c,d=null;return"string"==typeof b&&b.length?(c=new RegExp("\\s*"+a.trim(this.options.separator)+"\\s*"),d=b.split(c)):d=a.isArray(b)?b:[b],d},value2input:function(b){this.$input.prop("checked",!1),a.isArray(b)&&b.length&&this.$input.each(function(c,d){var e=a(d);a.each(b,function(a,b){e.val()==b&&e.prop("checked",!0)})})},input2value:function(){var b=[];return this.$input.filter(":checked").each(function(c,d){b.push(a(d).val())}),b},value2htmlFinal:function(b,c){var d=[],e=a.fn.editableutils.itemsByValue(b,this.sourceData),f=this.options.escape;e.length?(a.each(e,function(b,c){var e=f?a.fn.editableutils.escape(c.text):c.text;d.push(e)}),a(c).html(d.join("<br>"))):a(c).empty()},activate:function(){this.$input.first().focus()},autosubmit:function(){this.$input.on("keydown",function(b){13===b.which&&a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:'<div class="editable-checklist"></div>',inputclass:null,separator:","}),a.fn.editabletypes.checklist=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("password",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{value2html:function(b,c){b?a(c).text("[hidden]"):a(c).empty()},html2value:function(){return null}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),a.fn.editabletypes.password=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("email",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),a.fn.editabletypes.email=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("url",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),a.fn.editabletypes.url=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("tel",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),a.fn.editabletypes.tel=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("number",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{render:function(){b.superclass.render.call(this),this.setAttr("min"),this.setAttr("max"),this.setAttr("step")},postrender:function(){this.$clear&&this.$clear.css({right:24})}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),a.fn.editabletypes.number=b}(window.jQuery),function(a){"use strict";
|
6 |
-
var b=function(a){this.init("range",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.number),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.filter("input"),this.setClass(),this.setAttr("min"),this.setAttr("max"),this.setAttr("step"),this.$input.on("input",function(){a(this).siblings("output").text(a(this).val())})},activate:function(){this.$input.focus()}}),b.defaults=a.extend({},a.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),a.fn.editabletypes.range=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("time",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="time">'}),a.fn.editabletypes.time=b}(window.jQuery),function(a){"use strict";var b=function(c){if(this.init("select2",c,b.defaults),c.select2=c.select2||{},this.sourceData=null,c.placeholder&&(c.select2.placeholder=c.placeholder),!c.select2.tags&&c.source){var d=c.source;a.isFunction(c.source)&&(d=c.source.call(c.scope)),"string"==typeof d?(c.select2.ajax=c.select2.ajax||{},c.select2.ajax.data||(c.select2.ajax.data=function(a){return{query:a}}),c.select2.ajax.results||(c.select2.ajax.results=function(a){return{results:a}}),c.select2.ajax.url=d):(this.sourceData=this.convertSource(d),c.select2.data=this.sourceData)}if(this.options.select2=a.extend({},b.defaults.select2,c.select2),this.isMultiple=this.options.select2.tags||this.options.select2.multiple,this.isRemote="ajax"in this.options.select2,this.idFunc=this.options.select2.id,"function"!=typeof this.idFunc){var e=this.idFunc||"id";this.idFunc=function(a){return a[e]}}this.formatSelection=this.options.select2.formatSelection,"function"!=typeof this.formatSelection&&(this.formatSelection=function(a){return a.text})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.isRemote&&this.$input.on("select2-loaded",a.proxy(function(a){this.sourceData=a.items.results},this)),this.isMultiple&&this.$input.on("change",function(){a(this).closest("form").parent().triggerHandler("resize")})},value2html:function(c,d){var e,f="",g=this;this.options.select2.tags?e=c:this.sourceData&&(e=a.fn.editableutils.itemsByValue(c,this.sourceData,this.idFunc)),a.isArray(e)?(f=[],a.each(e,function(a,b){f.push(b&&"object"==typeof b?g.formatSelection(b):b)})):e&&(f=g.formatSelection(e)),f=a.isArray(f)?f.join(this.options.viewseparator):f,b.superclass.value2html.call(this,f,d)},html2value:function(a){return this.options.select2.tags?this.str2value(a,this.options.viewseparator):null},value2input:function(b){if(a.isArray(b)&&(b=b.join(this.getSeparator())),this.$input.data("select2")?this.$input.val(b).trigger("change",!0):(this.$input.val(b),this.$input.select2(this.options.select2)),this.isRemote&&!this.isMultiple&&!this.options.select2.initSelection){var c=this.options.select2.id,d=this.options.select2.formatSelection;if(!c&&!d){var e=a(this.options.scope);if(!e.data("editable").isEmpty){var f={id:b,text:e.text()};this.$input.select2("data",f)}}}},input2value:function(){return this.$input.select2("val")},str2value:function(b,c){if("string"!=typeof b||!this.isMultiple)return b;c=c||this.getSeparator();var d,e,f;if(null===b||b.length<1)return null;for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d},autosubmit:function(){this.$input.on("change",function(b,c){c||a(this).closest("form").submit()})},getSeparator:function(){return this.options.select2.separator||a.fn.select2.defaults.separator},convertSource:function(b){if(a.isArray(b)&&b.length&&void 0!==b[0].value)for(var c=0;c<b.length;c++)void 0!==b[c].value&&(b[c].id=b[c].value,delete b[c].value);return b},destroy:function(){this.$input.data("select2")&&this.$input.select2("destroy")}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="hidden">',select2:null,placeholder:null,source:null,viewseparator:", "}),a.fn.editabletypes.select2=b}(window.jQuery),function(a){var b=function(b,c){return this.$element=a(b),this.$element.is("input")?(this.options=a.extend({},a.fn.combodate.defaults,c,this.$element.data()),this.init(),void 0):(a.error("Combodate should be applied to INPUT element"),void 0)};b.prototype={constructor:b,init:function(){this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=a('<span class="combodate"></span>').html(this.getTemplate()),this.initCombos(),this.$widget.on("change","select",a.proxy(function(b){this.$element.val(this.getValue()).change(),this.options.smartDays&&(a(b.target).is(".month")||a(b.target).is(".year"))&&this.fillCombo("day")},this)),this.$widget.find("select").css("width","auto"),this.$element.hide().after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var b=this.options.template;return a.each(this.map,function(a,c){c=c[0];var d=new RegExp(c+"+"),e=c.length>1?c.substring(1,2):c;b=b.replace(d,"{"+e+"}")}),b=b.replace(/ /g," "),a.each(this.map,function(a,c){c=c[0];var d=c.length>1?c.substring(1,2):c;b=b.replace("{"+d+"}",'<select class="'+a+'"></select>')}),b},initCombos:function(){for(var a in this.map){var b=this.$widget.find("."+a);this["$"+a]=b.length?b:null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.empty();for(var f=0;f<d.length;f++)b.append('<option value="'+d[f][0]+'">'+d[f][1]+"</option>");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(b){var c,d={},e=this,f=!1;return a.each(this.map,function(a){if("ampm"!==a){var b="day"===a?1:0;return d[a]=e["$"+a]?parseInt(e["$"+a].val(),10):b,isNaN(d[a])?(f=!0,!1):void 0}}),f?"":(this.$ampm&&(d.hour=12===d.hour?"am"===this.$ampm.val()?0:12:"am"===this.$ampm.val()?d.hour:d.hour+12),c=moment([d.year,d.month,d.day,d.hour,d.minute,d.second]),this.highlight(c),b=void 0===b?this.options.format:b,null===b?c.isValid()?c:null:c.isValid()?c.format(b):"")},setValue:function(b){function c(b,c){var d={};return b.children("option").each(function(b,e){var f,g=a(e).attr("value");""!==g&&(f=Math.abs(g-c),("undefined"==typeof d.distance||f<d.distance)&&(d={value:g,distance:f}))}),d.value}if(b){var d="string"==typeof b?moment(b,this.options.format):moment(b),e=this,f={};d.isValid()&&(a.each(this.map,function(a,b){"ampm"!==a&&(f[a]=d[b[1]]())}),this.$ampm&&(f.hour>=12?(f.ampm="pm",f.hour>12&&(f.hour-=12)):(f.ampm="am",0===f.hour&&(f.hour=12))),a.each(f,function(a,b){e["$"+a]&&("minute"===a&&e.options.minuteStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),"second"===a&&e.options.secondStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),e["$"+a].val(b))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(d.format(this.options.format)).change())}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},a.fn.combodate=function(c){var d,e=Array.apply(null,arguments);return e.shift(),"getValue"===c&&this.length&&(d=this.eq(0).data("combodate"))?d.getValue.apply(d,e):this.each(function(){var d=a(this),f=d.data("combodate"),g="object"==typeof c&&c;f||d.data("combodate",f=new b(this,g)),"string"==typeof c&&"function"==typeof f[c]&&f[c].apply(f,e)})},a.fn.combodate.defaults={format:"DD-MM-YYYY HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:2015,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,roundTime:!0,smartDays:!1}}(window.jQuery),function(a){"use strict";var b=function(c){this.init("combodate",c,b.defaults),this.options.viewformat||(this.options.viewformat=this.options.format),c.combodate=a.fn.editableutils.tryParseJson(c.combodate,!0),this.options.combodate=a.extend({},b.defaults.combodate,c.combodate,{format:this.options.format,template:this.options.template})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.$input.combodate(this.options.combodate),"bs3"===a.fn.editableform.engine&&this.$input.siblings().find("select").addClass("form-control"),this.options.inputclass&&this.$input.siblings().find("select").addClass(this.options.inputclass)},value2html:function(a,c){var d=a?a.format(this.options.viewformat):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return a?moment(a,this.options.viewformat):null},value2str:function(a){return a?a.format(this.options.format):""},str2value:function(a){return a?moment(a,this.options.format):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.combodate("setValue",a)},input2value:function(){return this.$input.combodate("getValue",null)},activate:function(){this.$input.siblings(".combodate").find("select").eq(0).focus()},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',inputclass:null,format:"YYYY-MM-DD",viewformat:null,template:"D / MMM / YYYY",combodate:null}),a.fn.editabletypes.combodate=b}(window.jQuery),function(a){"use strict";var b=a.fn.editableform.Constructor.prototype.initInput;a.extend(a.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=a(a.fn.editableform.template),this.$form.find(".control-group").addClass("form-group"),this.$form.find(".editable-error-block").addClass("help-block")},initInput:function(){b.apply(this);var c=null===this.input.options.inputclass||this.input.options.inputclass===!1,d="input-sm",e="text,select,textarea,password,email,url,tel,number,range,time,typeaheadjs".split(",");~a.inArray(this.input.type,e)&&(this.input.$input.addClass("form-control"),c&&(this.input.options.inputclass=d,this.input.$input.addClass(d)));for(var f=this.$form.find(".editable-buttons"),g=c?[d]:this.input.options.inputclass.split(" "),h=0;h<g.length;h++)"input-lg"===g[h].toLowerCase()&&f.find("button").removeClass("btn-sm").addClass("btn-lg")}}),a.fn.editableform.buttons='<button type="submit" class="btn btn-primary btn-sm editable-submit"><i class="glyphicon glyphicon-ok"></i></button><button type="button" class="btn btn-default btn-sm editable-cancel"><i class="glyphicon glyphicon-remove"></i></button>',a.fn.editableform.errorGroupClass="has-error",a.fn.editableform.errorBlockClass=null,a.fn.editableform.engine="bs3"}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Popup.prototype,{containerName:"popover",containerDataName:"bs.popover",innerCss:".popover-content",defaults:a.fn.popover.Constructor.DEFAULTS,initContainer:function(){a.extend(this.containerOptions,{trigger:"manual",selector:!1,content:" ",template:this.defaults.template});var b;this.$element.data("template")&&(b=this.$element.data("template"),this.$element.removeData("template")),this.call(this.containerOptions),b&&this.$element.data("template",b)},innerShow:function(){this.call("show")},innerHide:function(){this.call("hide")},innerDestroy:function(){this.call("destroy")},setContainerOption:function(a,b){this.container().options[a]=b},setPosition:function(){!function(){var a=this.tip(),b="function"==typeof this.options.placement?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,c=/\s?auto?\s?/i,d=c.test(b);d&&(b=b.replace(c,"")||"top");var e=this.getPosition(),f=a[0].offsetWidth,g=a[0].offsetHeight;if(d){var h=this.$element.parent(),i=b,j=document.documentElement.scrollTop||document.body.scrollTop,k="body"==this.options.container?window.innerWidth:h.outerWidth(),l="body"==this.options.container?window.innerHeight:h.outerHeight(),m="body"==this.options.container?0:h.offset().left;b="bottom"==b&&e.top+e.height+g-j>l?"top":"top"==b&&e.top-j-g<0?"bottom":"right"==b&&e.right+f>k?"left":"left"==b&&e.left-f<m?"right":b,a.removeClass(i).addClass(b)}var n=this.getCalculatedOffset(b,e,f,g);this.applyPlacement(n,b)}.call(this.container())}})}(window.jQuery),function(a){function b(){return new Date(Date.UTC.apply(Date,arguments))}function c(b,c){var d,e=a(b).data(),f={},g=new RegExp("^"+c.toLowerCase()+"([A-Z])"),c=new RegExp("^"+c.toLowerCase());for(var h in e)c.test(h)&&(d=h.replace(g,function(a,b){return b.toLowerCase()}),f[d]=e[h]);return f}function d(b){var c={};if(k[b]||(b=b.split("-")[0],k[b])){var d=k[b];return a.each(j,function(a,b){b in d&&(c[b]=d[b])}),c}}var e=function(b,c){this._process_options(c),this.element=a(b),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on, .btn"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&0===this.component.length&&(this.component=!1),this.picker=a(l.template),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&(this.picker.addClass("datepicker-rtl"),this.picker.find(".prev i, .next i").toggleClass("icon-arrow-left icon-arrow-right")),this.viewMode=this.o.startView,this.o.calendarWeeks&&this.picker.find("tfoot th.today").attr("colspan",function(a,b){return parseInt(b)+1}),this._allow_update=!1,this.setStartDate(this.o.startDate),this.setEndDate(this.o.endDate),this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled),this.fillDow(),this.fillMonths(),this._allow_update=!0,this.update(),this.showMode(),this.isInline&&this.show()};e.prototype={constructor:e,_process_options:function(b){this._o=a.extend({},this._o,b);var c=this.o=a.extend({},this._o),d=c.language;switch(k[d]||(d=d.split("-")[0],k[d]||(d=i.language)),c.language=d,c.startView){case 2:case"decade":c.startView=2;break;case 1:case"year":c.startView=1;break;default:c.startView=0}switch(c.minViewMode){case 1:case"months":c.minViewMode=1;break;case 2:case"years":c.minViewMode=2;break;default:c.minViewMode=0}c.startView=Math.max(c.startView,c.minViewMode),c.weekStart%=7,c.weekEnd=(c.weekStart+6)%7;var e=l.parseFormat(c.format);c.startDate!==-1/0&&(c.startDate=l.parseDate(c.startDate,e,c.language)),1/0!==c.endDate&&(c.endDate=l.parseDate(c.endDate,e,c.language)),c.daysOfWeekDisabled=c.daysOfWeekDisabled||[],a.isArray(c.daysOfWeekDisabled)||(c.daysOfWeekDisabled=c.daysOfWeekDisabled.split(/[,\s]*/)),c.daysOfWeekDisabled=a.map(c.daysOfWeekDisabled,function(a){return parseInt(a,10)})},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.on(c)},_unapplyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.off(c)},_buildEvents:function(){this.isInput?this._events=[[this.element,{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}]]:this.component&&this.hasInput?this._events=[[this.element.find("input"),{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}],[this.component,{click:a.proxy(this.show,this)}]]:this.element.is("div")?this.isInline=!0:this._events=[[this.element,{click:a.proxy(this.show,this)}]],this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{mousedown:a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).size()||this.picker.is(a.target)||this.picker.find(a.target).size()||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.date,e=new Date(d.getTime()+6e4*d.getTimezoneOffset());this.element.trigger({type:b,date:e,format:a.proxy(function(a){var b=a||this.o.format;return l.formatDate(d,b,this.o.language)},this)})},show:function(a){this.isInline||this.picker.appendTo("body"),this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.place(),this._attachSecondaryEvents(),a&&a.preventDefault(),this._trigger("show")},hide:function(){this.isInline||this.picker.is(":visible")&&(this.picker.hide().detach(),this._detachSecondaryEvents(),this.viewMode=this.o.startView,this.showMode(),this.o.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())&&this.setValue(),this._trigger("hide"))},remove:function(){this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date},getDate:function(){var a=this.getUTCDate();return new Date(a.getTime()+6e4*a.getTimezoneOffset())},getUTCDate:function(){return this.date},setDate:function(a){this.setUTCDate(new Date(a.getTime()-6e4*a.getTimezoneOffset()))},setUTCDate:function(a){this.date=a,this.setValue()},setValue:function(){var a=this.getFormattedDate();this.isInput?this.element.val(a):this.component&&this.element.find("input").val(a)},getFormattedDate:function(a){return void 0===a&&(a=this.o.format),l.formatDate(this.date,a,this.o.language)},setStartDate:function(a){this._process_options({startDate:a}),this.update(),this.updateNavArrows()},setEndDate:function(a){this._process_options({endDate:a}),this.update(),this.updateNavArrows()},setDaysOfWeekDisabled:function(a){this._process_options({daysOfWeekDisabled:a}),this.update(),this.updateNavArrows()},place:function(){if(!this.isInline){var b=parseInt(this.element.parents().filter(function(){return"auto"!=a(this).css("z-index")}).first().css("z-index"))+10,c=this.component?this.component.parent().offset():this.element.offset(),d=this.component?this.component.outerHeight(!0):this.element.outerHeight(!0);this.picker.css({top:c.top+d,left:c.left,zIndex:b})}},_allow_update:!0,update:function(){if(this._allow_update){var a,b=!1;arguments&&arguments.length&&("string"==typeof arguments[0]||arguments[0]instanceof Date)?(a=arguments[0],b=!0):(a=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),delete this.element.data().date),this.date=l.parseDate(a,this.o.format,this.o.language),b&&this.setValue(),this.viewDate=this.date<this.o.startDate?new Date(this.o.startDate):this.date>this.o.endDate?new Date(this.o.endDate):new Date(this.date),this.fill()}},fillDow:function(){var a=this.o.weekStart,b="<tr>";if(this.o.calendarWeeks){var c='<th class="cw"> </th>';b+=c,this.picker.find(".datepicker-days thead tr:first-child").prepend(c)}for(;a<this.o.weekStart+7;)b+='<th class="dow">'+k[this.o.language].daysMin[a++%7]+"</th>";b+="</tr>",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+='<span class="month">'+k[this.o.language].monthsShort[b++]+"</span>";this.picker.find(".datepicker-months td").html(a)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],d=this.viewDate.getUTCFullYear(),e=this.viewDate.getUTCMonth(),f=this.date.valueOf(),g=new Date;return b.getUTCFullYear()<d||b.getUTCFullYear()==d&&b.getUTCMonth()<e?c.push("old"):(b.getUTCFullYear()>d||b.getUTCFullYear()==d&&b.getUTCMonth()>e)&&c.push("new"),this.o.todayHighlight&&b.getUTCFullYear()==g.getFullYear()&&b.getUTCMonth()==g.getMonth()&&b.getUTCDate()==g.getDate()&&c.push("today"),f&&b.valueOf()==f&&c.push("active"),(b.valueOf()<this.o.startDate||b.valueOf()>this.o.endDate||-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled))&&c.push("disabled"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!=a.inArray(b.valueOf(),this.range)&&c.push("selected")),c},fill:function(){var c,d=new Date(this.viewDate),e=d.getUTCFullYear(),f=d.getUTCMonth(),g=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,h=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,i=1/0!==this.o.endDate?this.o.endDate.getUTCFullYear():1/0,j=1/0!==this.o.endDate?this.o.endDate.getUTCMonth():1/0;this.date&&this.date.valueOf(),this.picker.find(".datepicker-days thead th.datepicker-switch").text(k[this.o.language].months[f]+" "+e),this.picker.find("tfoot th.today").text(k[this.o.language].today).toggle(this.o.todayBtn!==!1),this.picker.find("tfoot th.clear").text(k[this.o.language].clear).toggle(this.o.clearBtn!==!1),this.updateNavArrows(),this.fillMonths();var m=b(e,f-1,28,0,0,0,0),n=l.getDaysInMonth(m.getUTCFullYear(),m.getUTCMonth());m.setUTCDate(n),m.setUTCDate(n-(m.getUTCDay()-this.o.weekStart+7)%7);var o=new Date(m);o.setUTCDate(o.getUTCDate()+42),o=o.valueOf();for(var p,q=[];m.valueOf()<o;){if(m.getUTCDay()==this.o.weekStart&&(q.push("<tr>"),this.o.calendarWeeks)){var r=new Date(+m+864e5*((this.o.weekStart-m.getUTCDay()-7)%7)),s=new Date(+r+864e5*((11-r.getUTCDay())%7)),t=new Date(+(t=b(s.getUTCFullYear(),0,1))+864e5*((11-t.getUTCDay())%7)),u=(s-t)/864e5/7+1;q.push('<td class="cw">'+u+"</td>")}p=this.getClassNames(m),p.push("day");var v=this.o.beforeShowDay(m);void 0===v?v={}:"boolean"==typeof v?v={enabled:v}:"string"==typeof v&&(v={classes:v}),v.enabled===!1&&p.push("disabled"),v.classes&&(p=p.concat(v.classes.split(/\s+/))),v.tooltip&&(c=v.tooltip),p=a.unique(p),q.push('<td class="'+p.join(" ")+'"'+(c?' title="'+c+'"':"")+">"+m.getUTCDate()+"</td>"),m.getUTCDay()==this.o.weekEnd&&q.push("</tr>"),m.setUTCDate(m.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(q.join(""));var w=this.date&&this.date.getUTCFullYear(),x=this.picker.find(".datepicker-months").find("th:eq(1)").text(e).end().find("span").removeClass("active");w&&w==e&&x.eq(this.date.getUTCMonth()).addClass("active"),(g>e||e>i)&&x.addClass("disabled"),e==g&&x.slice(0,h).addClass("disabled"),e==i&&x.slice(j+1).addClass("disabled"),q="",e=10*parseInt(e/10,10);var y=this.picker.find(".datepicker-years").find("th:eq(1)").text(e+"-"+(e+9)).end().find("td");e-=1;for(var z=-1;11>z;z++)q+='<span class="year'+(-1==z?" old":10==z?" new":"")+(w==e?" active":"")+(g>e||e>i?" disabled":"")+'">'+e+"</span>",e+=1;y.html(q)},updateNavArrows:function(){if(this._allow_update){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth();switch(this.viewMode){case 0:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()&&c<=this.o.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()&&c>=this.o.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}}},click:function(c){c.preventDefault();var d=a(c.target).closest("span, td, th");if(1==d.length)switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var e=l.modes[this.viewMode].navStep*("prev"==d[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,e);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,e)}this.fill();break;case"today":var f=new Date;f=b(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0),this.showMode(-2);var g="linked"==this.o.todayBtn?null:"view";this._setDate(f,g);break;case"clear":var h;this.isInput?h=this.element:this.component&&(h=this.element.find("input")),h&&h.val("").change(),this._trigger("changeDate"),this.update(),this.o.autoclose&&this.hide()}break;case"span":if(!d.is(".disabled")){if(this.viewDate.setUTCDate(1),d.is(".month")){var i=1,j=d.parent().find("span").index(d),k=this.viewDate.getUTCFullYear();this.viewDate.setUTCMonth(j),this._trigger("changeMonth",this.viewDate),1===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}else{var k=parseInt(d.text(),10)||0,i=1,j=0;this.viewDate.setUTCFullYear(k),this._trigger("changeYear",this.viewDate),2===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}this.showMode(-1),this.fill()}break;case"td":if(d.is(".day")&&!d.is(".disabled")){var i=parseInt(d.text(),10)||1,k=this.viewDate.getUTCFullYear(),j=this.viewDate.getUTCMonth();d.is(".old")?0===j?(j=11,k-=1):j-=1:d.is(".new")&&(11==j?(j=0,k+=1):j+=1),this._setDate(b(k,j,i,0,0,0,0))}}},_setDate:function(a,b){b&&"date"!=b||(this.date=new Date(a)),b&&"view"!=b||(this.viewDate=new Date(a)),this.fill(),this.setValue(),this._trigger("changeDate");var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&(c.change(),!this.o.autoclose||b&&"date"!=b||this.hide())},moveMonth:function(a,b){if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),g=e.getUTCMonth(),h=Math.abs(b);if(b=b>0?1:-1,1==h)d=-1==b?function(){return e.getUTCMonth()==g}:function(){return e.getUTCMonth()!=c},c=g+b,e.setUTCMonth(c),(0>c||c>11)&&(c=(c+12)%12);else{for(var i=0;h>i;i++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!=e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(this.picker.is(":not(:visible)"))return 27==a.keyCode&&this.show(),void 0;var b,c,d,e=!1;switch(a.keyCode){case 27:this.hide(),a.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;b=37==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 38:case 40:if(!this.o.keyboardNavigation)break;b=38==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+7*b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+7*b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 13:this.hide(),a.preventDefault();break;case 9:this.hide()}if(e){this._trigger("changeDate");var f;this.isInput?f=this.element:this.component&&(f=this.element.find("input")),f&&f.change()}},showMode:function(a){a&&(this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+a))),this.picker.find(">div").hide().filter(".datepicker-"+l.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}};var f=function(b,c){this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,a(this.inputs).datepicker(c).bind("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a(b).data("datepicker")}),this.updateDates()};f.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.date}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(b){var c=a(b.target).data("datepicker"),d=c.getUTCDate(),e=a.inArray(b.target,this.inputs),f=this.inputs.length;if(-1!=e){if(d<this.dates[e])for(;e>=0&&d<this.dates[e];)this.pickers[e--].setUTCDate(d);else if(d>this.dates[e])for(;f>e&&d>this.dates[e];)this.pickers[e++].setUTCDate(d);this.updateDates()}},remove:function(){a.map(this.pickers,function(a){a.remove()}),delete this.element.data().datepicker}};var g=a.fn.datepicker,h=a.fn.datepicker=function(b){var g=Array.apply(null,arguments);g.shift();var h;return this.each(function(){var j=a(this),k=j.data("datepicker"),l="object"==typeof b&&b;if(!k){var m=c(this,"date"),n=a.extend({},i,m,l),o=d(n.language),p=a.extend({},i,o,m,l);if(j.is(".input-daterange")||p.inputs){var q={inputs:p.inputs||j.find("input").toArray()};j.data("datepicker",k=new f(this,a.extend(p,q)))}else j.data("datepicker",k=new e(this,p))}return"string"==typeof b&&"function"==typeof k[b]&&(h=k[b].apply(k,g),void 0!==h)?!1:void 0}),void 0!==h?h:this},i=a.fn.datepicker.defaults={autoclose:!1,beforeShowDay:a.noop,calendarWeeks:!1,clearBtn:!1,daysOfWeekDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keyboardNavigation:!0,language:"en",minViewMode:0,rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,weekStart:0},j=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=e;var k=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}},l={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return 0===a%4&&0!==a%100||0===a%400
|
7 |
},getDaysInMonth:function(a,b){return[31,l.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,d,f){if(c instanceof Date)return c;if("string"==typeof d&&(d=l.parseFormat(d)),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(c)){var g,h,i=/([\-+]\d+)([dmwy])/,j=c.match(/([\-+]\d+)([dmwy])/g);c=new Date;for(var m=0;m<j.length;m++)switch(g=i.exec(j[m]),h=parseInt(g[1]),g[2]){case"d":c.setUTCDate(c.getUTCDate()+h);break;case"m":c=e.prototype.moveMonth.call(e.prototype,c,h);break;case"w":c.setUTCDate(c.getUTCDate()+7*h);break;case"y":c=e.prototype.moveYear.call(e.prototype,c,h)}return b(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate(),0,0,0)}var n,o,g,j=c&&c.match(this.nonpunctuation)||[],c=new Date,p={},q=["yyyy","yy","M","MM","m","mm","d","dd"],r={yyyy:function(a,b){return a.setUTCFullYear(b)},yy:function(a,b){return a.setUTCFullYear(2e3+b)},m:function(a,b){for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!=b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};r.M=r.MM=r.mm=r.m,r.dd=r.d,c=b(c.getFullYear(),c.getMonth(),c.getDate(),0,0,0);var s=d.parts.slice();if(j.length!=s.length&&(s=a(s).filter(function(b,c){return-1!==a.inArray(c,q)}).toArray()),j.length==s.length){for(var m=0,t=s.length;t>m;m++){if(n=parseInt(j[m],10),g=s[m],isNaN(n))switch(g){case"MM":o=a(k[f].months).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].months)+1;break;case"M":o=a(k[f].monthsShort).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].monthsShort)+1}p[g]=n}for(var u,m=0;m<q.length;m++)u=q[m],u in p&&!isNaN(p[u])&&r[u](c,p[u])}return c},formatDate:function(b,c,d){"string"==typeof c&&(c=l.parseFormat(c));var e={d:b.getUTCDate(),D:k[d].daysShort[b.getUTCDay()],DD:k[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:k[d].monthsShort[b.getUTCMonth()],MM:k[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m;for(var b=[],f=a.extend([],c.separators),g=0,h=c.parts.length;h>=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="datepicker-switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};l.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+l.headTemplate+"<tbody></tbody>"+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+"</div>",a.fn.datepicker.DPGlobal=l,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=g,this},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),h.call(c,"show"))}),a(function(){h.call(a('[data-provide="datepicker-inline"]'))})}(window.jQuery),function(a){"use strict";a.fn.bdatepicker=a.fn.datepicker.noConflict(),a.fn.datepicker||(a.fn.datepicker=a.fn.bdatepicker);var b=function(a){this.init("date",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datepicker=a.fn.editableutils.tryParseJson(b.datepicker,!0),this.options.datepicker=a.extend({},c.datepicker,b.datepicker,{format:this.options.viewformat}),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=a.fn.bdatepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)},render:function(){this.$input.bdatepicker(this.options.datepicker),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return this.parseDate(a,this.parsedViewFormat)},value2str:function(a){return a?this.dpg.formatDate(a,this.parsedFormat,this.options.datepicker.language):""},str2value:function(a){return this.parseDate(a,this.parsedFormat)},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.bdatepicker("update",a)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".day",function(b){if(!a(b.currentTarget).is(".old")&&!a(b.currentTarget).is(".new")){var c=a(this).closest("form");setTimeout(function(){c.submit()},200)}})},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datepicker.language),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datepicker.language),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!1},clear:"× clear"}),a.fn.editabletypes.date=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.date),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.bdatepicker(this.options.datepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.bdatepicker("update")},this))},value2input:function(a){this.$input.val(a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):""),this.$tpl.bdatepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.date.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-small",datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!0}}),a.fn.editabletypes.datefield=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetime",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datetimepicker=a.fn.editableutils.tryParseJson(b.datetimepicker,!0),this.options.datetimepicker=a.extend({},c.datetimepicker,b.datetimepicker,{format:this.options.viewformat}),this.options.datetimepicker.language=this.options.datetimepicker.language||"en",this.dpg=a.fn.datetimepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format,this.options.formatType),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat,this.options.formatType)},render:function(){this.$input.datetimepicker(this.options.datetimepicker),this.$input.on("changeMode",function(){var b=a(this).closest("form").parent();setTimeout(function(){b.triggerHandler("resize")},0)}),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(this.toUTC(a),this.parsedViewFormat,this.options.datetimepicker.language,this.options.formatType):"";return c?(b.superclass.value2html.call(this,d,c),void 0):d},html2value:function(a){var b=this.parseDate(a,this.parsedViewFormat);return b?this.fromUTC(b):null},value2str:function(a){return a?this.dpg.formatDate(this.toUTC(a),this.parsedFormat,this.options.datetimepicker.language,this.options.formatType):""},str2value:function(a){var b=this.parseDate(a,this.parsedFormat);return b?this.fromUTC(b):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){a&&this.$input.data("datetimepicker").setDate(a)},input2value:function(){var a=this.$input.data("datetimepicker");return a.date?a.getDate():null},activate:function(){},clear:function(){this.$input.data("datetimepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".minute",function(){var b=a(this).closest("form");setTimeout(function(){b.submit()},200)})},toUTC:function(a){return a?new Date(a.valueOf()-6e4*a.getTimezoneOffset()):a},fromUTC:function(a){return a?new Date(a.valueOf()+6e4*a.getTimezoneOffset()):a},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datetimepicker.language,this.options.formatType),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datetimepicker.language,this.options.formatType),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd hh:ii",formatType:"standard",viewformat:null,datetimepicker:{todayHighlight:!1,autoclose:!1},clear:"× clear"}),a.fn.editabletypes.datetime=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetimefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.datetime),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.datetimepicker(this.options.datetimepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.datetimepicker("update")},this))},value2input:function(a){this.$input.val(this.value2html(a)),this.$tpl.datetimepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.datetime.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-medium",datetimepicker:{todayHighlight:!1,autoclose:!0}}),a.fn.editabletypes.datetimefield=b}(window.jQuery);
|
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 */
|
5 |
+
!function(a){"use strict";var b=function(b,c){this.options=a.extend({},a.fn.editableform.defaults,c),this.$div=a(b),this.options.scope||(this.options.scope=this)};b.prototype={constructor:b,initInput:function(){this.input=this.options.input,this.value=this.input.str2value(this.options.value),this.input.prerender()},initTemplate:function(){this.$form=a(a.fn.editableform.template)},initButtons:function(){var b=this.$form.find(".editable-buttons");b.append(a.fn.editableform.buttons),"bottom"===this.options.showbuttons&&b.addClass("editable-buttons-bottom")},render:function(){this.$loading=a(a.fn.editableform.loading),this.$div.empty().append(this.$loading),this.initTemplate(),this.options.showbuttons?this.initButtons():this.$form.find(".editable-buttons").remove(),this.showLoading(),this.isSaving=!1,this.$div.triggerHandler("rendering"),this.initInput(),this.$form.find("div.editable-input").append(this.input.$tpl),this.$div.append(this.$form),a.when(this.input.render()).then(a.proxy(function(){if(this.options.showbuttons||this.input.autosubmit(),this.$form.find(".editable-cancel").click(a.proxy(this.cancel,this)),this.input.error)this.error(this.input.error),this.$form.find(".editable-submit").attr("disabled",!0),this.input.$input.attr("disabled",!0),this.$form.submit(function(a){a.preventDefault()});else{this.error(!1),this.input.$input.removeAttr("disabled"),this.$form.find(".editable-submit").removeAttr("disabled");var b=null===this.value||void 0===this.value||""===this.value?this.options.defaultValue:this.value;this.input.value2input(b),this.$form.submit(a.proxy(this.submit,this))}this.$div.triggerHandler("rendered"),this.showForm(),this.input.postrender&&this.input.postrender()},this))},cancel:function(){this.$div.triggerHandler("cancel")},showLoading:function(){var a,b;this.$form?(a=this.$form.outerWidth(),b=this.$form.outerHeight(),a&&this.$loading.width(a),b&&this.$loading.height(b),this.$form.hide()):(a=this.$loading.parent().width(),a&&this.$loading.width(a)),this.$loading.show()},showForm:function(a){this.$loading.hide(),this.$form.show(),a!==!1&&this.input.activate(),this.$div.triggerHandler("show")},error:function(b){var c,d=this.$form.find(".control-group"),e=this.$form.find(".editable-error-block");if(b===!1)d.removeClass(a.fn.editableform.errorGroupClass),e.removeClass(a.fn.editableform.errorBlockClass).empty().hide();else{if(b){c=(""+b).split("\n");for(var f=0;f<c.length;f++)c[f]=a("<div>").text(c[f]).html();b=c.join("<br>")}d.addClass(a.fn.editableform.errorGroupClass),e.addClass(a.fn.editableform.errorBlockClass).html(b).show()}},submit:function(b){b.stopPropagation(),b.preventDefault();var c=this.input.input2value(),d=this.validate(c);if("object"===a.type(d)&&void 0!==d.newValue){if(c=d.newValue,this.input.value2input(c),"string"==typeof d.msg)return this.error(d.msg),this.showForm(),void 0}else if(d)return this.error(d),this.showForm(),void 0;if(!this.options.savenochange&&this.input.value2str(c)==this.input.value2str(this.value))return this.$div.triggerHandler("nochange"),void 0;var e=this.input.value2submit(c);this.isSaving=!0,a.when(this.save(e)).done(a.proxy(function(a){this.isSaving=!1;var b="function"==typeof this.options.success?this.options.success.call(this.options.scope,a,c):null;return b===!1?(this.error(!1),this.showForm(!1),void 0):"string"==typeof b?(this.error(b),this.showForm(),void 0):(b&&"object"==typeof b&&b.hasOwnProperty("newValue")&&(c=b.newValue),this.error(!1),this.value=c,this.$div.triggerHandler("save",{newValue:c,submitValue:e,response:a}),void 0)},this)).fail(a.proxy(function(a){this.isSaving=!1;var b;b="function"==typeof this.options.error?this.options.error.call(this.options.scope,a,c):"string"==typeof a?a:a.responseText||a.statusText||"Unknown error!",this.error(b),this.showForm()},this))},save:function(b){this.options.pk=a.fn.editableutils.tryParseJson(this.options.pk,!0);var c,d="function"==typeof this.options.pk?this.options.pk.call(this.options.scope):this.options.pk,e=!!("function"==typeof this.options.url||this.options.url&&("always"===this.options.send||"auto"===this.options.send&&null!==d&&void 0!==d));return e?(this.showLoading(),c={name:this.options.name||"",value:b,pk:d},"function"==typeof this.options.params?c=this.options.params.call(this.options.scope,c):(this.options.params=a.fn.editableutils.tryParseJson(this.options.params,!0),a.extend(c,this.options.params)),"function"==typeof this.options.url?this.options.url.call(this.options.scope,c):a.ajax(a.extend({url:this.options.url,data:c,type:"POST"},this.options.ajaxOptions))):void 0},validate:function(a){return void 0===a&&(a=this.value),"function"==typeof this.options.validate?this.options.validate.call(this.options.scope,a):void 0},option:function(a,b){a in this.options&&(this.options[a]=b),"value"===a&&this.setValue(b)},setValue:function(a,b){this.value=b?this.input.str2value(a):a,this.$form&&this.$form.is(":visible")&&this.input.value2input(this.value)}},a.fn.editableform=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("editableform"),g="object"==typeof c&&c;f||e.data("editableform",f=new b(this,g)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.editableform.Constructor=b,a.fn.editableform.defaults={type:"text",url:null,params:null,name:null,pk:null,value:null,defaultValue:null,send:"auto",validate:null,success:null,error:null,ajaxOptions:null,showbuttons:!0,scope:null,savenochange:!1},a.fn.editableform.template='<form class="form-inline editableform"><div class="control-group"><div><div class="editable-input"></div><div class="editable-buttons"></div></div><div class="editable-error-block"></div></div></form>',a.fn.editableform.loading='<div class="editableform-loading"></div>',a.fn.editableform.buttons='<button type="submit" class="editable-submit">ok</button><button type="button" class="editable-cancel">cancel</button>',a.fn.editableform.errorGroupClass=null,a.fn.editableform.errorBlockClass="editable-error",a.fn.editableform.engine="jquery"}(window.jQuery),function(a){"use strict";a.fn.editableutils={inherit:function(a,b){var c=function(){};c.prototype=b.prototype,a.prototype=new c,a.prototype.constructor=a,a.superclass=b.prototype},setCursorPosition:function(a,b){if(a.setSelectionRange)a.setSelectionRange(b,b);else if(a.createTextRange){var c=a.createTextRange();c.collapse(!0),c.moveEnd("character",b),c.moveStart("character",b),c.select()}},tryParseJson:function(a,b){if("string"==typeof a&&a.length&&a.match(/^[\{\[].*[\}\]]$/))if(b)try{a=new Function("return "+a)()}catch(c){}finally{return a}else a=new Function("return "+a)();return a},sliceObj:function(b,c,d){var e,f,g={};if(!a.isArray(c)||!c.length)return g;for(var h=0;h<c.length;h++)e=c[h],b.hasOwnProperty(e)&&(g[e]=b[e]),d!==!0&&(f=e.toLowerCase(),b.hasOwnProperty(f)&&(g[e]=b[f]));return g},getConfigData:function(b){var c={};return a.each(b.data(),function(a,b){("object"!=typeof b||b&&"object"==typeof b&&(b.constructor===Object||b.constructor===Array))&&(c[a]=b)}),c},objectKeys:function(a){if(Object.keys)return Object.keys(a);if(a!==Object(a))throw new TypeError("Object.keys called on a non-object");var b,c=[];for(b in a)Object.prototype.hasOwnProperty.call(a,b)&&c.push(b);return c},escape:function(b){return a("<div>").text(b).html()},itemsByValue:function(b,c,d){if(!c||null===b)return[];if("function"!=typeof d){var e=d||"value";d=function(a){return a[e]}}var f=a.isArray(b),g=[],h=this;return a.each(c,function(c,e){if(e.children)g=g.concat(h.itemsByValue(b,e.children,d));else if(f)a.grep(b,function(a){return a==(e&&"object"==typeof e?d(e):e)}).length&&g.push(e);else{var i=e&&"object"==typeof e?d(e):e;b==i&&g.push(e)}}),g},createInput:function(b){var c,d,e,f=b.type;return"date"===f&&("inline"===b.mode?a.fn.editabletypes.datefield?f="datefield":a.fn.editabletypes.dateuifield&&(f="dateuifield"):a.fn.editabletypes.date?f="date":a.fn.editabletypes.dateui&&(f="dateui"),"date"!==f||a.fn.editabletypes.date||(f="combodate")),"datetime"===f&&"inline"===b.mode&&(f="datetimefield"),"wysihtml5"!==f||a.fn.editabletypes[f]||(f="textarea"),"function"==typeof a.fn.editabletypes[f]?(c=a.fn.editabletypes[f],d=this.sliceObj(b,this.objectKeys(c.defaults)),e=new c(d)):(a.error("Unknown type: "+f),!1)},supportsTransitions:function(){var a=document.body||document.documentElement,b=a.style,c="transition",d=["Moz","Webkit","Khtml","O","ms"];if("string"==typeof b[c])return!0;c=c.charAt(0).toUpperCase()+c.substr(1);for(var e=0;e<d.length;e++)if("string"==typeof b[d[e]+c])return!0;return!1}}}(window.jQuery),function(a){"use strict";var b=function(a,b){this.init(a,b)},c=function(a,b){this.init(a,b)};b.prototype={containerName:null,containerDataName:null,innerCss:null,containerClass:"editable-container editable-popup",defaults:{},init:function(c,d){this.$element=a(c),this.options=a.extend({},a.fn.editableContainer.defaults,d),this.splitOptions(),this.formOptions.scope=this.$element[0],this.initContainer(),this.delayedHide=!1,this.$element.on("destroyed",a.proxy(function(){this.destroy()},this)),a(document).data("editable-handlers-attached")||(a(document).on("keyup.editable",function(b){27===b.which&&a(".editable-open").editableContainer("hide")}),a(document).on("click.editable",function(c){var d,e=a(c.target),f=[".editable-container",".ui-datepicker-header",".datepicker",".modal-backdrop",".bootstrap-wysihtml5-insert-image-modal",".bootstrap-wysihtml5-insert-link-modal"];if(a.contains(document.documentElement,c.target)&&!e.is(document)){for(d=0;d<f.length;d++)if(e.is(f[d])||e.parents(f[d]).length)return;b.prototype.closeOthers(c.target)}}),a(document).data("editable-handlers-attached",!0))},splitOptions:function(){if(this.containerOptions={},this.formOptions={},!a.fn[this.containerName])throw new Error(this.containerName+" not found. Have you included corresponding js file?");for(var b in this.options)b in this.defaults?this.containerOptions[b]=this.options[b]:this.formOptions[b]=this.options[b]},tip:function(){return this.container()?this.container().$tip:null},container:function(){var a;return this.containerDataName&&(a=this.$element.data(this.containerDataName))?a:a=this.$element.data(this.containerName)},call:function(){this.$element[this.containerName].apply(this.$element,arguments)},initContainer:function(){this.call(this.containerOptions)},renderForm:function(){this.$form.editableform(this.formOptions).on({save:a.proxy(this.save,this),nochange:a.proxy(function(){this.hide("nochange")},this),cancel:a.proxy(function(){this.hide("cancel")},this),show:a.proxy(function(){this.delayedHide?(this.hide(this.delayedHide.reason),this.delayedHide=!1):this.setPosition()},this),rendering:a.proxy(this.setPosition,this),resize:a.proxy(this.setPosition,this),rendered:a.proxy(function(){this.$element.triggerHandler("shown",a(this.options.scope).data("editable"))},this)}).editableform("render")},show:function(b){this.$element.addClass("editable-open"),b!==!1&&this.closeOthers(this.$element[0]),this.innerShow(),this.tip().addClass(this.containerClass),this.$form,this.$form=a("<div>"),this.tip().is(this.innerCss)?this.tip().append(this.$form):this.tip().find(this.innerCss).append(this.$form),this.renderForm()},hide:function(a){if(this.tip()&&this.tip().is(":visible")&&this.$element.hasClass("editable-open")){if(this.$form.data("editableform").isSaving)return this.delayedHide={reason:a},void 0;this.delayedHide=!1,this.$element.removeClass("editable-open"),this.innerHide(),this.$element.triggerHandler("hidden",a||"manual")}},innerShow:function(){},innerHide:function(){},toggle:function(a){this.container()&&this.tip()&&this.tip().is(":visible")?this.hide():this.show(a)},setPosition:function(){},save:function(a,b){this.$element.triggerHandler("save",b),this.hide("save")},option:function(a,b){this.options[a]=b,a in this.containerOptions?(this.containerOptions[a]=b,this.setContainerOption(a,b)):(this.formOptions[a]=b,this.$form&&this.$form.editableform("option",a,b))},setContainerOption:function(a,b){this.call("option",a,b)},destroy:function(){this.hide(),this.innerDestroy(),this.$element.off("destroyed"),this.$element.removeData("editableContainer")},innerDestroy:function(){},closeOthers:function(b){a(".editable-open").each(function(c,d){if(d!==b&&!a(d).find(b).length){var e=a(d),f=e.data("editableContainer");f&&("cancel"===f.options.onblur?e.data("editableContainer").hide("onblur"):"submit"===f.options.onblur&&e.data("editableContainer").tip().find("form").submit())}})},activate:function(){this.tip&&this.tip().is(":visible")&&this.$form&&this.$form.data("editableform").input.activate()}},a.fn.editableContainer=function(d){var e=arguments;return this.each(function(){var f=a(this),g="editableContainer",h=f.data(g),i="object"==typeof d&&d,j="inline"===i.mode?c:b;h||f.data(g,h=new j(this,i)),"string"==typeof d&&h[d].apply(h,Array.prototype.slice.call(e,1))})},a.fn.editableContainer.Popup=b,a.fn.editableContainer.Inline=c,a.fn.editableContainer.defaults={value:null,placement:"top",autohide:!0,onblur:"cancel",anim:!1,mode:"popup"},jQuery.event.special.destroyed={remove:function(a){a.handler&&a.handler()}}}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Inline.prototype,a.fn.editableContainer.Popup.prototype,{containerName:"editableform",innerCss:".editable-inline",containerClass:"editable-container editable-inline",initContainer:function(){this.$tip=a("<span></span>"),this.options.anim||(this.options.anim=0)},splitOptions:function(){this.containerOptions={},this.formOptions=this.options},tip:function(){return this.$tip},innerShow:function(){this.$element.hide(),this.tip().insertAfter(this.$element).show()},innerHide:function(){this.$tip.hide(this.options.anim,a.proxy(function(){this.$element.show(),this.innerDestroy()},this))},innerDestroy:function(){this.tip()&&this.tip().empty().remove()}})}(window.jQuery),function(a){"use strict";var b=function(b,c){this.$element=a(b),this.options=a.extend({},a.fn.editable.defaults,c,a.fn.editableutils.getConfigData(this.$element)),this.options.selector?this.initLive():this.init(),this.options.highlight&&!a.fn.editableutils.supportsTransitions()&&(this.options.highlight=!1)};b.prototype={constructor:b,init:function(){var b,c=!1;if(this.options.name=this.options.name||this.$element.attr("id"),this.options.scope=this.$element[0],this.input=a.fn.editableutils.createInput(this.options),this.input){switch(void 0===this.options.value||null===this.options.value?(this.value=this.input.html2value(a.trim(this.$element.html())),c=!0):(this.options.value=a.fn.editableutils.tryParseJson(this.options.value,!0),this.value="string"==typeof this.options.value?this.input.str2value(this.options.value):this.options.value),this.$element.addClass("editable"),"textarea"===this.input.type&&this.$element.addClass("editable-pre-wrapped"),"manual"!==this.options.toggle?(this.$element.addClass("editable-click"),this.$element.on(this.options.toggle+".editable",a.proxy(function(a){if(this.options.disabled||a.preventDefault(),"mouseenter"===this.options.toggle)this.show();else{var b="click"!==this.options.toggle;this.toggle(b)}},this))):this.$element.attr("tabindex",-1),"function"==typeof this.options.display&&(this.options.autotext="always"),this.options.autotext){case"always":b=!0;break;case"auto":b=!a.trim(this.$element.text()).length&&null!==this.value&&void 0!==this.value&&!c;break;default:b=!1}a.when(b?this.render():!0).then(a.proxy(function(){this.options.disabled?this.disable():this.enable(),this.$element.triggerHandler("init",this)},this))}},initLive:function(){var b=this.options.selector;this.options.selector=!1,this.options.autotext="never",this.$element.on(this.options.toggle+".editable",b,a.proxy(function(b){var c=a(b.target);c.data("editable")||(c.hasClass(this.options.emptyclass)&&c.empty(),c.editable(this.options).trigger(b))},this))},render:function(a){return this.options.display!==!1?this.input.value2htmlFinal?this.input.value2html(this.value,this.$element[0],this.options.display,a):"function"==typeof this.options.display?this.options.display.call(this.$element[0],this.value,a):this.input.value2html(this.value,this.$element[0]):void 0},enable:function(){this.options.disabled=!1,this.$element.removeClass("editable-disabled"),this.handleEmpty(this.isEmpty),"manual"!==this.options.toggle&&"-1"===this.$element.attr("tabindex")&&this.$element.removeAttr("tabindex")},disable:function(){this.options.disabled=!0,this.hide(),this.$element.addClass("editable-disabled"),this.handleEmpty(this.isEmpty),this.$element.attr("tabindex",-1)},toggleDisabled:function(){this.options.disabled?this.enable():this.disable()},option:function(b,c){return b&&"object"==typeof b?(a.each(b,a.proxy(function(b,c){this.option(a.trim(b),c)},this)),void 0):(this.options[b]=c,"disabled"===b?c?this.disable():this.enable():("value"===b&&this.setValue(c),this.container&&this.container.option(b,c),this.input.option&&this.input.option(b,c),void 0))},handleEmpty:function(b){this.options.display!==!1&&(this.isEmpty=void 0!==b?b:"function"==typeof this.input.isEmpty?this.input.isEmpty(this.$element):""===a.trim(this.$element.html()),this.options.disabled?this.isEmpty&&(this.$element.empty(),this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass)):this.isEmpty?(this.$element.html(this.options.emptytext),this.options.emptyclass&&this.$element.addClass(this.options.emptyclass)):this.options.emptyclass&&this.$element.removeClass(this.options.emptyclass))},show:function(b){if(!this.options.disabled){if(this.container){if(this.container.tip().is(":visible"))return}else{var c=a.extend({},this.options,{value:this.value,input:this.input});this.$element.editableContainer(c),this.$element.on("save.internal",a.proxy(this.save,this)),this.container=this.$element.data("editableContainer")}this.container.show(b)}},hide:function(){this.container&&this.container.hide()},toggle:function(a){this.container&&this.container.tip().is(":visible")?this.hide():this.show(a)},save:function(a,b){if(this.options.unsavedclass){var c=!1;c=c||"function"==typeof this.options.url,c=c||this.options.display===!1,c=c||void 0!==b.response,c=c||this.options.savenochange&&this.input.value2str(this.value)!==this.input.value2str(b.newValue),c?this.$element.removeClass(this.options.unsavedclass):this.$element.addClass(this.options.unsavedclass)}if(this.options.highlight){var d=this.$element,e=d.css("background-color");d.css("background-color",this.options.highlight),setTimeout(function(){"transparent"===e&&(e=""),d.css("background-color",e),d.addClass("editable-bg-transition"),setTimeout(function(){d.removeClass("editable-bg-transition")},1700)},10)}this.setValue(b.newValue,!1,b.response)},validate:function(){return"function"==typeof this.options.validate?this.options.validate.call(this,this.value):void 0},setValue:function(b,c,d){this.value=c?this.input.str2value(b):b,this.container&&this.container.option("value",this.value),a.when(this.render(d)).then(a.proxy(function(){this.handleEmpty()},this))},activate:function(){this.container&&this.container.activate()},destroy:function(){this.disable(),this.container&&this.container.destroy(),this.input.destroy(),"manual"!==this.options.toggle&&(this.$element.removeClass("editable-click"),this.$element.off(this.options.toggle+".editable")),this.$element.off("save.internal"),this.$element.removeClass("editable editable-open editable-disabled"),this.$element.removeData("editable")}},a.fn.editable=function(c){var d={},e=arguments,f="editable";switch(c){case"validate":return this.each(function(){var b,c=a(this),e=c.data(f);e&&(b=e.validate())&&(d[e.options.name]=b)}),d;case"getValue":return 2===arguments.length&&arguments[1]===!0?d=this.eq(0).data(f).value:this.each(function(){var b=a(this),c=b.data(f);c&&void 0!==c.value&&null!==c.value&&(d[c.options.name]=c.input.value2submit(c.value))}),d;case"submit":var g=arguments[1]||{},h=this,i=this.editable("validate");if(a.isEmptyObject(i)){var j={};if(1===h.length){var k=h.data("editable"),l={name:k.options.name||"",value:k.input.value2submit(k.value),pk:"function"==typeof k.options.pk?k.options.pk.call(k.options.scope):k.options.pk};"function"==typeof k.options.params?l=k.options.params.call(k.options.scope,l):(k.options.params=a.fn.editableutils.tryParseJson(k.options.params,!0),a.extend(l,k.options.params)),j={url:k.options.url,data:l,type:"POST"},g.success=g.success||k.options.success,g.error=g.error||k.options.error}else{var m=this.editable("getValue");j={url:g.url,data:m,type:"POST"}}j.success="function"==typeof g.success?function(a){g.success.call(h,a,g)}:a.noop,j.error="function"==typeof g.error?function(){g.error.apply(h,arguments)}:a.noop,g.ajaxOptions&&a.extend(j,g.ajaxOptions),g.data&&a.extend(j.data,g.data),a.ajax(j)}else"function"==typeof g.error&&g.error.call(h,i);return this}return this.each(function(){var d=a(this),g=d.data(f),h="object"==typeof c&&c;return h&&h.selector?(g=new b(this,h),void 0):(g||d.data(f,g=new b(this,h)),"string"==typeof c&&g[c].apply(g,Array.prototype.slice.call(e,1)),void 0)})},a.fn.editable.defaults={type:"text",disabled:!1,toggle:"click",emptytext:"Empty",autotext:"auto",value:null,display:null,emptyclass:"editable-empty",unsavedclass:"editable-unsaved",selector:null,highlight:"#FFFF80"}}(window.jQuery),function(a){"use strict";a.fn.editabletypes={};var b=function(){};b.prototype={init:function(b,c,d){this.type=b,this.options=a.extend({},d,c)},prerender:function(){this.$tpl=a(this.options.tpl),this.$input=this.$tpl,this.$clear=null,this.error=null},render:function(){},value2html:function(b,c){a(c)[this.options.escape?"text":"html"](a.trim(b))},html2value:function(b){return a("<div>").html(b).text()},value2str:function(a){return a},str2value:function(a){return a},value2submit:function(a){return a},value2input:function(a){this.$input.val(a)},input2value:function(){return this.$input.val()},activate:function(){this.$input.is(":visible")&&this.$input.focus()},clear:function(){this.$input.val(null)},escape:function(b){return a("<div>").text(b).html()},autosubmit:function(){},destroy:function(){},setClass:function(){this.options.inputclass&&this.$input.addClass(this.options.inputclass)},setAttr:function(a){void 0!==this.options[a]&&null!==this.options[a]&&this.$input.attr(a,this.options[a])},option:function(a,b){this.options[a]=b}},b.defaults={tpl:"",inputclass:null,escape:!0,scope:null,showbuttons:!0},a.extend(a.fn.editabletypes,{abstractinput:b})}(window.jQuery),function(a){"use strict";var b=function(){};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){var b=a.Deferred();return this.error=null,this.onSourceReady(function(){this.renderList(),b.resolve()},function(){this.error=this.options.sourceError,b.resolve()}),b.promise()},html2value:function(){return null},value2html:function(b,c,d,e){var f=a.Deferred(),g=function(){"function"==typeof d?d.call(c,b,this.sourceData,e):this.value2htmlFinal(b,c),f.resolve()};return null===b?g.call(this):this.onSourceReady(g,function(){f.resolve()}),f.promise()},onSourceReady:function(b,c){var d;if(a.isFunction(this.options.source)?(d=this.options.source.call(this.options.scope),this.sourceData=null):d=this.options.source,this.options.sourceCache&&a.isArray(this.sourceData))return b.call(this),void 0;try{d=a.fn.editableutils.tryParseJson(d,!1)}catch(e){return c.call(this),void 0}if("string"==typeof d){if(this.options.sourceCache){var f,g=d;if(a(document).data(g)||a(document).data(g,{}),f=a(document).data(g),f.loading===!1&&f.sourceData)return this.sourceData=f.sourceData,this.doPrepend(),b.call(this),void 0;if(f.loading===!0)return f.callbacks.push(a.proxy(function(){this.sourceData=f.sourceData,this.doPrepend(),b.call(this)},this)),f.err_callbacks.push(a.proxy(c,this)),void 0;f.loading=!0,f.callbacks=[],f.err_callbacks=[]}var h=a.extend({url:d,type:"get",cache:!1,dataType:"json",success:a.proxy(function(d){f&&(f.loading=!1),this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(f&&(f.sourceData=this.sourceData,a.each(f.callbacks,function(){this.call()})),this.doPrepend(),b.call(this)):(c.call(this),f&&a.each(f.err_callbacks,function(){this.call()}))},this),error:a.proxy(function(){c.call(this),f&&(f.loading=!1,a.each(f.err_callbacks,function(){this.call()}))},this)},this.options.sourceOptions);a.ajax(h)}else this.sourceData=this.makeArray(d),a.isArray(this.sourceData)?(this.doPrepend(),b.call(this)):c.call(this)},doPrepend:function(){null!==this.options.prepend&&void 0!==this.options.prepend&&(a.isArray(this.prependData)||(a.isFunction(this.options.prepend)&&(this.options.prepend=this.options.prepend.call(this.options.scope)),this.options.prepend=a.fn.editableutils.tryParseJson(this.options.prepend,!0),"string"==typeof this.options.prepend&&(this.options.prepend={"":this.options.prepend}),this.prependData=this.makeArray(this.options.prepend)),a.isArray(this.prependData)&&a.isArray(this.sourceData)&&(this.sourceData=this.prependData.concat(this.sourceData)))},renderList:function(){},value2htmlFinal:function(){},makeArray:function(b){var c,d,e,f,g=[];if(!b||"string"==typeof b)return null;if(a.isArray(b)){f=function(a,b){return d={value:a,text:b},c++>=2?!1:void 0};for(var h=0;h<b.length;h++)e=b[h],"object"==typeof e?(c=0,a.each(e,f),1===c?g.push(d):c>1&&(e.children&&(e.children=this.makeArray(e.children)),g.push(e))):g.push({value:e,text:e})}else a.each(b,function(a,b){g.push({value:a,text:b})});return g},option:function(a,b){this.options[a]=b,"source"===a&&(this.sourceData=null),"prepend"===a&&(this.prependData=null)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{source:null,prepend:!1,sourceError:"Error when loading list",sourceCache:!0,sourceOptions:null}),a.fn.editabletypes.list=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("text",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.renderClear(),this.setClass(),this.setAttr("placeholder")},activate:function(){this.$input.is(":visible")&&(this.$input.focus(),a.fn.editableutils.setCursorPosition(this.$input.get(0),this.$input.val().length),this.toggleClear&&this.toggleClear())},renderClear:function(){this.options.clear&&(this.$clear=a('<span class="editable-clear-x"></span>'),this.$input.after(this.$clear).css("padding-right",24).keyup(a.proxy(function(b){if(!~a.inArray(b.keyCode,[40,38,9,13,27])){clearTimeout(this.t);var c=this;this.t=setTimeout(function(){c.toggleClear(b)},100)}},this)).parent().css("position","relative"),this.$clear.click(a.proxy(this.clear,this)))},postrender:function(){},toggleClear:function(){if(this.$clear){var a=this.$input.val().length,b=this.$clear.is(":visible");a&&!b&&this.$clear.show(),!a&&b&&this.$clear.hide()}},clear:function(){this.$clear.hide(),this.$input.val("").focus()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',placeholder:null,clear:!0}),a.fn.editabletypes.text=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("textarea",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.setAttr("placeholder"),this.setAttr("rows"),this.$input.keydown(function(b){b.ctrlKey&&13===b.which&&a(this).closest("form").submit()})},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:"<textarea></textarea>",inputclass:"input-large",placeholder:null,rows:7}),a.fn.editabletypes.textarea=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("select",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){this.$input.empty();var b=function(c,d){var e;if(a.isArray(d))for(var f=0;f<d.length;f++)e={},d[f].children?(e.label=d[f].text,c.append(b(a("<optgroup>",e),d[f].children))):(e.value=d[f].value,d[f].disabled&&(e.disabled=!0),c.append(a("<option>",e).text(d[f].text)));return c};b(this.$input,this.sourceData),this.setClass(),this.$input.on("keydown.editable",function(b){13===b.which&&a(this).closest("form").submit()})},value2htmlFinal:function(b,c){var d="",e=a.fn.editableutils.itemsByValue(b,this.sourceData);e.length&&(d=e[0].text),a.fn.editabletypes.abstractinput.prototype.value2html.call(this,d,c)},autosubmit:function(){this.$input.off("keydown.editable").on("change.editable",function(){a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:"<select></select>"}),a.fn.editabletypes.select=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("checklist",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.list),a.extend(b.prototype,{renderList:function(){var b;if(this.$tpl.empty(),a.isArray(this.sourceData)){for(var c=0;c<this.sourceData.length;c++)b=a("<label>").append(a("<input>",{type:"checkbox",value:this.sourceData[c].value})).append(a("<span>").text(" "+this.sourceData[c].text)),a("<div>").append(b).appendTo(this.$tpl);this.$input=this.$tpl.find('input[type="checkbox"]'),this.setClass()}},value2str:function(b){return a.isArray(b)?b.sort().join(a.trim(this.options.separator)):""},str2value:function(b){var c,d=null;return"string"==typeof b&&b.length?(c=new RegExp("\\s*"+a.trim(this.options.separator)+"\\s*"),d=b.split(c)):d=a.isArray(b)?b:[b],d},value2input:function(b){this.$input.prop("checked",!1),a.isArray(b)&&b.length&&this.$input.each(function(c,d){var e=a(d);a.each(b,function(a,b){e.val()==b&&e.prop("checked",!0)})})},input2value:function(){var b=[];return this.$input.filter(":checked").each(function(c,d){b.push(a(d).val())}),b},value2htmlFinal:function(b,c){var d=[],e=a.fn.editableutils.itemsByValue(b,this.sourceData),f=this.options.escape;e.length?(a.each(e,function(b,c){var e=f?a.fn.editableutils.escape(c.text):c.text;d.push(e)}),a(c).html(d.join("<br>"))):a(c).empty()},activate:function(){this.$input.first().focus()},autosubmit:function(){this.$input.on("keydown",function(b){13===b.which&&a(this).closest("form").submit()})}}),b.defaults=a.extend({},a.fn.editabletypes.list.defaults,{tpl:'<div class="editable-checklist"></div>',inputclass:null,separator:","}),a.fn.editabletypes.checklist=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("password",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{value2html:function(b,c){b?a(c).text("[hidden]"):a(c).empty()},html2value:function(){return null}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="password">'}),a.fn.editabletypes.password=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("email",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="email">'}),a.fn.editabletypes.email=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("url",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="url">'}),a.fn.editabletypes.url=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("tel",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="tel">'}),a.fn.editabletypes.tel=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("number",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.text),a.extend(b.prototype,{render:function(){b.superclass.render.call(this),this.setAttr("min"),this.setAttr("max"),this.setAttr("step")},postrender:function(){this.$clear&&this.$clear.css({right:24})}}),b.defaults=a.extend({},a.fn.editabletypes.text.defaults,{tpl:'<input type="number">',inputclass:"input-mini",min:null,max:null,step:null}),a.fn.editabletypes.number=b}(window.jQuery),function(a){"use strict";
|
6 |
+
var b=function(a){this.init("range",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.number),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.filter("input"),this.setClass(),this.setAttr("min"),this.setAttr("max"),this.setAttr("step"),this.$input.on("input",function(){a(this).siblings("output").text(a(this).val())})},activate:function(){this.$input.focus()}}),b.defaults=a.extend({},a.fn.editabletypes.number.defaults,{tpl:'<input type="range"><output style="width: 30px; display: inline-block"></output>',inputclass:"input-medium"}),a.fn.editabletypes.range=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("time",a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass()}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="time">'}),a.fn.editabletypes.time=b}(window.jQuery),function(a){"use strict";var b=function(c){if(this.init("select2",c,b.defaults),c.select2=c.select2||{},this.sourceData=null,c.placeholder&&(c.select2.placeholder=c.placeholder),!c.select2.tags&&c.source){var d=c.source;a.isFunction(c.source)&&(d=c.source.call(c.scope)),"string"==typeof d?(c.select2.ajax=c.select2.ajax||{},c.select2.ajax.data||(c.select2.ajax.data=function(a){return{query:a}}),c.select2.ajax.results||(c.select2.ajax.results=function(a){return{results:a}}),c.select2.ajax.url=d):(this.sourceData=this.convertSource(d),c.select2.data=this.sourceData)}if(this.options.select2=a.extend({},b.defaults.select2,c.select2),this.isMultiple=this.options.select2.tags||this.options.select2.multiple,this.isRemote="ajax"in this.options.select2,this.idFunc=this.options.select2.id,"function"!=typeof this.idFunc){var e=this.idFunc||"id";this.idFunc=function(a){return a[e]}}this.formatSelection=this.options.select2.formatSelection,"function"!=typeof this.formatSelection&&(this.formatSelection=function(a){return a.text})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.setClass(),this.isRemote&&this.$input.on("select2-loaded",a.proxy(function(a){this.sourceData=a.items.results},this)),this.isMultiple&&this.$input.on("change",function(){a(this).closest("form").parent().triggerHandler("resize")})},value2html:function(c,d){var e,f="",g=this;this.options.select2.tags?e=c:this.sourceData&&(e=a.fn.editableutils.itemsByValue(c,this.sourceData,this.idFunc)),a.isArray(e)?(f=[],a.each(e,function(a,b){f.push(b&&"object"==typeof b?g.formatSelection(b):b)})):e&&(f=g.formatSelection(e)),f=a.isArray(f)?f.join(this.options.viewseparator):f,b.superclass.value2html.call(this,f,d)},html2value:function(a){return this.options.select2.tags?this.str2value(a,this.options.viewseparator):null},value2input:function(b){if(a.isArray(b)&&(b=b.join(this.getSeparator())),this.$input.data("select2")?this.$input.val(b).trigger("change",!0):(this.$input.val(b),this.$input.select2(this.options.select2)),this.isRemote&&!this.isMultiple&&!this.options.select2.initSelection){var c=this.options.select2.id,d=this.options.select2.formatSelection;if(!c&&!d){var e=a(this.options.scope);if(!e.data("editable").isEmpty){var f={id:b,text:e.text()};this.$input.select2("data",f)}}}},input2value:function(){return this.$input.select2("val")},str2value:function(b,c){if("string"!=typeof b||!this.isMultiple)return b;c=c||this.getSeparator();var d,e,f;if(null===b||b.length<1)return null;for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d},autosubmit:function(){this.$input.on("change",function(b,c){c||a(this).closest("form").submit()})},getSeparator:function(){return this.options.select2.separator||a.fn.select2.defaults.separator},convertSource:function(b){if(a.isArray(b)&&b.length&&void 0!==b[0].value)for(var c=0;c<b.length;c++)void 0!==b[c].value&&(b[c].id=b[c].value,delete b[c].value);return b},destroy:function(){this.$input.data("select2")&&this.$input.select2("destroy")}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="hidden">',select2:null,placeholder:null,source:null,viewseparator:", "}),a.fn.editabletypes.select2=b}(window.jQuery),function(a){var b=function(b,c){return this.$element=a(b),this.$element.is("input")?(this.options=a.extend({},a.fn.combodate.defaults,c,this.$element.data()),this.init(),void 0):(a.error("Combodate should be applied to INPUT element"),void 0)};b.prototype={constructor:b,init:function(){this.map={day:["D","date"],month:["M","month"],year:["Y","year"],hour:["[Hh]","hours"],minute:["m","minutes"],second:["s","seconds"],ampm:["[Aa]",""]},this.$widget=a('<span class="combodate"></span>').html(this.getTemplate()),this.initCombos(),this.$widget.on("change","select",a.proxy(function(b){this.$element.val(this.getValue()).change(),this.options.smartDays&&(a(b.target).is(".month")||a(b.target).is(".year"))&&this.fillCombo("day")},this)),this.$widget.find("select").css("width","auto"),this.$element.hide().after(this.$widget),this.setValue(this.$element.val()||this.options.value)},getTemplate:function(){var b=this.options.template;return a.each(this.map,function(a,c){c=c[0];var d=new RegExp(c+"+"),e=c.length>1?c.substring(1,2):c;b=b.replace(d,"{"+e+"}")}),b=b.replace(/ /g," "),a.each(this.map,function(a,c){c=c[0];var d=c.length>1?c.substring(1,2):c;b=b.replace("{"+d+"}",'<select class="'+a+'"></select>')}),b},initCombos:function(){for(var a in this.map){var b=this.$widget.find("."+a);this["$"+a]=b.length?b:null,this.fillCombo(a)}},fillCombo:function(a){var b=this["$"+a];if(b){var c="fill"+a.charAt(0).toUpperCase()+a.slice(1),d=this[c](),e=b.val();b.empty();for(var f=0;f<d.length;f++)b.append('<option value="'+d[f][0]+'">'+d[f][1]+"</option>");b.val(e)}},fillCommon:function(a){var b,c=[];if("name"===this.options.firstItem){b=moment.relativeTime||moment.langData()._relativeTime;var d="function"==typeof b[a]?b[a](1,!0,a,!1):b[a];d=d.split(" ").reverse()[0],c.push(["",d])}else"empty"===this.options.firstItem&&c.push(["",""]);return c},fillDay:function(){var a,b,c=this.fillCommon("d"),d=-1!==this.options.template.indexOf("DD"),e=31;if(this.options.smartDays&&this.$month&&this.$year){var f=parseInt(this.$month.val(),10),g=parseInt(this.$year.val(),10);isNaN(f)||isNaN(g)||(e=moment([g,f]).daysInMonth())}for(b=1;e>=b;b++)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillMonth:function(){var a,b,c=this.fillCommon("M"),d=-1!==this.options.template.indexOf("MMMM"),e=-1!==this.options.template.indexOf("MMM"),f=-1!==this.options.template.indexOf("MM");for(b=0;11>=b;b++)a=d?moment().date(1).month(b).format("MMMM"):e?moment().date(1).month(b).format("MMM"):f?this.leadZero(b+1):b+1,c.push([b,a]);return c},fillYear:function(){var a,b,c=[],d=-1!==this.options.template.indexOf("YYYY");for(b=this.options.maxYear;b>=this.options.minYear;b--)a=d?b:(b+"").substring(2),c[this.options.yearDescending?"push":"unshift"]([b,a]);return c=this.fillCommon("y").concat(c)},fillHour:function(){var a,b,c=this.fillCommon("h"),d=-1!==this.options.template.indexOf("h"),e=(-1!==this.options.template.indexOf("H"),-1!==this.options.template.toLowerCase().indexOf("hh")),f=d?1:0,g=d?12:23;for(b=f;g>=b;b++)a=e?this.leadZero(b):b,c.push([b,a]);return c},fillMinute:function(){var a,b,c=this.fillCommon("m"),d=-1!==this.options.template.indexOf("mm");for(b=0;59>=b;b+=this.options.minuteStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillSecond:function(){var a,b,c=this.fillCommon("s"),d=-1!==this.options.template.indexOf("ss");for(b=0;59>=b;b+=this.options.secondStep)a=d?this.leadZero(b):b,c.push([b,a]);return c},fillAmpm:function(){var a=-1!==this.options.template.indexOf("a"),b=(-1!==this.options.template.indexOf("A"),[["am",a?"am":"AM"],["pm",a?"pm":"PM"]]);return b},getValue:function(b){var c,d={},e=this,f=!1;return a.each(this.map,function(a){if("ampm"!==a){var b="day"===a?1:0;return d[a]=e["$"+a]?parseInt(e["$"+a].val(),10):b,isNaN(d[a])?(f=!0,!1):void 0}}),f?"":(this.$ampm&&(d.hour=12===d.hour?"am"===this.$ampm.val()?0:12:"am"===this.$ampm.val()?d.hour:d.hour+12),c=moment([d.year,d.month,d.day,d.hour,d.minute,d.second]),this.highlight(c),b=void 0===b?this.options.format:b,null===b?c.isValid()?c:null:c.isValid()?c.format(b):"")},setValue:function(b){function c(b,c){var d={};return b.children("option").each(function(b,e){var f,g=a(e).attr("value");""!==g&&(f=Math.abs(g-c),("undefined"==typeof d.distance||f<d.distance)&&(d={value:g,distance:f}))}),d.value}if(b){var d="string"==typeof b?moment(b,this.options.format):moment(b),e=this,f={};d.isValid()&&(a.each(this.map,function(a,b){"ampm"!==a&&(f[a]=d[b[1]]())}),this.$ampm&&(f.hour>=12?(f.ampm="pm",f.hour>12&&(f.hour-=12)):(f.ampm="am",0===f.hour&&(f.hour=12))),a.each(f,function(a,b){e["$"+a]&&("minute"===a&&e.options.minuteStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),"second"===a&&e.options.secondStep>1&&e.options.roundTime&&(b=c(e["$"+a],b)),e["$"+a].val(b))}),this.options.smartDays&&this.fillCombo("day"),this.$element.val(d.format(this.options.format)).change())}},highlight:function(a){a.isValid()?this.options.errorClass?this.$widget.removeClass(this.options.errorClass):this.$widget.find("select").css("border-color",this.borderColor):this.options.errorClass?this.$widget.addClass(this.options.errorClass):(this.borderColor||(this.borderColor=this.$widget.find("select").css("border-color")),this.$widget.find("select").css("border-color","red"))},leadZero:function(a){return 9>=a?"0"+a:a},destroy:function(){this.$widget.remove(),this.$element.removeData("combodate").show()}},a.fn.combodate=function(c){var d,e=Array.apply(null,arguments);return e.shift(),"getValue"===c&&this.length&&(d=this.eq(0).data("combodate"))?d.getValue.apply(d,e):this.each(function(){var d=a(this),f=d.data("combodate"),g="object"==typeof c&&c;f||d.data("combodate",f=new b(this,g)),"string"==typeof c&&"function"==typeof f[c]&&f[c].apply(f,e)})},a.fn.combodate.defaults={format:"DD-MM-YYYY HH:mm",template:"D / MMM / YYYY H : mm",value:null,minYear:1970,maxYear:2015,yearDescending:!0,minuteStep:5,secondStep:1,firstItem:"empty",errorClass:null,roundTime:!0,smartDays:!1}}(window.jQuery),function(a){"use strict";var b=function(c){this.init("combodate",c,b.defaults),this.options.viewformat||(this.options.viewformat=this.options.format),c.combodate=a.fn.editableutils.tryParseJson(c.combodate,!0),this.options.combodate=a.extend({},b.defaults.combodate,c.combodate,{format:this.options.format,template:this.options.template})};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{render:function(){this.$input.combodate(this.options.combodate),"bs3"===a.fn.editableform.engine&&this.$input.siblings().find("select").addClass("form-control"),this.options.inputclass&&this.$input.siblings().find("select").addClass(this.options.inputclass)},value2html:function(a,c){var d=a?a.format(this.options.viewformat):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return a?moment(a,this.options.viewformat):null},value2str:function(a){return a?a.format(this.options.format):""},str2value:function(a){return a?moment(a,this.options.format):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.combodate("setValue",a)},input2value:function(){return this.$input.combodate("getValue",null)},activate:function(){this.$input.siblings(".combodate").find("select").eq(0).focus()},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<input type="text">',inputclass:null,format:"YYYY-MM-DD",viewformat:null,template:"D / MMM / YYYY",combodate:null}),a.fn.editabletypes.combodate=b}(window.jQuery),function(a){"use strict";var b=a.fn.editableform.Constructor.prototype.initInput;a.extend(a.fn.editableform.Constructor.prototype,{initTemplate:function(){this.$form=a(a.fn.editableform.template),this.$form.find(".control-group").addClass("form-group"),this.$form.find(".editable-error-block").addClass("help-block")},initInput:function(){b.apply(this);var c=null===this.input.options.inputclass||this.input.options.inputclass===!1,d="input-sm",e="text,select,textarea,password,email,url,tel,number,range,time,typeaheadjs".split(",");~a.inArray(this.input.type,e)&&(this.input.$input.addClass("form-control"),c&&(this.input.options.inputclass=d,this.input.$input.addClass(d)));for(var f=this.$form.find(".editable-buttons"),g=c?[d]:this.input.options.inputclass.split(" "),h=0;h<g.length;h++)"input-lg"===g[h].toLowerCase()&&f.find("button").removeClass("btn-sm").addClass("btn-lg")}}),a.fn.editableform.buttons='<button type="submit" class="btn btn-primary btn-sm editable-submit"><i class="glyphicon glyphicon-ok"></i></button><button type="button" class="btn btn-default btn-sm editable-cancel"><i class="glyphicon glyphicon-remove"></i></button>',a.fn.editableform.errorGroupClass="has-error",a.fn.editableform.errorBlockClass=null,a.fn.editableform.engine="bs3"}(window.jQuery),function(a){"use strict";a.extend(a.fn.editableContainer.Popup.prototype,{containerName:"popover",containerDataName:"bs.popover",innerCss:".popover-content",defaults:a.fn.popover.Constructor.DEFAULTS,initContainer:function(){a.extend(this.containerOptions,{trigger:"manual",selector:!1,content:" ",template:this.defaults.template});var b;this.$element.data("template")&&(b=this.$element.data("template"),this.$element.removeData("template")),this.call(this.containerOptions),b&&this.$element.data("template",b)},innerShow:function(){this.call("show")},innerHide:function(){this.call("hide")},innerDestroy:function(){this.call("destroy")},setContainerOption:function(a,b){this.container().options[a]=b},setPosition:function(){!function(){var a=this.tip(),b="function"==typeof this.options.placement?this.options.placement.call(this,a[0],this.$element[0]):this.options.placement,c=/\s?auto?\s?/i,d=c.test(b);d&&(b=b.replace(c,"")||"top");var e=this.getPosition(),f=a[0].offsetWidth,g=a[0].offsetHeight;if(d){var h=this.$element.parent(),i=b,j=document.documentElement.scrollTop||document.body.scrollTop,k="body"==this.options.container?window.innerWidth:h.outerWidth(),l="body"==this.options.container?window.innerHeight:h.outerHeight(),m="body"==this.options.container?0:h.offset().left;b="bottom"==b&&e.top+e.height+g-j>l?"top":"top"==b&&e.top-j-g<0?"bottom":"right"==b&&e.right+f>k?"left":"left"==b&&e.left-f<m?"right":b,a.removeClass(i).addClass(b)}var n=this.getCalculatedOffset(b,e,f,g);this.applyPlacement(n,b)}.call(this.container())}})}(window.jQuery),function(a){function b(){return new Date(Date.UTC.apply(Date,arguments))}function c(b,c){var d,e=a(b).data(),f={},g=new RegExp("^"+c.toLowerCase()+"([A-Z])"),c=new RegExp("^"+c.toLowerCase());for(var h in e)c.test(h)&&(d=h.replace(g,function(a,b){return b.toLowerCase()}),f[d]=e[h]);return f}function d(b){var c={};if(k[b]||(b=b.split("-")[0],k[b])){var d=k[b];return a.each(j,function(a,b){b in d&&(c[b]=d[b])}),c}}var e=function(b,c){this._process_options(c),this.element=a(b),this.isInline=!1,this.isInput=this.element.is("input"),this.component=this.element.is(".date")?this.element.find(".add-on, .btn"):!1,this.hasInput=this.component&&this.element.find("input").length,this.component&&0===this.component.length&&(this.component=!1),this.picker=a(l.template),this._buildEvents(),this._attachEvents(),this.isInline?this.picker.addClass("datepicker-inline").appendTo(this.element):this.picker.addClass("datepicker-dropdown dropdown-menu"),this.o.rtl&&(this.picker.addClass("datepicker-rtl"),this.picker.find(".prev i, .next i").toggleClass("icon-arrow-left icon-arrow-right")),this.viewMode=this.o.startView,this.o.calendarWeeks&&this.picker.find("tfoot th.today").attr("colspan",function(a,b){return parseInt(b)+1}),this._allow_update=!1,this.setStartDate(this.o.startDate),this.setEndDate(this.o.endDate),this.setDaysOfWeekDisabled(this.o.daysOfWeekDisabled),this.fillDow(),this.fillMonths(),this._allow_update=!0,this.update(),this.showMode(),this.isInline&&this.show()};e.prototype={constructor:e,_process_options:function(b){this._o=a.extend({},this._o,b);var c=this.o=a.extend({},this._o),d=c.language;switch(k[d]||(d=d.split("-")[0],k[d]||(d=i.language)),c.language=d,c.startView){case 2:case"decade":c.startView=2;break;case 1:case"year":c.startView=1;break;default:c.startView=0}switch(c.minViewMode){case 1:case"months":c.minViewMode=1;break;case 2:case"years":c.minViewMode=2;break;default:c.minViewMode=0}c.startView=Math.max(c.startView,c.minViewMode),c.weekStart%=7,c.weekEnd=(c.weekStart+6)%7;var e=l.parseFormat(c.format);c.startDate!==-1/0&&(c.startDate=l.parseDate(c.startDate,e,c.language)),1/0!==c.endDate&&(c.endDate=l.parseDate(c.endDate,e,c.language)),c.daysOfWeekDisabled=c.daysOfWeekDisabled||[],a.isArray(c.daysOfWeekDisabled)||(c.daysOfWeekDisabled=c.daysOfWeekDisabled.split(/[,\s]*/)),c.daysOfWeekDisabled=a.map(c.daysOfWeekDisabled,function(a){return parseInt(a,10)})},_events:[],_secondaryEvents:[],_applyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.on(c)},_unapplyEvents:function(a){for(var b,c,d=0;d<a.length;d++)b=a[d][0],c=a[d][1],b.off(c)},_buildEvents:function(){this.isInput?this._events=[[this.element,{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}]]:this.component&&this.hasInput?this._events=[[this.element.find("input"),{focus:a.proxy(this.show,this),keyup:a.proxy(this.update,this),keydown:a.proxy(this.keydown,this)}],[this.component,{click:a.proxy(this.show,this)}]]:this.element.is("div")?this.isInline=!0:this._events=[[this.element,{click:a.proxy(this.show,this)}]],this._secondaryEvents=[[this.picker,{click:a.proxy(this.click,this)}],[a(window),{resize:a.proxy(this.place,this)}],[a(document),{mousedown:a.proxy(function(a){this.element.is(a.target)||this.element.find(a.target).size()||this.picker.is(a.target)||this.picker.find(a.target).size()||this.hide()},this)}]]},_attachEvents:function(){this._detachEvents(),this._applyEvents(this._events)},_detachEvents:function(){this._unapplyEvents(this._events)},_attachSecondaryEvents:function(){this._detachSecondaryEvents(),this._applyEvents(this._secondaryEvents)},_detachSecondaryEvents:function(){this._unapplyEvents(this._secondaryEvents)},_trigger:function(b,c){var d=c||this.date,e=new Date(d.getTime()+6e4*d.getTimezoneOffset());this.element.trigger({type:b,date:e,format:a.proxy(function(a){var b=a||this.o.format;return l.formatDate(d,b,this.o.language)},this)})},show:function(a){this.isInline||this.picker.appendTo("body"),this.picker.show(),this.height=this.component?this.component.outerHeight():this.element.outerHeight(),this.place(),this._attachSecondaryEvents(),a&&a.preventDefault(),this._trigger("show")},hide:function(){this.isInline||this.picker.is(":visible")&&(this.picker.hide().detach(),this._detachSecondaryEvents(),this.viewMode=this.o.startView,this.showMode(),this.o.forceParse&&(this.isInput&&this.element.val()||this.hasInput&&this.element.find("input").val())&&this.setValue(),this._trigger("hide"))},remove:function(){this.hide(),this._detachEvents(),this._detachSecondaryEvents(),this.picker.remove(),delete this.element.data().datepicker,this.isInput||delete this.element.data().date},getDate:function(){var a=this.getUTCDate();return new Date(a.getTime()+6e4*a.getTimezoneOffset())},getUTCDate:function(){return this.date},setDate:function(a){this.setUTCDate(new Date(a.getTime()-6e4*a.getTimezoneOffset()))},setUTCDate:function(a){this.date=a,this.setValue()},setValue:function(){var a=this.getFormattedDate();this.isInput?this.element.val(a):this.component&&this.element.find("input").val(a)},getFormattedDate:function(a){return void 0===a&&(a=this.o.format),l.formatDate(this.date,a,this.o.language)},setStartDate:function(a){this._process_options({startDate:a}),this.update(),this.updateNavArrows()},setEndDate:function(a){this._process_options({endDate:a}),this.update(),this.updateNavArrows()},setDaysOfWeekDisabled:function(a){this._process_options({daysOfWeekDisabled:a}),this.update(),this.updateNavArrows()},place:function(){if(!this.isInline){var b=parseInt(this.element.parents().filter(function(){return"auto"!=a(this).css("z-index")}).first().css("z-index"))+10,c=this.component?this.component.parent().offset():this.element.offset(),d=this.component?this.component.outerHeight(!0):this.element.outerHeight(!0);this.picker.css({top:c.top+d,left:c.left,zIndex:b})}},_allow_update:!0,update:function(){if(this._allow_update){var a,b=!1;arguments&&arguments.length&&("string"==typeof arguments[0]||arguments[0]instanceof Date)?(a=arguments[0],b=!0):(a=this.isInput?this.element.val():this.element.data("date")||this.element.find("input").val(),delete this.element.data().date),this.date=l.parseDate(a,this.o.format,this.o.language),b&&this.setValue(),this.viewDate=this.date<this.o.startDate?new Date(this.o.startDate):this.date>this.o.endDate?new Date(this.o.endDate):new Date(this.date),this.fill()}},fillDow:function(){var a=this.o.weekStart,b="<tr>";if(this.o.calendarWeeks){var c='<th class="cw"> </th>';b+=c,this.picker.find(".datepicker-days thead tr:first-child").prepend(c)}for(;a<this.o.weekStart+7;)b+='<th class="dow">'+k[this.o.language].daysMin[a++%7]+"</th>";b+="</tr>",this.picker.find(".datepicker-days thead").append(b)},fillMonths:function(){for(var a="",b=0;12>b;)a+='<span class="month">'+k[this.o.language].monthsShort[b++]+"</span>";this.picker.find(".datepicker-months td").html(a)},setRange:function(b){b&&b.length?this.range=a.map(b,function(a){return a.valueOf()}):delete this.range,this.fill()},getClassNames:function(b){var c=[],d=this.viewDate.getUTCFullYear(),e=this.viewDate.getUTCMonth(),f=this.date.valueOf(),g=new Date;return b.getUTCFullYear()<d||b.getUTCFullYear()==d&&b.getUTCMonth()<e?c.push("old"):(b.getUTCFullYear()>d||b.getUTCFullYear()==d&&b.getUTCMonth()>e)&&c.push("new"),this.o.todayHighlight&&b.getUTCFullYear()==g.getFullYear()&&b.getUTCMonth()==g.getMonth()&&b.getUTCDate()==g.getDate()&&c.push("today"),f&&b.valueOf()==f&&c.push("active"),(b.valueOf()<this.o.startDate||b.valueOf()>this.o.endDate||-1!==a.inArray(b.getUTCDay(),this.o.daysOfWeekDisabled))&&c.push("disabled"),this.range&&(b>this.range[0]&&b<this.range[this.range.length-1]&&c.push("range"),-1!=a.inArray(b.valueOf(),this.range)&&c.push("selected")),c},fill:function(){var c,d=new Date(this.viewDate),e=d.getUTCFullYear(),f=d.getUTCMonth(),g=this.o.startDate!==-1/0?this.o.startDate.getUTCFullYear():-1/0,h=this.o.startDate!==-1/0?this.o.startDate.getUTCMonth():-1/0,i=1/0!==this.o.endDate?this.o.endDate.getUTCFullYear():1/0,j=1/0!==this.o.endDate?this.o.endDate.getUTCMonth():1/0;this.date&&this.date.valueOf(),this.picker.find(".datepicker-days thead th.datepicker-switch").text(k[this.o.language].months[f]+" "+e),this.picker.find("tfoot th.today").text(k[this.o.language].today).toggle(this.o.todayBtn!==!1),this.picker.find("tfoot th.clear").text(k[this.o.language].clear).toggle(this.o.clearBtn!==!1),this.updateNavArrows(),this.fillMonths();var m=b(e,f-1,28,0,0,0,0),n=l.getDaysInMonth(m.getUTCFullYear(),m.getUTCMonth());m.setUTCDate(n),m.setUTCDate(n-(m.getUTCDay()-this.o.weekStart+7)%7);var o=new Date(m);o.setUTCDate(o.getUTCDate()+42),o=o.valueOf();for(var p,q=[];m.valueOf()<o;){if(m.getUTCDay()==this.o.weekStart&&(q.push("<tr>"),this.o.calendarWeeks)){var r=new Date(+m+864e5*((this.o.weekStart-m.getUTCDay()-7)%7)),s=new Date(+r+864e5*((11-r.getUTCDay())%7)),t=new Date(+(t=b(s.getUTCFullYear(),0,1))+864e5*((11-t.getUTCDay())%7)),u=(s-t)/864e5/7+1;q.push('<td class="cw">'+u+"</td>")}p=this.getClassNames(m),p.push("day");var v=this.o.beforeShowDay(m);void 0===v?v={}:"boolean"==typeof v?v={enabled:v}:"string"==typeof v&&(v={classes:v}),v.enabled===!1&&p.push("disabled"),v.classes&&(p=p.concat(v.classes.split(/\s+/))),v.tooltip&&(c=v.tooltip),p=a.unique(p),q.push('<td class="'+p.join(" ")+'"'+(c?' title="'+c+'"':"")+">"+m.getUTCDate()+"</td>"),m.getUTCDay()==this.o.weekEnd&&q.push("</tr>"),m.setUTCDate(m.getUTCDate()+1)}this.picker.find(".datepicker-days tbody").empty().append(q.join(""));var w=this.date&&this.date.getUTCFullYear(),x=this.picker.find(".datepicker-months").find("th:eq(1)").text(e).end().find("span").removeClass("active");w&&w==e&&x.eq(this.date.getUTCMonth()).addClass("active"),(g>e||e>i)&&x.addClass("disabled"),e==g&&x.slice(0,h).addClass("disabled"),e==i&&x.slice(j+1).addClass("disabled"),q="",e=10*parseInt(e/10,10);var y=this.picker.find(".datepicker-years").find("th:eq(1)").text(e+"-"+(e+9)).end().find("td");e-=1;for(var z=-1;11>z;z++)q+='<span class="year'+(-1==z?" old":10==z?" new":"")+(w==e?" active":"")+(g>e||e>i?" disabled":"")+'">'+e+"</span>",e+=1;y.html(q)},updateNavArrows:function(){if(this._allow_update){var a=new Date(this.viewDate),b=a.getUTCFullYear(),c=a.getUTCMonth();switch(this.viewMode){case 0:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()&&c<=this.o.startDate.getUTCMonth()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()&&c>=this.o.endDate.getUTCMonth()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"});break;case 1:case 2:this.o.startDate!==-1/0&&b<=this.o.startDate.getUTCFullYear()?this.picker.find(".prev").css({visibility:"hidden"}):this.picker.find(".prev").css({visibility:"visible"}),1/0!==this.o.endDate&&b>=this.o.endDate.getUTCFullYear()?this.picker.find(".next").css({visibility:"hidden"}):this.picker.find(".next").css({visibility:"visible"})}}},click:function(c){c.preventDefault();var d=a(c.target).closest("span, td, th");if(1==d.length)switch(d[0].nodeName.toLowerCase()){case"th":switch(d[0].className){case"datepicker-switch":this.showMode(1);break;case"prev":case"next":var e=l.modes[this.viewMode].navStep*("prev"==d[0].className?-1:1);switch(this.viewMode){case 0:this.viewDate=this.moveMonth(this.viewDate,e);break;case 1:case 2:this.viewDate=this.moveYear(this.viewDate,e)}this.fill();break;case"today":var f=new Date;f=b(f.getFullYear(),f.getMonth(),f.getDate(),0,0,0),this.showMode(-2);var g="linked"==this.o.todayBtn?null:"view";this._setDate(f,g);break;case"clear":var h;this.isInput?h=this.element:this.component&&(h=this.element.find("input")),h&&h.val("").change(),this._trigger("changeDate"),this.update(),this.o.autoclose&&this.hide()}break;case"span":if(!d.is(".disabled")){if(this.viewDate.setUTCDate(1),d.is(".month")){var i=1,j=d.parent().find("span").index(d),k=this.viewDate.getUTCFullYear();this.viewDate.setUTCMonth(j),this._trigger("changeMonth",this.viewDate),1===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}else{var k=parseInt(d.text(),10)||0,i=1,j=0;this.viewDate.setUTCFullYear(k),this._trigger("changeYear",this.viewDate),2===this.o.minViewMode&&this._setDate(b(k,j,i,0,0,0,0))}this.showMode(-1),this.fill()}break;case"td":if(d.is(".day")&&!d.is(".disabled")){var i=parseInt(d.text(),10)||1,k=this.viewDate.getUTCFullYear(),j=this.viewDate.getUTCMonth();d.is(".old")?0===j?(j=11,k-=1):j-=1:d.is(".new")&&(11==j?(j=0,k+=1):j+=1),this._setDate(b(k,j,i,0,0,0,0))}}},_setDate:function(a,b){b&&"date"!=b||(this.date=new Date(a)),b&&"view"!=b||(this.viewDate=new Date(a)),this.fill(),this.setValue(),this._trigger("changeDate");var c;this.isInput?c=this.element:this.component&&(c=this.element.find("input")),c&&(c.change(),!this.o.autoclose||b&&"date"!=b||this.hide())},moveMonth:function(a,b){if(!b)return a;var c,d,e=new Date(a.valueOf()),f=e.getUTCDate(),g=e.getUTCMonth(),h=Math.abs(b);if(b=b>0?1:-1,1==h)d=-1==b?function(){return e.getUTCMonth()==g}:function(){return e.getUTCMonth()!=c},c=g+b,e.setUTCMonth(c),(0>c||c>11)&&(c=(c+12)%12);else{for(var i=0;h>i;i++)e=this.moveMonth(e,b);c=e.getUTCMonth(),e.setUTCDate(f),d=function(){return c!=e.getUTCMonth()}}for(;d();)e.setUTCDate(--f),e.setUTCMonth(c);return e},moveYear:function(a,b){return this.moveMonth(a,12*b)},dateWithinRange:function(a){return a>=this.o.startDate&&a<=this.o.endDate},keydown:function(a){if(this.picker.is(":not(:visible)"))return 27==a.keyCode&&this.show(),void 0;var b,c,d,e=!1;switch(a.keyCode){case 27:this.hide(),a.preventDefault();break;case 37:case 39:if(!this.o.keyboardNavigation)break;b=37==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 38:case 40:if(!this.o.keyboardNavigation)break;b=38==a.keyCode?-1:1,a.ctrlKey?(c=this.moveYear(this.date,b),d=this.moveYear(this.viewDate,b)):a.shiftKey?(c=this.moveMonth(this.date,b),d=this.moveMonth(this.viewDate,b)):(c=new Date(this.date),c.setUTCDate(this.date.getUTCDate()+7*b),d=new Date(this.viewDate),d.setUTCDate(this.viewDate.getUTCDate()+7*b)),this.dateWithinRange(c)&&(this.date=c,this.viewDate=d,this.setValue(),this.update(),a.preventDefault(),e=!0);break;case 13:this.hide(),a.preventDefault();break;case 9:this.hide()}if(e){this._trigger("changeDate");var f;this.isInput?f=this.element:this.component&&(f=this.element.find("input")),f&&f.change()}},showMode:function(a){a&&(this.viewMode=Math.max(this.o.minViewMode,Math.min(2,this.viewMode+a))),this.picker.find(">div").hide().filter(".datepicker-"+l.modes[this.viewMode].clsName).css("display","block"),this.updateNavArrows()}};var f=function(b,c){this.element=a(b),this.inputs=a.map(c.inputs,function(a){return a.jquery?a[0]:a}),delete c.inputs,a(this.inputs).datepicker(c).bind("changeDate",a.proxy(this.dateUpdated,this)),this.pickers=a.map(this.inputs,function(b){return a(b).data("datepicker")}),this.updateDates()};f.prototype={updateDates:function(){this.dates=a.map(this.pickers,function(a){return a.date}),this.updateRanges()},updateRanges:function(){var b=a.map(this.dates,function(a){return a.valueOf()});a.each(this.pickers,function(a,c){c.setRange(b)})},dateUpdated:function(b){var c=a(b.target).data("datepicker"),d=c.getUTCDate(),e=a.inArray(b.target,this.inputs),f=this.inputs.length;if(-1!=e){if(d<this.dates[e])for(;e>=0&&d<this.dates[e];)this.pickers[e--].setUTCDate(d);else if(d>this.dates[e])for(;f>e&&d>this.dates[e];)this.pickers[e++].setUTCDate(d);this.updateDates()}},remove:function(){a.map(this.pickers,function(a){a.remove()}),delete this.element.data().datepicker}};var g=a.fn.datepicker,h=a.fn.datepicker=function(b){var g=Array.apply(null,arguments);g.shift();var h;return this.each(function(){var j=a(this),k=j.data("datepicker"),l="object"==typeof b&&b;if(!k){var m=c(this,"date"),n=a.extend({},i,m,l),o=d(n.language),p=a.extend({},i,o,m,l);if(j.is(".input-daterange")||p.inputs){var q={inputs:p.inputs||j.find("input").toArray()};j.data("datepicker",k=new f(this,a.extend(p,q)))}else j.data("datepicker",k=new e(this,p))}return"string"==typeof b&&"function"==typeof k[b]&&(h=k[b].apply(k,g),void 0!==h)?!1:void 0}),void 0!==h?h:this},i=a.fn.datepicker.defaults={autoclose:!1,beforeShowDay:a.noop,calendarWeeks:!1,clearBtn:!1,daysOfWeekDisabled:[],endDate:1/0,forceParse:!0,format:"mm/dd/yyyy",keyboardNavigation:!0,language:"en",minViewMode:0,rtl:!1,startDate:-1/0,startView:0,todayBtn:!1,todayHighlight:!1,weekStart:0},j=a.fn.datepicker.locale_opts=["format","rtl","weekStart"];a.fn.datepicker.Constructor=e;var k=a.fn.datepicker.dates={en:{days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"],daysShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat","Sun"],daysMin:["Su","Mo","Tu","We","Th","Fr","Sa","Su"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],monthsShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],today:"Today",clear:"Clear"}},l={modes:[{clsName:"days",navFnc:"Month",navStep:1},{clsName:"months",navFnc:"FullYear",navStep:1},{clsName:"years",navFnc:"FullYear",navStep:10}],isLeapYear:function(a){return 0===a%4&&0!==a%100||0===a%400
|
7 |
},getDaysInMonth:function(a,b){return[31,l.isLeapYear(a)?29:28,31,30,31,30,31,31,30,31,30,31][b]},validParts:/dd?|DD?|mm?|MM?|yy(?:yy)?/g,nonpunctuation:/[^ -\/:-@\[\u3400-\u9fff-`{-~\t\n\r]+/g,parseFormat:function(a){var b=a.replace(this.validParts,"\0").split("\0"),c=a.match(this.validParts);if(!b||!b.length||!c||0===c.length)throw new Error("Invalid date format.");return{separators:b,parts:c}},parseDate:function(c,d,f){if(c instanceof Date)return c;if("string"==typeof d&&(d=l.parseFormat(d)),/^[\-+]\d+[dmwy]([\s,]+[\-+]\d+[dmwy])*$/.test(c)){var g,h,i=/([\-+]\d+)([dmwy])/,j=c.match(/([\-+]\d+)([dmwy])/g);c=new Date;for(var m=0;m<j.length;m++)switch(g=i.exec(j[m]),h=parseInt(g[1]),g[2]){case"d":c.setUTCDate(c.getUTCDate()+h);break;case"m":c=e.prototype.moveMonth.call(e.prototype,c,h);break;case"w":c.setUTCDate(c.getUTCDate()+7*h);break;case"y":c=e.prototype.moveYear.call(e.prototype,c,h)}return b(c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate(),0,0,0)}var n,o,g,j=c&&c.match(this.nonpunctuation)||[],c=new Date,p={},q=["yyyy","yy","M","MM","m","mm","d","dd"],r={yyyy:function(a,b){return a.setUTCFullYear(b)},yy:function(a,b){return a.setUTCFullYear(2e3+b)},m:function(a,b){for(b-=1;0>b;)b+=12;for(b%=12,a.setUTCMonth(b);a.getUTCMonth()!=b;)a.setUTCDate(a.getUTCDate()-1);return a},d:function(a,b){return a.setUTCDate(b)}};r.M=r.MM=r.mm=r.m,r.dd=r.d,c=b(c.getFullYear(),c.getMonth(),c.getDate(),0,0,0);var s=d.parts.slice();if(j.length!=s.length&&(s=a(s).filter(function(b,c){return-1!==a.inArray(c,q)}).toArray()),j.length==s.length){for(var m=0,t=s.length;t>m;m++){if(n=parseInt(j[m],10),g=s[m],isNaN(n))switch(g){case"MM":o=a(k[f].months).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].months)+1;break;case"M":o=a(k[f].monthsShort).filter(function(){var a=this.slice(0,j[m].length),b=j[m].slice(0,a.length);return a==b}),n=a.inArray(o[0],k[f].monthsShort)+1}p[g]=n}for(var u,m=0;m<q.length;m++)u=q[m],u in p&&!isNaN(p[u])&&r[u](c,p[u])}return c},formatDate:function(b,c,d){"string"==typeof c&&(c=l.parseFormat(c));var e={d:b.getUTCDate(),D:k[d].daysShort[b.getUTCDay()],DD:k[d].days[b.getUTCDay()],m:b.getUTCMonth()+1,M:k[d].monthsShort[b.getUTCMonth()],MM:k[d].months[b.getUTCMonth()],yy:b.getUTCFullYear().toString().substring(2),yyyy:b.getUTCFullYear()};e.dd=(e.d<10?"0":"")+e.d,e.mm=(e.m<10?"0":"")+e.m;for(var b=[],f=a.extend([],c.separators),g=0,h=c.parts.length;h>=g;g++)f.length&&b.push(f.shift()),b.push(e[c.parts[g]]);return b.join("")},headTemplate:'<thead><tr><th class="prev"><i class="icon-arrow-left"/></th><th colspan="5" class="datepicker-switch"></th><th class="next"><i class="icon-arrow-right"/></th></tr></thead>',contTemplate:'<tbody><tr><td colspan="7"></td></tr></tbody>',footTemplate:'<tfoot><tr><th colspan="7" class="today"></th></tr><tr><th colspan="7" class="clear"></th></tr></tfoot>'};l.template='<div class="datepicker"><div class="datepicker-days"><table class=" table-condensed">'+l.headTemplate+"<tbody></tbody>"+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-months">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+'<div class="datepicker-years">'+'<table class="table-condensed">'+l.headTemplate+l.contTemplate+l.footTemplate+"</table>"+"</div>"+"</div>",a.fn.datepicker.DPGlobal=l,a.fn.datepicker.noConflict=function(){return a.fn.datepicker=g,this},a(document).on("focus.datepicker.data-api click.datepicker.data-api",'[data-provide="datepicker"]',function(b){var c=a(this);c.data("datepicker")||(b.preventDefault(),h.call(c,"show"))}),a(function(){h.call(a('[data-provide="datepicker-inline"]'))})}(window.jQuery),function(a){"use strict";a.fn.bdatepicker=a.fn.datepicker.noConflict(),a.fn.datepicker||(a.fn.datepicker=a.fn.bdatepicker);var b=function(a){this.init("date",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datepicker=a.fn.editableutils.tryParseJson(b.datepicker,!0),this.options.datepicker=a.extend({},c.datepicker,b.datepicker,{format:this.options.viewformat}),this.options.datepicker.language=this.options.datepicker.language||"en",this.dpg=a.fn.bdatepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat)},render:function(){this.$input.bdatepicker(this.options.datepicker),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):"";b.superclass.value2html.call(this,d,c)},html2value:function(a){return this.parseDate(a,this.parsedViewFormat)},value2str:function(a){return a?this.dpg.formatDate(a,this.parsedFormat,this.options.datepicker.language):""},str2value:function(a){return this.parseDate(a,this.parsedFormat)},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.bdatepicker("update",a)},input2value:function(){return this.$input.data("datepicker").date},activate:function(){},clear:function(){this.$input.data("datepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".day",function(b){if(!a(b.currentTarget).is(".old")&&!a(b.currentTarget).is(".new")){var c=a(this).closest("form");setTimeout(function(){c.submit()},200)}})},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datepicker.language),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datepicker.language),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd",viewformat:null,datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!1},clear:"× clear"}),a.fn.editabletypes.date=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.date),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.bdatepicker(this.options.datepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.bdatepicker("update")},this))},value2input:function(a){this.$input.val(a?this.dpg.formatDate(a,this.parsedViewFormat,this.options.datepicker.language):""),this.$tpl.bdatepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.date.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-small",datepicker:{weekStart:0,startView:0,minViewMode:0,autoclose:!0}}),a.fn.editabletypes.datefield=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetime",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.abstractinput),a.extend(b.prototype,{initPicker:function(b,c){this.options.viewformat||(this.options.viewformat=this.options.format),b.datetimepicker=a.fn.editableutils.tryParseJson(b.datetimepicker,!0),this.options.datetimepicker=a.extend({},c.datetimepicker,b.datetimepicker,{format:this.options.viewformat}),this.options.datetimepicker.language=this.options.datetimepicker.language||"en",this.dpg=a.fn.datetimepicker.DPGlobal,this.parsedFormat=this.dpg.parseFormat(this.options.format,this.options.formatType),this.parsedViewFormat=this.dpg.parseFormat(this.options.viewformat,this.options.formatType)},render:function(){this.$input.datetimepicker(this.options.datetimepicker),this.$input.on("changeMode",function(){var b=a(this).closest("form").parent();setTimeout(function(){b.triggerHandler("resize")},0)}),this.options.clear&&(this.$clear=a('<a href="#"></a>').html(this.options.clear).click(a.proxy(function(a){a.preventDefault(),a.stopPropagation(),this.clear()},this)),this.$tpl.parent().append(a('<div class="editable-clear">').append(this.$clear)))},value2html:function(a,c){var d=a?this.dpg.formatDate(this.toUTC(a),this.parsedViewFormat,this.options.datetimepicker.language,this.options.formatType):"";return c?(b.superclass.value2html.call(this,d,c),void 0):d},html2value:function(a){var b=this.parseDate(a,this.parsedViewFormat);return b?this.fromUTC(b):null},value2str:function(a){return a?this.dpg.formatDate(this.toUTC(a),this.parsedFormat,this.options.datetimepicker.language,this.options.formatType):""},str2value:function(a){var b=this.parseDate(a,this.parsedFormat);return b?this.fromUTC(b):null},value2submit:function(a){return this.value2str(a)},value2input:function(a){a&&this.$input.data("datetimepicker").setDate(a)},input2value:function(){var a=this.$input.data("datetimepicker");return a.date?a.getDate():null},activate:function(){},clear:function(){this.$input.data("datetimepicker").date=null,this.$input.find(".active").removeClass("active"),this.options.showbuttons||this.$input.closest("form").submit()},autosubmit:function(){this.$input.on("mouseup",".minute",function(){var b=a(this).closest("form");setTimeout(function(){b.submit()},200)})},toUTC:function(a){return a?new Date(a.valueOf()-6e4*a.getTimezoneOffset()):a},fromUTC:function(a){return a?new Date(a.valueOf()+6e4*a.getTimezoneOffset()):a},parseDate:function(a,b){var c,d=null;return a&&(d=this.dpg.parseDate(a,b,this.options.datetimepicker.language,this.options.formatType),"string"==typeof a&&(c=this.dpg.formatDate(d,b,this.options.datetimepicker.language,this.options.formatType),a!==c&&(d=null))),d}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'<div class="editable-date well"></div>',inputclass:null,format:"yyyy-mm-dd hh:ii",formatType:"standard",viewformat:null,datetimepicker:{todayHighlight:!1,autoclose:!1},clear:"× clear"}),a.fn.editabletypes.datetime=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("datetimefield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.datetime),a.extend(b.prototype,{render:function(){this.$input=this.$tpl.find("input"),this.setClass(),this.setAttr("placeholder"),this.$tpl.datetimepicker(this.options.datetimepicker),this.$input.off("focus keydown"),this.$input.keyup(a.proxy(function(){this.$tpl.removeData("date"),this.$tpl.datetimepicker("update")},this))},value2input:function(a){this.$input.val(this.value2html(a)),this.$tpl.datetimepicker("update")},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.datetime.defaults,{tpl:'<div class="input-append date"><input type="text"/><span class="add-on"><i class="icon-th"></i></span></div>',inputclass:"input-medium",datetimepicker:{todayHighlight:!1,autoclose:!0}}),a.fn.editabletypes.datetimefield=b}(window.jQuery);
|
backend/modules/appearance/templates/_1_service.php
CHANGED
@@ -1,166 +1,167 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Lib\Utils\Price;
|
3 |
-
use Bookly\Lib\Utils\DateTime;
|
4 |
-
use Bookly\Backend\Modules\Appearance\Proxy;
|
5 |
-
use Bookly\
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
<option value=""
|
27 |
-
<option value="
|
28 |
-
<option value="
|
29 |
-
<option value="
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
'
|
37 |
-
'
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
<option value="
|
43 |
-
<option value="1" class="service-name
|
44 |
-
<option value="
|
45 |
-
<option value="2" class="service-name
|
46 |
-
<option value="
|
47 |
-
<option value="3" class="service-name
|
48 |
-
<option value="
|
49 |
-
<option value="4" class="service-name
|
50 |
-
<option value="
|
51 |
-
<option value="5" class="service-name
|
52 |
-
<option value="
|
53 |
-
<option value="6" class="service-name
|
54 |
-
<option value="
|
55 |
-
<option value="7" class="service-name
|
56 |
-
<option value="
|
57 |
-
<option value="8" class="service-name
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
'
|
65 |
-
'
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
<option value="
|
71 |
-
<option value="1" class="employee-name
|
72 |
-
<option value="
|
73 |
-
<option value="2" class="employee-name
|
74 |
-
<option value="
|
75 |
-
<option value="3" class="employee-name
|
76 |
-
<option value="
|
77 |
-
<option value="4" class="employee-name
|
78 |
-
<option value="
|
79 |
-
<option value="5" class="employee-name
|
80 |
-
<option value="
|
81 |
-
<option value="6" class="employee-name
|
82 |
-
<option value="
|
83 |
-
<option value="7" class="employee-name
|
84 |
-
<option value="
|
85 |
-
<option value="8" class="employee-name
|
86 |
-
<option value="
|
87 |
-
<option value="9" class="employee-name
|
88 |
-
<option value="
|
89 |
-
<option value="10" class="employee-name
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
<?php Proxy\
|
95 |
-
<?php Proxy\
|
96 |
-
<?php Proxy\
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
<
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
<div class="bookly-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
</div>
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
|
|
166 |
<style id="bookly-pickadate-style"></style>
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Lib\Utils\Price;
|
3 |
+
use Bookly\Lib\Utils\DateTime;
|
4 |
+
use Bookly\Backend\Modules\Appearance\Proxy;
|
5 |
+
use Bookly\Backend\Components\Appearance\Editable;
|
6 |
+
/** @var WP_Locale $wp_locale */
|
7 |
+
global $wp_locale;
|
8 |
+
?>
|
9 |
+
<div class="bookly-form">
|
10 |
+
<?php include '_progress_tracker.php' ?>
|
11 |
+
|
12 |
+
<div class="bookly-service-step">
|
13 |
+
<div class="bookly-box">
|
14 |
+
<span class="bookly-bold bookly-desc">
|
15 |
+
<?php Editable::renderText( 'bookly_l10n_info_service_step' ) ?>
|
16 |
+
</span>
|
17 |
+
</div>
|
18 |
+
<div class="bookly-mobile-step-1 bookly-js-mobile-step-1 bookly-box">
|
19 |
+
<div class="bookly-js-chain-item bookly-table bookly-box">
|
20 |
+
<?php Proxy\Locations::renderLocation() ?>
|
21 |
+
<div class="bookly-form-group">
|
22 |
+
<?php Editable::renderLabel( array( 'bookly_l10n_label_category', 'bookly_l10n_option_category', ) ) ?>
|
23 |
+
<div>
|
24 |
+
<select class="bookly-select-mobile bookly-js-select-category">
|
25 |
+
<option value="" class="bookly-js-option bookly_l10n_option_category"><?php echo esc_html( get_option( 'bookly_l10n_option_category' ) ) ?></option>
|
26 |
+
<option value="1">Cosmetic Dentistry</option>
|
27 |
+
<option value="2">Invisalign</option>
|
28 |
+
<option value="3">Orthodontics</option>
|
29 |
+
<option value="4">Dentures</option>
|
30 |
+
</select>
|
31 |
+
</div>
|
32 |
+
</div>
|
33 |
+
<div class="bookly-form-group">
|
34 |
+
<?php Editable::renderLabel( array(
|
35 |
+
'bookly_l10n_label_service',
|
36 |
+
'bookly_l10n_option_service',
|
37 |
+
'bookly_l10n_required_service',
|
38 |
+
) ) ?>
|
39 |
+
<div>
|
40 |
+
<select class="bookly-select-mobile bookly-js-select-service">
|
41 |
+
<option value="0" class="bookly-js-option bookly_l10n_option_service"><?php echo esc_html( get_option( 'bookly_l10n_option_service' ) ) ?></option>
|
42 |
+
<option value="1" class="service-name-duration">Crown and Bridge (<?php echo DateTime::secondsToInterval( 3600 ) ?>)</option>
|
43 |
+
<option value="-1" class="service-name">Crown and Bridge</option>
|
44 |
+
<option value="2" class="service-name-duration">Teeth Whitening (<?php echo DateTime::secondsToInterval( 3600 * 2 ) ?>)</option>
|
45 |
+
<option value="-2" class="service-name">Teeth Whitening</option>
|
46 |
+
<option value="3" class="service-name-duration">Veneers (<?php echo DateTime::secondsToInterval( 3600 * 12 ) ?>)</option>
|
47 |
+
<option value="-3" class="service-name">Veneers</option>
|
48 |
+
<option value="4" class="service-name-duration">Invisalign (invisable braces) (<?php echo DateTime::secondsToInterval( 3600 * 24 ) ?>)</option>
|
49 |
+
<option value="-4" class="service-name">Invisalign (invisable braces)</option>
|
50 |
+
<option value="5" class="service-name-duration">Orthodontics (braces) (<?php echo DateTime::secondsToInterval( 3600 * 8 ) ?>)</option>
|
51 |
+
<option value="-5" class="service-name">Orthodontics (braces)</option>
|
52 |
+
<option value="6" class="service-name-duration">Wisdom tooth Removal (<?php echo DateTime::secondsToInterval( 3600 * 6 ) ?>)</option>
|
53 |
+
<option value="-6" class="service-name">Wisdom tooth Removal</option>
|
54 |
+
<option value="7" class="service-name-duration">Root Canal Treatment (<?php echo DateTime::secondsToInterval( 3600 * 16 ) ?>)</option>
|
55 |
+
<option value="-7" class="service-name">Root Canal Treatment</option>
|
56 |
+
<option value="8" class="service-name-duration">Dentures (<?php echo DateTime::secondsToInterval( 3600 * 48 ) ?>)</option>
|
57 |
+
<option value="-8" class="service-name">Dentures</option>
|
58 |
+
</select>
|
59 |
+
</div>
|
60 |
+
</div>
|
61 |
+
<div class="bookly-form-group">
|
62 |
+
<?php Editable::renderLabel( array(
|
63 |
+
'bookly_l10n_label_employee',
|
64 |
+
'bookly_l10n_option_employee',
|
65 |
+
'bookly_l10n_required_employee',
|
66 |
+
) ) ?>
|
67 |
+
<div>
|
68 |
+
<select class="bookly-select-mobile bookly-js-select-employee">
|
69 |
+
<option value="0" class="bookly-js-option bookly_l10n_option_employee"><?php echo esc_html( get_option( 'bookly_l10n_option_employee' ) ) ?></option>
|
70 |
+
<option value="1" class="employee-name-price">Nick Knight (<?php echo Price::format( 350 ) ?>)</option>
|
71 |
+
<option value="-1" class="employee-name">Nick Knight</option>
|
72 |
+
<option value="2" class="employee-name-price">Jane Howard (<?php echo Price::format( 375 ) ?>)</option>
|
73 |
+
<option value="-2" class="employee-name">Jane Howard</option>
|
74 |
+
<option value="3" class="employee-name-price">Ashley Stamp (<?php echo Price::format( 300 ) ?>)</option>
|
75 |
+
<option value="-3" class="employee-name">Ashley Stamp</option>
|
76 |
+
<option value="4" class="employee-name-price">Bradley Tannen (<?php echo Price::format( 400 ) ?>)</option>
|
77 |
+
<option value="-4" class="employee-name">Bradley Tannen</option>
|
78 |
+
<option value="5" class="employee-name-price">Wayne Turner (<?php echo Price::format( 350 ) ?>)</option>
|
79 |
+
<option value="-5" class="employee-name">Wayne Turner</option>
|
80 |
+
<option value="6" class="employee-name-price">Emily Taylor (<?php echo Price::format( 350 ) ?>)</option>
|
81 |
+
<option value="-6" class="employee-name">Emily Taylor</option>
|
82 |
+
<option value="7" class="employee-name-price">Hugh Canberg (<?php echo Price::format( 380 ) ?>)</option>
|
83 |
+
<option value="-7" class="employee-name">Hugh Canberg</option>
|
84 |
+
<option value="8" class="employee-name-price">Jim Gonzalez (<?php echo Price::format( 390 ) ?>)</option>
|
85 |
+
<option value="-8" class="employee-name">Jim Gonzalez</option>
|
86 |
+
<option value="9" class="employee-name-price">Nancy Stinson (<?php echo Price::format( 360 ) ?>)</option>
|
87 |
+
<option value="-9" class="employee-name">Nancy Stinson</option>
|
88 |
+
<option value="10" class="employee-name-price">Marry Murphy (<?php echo Price::format( 350 ) ?>)</option>
|
89 |
+
<option value="-10" class="employee-name">Marry Murphy</option>
|
90 |
+
</select>
|
91 |
+
</div>
|
92 |
+
</div>
|
93 |
+
<?php Proxy\CustomDuration::renderServiceDuration() ?>
|
94 |
+
<?php Proxy\GroupBooking::renderNOP() ?>
|
95 |
+
<?php Proxy\MultiplyAppointments::renderQuantity() ?>
|
96 |
+
<?php Proxy\ChainAppointments::renderChain() ?>
|
97 |
+
|
98 |
+
</div>
|
99 |
+
<div class="bookly-right bookly-mobile-next-step bookly-js-mobile-next-step bookly-btn bookly-none">
|
100 |
+
<?php Editable::renderString( array( 'bookly_l10n_step_service_mobile_button_next' ) ) ?>
|
101 |
+
</div>
|
102 |
+
</div>
|
103 |
+
<div class="bookly-mobile-step-2 bookly-js-mobile-step-2">
|
104 |
+
<div class="bookly-box">
|
105 |
+
<div class="bookly-left">
|
106 |
+
<div class="bookly-available-date bookly-js-available-date bookly-left">
|
107 |
+
<div class="bookly-form-group">
|
108 |
+
<?php Editable::renderLabel( array( 'bookly_l10n_label_select_date', ) ) ?>
|
109 |
+
<div>
|
110 |
+
<input class="bookly-date-from bookly-js-date-from" style="background-color: #fff;" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
111 |
+
</div>
|
112 |
+
</div>
|
113 |
+
</div>
|
114 |
+
<div class="bookly-week-days bookly-js-week-days bookly-table bookly-left">
|
115 |
+
<?php foreach ( $wp_locale->weekday_abbrev as $weekday_abbrev ) : ?>
|
116 |
+
<div>
|
117 |
+
<div class="bookly-font-bold"><?php echo $weekday_abbrev ?></div>
|
118 |
+
<label class="active">
|
119 |
+
<input class="bookly-js-week-day" value="1" checked="checked" type="checkbox">
|
120 |
+
</label>
|
121 |
+
</div>
|
122 |
+
<?php endforeach ?>
|
123 |
+
</div>
|
124 |
+
</div>
|
125 |
+
<div class="bookly-time-range bookly-js-time-range bookly-left">
|
126 |
+
<div class="bookly-form-group bookly-time-from bookly-left">
|
127 |
+
<?php Editable::renderLabel( array( 'bookly_l10n_label_start_from', ) ) ?>
|
128 |
+
<div>
|
129 |
+
<select class="bookly-js-select-time-from">
|
130 |
+
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
131 |
+
<option><?php echo DateTime::formatTime( $i ) ?></option>
|
132 |
+
<?php endfor ?>
|
133 |
+
</select>
|
134 |
+
</div>
|
135 |
+
</div>
|
136 |
+
<div class="bookly-form-group bookly-time-to bookly-left">
|
137 |
+
<?php Editable::renderLabel( array( 'bookly_l10n_label_finish_by', ) ) ?>
|
138 |
+
<div>
|
139 |
+
<select class="bookly-js-select-time-to">
|
140 |
+
<?php for ( $i = 28800; $i <= 64800; $i += 3600 ) : ?>
|
141 |
+
<option<?php selected( $i == 64800 ) ?>><?php echo DateTime::formatTime( $i ) ?></option>
|
142 |
+
<?php endfor ?>
|
143 |
+
</select>
|
144 |
+
</div>
|
145 |
+
</div>
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
<div class="bookly-box bookly-nav-steps">
|
149 |
+
<div class="bookly-right bookly-mobile-prev-step bookly-js-mobile-prev-step bookly-btn bookly-none">
|
150 |
+
<?php Editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
151 |
+
</div>
|
152 |
+
<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>
|
153 |
+
<div class="<?php echo get_option( 'bookly_app_align_buttons_left' ) ? 'bookly-left' : 'bookly-right' ?>">
|
154 |
+
<div class="bookly-next-step bookly-js-next-step bookly-btn">
|
155 |
+
<?php Editable::renderString( array( 'bookly_l10n_step_service_button_next' ) ) ?>
|
156 |
+
</div>
|
157 |
+
</div>
|
158 |
+
</div>
|
159 |
+
</div>
|
160 |
+
</div>
|
161 |
+
</div>
|
162 |
+
<div style="display: none">
|
163 |
+
<?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 ) : ?>
|
164 |
+
<div class="bookly-js-option <?php echo $validator ?>"><?php echo get_option( $validator ) ?></div>
|
165 |
+
<?php endforeach ?>
|
166 |
+
</div>
|
167 |
<style id="bookly-pickadate-style"></style>
|
backend/modules/appearance/templates/_3_time.php
CHANGED
@@ -1,204 +1,207 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Lib\Utils\DateTime;
|
3 |
-
use Bookly\Lib\Config;
|
4 |
-
use Bookly\Backend\Components\Appearance\Codes;
|
5 |
-
use Bookly\Backend\Components\Appearance\Editable;
|
6 |
-
use Bookly\Backend\Modules\Appearance\Proxy;
|
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_time_step', Codes::getHtml( 3 ) ) ?>
|
13 |
-
</div>
|
14 |
-
<?php Proxy\WaitingList::renderInfoText() ?>
|
15 |
-
<div class="bookly-box bookly-label-error" style="padding-bottom:2px">
|
16 |
-
<?php Editable::renderText( 'bookly_l10n_step_time_slot_not_available', null, 'bottom', __( 'Visible when the chosen time slot has been already booked', 'bookly' ) ) ?>
|
17 |
-
</div>
|
18 |
-
<?php Proxy\Pro::renderTimeZoneSwitcher() ?>
|
19 |
-
|
20 |
-
<!-- timeslots -->
|
21 |
-
<div class="bookly-time-step">
|
22 |
-
<div class="bookly-columnizer-wrap">
|
23 |
-
<div class="bookly-columnizer">
|
24 |
-
<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' ?>">
|
25 |
-
<div class="bookly-input-wrap bookly-slot-calendar bookly-js-slot-calendar">
|
26 |
-
<span class="bookly-date-wrap">
|
27 |
-
<input style="display: none" class="bookly-js-selected-date bookly-form-element" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
28 |
-
</span>
|
29 |
-
</div>
|
30 |
-
<div class="bookly-column col1">
|
31 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', current_time( 'timestamp' ) ) ?></button>
|
32 |
-
<?php for ( $i = 28800; $i <= 57600; $i += 3600 ) : ?>
|
33 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
34 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked'; elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list' ?>">
|
35 |
-
<span class="ladda-label bookly-time-main">
|
36 |
-
<i class="bookly-hour-icon"><span></span></i>
|
37 |
-
<?php echo DateTime::formatTime( $i ) ?>
|
38 |
-
</span>
|
39 |
-
<span class="bookly-time-additional"></span>
|
40 |
-
</button>
|
41 |
-
<?php endfor ?>
|
42 |
-
</div>
|
43 |
-
<div class="bookly-column col2">
|
44 |
-
<button class="bookly-hour ladda-button bookly-last-child">
|
45 |
-
<span class="ladda-label bookly-time-main">
|
46 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( 61200 ) ?>
|
47 |
-
</span>
|
48 |
-
<span class="bookly-time-additional"></span>
|
49 |
-
</button>
|
50 |
-
<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>
|
51 |
-
<?php for ( $i = 28800; $i <= 54000; $i += 3600 ) : ?>
|
52 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
53 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'block' ?>">
|
54 |
-
<span class="ladda-label bookly-time-main">
|
55 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
56 |
-
</span>
|
57 |
-
<span class="bookly-time-additional"></span>
|
58 |
-
</button>
|
59 |
-
<?php endfor ?>
|
60 |
-
</div>
|
61 |
-
<div class="bookly-column col3" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
62 |
-
<?php for ( $i = 57600; $i <= 61200; $i += 3600 ) : ?>
|
63 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
64 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
65 |
-
<span class="ladda-label bookly-time-main">
|
66 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
67 |
-
</span>
|
68 |
-
<span class="bookly-time-additional"></span>
|
69 |
-
</button>
|
70 |
-
<?php endfor ?>
|
71 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+2 days', current_time('timestamp') ) ) ?></button>
|
72 |
-
<?php for ( $i = 28800; $i <= 50400; $i += 3600 ) : ?>
|
73 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
74 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
75 |
-
<span class="ladda-label bookly-time-main">
|
76 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
77 |
-
</span>
|
78 |
-
<span class="bookly-time-additional"></span>
|
79 |
-
</button>
|
80 |
-
<?php endfor ?>
|
81 |
-
</div>
|
82 |
-
<div class="bookly-column col4" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
83 |
-
<?php for ( $i = 54000; $i <= 61200; $i += 3600 ) : ?>
|
84 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
85 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
86 |
-
<span class="ladda-label bookly-time-main">
|
87 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
88 |
-
</span>
|
89 |
-
<span class="bookly-time-additional"></span>
|
90 |
-
</button>
|
91 |
-
<?php endfor ?>
|
92 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+3 days', current_time( 'timestamp' ) ) ) ?></button>
|
93 |
-
<?php for ( $i = 28800; $i <= 46800; $i += 3600 ) : ?>
|
94 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
95 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
96 |
-
<span class="ladda-label bookly-time-main">
|
97 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
98 |
-
</span>
|
99 |
-
<span class="bookly-time-additional"></span>
|
100 |
-
</button>
|
101 |
-
<?php endfor ?>
|
102 |
-
</div>
|
103 |
-
<div class="bookly-column col5" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
104 |
-
<?php for ( $i = 50400; $i <= 61200; $i += 3600 ) : ?>
|
105 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
106 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
107 |
-
<span class="ladda-label bookly-time-main">
|
108 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
109 |
-
</span>
|
110 |
-
<span class="bookly-time-additional"></span>
|
111 |
-
</button>
|
112 |
-
<?php endfor ?>
|
113 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+4 days', current_time( 'timestamp' ) ) ) ?></button>
|
114 |
-
<?php for ( $i = 28800; $i <= 43200; $i += 3600 ) : ?>
|
115 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
116 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
117 |
-
<span class="ladda-label bookly-time-main">
|
118 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
119 |
-
</span>
|
120 |
-
<span class="bookly-time-additional"></span>
|
121 |
-
</button>
|
122 |
-
<?php endfor ?>
|
123 |
-
</div>
|
124 |
-
<div class="bookly-column col6" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
125 |
-
<?php for ( $i = 46800; $i <= 61200; $i += 3600 ) : ?>
|
126 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
127 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
128 |
-
<span class="ladda-label bookly-time-main">
|
129 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
130 |
-
</span>
|
131 |
-
<span class="bookly-time-additional"></span>
|
132 |
-
</button>
|
133 |
-
<?php endfor ?>
|
134 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+5 days', current_time( 'timestamp' ) ) ) ?></button>
|
135 |
-
<?php for ( $i = 28800; $i <= 39600; $i += 3600 ) : ?>
|
136 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
137 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
138 |
-
<span class="ladda-label bookly-time-main">
|
139 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
140 |
-
</span>
|
141 |
-
<span class="bookly-time-additional"></span>
|
142 |
-
</button>
|
143 |
-
<?php endfor ?>
|
144 |
-
</div>
|
145 |
-
<div class="bookly-column col7" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
146 |
-
<?php for ( $i = 43200; $i <= 61200; $i += 3600 ) : ?>
|
147 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
148 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
149 |
-
<span class="ladda-label bookly-time-main">
|
150 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
151 |
-
</span>
|
152 |
-
<span class="bookly-time-additional"></span>
|
153 |
-
</button>
|
154 |
-
<?php endfor ?>
|
155 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+6 days', current_time( 'timestamp' ) ) ) ?></button>
|
156 |
-
<?php for ( $i = 28800; $i <= 36000; $i += 3600 ) : ?>
|
157 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
158 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
159 |
-
<span class="ladda-label bookly-time-main">
|
160 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
161 |
-
</span>
|
162 |
-
<span class="bookly-time-additional"></span>
|
163 |
-
</button>
|
164 |
-
<?php endfor ?>
|
165 |
-
</div>
|
166 |
-
</div>
|
167 |
-
|
168 |
-
<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' ?>">
|
169 |
-
<div class="bookly-input-wrap bookly-slot-calendar bookly-js-slot-calendar">
|
170 |
-
<span class="bookly-date-wrap">
|
171 |
-
<input style="display: none" class="bookly-js-selected-date bookly-form-element" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
172 |
-
</span>
|
173 |
-
</div>
|
174 |
-
<?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
|
175 |
-
<div class="bookly-column col<?php echo $i ?>">
|
176 |
-
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+' . ( $i - 1 ) . ' days', current_time( 'timestamp' ) ) ) ?></button>
|
177 |
-
<?php for ( $j = 28800; $j <= 61200; $j += 3600 ) : ?>
|
178 |
-
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
179 |
-
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
180 |
-
<span class="ladda-label bookly-time-main">
|
181 |
-
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $j ) ?>
|
182 |
-
</span>
|
183 |
-
<span class="bookly-time-additional"></span>
|
184 |
-
</button>
|
185 |
-
<?php endfor ?>
|
186 |
-
</div>
|
187 |
-
<?php endfor ?>
|
188 |
-
</div>
|
189 |
-
</div>
|
190 |
-
</div>
|
191 |
-
</div>
|
192 |
-
<div class="bookly-box bookly-nav-steps">
|
193 |
-
<
|
194 |
-
|
195 |
-
</
|
196 |
-
<button class="bookly-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
|
|
|
|
|
1 |
+
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
+
use Bookly\Lib\Utils\DateTime;
|
3 |
+
use Bookly\Lib\Config;
|
4 |
+
use Bookly\Backend\Components\Appearance\Codes;
|
5 |
+
use Bookly\Backend\Components\Appearance\Editable;
|
6 |
+
use Bookly\Backend\Modules\Appearance\Proxy;
|
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_time_step', Codes::getHtml( 3 ) ) ?>
|
13 |
+
</div>
|
14 |
+
<?php Proxy\WaitingList::renderInfoText() ?>
|
15 |
+
<div class="bookly-box bookly-label-error" style="padding-bottom:2px">
|
16 |
+
<?php Editable::renderText( 'bookly_l10n_step_time_slot_not_available', null, 'bottom', __( 'Visible when the chosen time slot has been already booked', 'bookly' ) ) ?>
|
17 |
+
</div>
|
18 |
+
<?php Proxy\Pro::renderTimeZoneSwitcher() ?>
|
19 |
+
|
20 |
+
<!-- timeslots -->
|
21 |
+
<div class="bookly-time-step">
|
22 |
+
<div class="bookly-columnizer-wrap">
|
23 |
+
<div class="bookly-columnizer">
|
24 |
+
<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' ?>">
|
25 |
+
<div class="bookly-input-wrap bookly-slot-calendar bookly-js-slot-calendar">
|
26 |
+
<span class="bookly-date-wrap">
|
27 |
+
<input style="display: none" class="bookly-js-selected-date bookly-form-element" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
28 |
+
</span>
|
29 |
+
</div>
|
30 |
+
<div class="bookly-column col1">
|
31 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', current_time( 'timestamp' ) ) ?></button>
|
32 |
+
<?php for ( $i = 28800; $i <= 57600; $i += 3600 ) : ?>
|
33 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
34 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked'; elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list' ?>">
|
35 |
+
<span class="ladda-label bookly-time-main">
|
36 |
+
<i class="bookly-hour-icon"><span></span></i>
|
37 |
+
<?php echo DateTime::formatTime( $i ) ?>
|
38 |
+
</span>
|
39 |
+
<span class="bookly-time-additional"></span>
|
40 |
+
</button>
|
41 |
+
<?php endfor ?>
|
42 |
+
</div>
|
43 |
+
<div class="bookly-column col2">
|
44 |
+
<button class="bookly-hour ladda-button bookly-last-child">
|
45 |
+
<span class="ladda-label bookly-time-main">
|
46 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( 61200 ) ?>
|
47 |
+
</span>
|
48 |
+
<span class="bookly-time-additional"></span>
|
49 |
+
</button>
|
50 |
+
<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>
|
51 |
+
<?php for ( $i = 28800; $i <= 54000; $i += 3600 ) : ?>
|
52 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
53 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'block' ?>">
|
54 |
+
<span class="ladda-label bookly-time-main">
|
55 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
56 |
+
</span>
|
57 |
+
<span class="bookly-time-additional"></span>
|
58 |
+
</button>
|
59 |
+
<?php endfor ?>
|
60 |
+
</div>
|
61 |
+
<div class="bookly-column col3" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
62 |
+
<?php for ( $i = 57600; $i <= 61200; $i += 3600 ) : ?>
|
63 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
64 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
65 |
+
<span class="ladda-label bookly-time-main">
|
66 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
67 |
+
</span>
|
68 |
+
<span class="bookly-time-additional"></span>
|
69 |
+
</button>
|
70 |
+
<?php endfor ?>
|
71 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+2 days', current_time('timestamp') ) ) ?></button>
|
72 |
+
<?php for ( $i = 28800; $i <= 50400; $i += 3600 ) : ?>
|
73 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
74 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
75 |
+
<span class="ladda-label bookly-time-main">
|
76 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
77 |
+
</span>
|
78 |
+
<span class="bookly-time-additional"></span>
|
79 |
+
</button>
|
80 |
+
<?php endfor ?>
|
81 |
+
</div>
|
82 |
+
<div class="bookly-column col4" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
83 |
+
<?php for ( $i = 54000; $i <= 61200; $i += 3600 ) : ?>
|
84 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
85 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
86 |
+
<span class="ladda-label bookly-time-main">
|
87 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
88 |
+
</span>
|
89 |
+
<span class="bookly-time-additional"></span>
|
90 |
+
</button>
|
91 |
+
<?php endfor ?>
|
92 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+3 days', current_time( 'timestamp' ) ) ) ?></button>
|
93 |
+
<?php for ( $i = 28800; $i <= 46800; $i += 3600 ) : ?>
|
94 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
95 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
96 |
+
<span class="ladda-label bookly-time-main">
|
97 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
98 |
+
</span>
|
99 |
+
<span class="bookly-time-additional"></span>
|
100 |
+
</button>
|
101 |
+
<?php endfor ?>
|
102 |
+
</div>
|
103 |
+
<div class="bookly-column col5" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
104 |
+
<?php for ( $i = 50400; $i <= 61200; $i += 3600 ) : ?>
|
105 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
106 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
107 |
+
<span class="ladda-label bookly-time-main">
|
108 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
109 |
+
</span>
|
110 |
+
<span class="bookly-time-additional"></span>
|
111 |
+
</button>
|
112 |
+
<?php endfor ?>
|
113 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+4 days', current_time( 'timestamp' ) ) ) ?></button>
|
114 |
+
<?php for ( $i = 28800; $i <= 43200; $i += 3600 ) : ?>
|
115 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
116 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
117 |
+
<span class="ladda-label bookly-time-main">
|
118 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
119 |
+
</span>
|
120 |
+
<span class="bookly-time-additional"></span>
|
121 |
+
</button>
|
122 |
+
<?php endfor ?>
|
123 |
+
</div>
|
124 |
+
<div class="bookly-column col6" style="display: <?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : 'inline-block' ?>">
|
125 |
+
<?php for ( $i = 46800; $i <= 61200; $i += 3600 ) : ?>
|
126 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
127 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
128 |
+
<span class="ladda-label bookly-time-main">
|
129 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
130 |
+
</span>
|
131 |
+
<span class="bookly-time-additional"></span>
|
132 |
+
</button>
|
133 |
+
<?php endfor ?>
|
134 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+5 days', current_time( 'timestamp' ) ) ) ?></button>
|
135 |
+
<?php for ( $i = 28800; $i <= 39600; $i += 3600 ) : ?>
|
136 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
137 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
138 |
+
<span class="ladda-label bookly-time-main">
|
139 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
140 |
+
</span>
|
141 |
+
<span class="bookly-time-additional"></span>
|
142 |
+
</button>
|
143 |
+
<?php endfor ?>
|
144 |
+
</div>
|
145 |
+
<div class="bookly-column col7" style="display:<?php echo get_option( 'bookly_app_show_calendar' ) == 1 ? ' none' : ' inline-block' ?>">
|
146 |
+
<?php for ( $i = 43200; $i <= 61200; $i += 3600 ) : ?>
|
147 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
148 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
149 |
+
<span class="ladda-label bookly-time-main">
|
150 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
151 |
+
</span>
|
152 |
+
<span class="bookly-time-additional"></span>
|
153 |
+
</button>
|
154 |
+
<?php endfor ?>
|
155 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+6 days', current_time( 'timestamp' ) ) ) ?></button>
|
156 |
+
<?php for ( $i = 28800; $i <= 36000; $i += 3600 ) : ?>
|
157 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
158 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
159 |
+
<span class="ladda-label bookly-time-main">
|
160 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $i ) ?>
|
161 |
+
</span>
|
162 |
+
<span class="bookly-time-additional"></span>
|
163 |
+
</button>
|
164 |
+
<?php endfor ?>
|
165 |
+
</div>
|
166 |
+
</div>
|
167 |
+
|
168 |
+
<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' ?>">
|
169 |
+
<div class="bookly-input-wrap bookly-slot-calendar bookly-js-slot-calendar">
|
170 |
+
<span class="bookly-date-wrap">
|
171 |
+
<input style="display: none" class="bookly-js-selected-date bookly-form-element" type="text" data-value="<?php echo date( 'Y-m-d' ) ?>" />
|
172 |
+
</span>
|
173 |
+
</div>
|
174 |
+
<?php for ( $i = 1; $i <= 7; ++ $i ) : ?>
|
175 |
+
<div class="bookly-column col<?php echo $i ?>">
|
176 |
+
<button class="bookly-day bookly-js-first-child"><?php echo date_i18n( 'D, M d', strtotime( '+' . ( $i - 1 ) . ' days', current_time( 'timestamp' ) ) ) ?></button>
|
177 |
+
<?php for ( $j = 28800; $j <= 61200; $j += 3600 ) : ?>
|
178 |
+
<?php $slot_type = mt_rand( 0, 2 ) ?>
|
179 |
+
<button class="bookly-hour ladda-button<?php if ( $slot_type == 1 ) echo get_option( 'bookly_app_show_blocked_timeslots' ) == 1 ? ' booked' : ' no-booked';elseif ( $slot_type == 2 && Config::waitingListActive() ) echo ' no-waiting-list'?>">
|
180 |
+
<span class="ladda-label bookly-time-main">
|
181 |
+
<i class="bookly-hour-icon"><span></span></i><?php echo DateTime::formatTime( $j ) ?>
|
182 |
+
</span>
|
183 |
+
<span class="bookly-time-additional"></span>
|
184 |
+
</button>
|
185 |
+
<?php endfor ?>
|
186 |
+
</div>
|
187 |
+
<?php endfor ?>
|
188 |
+
</div>
|
189 |
+
</div>
|
190 |
+
</div>
|
191 |
+
</div>
|
192 |
+
<div class="bookly-box bookly-nav-steps">
|
193 |
+
<div class="bookly-back-step bookly-js-back-step bookly-btn">
|
194 |
+
<?php Editable::renderString( array( 'bookly_l10n_button_back' ) ) ?>
|
195 |
+
</div>
|
196 |
+
<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>
|
197 |
+
<div class="<?php echo get_option( 'bookly_app_align_buttons_left' ) ? 'bookly-left' : 'bookly-right' ?>">
|
198 |
+
<button class="bookly-time-next bookly-btn bookly-right ladda-button">
|
199 |
+
<span class="bookly-label">></span>
|
200 |
+
</button>
|
201 |
+
<button class="bookly-time-prev bookly-btn bookly-right ladda-button">
|
202 |
+
<span class="bookly-label"><</span>
|
203 |
+
</button>
|
204 |
+
<?php Proxy\Tasks::renderSkipButton() ?>
|
205 |
+
</div>
|
206 |
+
</div>
|
207 |
+
</div>
|
backend/modules/appearance/templates/_6_details.php
CHANGED
@@ -1,89 +1,112 @@
|
|
1 |
-
<?php if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
|
2 |
-
use Bookly\Backend\Components;
|
3 |
-
use Bookly\Backend\Components\Appearance\Codes;
|
4 |
-
use Bookly\Backend\Components\Appearance\Editable;
|
5 |
-
use Bookly\Backend\Modules\Appearance\Proxy;
|
6 |
-
/** @var array $userData */
|
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_details_step', Codes::getHtml( 6 ) ) ?>
|
13 |
-
</div>
|
14 |
-
<div class="bookly-box">
|
15 |
-
<?php Editable::renderText( 'bookly_l10n_info_details_step_guest', Codes::getHtml( 6, true ), 'bottom', __( 'Visible to non-logged in customers only', 'bookly' ) ) ?>
|
16 |
-
</div>
|
17 |
-
<div class="bookly-box bookly-guest">
|
18 |
-
<div class="bookly-btn" id="bookly-login-button">
|
19 |
-
<?php Editable::renderString( array( 'bookly_l10n_step_details_button_login' ) ) ?>
|
20 |
-
</div>
|
21 |
-
<div class="fb-login-button" id="bookly-facebook-login-button" data-max-rows="1" data-size="large" data-button-type="login_with" data-show-faces="false" data-auto-logout-link="false" data-use-continue-as="false" data-scope="public_profile,email" style="display:none"></div>
|
22 |
-
</div>
|
23 |
-
<div class="bookly-details-step">
|
24 |
-
|
25 |
-
<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' ?>">
|
26 |
-
<div class="bookly-form-group">
|
27 |
-
<?php Editable::renderLabel( array( 'bookly_l10n_label_first_name', 'bookly_l10n_required_first_name', ) ) ?>
|
28 |
-
<div>
|
29 |
-
<input type="text" value="" maxlength="60" />
|
30 |
-
</div>
|
31 |
-
</div>
|
32 |
-
<div class="bookly-form-group">
|
33 |
-
<?php Editable::renderLabel( array( 'bookly_l10n_label_last_name', 'bookly_l10n_required_last_name', ) ) ?>
|
34 |
-
<div>
|
35 |
-
<input type="text" value="" maxlength="60" />
|
36 |
-
</div>
|
37 |
-
</div>
|
38 |
-
</div>
|
39 |
-
|
40 |
-
<div class="bookly-box bookly-table">
|
41 |
-
<div class="bookly-form-group bookly-details-full-name" style="display: <?php echo get_option( 'bookly_cst_first_last_name' ) == 1 ? ' none' : 'block' ?>">
|
42 |
-
<?php Editable::renderLabel( array( 'bookly_l10n_label_name', 'bookly_l10n_required_name', ) ) ?>
|
43 |
-
<div>
|
44 |
-
<input type="text" value="" maxlength="60" />
|
45 |
-
</div>
|
46 |
-
</div>
|
47 |
-
<div class="bookly-form-group">
|
48 |
-
<?php Editable::renderLabel( array( 'bookly_l10n_label_phone', 'bookly_l10n_required_phone', ) ) ?>
|
49 |
-
<div>
|
50 |
-
<input type="text" class="<?php if ( get_option( 'bookly_cst_phone_default_country' ) != 'disabled' ) : ?>bookly-user-phone<?php endif ?>" value="" />
|
51 |
-
</div>
|
52 |
-
</div>
|
53 |
-
<div class="bookly-form-group">
|
54 |
-
<?php Editable::renderLabel( array( 'bookly_l10n_label_email', 'bookly_l10n_required_email' ) ) ?>
|
55 |
-
<div>
|
56 |
-
<input maxlength="40" type="text" value="" />
|
57 |
-
</div>
|
58 |
-
</div>
|
59 |
-
</div>
|
60 |
-
|
61 |
-
<?php Components\Appearance\Proxy\Pro::renderAddress() ?>
|
62 |
-
<?php Components\Appearance\Proxy\Pro::renderBirthday() ?>
|
63 |
-
<?php Proxy\CustomerInformation::renderCustomerInformation() ?>
|
64 |
-
<?php Proxy\CustomFields::renderCustomFields() ?>
|
65 |
-
|
66 |
-
<div class="bookly-box" id="bookly-js-notes">
|
67 |
-
<div class="bookly-form-group">
|
68 |
-
<?php Editable::renderLabel( array( 'bookly_l10n_label_notes' ) ) ?>
|
69 |
-
<div>
|
70 |
-
<textarea rows="3"></textarea>
|
71 |
-
</div>
|
72 |
-
</div>
|
73 |
-
</div>
|
74 |
-
|
75 |
-
<?php Proxy\Files::renderAppearance() ?>
|
76 |
-
</div>
|
77 |
-
|
78 |
-
<?php Proxy\RecurringAppointments::renderInfoMe
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|