PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.5.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.5.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
← All changes | app/Hooks/Handlers/AdminMenuHandler.php +268 -87 1.5.0 → 2.5.0 View file →
@@ -2,15 +2,16 @@
2 2
3 3 namespace FluentBooking\App\Hooks\Handlers;
4 4
5 5 use FluentBooking\App\App;
6 +use FluentBooking\App\Vite;
7 +use FluentBooking\App\Models\Booking;
6 8 use FluentBooking\App\Models\Calendar;
7 -use FluentBooking\App\Models\CalendarSlot;
8 -use FluentBooking\App\Models\User;
9 9 use FluentBooking\App\Services\DateTimeHelper;
10 10 use FluentBooking\App\Services\Helper;
11 11 use FluentBooking\App\Services\PermissionManager;
12 12 use FluentBooking\App\Services\TransStrings;
13 +use FluentBooking\Framework\Support\Arr;
13 14
14 15 class AdminMenuHandler
15 16 {
16 17 public function register()
@@ -16,16 +17,50 @@
16 17 public function register()
17 18 {
18 19 add_action('admin_menu', [$this, 'add']);
19 20
20 - add_action('admin_enqueue_scripts', function () {
21 - if (!isset($_REQUEST['page']) || $_REQUEST['page'] != 'fluent-booking') { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
21 + add_action('admin_enqueue_scripts', function ($hookSuffix) {
22 + if ($hookSuffix !== 'toplevel_page_fluent-booking') {
22 23 return;
23 24 }
25 +
24 26 $this->enqueueAssets();
27 +
28 + add_action('admin_head', function () {
29 + $this->printThemeClass();
30 + }, 1);
31 +
25 32 }, 100);
26 33 }
27 34
35 + /**
36 + * Put the dark class on the document before the page paints.
37 + *
38 + * The theme is chosen in the browser, so the server cannot know it - which means
39 + * without this the first frame is always light, and somebody on dark gets a white flash
40 + * on every page load. This runs in <head>, before wp-admin's own markup, and is the
41 + * only reason it is inline rather than in global_admin.js: a file in the footer is too
42 + * late to matter, and one in the header is still a request the paint would wait on.
43 + *
44 + * `fluent_theme_mode` is the key every Fluent plugin shares (see global_admin.js), and it
45 + * holds a bare `light`, `dark` or `system`, so `system` is resolved here against the
46 + * machine's own preference. <body> does not exist yet, so only <html> is marked;
47 + * global_admin.js puts the same classes on <body> and #wpbody-content once it runs.
48 + *
49 + * @return void
50 + */
51 + public function printThemeClass()
52 + {
53 + $script = <<<'JS'
54 +(function(){try{var s=localStorage.getItem('fluent_theme_mode')||'';
55 +if(!s){s=localStorage.getItem('fcal_color_mode')==='dark'?'dark':'light';}
56 +if(s==='system'){s='system:'+(window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light');}
57 +if(s==='dark'||s==='system:dark'){var e=document.documentElement;e.classList.add('fluent_theme_dark');e.classList.add('dark');}}catch(e){}})();
58 +JS;
59 +
60 + echo '<script id="fluent-booking-theme-class">' . $script . '</script>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
61 + }
62 +
28 63 public function add()
29 64 {
30 65 $capability = PermissionManager::getMenuPermission();
31 66 $menuPriority = 26;
@@ -83,14 +118,94 @@
83 118 add_submenu_page(
84 119 'fluent-booking',
85 120 __('Settings', 'fluent-booking'),
86 121 __('Settings', 'fluent-booking'),
87 - 'manage_options',
122 + $capability,
88 123 'fluent-booking#/settings/general-settings',
89 124 [$this, 'render']
90 125 );
126 +
127 + if ($this->shouldShowUpgrade()) {
128 + add_submenu_page(
129 + 'fluent-booking',
130 + __('Upgrade to Pro', 'fluent-booking'),
131 + '<span class="fcal_upgrade_pro_menu">' . esc_html__('Upgrade to Pro', 'fluent-booking') . '</span>',
132 + 'manage_options',
133 + Helper::getUpgradeUrl('admin_sidebar_menu')
134 + );
135 +
136 + add_action('admin_head', [$this, 'printUpgradeMenuStyle']);
137 + add_action('admin_footer', [$this, 'printUpgradeMenuScript']);
138 + }
91 139 }
92 140
141 + /**
142 + * The upsell is for whoever can buy the license, so it stays hidden once Pro is loaded
143 + * and from hosts who only reach the app through their own calendars.
144 + *
145 + * @return bool
146 + */
147 + public function shouldShowUpgrade()
148 + {
149 + return !defined('FLUENT_BOOKING_PRO_DIR_FILE') && current_user_can('manage_options');
150 + }
151 +
152 + /**
153 + * Onboarding asks on its final step. The dashboard card waits until the site has a completed
154 + * booking, when FluentBooking has proven useful, and counts one the way the Bookings page's
155 + * "Completed" tab does.
156 + *
157 + * @return array
158 + */
159 + private function getOptinVars()
160 + {
161 + $showPrompt = $this->showOptinPrompt();
162 +
163 + return [
164 + 'share_stats' => Arr::get((array) Helper::getMeta('option', 0, 'optin'), 'share_stats', ''),
165 + 'can_manage' => PermissionManager::userCan('manage_all_data'),
166 + 'show_prompt' => $showPrompt,
167 + 'show_card' => $showPrompt && Booking::applyComputedStatus('completed')->exists(),
168 + ];
169 + }
170 +
171 + /**
172 + * The email opt-in prompt (dashboard card and onboarding) is for free sites that have not
173 + * subscribed yet. Closing it hides it for 30 days.
174 + *
175 + * @return bool
176 + */
177 + private function showOptinPrompt()
178 + {
179 + if (defined('FLUENT_BOOKING_PRO_DIR_FILE') || !PermissionManager::userCan('manage_all_data')) {
180 + return false;
181 + }
182 +
183 + $optin = (array) Helper::getMeta('option', 0, 'optin');
184 +
185 + if (!empty($optin['email'])) {
186 + return false;
187 + }
188 +
189 + return empty($optin['dismissed_at']) || (time() - (int) $optin['dismissed_at']) > 30 * DAY_IN_SECONDS;
190 + }
191 +
192 + public function printUpgradeMenuStyle()
193 + {
194 + echo '<style id="fluent-booking-upgrade-menu">#adminmenu .fcal_upgrade_pro_menu{color:#72aee6;font-weight:500;}</style>';
195 + }
196 +
197 + /**
198 + * The submenu points off-site, and WordPress gives submenu links no target, so it would
199 + * otherwise take the admin away from the dashboard.
200 + *
201 + * @return void
202 + */
203 + public function printUpgradeMenuScript()
204 + {
205 + echo '<script id="fluent-booking-upgrade-menu-js">(function(){var s=document.querySelector("#adminmenu .fcal_upgrade_pro_menu");if(s&&s.parentNode){s.parentNode.setAttribute("target","_blank");s.parentNode.setAttribute("rel","noopener");}})();</script>';
206 + }
207 +
93 208 public function render()
94 209 {
95 210 if (!as_has_scheduled_action('fluent_booking_five_minutes_tasks')) {
96 211 as_schedule_recurring_action(time(), (60 * 5), 'fluent_booking_five_minutes_tasks', [], 'fluent-booking', true);
@@ -95,9 +210,17 @@
95 210 if (!as_has_scheduled_action('fluent_booking_five_minutes_tasks')) {
96 211 as_schedule_recurring_action(time(), (60 * 5), 'fluent_booking_five_minutes_tasks', [], 'fluent-booking', true);
97 212 }
98 213
214 + // The daily task carries the summary report and the MCP record purge.
215 + // A site that never got it — a secondary blog on a network activation,
216 + // or one that lost it — would grow fcal_mcp_g_* rows forever.
217 + if (!as_has_scheduled_action('fluent_booking/daily_tasks')) {
218 + as_schedule_recurring_action(time(), (60 * 60 * 24), 'fluent_booking/daily_tasks', [], 'fluent-booking', true);
219 + }
220 +
99 221 $this->changeFooter();
222 +
100 223 $app = App::getInstance();
101 224
102 225 $config = $app->config;
103 226
@@ -126,9 +249,9 @@
126 249 ],
127 250 [
128 251 'key' => 'scheduled-events',
129 252 'label' => __('Bookings', 'fluent-booking'),
130 - 'permalink' => $baseUrl . 'scheduled-events?period=upcoming&author=me',
253 + 'permalink' => $baseUrl . 'scheduled-events',
131 254 ],
132 255 [
133 256 'key' => 'availability',
134 257 'label' => __('Availability', 'fluent-booking'),
@@ -135,10 +258,11 @@
135 258 'permalink' => $baseUrl . 'availability'
136 259 ]
137 260 ];
138 261
139 - if (current_user_can('manage_options')) {
140 - $menuItems[] = [
262 + $settingItems = [];
263 + if (PermissionManager::userCan('manage_all_data')) {
264 + $settingItems = [
141 265 'key' => 'settings',
142 266 'label' => __('Settings', 'fluent-booking'),
143 267 'permalink' => $baseUrl . 'settings/general-settings'
144 268 ];
@@ -143,28 +267,25 @@
143 267 'permalink' => $baseUrl . 'settings/general-settings'
144 268 ];
145 269 }
146 270
147 - if (!defined('FLUENT_BOOKING_PRO_DIR_FILE')) {
148 - $menuItems[] = [
149 - 'key' => 'buy',
150 - 'label' => __('Upgrade to Pro', 'fluent-booking'),
151 - 'permalink' => Helper::getUpgradeUrl()
152 - ];
153 - }
154 -
155 271 $menuItems = apply_filters('fluent_booking/admin_menu_items', $menuItems);
156 272
157 273 $assets = $app['url.assets'];
158 274
159 275 $portalVars = apply_filters('fluent_booking/admin_portal_vars', [
160 - 'name' => $name,
161 - 'slug' => $slug,
162 - 'menuItems' => $menuItems,
163 - 'baseUrl' => $baseUrl,
164 - 'logo' => $assets . 'images/logo.svg',
276 + 'name' => $name,
277 + 'slug' => $slug,
278 + 'menuItems' => $menuItems,
279 + 'settings' => $settingItems,
280 + 'baseUrl' => $baseUrl,
281 + 'logo' => $assets . 'images/logo.svg',
282 + 'dark_logo' => $assets . 'images/logo_dark.svg',
283 + 'upgradeUrl' => $this->shouldShowUpgrade() ? Helper::getUpgradeUrl('top_bar') : '',
165 284 ]);
166 285
286 + do_action('fluent_booking/admin_app_rendering');
287 +
167 288 $app->view->render('admin.menu', $portalVars);
168 289 }
169 290
170 291 public function changeFooter()
@@ -179,22 +300,20 @@
179 300 return FLUENT_BOOKING_VERSION;
180 301 });
181 302 }
182 303
183 - public function enqueueAssets()
304 + public function enqueueAssets($withApp = true)
184 305 {
185 306 $app = App::getInstance();
186 307
187 308 $isRtl = Helper::fluentbooking_is_rtl();
188 309
189 - $assets = $app['url.assets'];
310 + $slug = $app->config->get('app.slug');
190 311
191 - $slug = $app->config->get('app.slug');
312 + $assetsVersion = Vite::isDev() ? time() : FLUENT_BOOKING_ASSETS_VERSION;
192 313
193 - $adminAppCss = 'admin/admin.css';
194 314 if ($isRtl) {
195 - $adminAppCss = 'admin/admin-rtl.css';
196 - wp_enqueue_style('fluentbooking_admin_rtl', $assets . 'admin/fluentbooking_admin_rtl.css', [], FLUENT_BOOKING_ASSETS_VERSION);
315 + Vite::enqueueStyle('fluentbooking_admin_rtl', 'admin_rtl_css', [], $assetsVersion);
197 316 }
198 317
199 318 add_action('wp_print_scripts', function () {
200 319
@@ -285,28 +404,22 @@
285 404 wp_dequeue_style($wp_styles->registered[$script]->handle);
286 405 }
287 406 }, 999999);
288 407
289 - wp_enqueue_style('fluent_booing_admin_app', $assets . $adminAppCss, [], FLUENT_BOOKING_ASSETS_VERSION, 'all');
408 + Vite::enqueueStyle('fluent_booing_admin_app', 'admin_css', [], $assetsVersion, 'all');
290 409
291 - do_action($slug . '_loading_app');
410 + // The dashboard payload is per-user and includes every host's email address,
411 + // so the app bundle is only ever emitted for an authenticated, permitted viewer.
412 + if (!$withApp || !get_current_user_id()) {
413 + return;
414 + }
292 415
293 - wp_enqueue_script(
294 - $slug . '_admin_app',
295 - $assets . 'admin/app.js',
296 - array('jquery'),
297 - FLUENT_BOOKING_ASSETS_VERSION,
298 - true
299 - );
416 + do_action($slug . '_loading_app'); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound
300 417
301 - wp_enqueue_script(
302 - $slug . '_global_admin',
303 - $assets . 'admin/global_admin.js',
304 - array(),
305 - FLUENT_BOOKING_ASSETS_VERSION,
306 - true
307 - );
418 + Vite::enqueueScript($slug . '_admin_app', 'admin_app', array('jquery'), $assetsVersion);
308 419
420 + Vite::enqueueScript($slug . '_global_admin', 'global_admin', array(), $assetsVersion);
421 +
309 422 if (function_exists('wp_enqueue_editor')) {
310 423 add_filter('user_can_richedit', '__return_true');
311 424 wp_enqueue_editor();
312 425 wp_enqueue_media();
@@ -319,8 +432,13 @@
319 432 {
320 433 $assets = $app['url.assets'];
321 434 $currentUser = get_user_by('ID', get_current_user_id());
322 435
436 + $currentUsername = trim($currentUser->first_name . ' ' . $currentUser->last_name);
437 + if (!$currentUsername) {
438 + $currentUsername = $currentUser->display_name;
439 + }
440 +
323 441 $isNew = $this->isNew();
324 442
325 443 $requireSlug = false;
326 444
@@ -355,9 +473,9 @@
355 473 $customFieldTypes = Helper::getCustomFieldTypes();
356 474 $weekSelectTimes = Helper::getWeekSelectTimes();
357 475 $overrideSelectTimes = Helper::getOverrideSelectTimes();
358 476 $statusChangingTimes = Helper::getBookingStatusChangingTimes();
359 - $locationFields = (new CalendarSlot())->getLocationFields();
477 + $defaultTermsAndConditions = Helper::getDefaultTermsAndConditions();
360 478
361 479 return apply_filters('fluent_booking/admin_vars', [
362 480 'slug' => $slug = $app->config->get('app.slug'),
363 481 'nonce' => wp_create_nonce($slug),
@@ -369,9 +487,8 @@
369 487 'multi_durations' => $multiDurations,
370 488 'buffer_times' => $bufferTimes,
371 489 'slot_intervals' => $slotIntervals,
372 490 'schedule_schema' => $scheduleSchema,
373 - 'location_fields' => $locationFields,
374 491 'custom_field_types' => $customFieldTypes,
375 492 'week_select_times' => $weekSelectTimes,
376 493 'duration_lookup' => $durationLookup,
377 494 'multi_duration_lookup' => $multiDurationLookup,
@@ -376,33 +493,49 @@
376 493 'duration_lookup' => $durationLookup,
377 494 'multi_duration_lookup' => $multiDurationLookup,
378 495 'override_select_times' => $overrideSelectTimes,
379 496 'status_changing_times' => $statusChangingTimes,
497 + 'default_terms' => $defaultTermsAndConditions,
380 498 'me' => [
381 499 'id' => $currentUser->ID,
382 500 'calendar_id' => $calendarId,
383 - 'full_name' => trim($currentUser->first_name . ' ' . $currentUser->last_name),
501 + 'full_name' => $currentUsername,
502 + 'avatar' => get_avatar_url($currentUser->ID, ['size' => 96]),
384 503 'email' => $currentUser->user_email,
385 504 'is_admin' => $hasAllAccess,
386 505 'permissions' => PermissionManager::getUserPermissions($currentUser, false),
387 506 ],
507 + 'all_hosts' => Calendar::getAllHosts(),
388 508 'is_new' => $isNew,
389 509 'require_slug' => $requireSlug,
390 510 'site_url' => site_url('/'),
511 + 'site_title' => get_bloginfo('name'),
391 512 'upgrade_url' => Helper::getUpgradeUrl(),
392 513 'timezones' => DateTimeHelper::getTimeZones(true),
514 + 'features' => Helper::getFeatures(),
393 515 'supported_features' => apply_filters('fluent_booking/supported_featured', [
394 516 'multi_users' => true
395 517 ]),
396 - 'has_pro' => defined('FLUENT_BOOKING_PRO_DIR_FILE'),
397 - 'require_upgrade' => defined('FLUENT_BOOKING_PRO_DIR_FILE') && !defined('FLUENT_BOOKING_LITE'),
398 - 'dashboard_notices' => apply_filters('fluent_booking/dashboard_notices', []),
399 - 'trans' => TransStrings::getStrings(),
400 - 'date_format' => DateTimeHelper::getDateFormatter(true),
401 - 'time_format' => DateTimeHelper::getTimeFormatter(true),
402 - 'date_time_formatter' => DateTimeHelper::getDateFormatter(true) . ', ' . DateTimeHelper::getTimeFormatter(true),
403 - 'available_date_formats' => DateTimeHelper::getAvailableDateFormats(),
404 - 'admin_url' => admin_url(),
518 + 'i18' => [
519 + 'date_time_config' => DateTimeHelper::getI18nDateTimeConfig(),
520 + ],
521 + 'has_pro' => defined('FLUENT_BOOKING_PRO_DIR_FILE'),
522 + 'require_upgrade' => defined('FLUENT_BOOKING_PRO_DIR_FILE') && !defined('FLUENT_BOOKING_LITE'),
523 + 'dashboard_notices' => apply_filters('fluent_booking/dashboard_notices', []),
524 + 'optin' => $this->getOptinVars(),
525 + 'payment_methods' => apply_filters('fluent_booking/payment/get_all_methods', []),
526 + 'trans' => TransStrings::getStrings(),
527 + 'date_format' => DateTimeHelper::getDateFormatter(true),
528 + 'time_format' => DateTimeHelper::getTimeFormatter(true),
529 + 'date_time_formatter' => DateTimeHelper::getDateFormatter(true) . ', ' . DateTimeHelper::getTimeFormatter(true),
530 + 'available_date_formats' => DateTimeHelper::getAvailableDateFormats(),
531 + 'default_booking_filters' => Helper::getDefaultBookingFilters(),
532 + 'default_paginations' => Helper::getDefaultPaginations(),
533 + 'pref_settings' => Helper::getPrefSettings(),
534 + 'settings_menu_items' => static::settingsMenuItems(),
535 + 'admin_url' => admin_url(),
536 + 'is_rtl' => Helper::fluentbooking_is_rtl(),
537 + 'iframe_html' => Helper::getIframeHtml()
405 538 ]);
406 539 }
407 540
408 541 protected function getRestInfo($app)
@@ -471,12 +604,13 @@
471 604 $urlAssets = $app['url.assets'];
472 605
473 606 return apply_filters('fluent_booking/settings_menu_items', [
474 607 'general_settings' => [
475 - 'title' => __('General Settings', 'fluent-booking'),
608 + 'title' => __('General', 'fluent-booking'),
476 609 'disable' => false,
477 610 'el_icon' => 'Operation',
478 611 'component_type' => 'StandAloneComponent',
612 + 'class' => 'general_settings',
479 613 'route' => [
480 614 'name' => 'general_settings'
481 615 ]
482 616 ],
@@ -484,17 +618,55 @@
484 618 'title' => __('Team', 'fluent-booking'),
485 619 'disable' => true,
486 620 'el_icon' => 'TeamIcon',
487 621 'component_type' => 'StandAloneComponent',
622 + 'class' => 'team_members',
488 623 'route' => [
489 624 'name' => 'team_members'
490 625 ]
491 626 ],
627 + 'payment_settings' => [
628 + 'title' => __('Payment', 'fluent-booking'),
629 + 'disable' => true,
630 + 'el_icon' => 'Money',
631 + 'component_type' => 'PaymentSettingsComponent',
632 + 'class' => 'payment_settings',
633 + 'route' => [
634 + 'name' => 'global_payment_settings',
635 + ],
636 + 'children' => [
637 + 'payment_settings' => [
638 + 'title' => __('Settings', 'fluent-booking'),
639 + 'disable' => true,
640 + 'route' => [
641 + 'name' => 'global_payment_settings'
642 + ]
643 + ],
644 + 'payment_methods' => [
645 + 'title' => __('Payment Methods', 'fluent-booking'),
646 + 'disable' => true,
647 + 'route' => [
648 + 'name' => 'payment_methods',
649 + 'params' => [
650 + 'settings_key' => 'stripe'
651 + ]
652 + ]
653 + ],
654 + 'payment_coupons' => [
655 + 'title' => __('Coupons', 'fluent-booking'),
656 + 'disable' => true,
657 + 'route' => [
658 + 'name' => 'payment_coupons'
659 + ]
660 + ]
661 + ],
662 + ],
492 663 'google' => [
493 664 'title' => __('Google Calendar / Meet', 'fluent-booking'),
494 665 'disable' => true,
495 666 'icon_url' => $urlAssets . 'images/gg-calendar.svg',
496 667 'component_type' => 'StandAloneComponent',
668 + 'class' => 'configure_google_calendar',
497 669 'route' => [
498 670 'name' => 'configure-google'
499 671 ]
500 672 ],
@@ -502,8 +674,9 @@
502 674 'title' => __('Outlook Calendar / MS Teams', 'fluent-booking'),
503 675 'disable' => true,
504 676 'icon_url' => $urlAssets . 'images/ol-icon-color.svg',
505 677 'component_type' => 'GlobalSettingsComponent',
678 + 'class' => 'configure_outlook_calendar',
506 679 'route' => [
507 680 'name' => 'configure-integrations',
508 681 'params' => [
509 682 'settings_key' => 'outlook'
@@ -514,8 +687,9 @@
514 687 'title' => __('Apple Calendar', 'fluent-booking'),
515 688 'disable' => true,
516 689 'icon_url' => $urlAssets . 'images/a-cal.svg',
517 690 'component_type' => 'GlobalSettingsComponent',
691 + 'class' => 'configure_apple_calendar',
518 692 'route' => [
519 693 'name' => 'configure-integrations',
520 694 'params' => [
521 695 'settings_key' => 'apple_calendar'
@@ -524,10 +698,11 @@
524 698 ],
525 699 'next_cloud_calendar' => [
526 700 'title' => __('Nextcloud Calendar', 'fluent-booking'),
527 701 'disable' => true,
528 - 'icon_url' => $urlAssets . 'images/Ncloud.svg',
702 + 'svg_icon' => '<svg xmlns="http://www.w3.org/2000/svg" height="800" width="1200" viewBox="-17.0838 -18.65685 148.0596 111.9411"><path d="M57.0328 0C45.2275 0 35.2216 8.0032 32.1204 18.8466c-2.6952-5.7515-8.5359-9.781-15.2633-9.781C7.6053 9.0657 0 16.671 0 25.9228c0 9.2519 7.6052 16.8606 16.857 16.8606 6.7275 0 12.5682-4.0319 15.2635-9.7844 3.1011 10.8442 13.107 18.85 24.9123 18.85 11.718 0 21.6729-7.885 24.8533-18.607 2.745 5.622 8.5135 9.5414 15.1454 9.5414 9.2518 0 16.8605-7.6087 16.8605-16.8606 0-9.2518-7.6087-16.857-16.8605-16.857-6.632 0-12.4003 3.917-15.1454 9.5378C78.7057 7.8825 68.7507 0 57.0328 0zm0 9.8955c8.9116 0 16.0307 7.1156 16.0307 16.0272s-7.119 16.0308-16.0307 16.0308c-8.9116 0-16.0272-7.1192-16.0272-16.0308S48.1212 9.8955 57.0328 9.8955zm-40.1757 9.0657c3.9044 0 6.965 3.0571 6.965 6.9615s-3.0606 6.965-6.965 6.965-6.9616-3.0606-6.9616-6.965 3.0572-6.9615 6.9616-6.9615zm80.1744 0c3.9044 0 6.965 3.0571 6.965 6.9615s-3.0606 6.965-6.965 6.965-6.9616-3.0606-6.9616-6.965 3.0572-6.9615 6.9616-6.9615z" color="currentColor" font-weight="400" font-family="sans-serif" overflow="visible" fill="currentColor"></path><path d="M29.1085 63.7615c2.7752 0 4.3275 1.9756 4.3275 4.939 0 .2822-.2352.5174-.5174.5174h-7.4792c.047 2.6342 1.8816 4.1394 3.9983 4.1394 1.3171 0 2.2579-.5644 2.7283-.9408.2822-.1881.5174-.141.6585.1412l.1411.2352c.1411.2351.094.4703-.1411.6585-.5645.4233-1.7875 1.129-3.4338 1.129-3.0575 0-5.4094-2.2109-5.4094-5.4095.047-3.3868 2.3048-5.4094 5.1272-5.4094zm2.8693 4.4216c-.094-2.1638-1.4112-3.2457-2.9164-3.2457-1.7404 0-3.2456 1.129-3.575 3.2457zm15.584-2.9164v-3.622c0-.3292.1882-.5174.5174-.5174h.3764c.3292 0 .4703.1882.4703.5174v2.446h2.1168c.3292 0 .5174.1882.5174.5174v.1412c0 .3292-.1882.4703-.5174.4703h-2.1168v5.1743c0 2.399 1.4582 2.6812 2.2579 2.7282.4233.047.5644.1411.5644.5174v.2823c0 .3292-.141.4704-.5644.4704-2.2579 0-3.622-1.3642-3.622-3.8102zm10.7718-1.5052c1.7875 0 2.9164.7526 3.4339 1.176.2351.188.2822.4233.047.7055l-.1411.2352c-.1882.2822-.4234.2822-.7056.094-.4704-.3292-1.3641-.9407-2.5871-.9407-2.2579 0-4.0453 1.6934-4.0453 4.1864 0 2.446 1.7874 4.1394 4.0453 4.1394 1.4582 0 2.446-.6585 2.9164-1.0819.2822-.1881.4704-.141.6585.1411l.1411.1882c.1411.2822.0941.4704-.141.7056-.5175.4233-1.7876 1.317-3.6691 1.317-3.0575 0-5.4094-2.2108-5.4094-5.4094.047-3.1986 2.399-5.4564 5.4564-5.4564zm6.2562-3.3398c0-.3292-.1882-.5174.141-.5174h.3764c.3293 0 .8467.1882.8467.5174V71.664c0 1.3171.6115 1.4582 1.0819 1.5053.2352 0 .4233.141.4233.4703v.3293c0 .3293-.1411.5174-.5174.5174-.8467 0-2.352-.2822-2.352-2.54zm9.6429 3.3398c3.0104 0 5.4564 2.3048 5.4564 5.3623 0 3.1046-2.446 5.4565-5.4564 5.4565-3.0105 0-5.4565-2.352-5.4565-5.4565 0-3.0575 2.446-5.3623 5.4565-5.3623zm0 9.5958c2.2108 0 3.9982-1.7875 3.9982-4.2335 0-2.3519-1.7874-4.0923-3.9982-4.0923s-4.0454 1.7875-4.0454 4.0923c.047 2.399 1.8346 4.2335 4.0454 4.2335zm23.4722-9.5958c2.493 0 3.3868 2.0697 3.3868 2.0697h.047s-.047-.3293-.047-.7997v-4.6568c0-.3293-.1412-.5174.1881-.5174h.3763c.3293 0 .8467.1881.8467.5174v13.406c0 .3292-.1411.5174-.4704.5174h-.3292c-.3293 0-.5175-.1411-.5175-.4704v-.7997c0-.3763.0941-.6585.0941-.6585h-.047s-.8938 2.1638-3.575 2.1638c-2.7752 0-4.5157-2.2108-4.5157-5.4095-.094-3.1986 1.8345-5.3623 4.5628-5.3623zm.047 9.5958c1.7404 0 3.3398-1.223 3.3398-4.1864 0-2.1167-1.082-4.1394-3.2927-4.1394-1.8345 0-3.3398 1.5052-3.3398 4.1394.047 2.54 1.3641 4.1864 3.2927 4.1864zm-85.8923.9878h.3763c.3293 0 .5174-.1881.5174-.5174V63.7274c0-1.5993 1.7404-2.7412 3.716-2.7412 1.9757 0 3.7161 1.142 3.7161 2.7412v10.1003c0 .3293.1882.5174.5174.5174h.3763c.3293 0 .4704-.1881.4704-.5174V63.6674c0-2.6812-2.6812-3.9983-5.1272-3.9983-2.3519 0-5.0331 1.317-5.0331 3.9983v10.1603c0 .3293.1411.5174.4704.5174zm78.5073-10.3485h-.3763c-.3293 0-.5175.1882-.5175.5175v5.6916c0 1.5993-1.0348 3.0575-3.0575 3.0575-1.9756 0-3.0575-1.4582-3.0575-3.0575v-5.6916c0-.3293-.1881-.5175-.5174-.5175h-.3763c-.3293 0-.4704.1882-.4704.5175v6.068c0 2.6811 1.9756 3.9982 4.4216 3.9982 2.446 0 4.4217-1.317 4.4217-3.9983v-6.068c.047-.3292-.1412-.5174-.4704-.5174zm-46.5643-.0771c-.1152.0184-.2258.0953-.3317.2214L41.5673 66.41l-1.4249 1.6978-2.1571-2.5715-1.1705-1.3955c-.1058-.1261-.2257-.195-.35-.2058-.1244-.0107-.2533.0366-.3795.1424l-.2884.2416c-.2523.2117-.2392.446-.0276.6982l1.9045 2.2693 1.5793 1.8815-2.3124 2.7553c-.0018.002-.0029.0043-.0046.0064l-1.1668 1.39c-.2117.2523-.188.5178.0643.7295l.2885.2407c.2522.2116.481.1585.6927-.0937l1.9036-2.2693 1.425-1.6977 2.157 2.5715c.0015.0016.0032.0029.0047.0046l1.1668 1.391c.2116.2521.4763.275.7285.0633l.2885-.2416c.2522-.2117.2392-.446.0275-.6983l-1.9045-2.2692-1.5792-1.8815 2.3124-2.7553c.0017-.002.0028-.0044.0046-.0064l1.1668-1.39c.2116-.2523.1879-.5179-.0643-.7295l-.2885-.2416c-.1261-.1058-.2459-.1452-.361-.1268z" fill="currentColor"></path></svg>',
529 703 'component_type' => 'GlobalSettingsComponent',
704 + 'class' => 'configure_nextcloud_calendar',
530 705 'route' => [
531 706 'name' => 'configure-integrations',
532 707 'params' => [
533 708 'settings_key' => 'next_cloud_calendar'
@@ -538,8 +713,9 @@
538 713 'title' => __('Zoom', 'fluent-booking'),
539 714 'disable' => true,
540 715 'icon_url' => $urlAssets . 'images/zoom.svg',
541 716 'component_type' => 'StandAloneComponent',
717 + 'class' => 'zoom_integrations',
542 718 'route' => [
543 719 'name' => 'zoom_integrations'
544 720 ]
545 721 ],
@@ -545,10 +721,11 @@
545 721 ],
546 722 'twilio' => [
547 723 'title' => __('SMS by Twilio', 'fluent-booking'),
548 724 'disable' => true,
549 - 'icon_url' => $urlAssets . 'images/tw.svg',
725 + 'svg_icon' => '<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" viewBox="0 0 24 24" id="twilio"><path d="M0,12c0,6.64,5.359,12,12,12s12-5.36,12-12c0-6.641-5.36-12-12-12C5.381-0.008,0.008,5.352,0,11.971V12z M3.199,12c-0.014-4.846,3.904-8.786,8.75-8.801H12c4.847-0.014,8.786,3.904,8.801,8.75V12c0.015,4.847-3.904,8.786-8.75,8.801H12c-4.846,0.015-8.786-3.904-8.801-8.75V12z"></path><path d="M14.959 17.44c1.361 0 2.481-1.12 2.481-2.48 0-1.359-1.12-2.48-2.481-2.479-1.359 0-2.479 1.12-2.479 2.479C12.486 16.326 13.592 17.432 14.959 17.44zM14.959 11.52c1.361 0 2.481-1.12 2.481-2.479 0-1.361-1.12-2.481-2.481-2.481-1.359 0-2.479 1.12-2.479 2.481C12.487 10.407 13.593 11.513 14.959 11.52zM9.042 17.44c1.359 0 2.479-1.12 2.479-2.48 0-1.359-1.121-2.48-2.479-2.479-1.361 0-2.481 1.12-2.481 2.479C6.567 16.327 7.674 17.433 9.042 17.44zM9.042 11.52c1.359 0 2.479-1.12 2.479-2.479 0-1.361-1.121-2.481-2.479-2.481-1.361 0-2.481 1.12-2.481 2.481C6.567 10.408 7.675 11.513 9.042 11.52z"></path></svg>',
550 726 'component_type' => 'GlobalSettingsComponent',
727 + 'class' => 'configure_twilio',
551 728 'route' => [
552 729 'name' => 'configure-integrations',
553 730 'params' => [
554 731 'settings_key' => 'twilio'
@@ -554,41 +731,18 @@
554 731 'settings_key' => 'twilio'
555 732 ]
556 733 ]
557 734 ],
558 - 'stripe' => [
559 - 'title' => __('Stripe', 'fluent-booking'),
560 - 'disable' => true,
561 - 'icon_url' => $urlAssets . 'images/payment-methods/stripe.svg',
562 - 'component_type' => 'GlobalSettingsComponent',
563 - 'route' => [
564 - 'name' => 'PaymentSettingsIndex',
565 - 'params' => [
566 - 'settings_key' => 'stripe'
567 - ]
568 - ]
569 - ],
570 - 'paypal' => [
571 - 'title' => __('PayPal', 'fluent-booking'),
572 - 'disable' => true,
573 - 'icon_url' => $urlAssets . 'images/payment-methods/paypal.svg',
574 - 'component_type' => 'GlobalSettingsComponent',
575 - 'route' => [
576 - 'name' => 'PaymentSettingsIndex',
577 - 'params' => [
578 - 'settings_key' => 'paypal'
579 - ]
580 - ]
581 - ],
582 735 'license' => [
583 736 'title' => __('License', 'fluent-booking'),
584 737 'disable' => true,
585 738 'el_icon' => 'Lock',
586 739 'component_type' => 'StandAloneComponent',
740 + 'class' => 'configure_license',
587 741 'route' => [
588 742 'name' => 'license'
589 743 ]
590 - ],
744 + ]
591 745 ]);
592 746 }
593 747
594 748 public static function getEventSettingsMenuItems($event)
@@ -605,9 +759,9 @@
605 759 'event_id' => $event->id
606 760 ]
607 761 ],
608 762 'label' => __('Event Details', 'fluent-booking'),
609 - 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M8 2V5" stroke="#1B2533" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 2V5" stroke="#1B2533" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 13H15" stroke="#1B2533" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 17H12" stroke="#1B2533" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 3.5C19.33 3.68 21 4.95 21 9.65V15.83C21 19.95 20 22.01 15 22.01H9C4 22.01 3 19.95 3 15.83V9.65C3 4.95 4.67 3.69 8 3.5H16Z" stroke="#1B2533" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
763 + 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"><path d="M8 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 13H15" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 17H12" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 3.5C19.33 3.68 21 4.95 21 9.65V15.83C21 19.95 20 22.01 15 22.01H9C4 22.01 3 19.95 3 15.83V9.65C3 4.95 4.67 3.69 8 3.5H16Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
610 764 ],
611 765 'assignment' => [
612 766 'type' => 'route',
613 767 'visible' => false,
@@ -633,9 +787,9 @@
633 787 'event_id' => $event->id
634 788 ]
635 789 ],
636 790 'label' => __('Availability', 'fluent-booking'),
637 - 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M6.66666 1.66699V4.16699" stroke="#445164" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.3333 1.66699V4.16699" stroke="#445164" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2.91666 7.5752H17.0833" stroke="#445164" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M17.5 7.08366V14.167C17.5 16.667 16.25 18.3337 13.3333 18.3337H6.66667C3.75 18.3337 2.5 16.667 2.5 14.167V7.08366C2.5 4.58366 3.75 2.91699 6.66667 2.91699H13.3333C16.25 2.91699 17.5 4.58366 17.5 7.08366Z" stroke="#445164" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.0789 11.4167H13.0864" stroke="#445164" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.0789 13.9167H13.0864" stroke="#445164" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.99623 11.4167H10.0037" stroke="#445164" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.99623 13.9167H10.0037" stroke="#445164" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.91194 11.4167H6.91942" stroke="#445164" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.91194 13.9167H6.91942" stroke="#445164" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
791 + 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M6.66666 1.66699V4.16699" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.3333 1.66699V4.16699" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2.91666 7.5752H17.0833" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M17.5 7.08366V14.167C17.5 16.667 16.25 18.3337 13.3333 18.3337H6.66667C3.75 18.3337 2.5 16.667 2.5 14.167V7.08366C2.5 4.58366 3.75 2.91699 6.66667 2.91699H13.3333C16.25 2.91699 17.5 4.58366 17.5 7.08366Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.0789 11.4167H13.0864" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M13.0789 13.9167H13.0864" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.99623 11.4167H10.0037" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M9.99623 13.9167H10.0037" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.91194 11.4167H6.91942" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M6.91194 13.9167H6.91942" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
638 792 ],
639 793 'limit_settings' => [
640 794 'type' => 'route',
641 795 'visible' => true,
@@ -661,9 +815,9 @@
661 815 'event_id' => $event->id
662 816 ]
663 817 ],
664 818 'label' => __('Question Settings', 'fluent-booking'),
665 - 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 2V5" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 2V5" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 13.8714V13.6441C12 12.908 12.5061 12.5182 13.0121 12.2043C13.5061 11.9012 14 11.5115 14 10.797C14 9.8011 13.1085 9 12 9C10.8915 9 10 9.8011 10 10.797" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.9945 16.4587H12.0053" stroke="#292D32" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 3.5C19.33 3.67504 21 4.91005 21 9.48055V15.4903C21 19.4968 20 21.5 15 21.5H9C4 21.5 3 19.4968 3 15.4903V9.48055C3 4.91005 4.67 3.68476 8 3.5H16Z" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
819 + 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 2V5" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M12 13.8714V13.6441C12 12.908 12.5061 12.5182 13.0121 12.2043C13.5061 11.9012 14 11.5115 14 10.797C14 9.8011 13.1085 9 12 9C10.8915 9 10 9.8011 10 10.797" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M11.9945 16.4587H12.0053" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M16 3.5C19.33 3.67504 21 4.91005 21 9.48055V15.4903C21 19.4968 20 21.5 15 21.5H9C4 21.5 3 19.4968 3 15.4903V9.48055C3 4.91005 4.67 3.68476 8 3.5H16Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
666 820 ],
667 821 'email_notification' => [
668 822 'type' => 'route',
669 823 'visible' => true,
@@ -691,8 +845,22 @@
691 845 ],
692 846 'label' => __('SMS Notification', 'fluent-booking'),
693 847 'elIcon' => 'Notification'
694 848 ],
849 + 'recurring_settings' => [
850 + 'type' => 'route',
851 + 'visible' => ($event->isOneToOne() || $event->isGroup()) ? true : false,
852 + 'disable' => true,
853 + 'route' => [
854 + 'name' => 'recurring_settings',
855 + 'params' => [
856 + 'calendar_id' => $event->calendar_id,
857 + 'event_id' => $event->id
858 + ]
859 + ],
860 + 'label' => __('Recurring Settings', 'fluent-booking'),
861 + 'svgIcon' => '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M6 4H21C21.5523 4 22 4.44772 22 5V12H20V6H6V9L1 5L6 1V4ZM18 20H3C2.44772 20 2 19.5523 2 19V12H4V18H18V15L23 19L18 23V20Z"></path></svg>'
862 + ],
695 863 'advanced_settings' => [
696 864 'type' => 'route',
697 865 'visible' => true,
698 866 'disable' => true,
@@ -764,9 +932,22 @@
764 932 'calendar_id' => $calendar->id
765 933 ]
766 934 ],
767 935 'label' => __('Calendar Settings', 'fluent-booking'),
768 - 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 12.8799V11.1199C2 10.0799 2.85 9.21994 3.9 9.21994C5.71 9.21994 6.45 7.93994 5.54 6.36994C5.02 5.46994 5.33 4.29994 6.24 3.77994L7.97 2.78994C8.76 2.31994 9.78 2.59994 10.25 3.38994L10.36 3.57994C11.26 5.14994 12.74 5.14994 13.65 3.57994L13.76 3.38994C14.23 2.59994 15.25 2.31994 16.04 2.78994L17.77 3.77994C18.68 4.29994 18.99 5.46994 18.47 6.36994C17.56 7.93994 18.3 9.21994 20.11 9.21994C21.15 9.21994 22.01 10.0699 22.01 11.1199V12.8799C22.01 13.9199 21.16 14.7799 20.11 14.7799C18.3 14.7799 17.56 16.0599 18.47 17.6299C18.99 18.5399 18.68 19.6999 17.77 20.2199L16.04 21.2099C15.25 21.6799 14.23 21.3999 13.76 20.6099L13.65 20.4199C12.75 18.8499 11.27 18.8499 10.36 20.4199L10.25 20.6099C9.78 21.3999 8.76 21.6799 7.97 21.2099L6.24 20.2199C5.33 19.6999 5.02 18.5299 5.54 17.6299C6.45 16.0599 5.71 14.7799 3.9 14.7799C2.85 14.7799 2 13.9199 2 12.8799Z" stroke="#292D32" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
936 + 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/><path d="M2 12.8799V11.1199C2 10.0799 2.85 9.21994 3.9 9.21994C5.71 9.21994 6.45 7.93994 5.54 6.36994C5.02 5.46994 5.33 4.29994 6.24 3.77994L7.97 2.78994C8.76 2.31994 9.78 2.59994 10.25 3.38994L10.36 3.57994C11.26 5.14994 12.74 5.14994 13.65 3.57994L13.76 3.38994C14.23 2.59994 15.25 2.31994 16.04 2.78994L17.77 3.77994C18.68 4.29994 18.99 5.46994 18.47 6.36994C17.56 7.93994 18.3 9.21994 20.11 9.21994C21.15 9.21994 22.01 10.0699 22.01 11.1199V12.8799C22.01 13.9199 21.16 14.7799 20.11 14.7799C18.3 14.7799 17.56 16.0599 18.47 17.6299C18.99 18.5399 18.68 19.6999 17.77 20.2199L16.04 21.2099C15.25 21.6799 14.23 21.3999 13.76 20.6099L13.65 20.4199C12.75 18.8499 11.27 18.8499 10.36 20.4199L10.25 20.6099C9.78 21.3999 8.76 21.6799 7.97 21.2099L6.24 20.2199C5.33 19.6999 5.02 18.5299 5.54 17.6299C6.45 16.0599 5.71 14.7799 3.9 14.7799C2.85 14.7799 2 13.9199 2 12.8799Z" stroke="currentColor" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/></svg>'
937 + ],
938 + 'calendar_events' => [
939 + 'type' => 'route',
940 + 'visible' => true,
941 + 'disable' => false,
942 + 'route' => [
943 + 'name' => 'calendar_events',
944 + 'params' => [
945 + 'calendar_id' => $calendar->id
946 + ]
947 + ],
948 + 'label' => __('Event Types', 'fluent-booking'),
949 + 'svgIcon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8 6H21" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 12H21" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M8 18H21" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 6H3.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 12H3.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/><path d="M3 18H3.01" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>'
769 950 ],
770 951 'remote_calendars' => [
771 952 'type' => 'route',
772 953 'visible' => true,