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 +267 -87 1.5.10 → 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,12 +493,14 @@
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 ],
@@ -388,22 +507,35 @@
388 507 'all_hosts' => Calendar::getAllHosts(),
389 508 'is_new' => $isNew,
390 509 'require_slug' => $requireSlug,
391 510 'site_url' => site_url('/'),
511 + 'site_title' => get_bloginfo('name'),
392 512 'upgrade_url' => Helper::getUpgradeUrl(),
393 513 'timezones' => DateTimeHelper::getTimeZones(true),
514 + 'features' => Helper::getFeatures(),
394 515 'supported_features' => apply_filters('fluent_booking/supported_featured', [
395 516 'multi_users' => true
396 517 ]),
397 - 'has_pro' => defined('FLUENT_BOOKING_PRO_DIR_FILE'),
398 - 'require_upgrade' => defined('FLUENT_BOOKING_PRO_DIR_FILE') && !defined('FLUENT_BOOKING_LITE'),
399 - 'dashboard_notices' => apply_filters('fluent_booking/dashboard_notices', []),
400 - 'trans' => TransStrings::getStrings(),
401 - 'date_format' => DateTimeHelper::getDateFormatter(true),
402 - 'time_format' => DateTimeHelper::getTimeFormatter(true),
403 - 'date_time_formatter' => DateTimeHelper::getDateFormatter(true) . ', ' . DateTimeHelper::getTimeFormatter(true),
404 - 'available_date_formats' => DateTimeHelper::getAvailableDateFormats(),
405 - '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()
406 538 ]);
407 539 }
408 540
409 541 protected function getRestInfo($app)
@@ -472,12 +604,13 @@
472 604 $urlAssets = $app['url.assets'];
473 605
474 606 return apply_filters('fluent_booking/settings_menu_items', [
475 607 'general_settings' => [
476 - 'title' => __('General Settings', 'fluent-booking'),
608 + 'title' => __('General', 'fluent-booking'),
477 609 'disable' => false,
478 610 'el_icon' => 'Operation',
479 611 'component_type' => 'StandAloneComponent',
612 + 'class' => 'general_settings',
480 613 'route' => [
481 614 'name' => 'general_settings'
482 615 ]
483 616 ],
@@ -485,17 +618,55 @@
485 618 'title' => __('Team', 'fluent-booking'),
486 619 'disable' => true,
487 620 'el_icon' => 'TeamIcon',
488 621 'component_type' => 'StandAloneComponent',
622 + 'class' => 'team_members',
489 623 'route' => [
490 624 'name' => 'team_members'
491 625 ]
492 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 + ],
493 663 'google' => [
494 664 'title' => __('Google Calendar / Meet', 'fluent-booking'),
495 665 'disable' => true,
496 666 'icon_url' => $urlAssets . 'images/gg-calendar.svg',
497 667 'component_type' => 'StandAloneComponent',
668 + 'class' => 'configure_google_calendar',
498 669 'route' => [
499 670 'name' => 'configure-google'
500 671 ]
501 672 ],
@@ -503,8 +674,9 @@
503 674 'title' => __('Outlook Calendar / MS Teams', 'fluent-booking'),
504 675 'disable' => true,
505 676 'icon_url' => $urlAssets . 'images/ol-icon-color.svg',
506 677 'component_type' => 'GlobalSettingsComponent',
678 + 'class' => 'configure_outlook_calendar',
507 679 'route' => [
508 680 'name' => 'configure-integrations',
509 681 'params' => [
510 682 'settings_key' => 'outlook'
@@ -515,8 +687,9 @@
515 687 'title' => __('Apple Calendar', 'fluent-booking'),
516 688 'disable' => true,
517 689 'icon_url' => $urlAssets . 'images/a-cal.svg',
518 690 'component_type' => 'GlobalSettingsComponent',
691 + 'class' => 'configure_apple_calendar',
519 692 'route' => [
520 693 'name' => 'configure-integrations',
521 694 'params' => [
522 695 'settings_key' => 'apple_calendar'
@@ -525,10 +698,11 @@
525 698 ],
526 699 'next_cloud_calendar' => [
527 700 'title' => __('Nextcloud Calendar', 'fluent-booking'),
528 701 'disable' => true,
529 - '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>',
530 703 'component_type' => 'GlobalSettingsComponent',
704 + 'class' => 'configure_nextcloud_calendar',
531 705 'route' => [
532 706 'name' => 'configure-integrations',
533 707 'params' => [
534 708 'settings_key' => 'next_cloud_calendar'
@@ -539,8 +713,9 @@
539 713 'title' => __('Zoom', 'fluent-booking'),
540 714 'disable' => true,
541 715 'icon_url' => $urlAssets . 'images/zoom.svg',
542 716 'component_type' => 'StandAloneComponent',
717 + 'class' => 'zoom_integrations',
543 718 'route' => [
544 719 'name' => 'zoom_integrations'
545 720 ]
546 721 ],
@@ -546,10 +721,11 @@
546 721 ],
547 722 'twilio' => [
548 723 'title' => __('SMS by Twilio', 'fluent-booking'),
549 724 'disable' => true,
550 - '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>',
551 726 'component_type' => 'GlobalSettingsComponent',
727 + 'class' => 'configure_twilio',
552 728 'route' => [
553 729 'name' => 'configure-integrations',
554 730 'params' => [
555 731 'settings_key' => 'twilio'
@@ -555,41 +731,18 @@
555 731 'settings_key' => 'twilio'
556 732 ]
557 733 ]
558 734 ],
559 - 'stripe' => [
560 - 'title' => __('Stripe', 'fluent-booking'),
561 - 'disable' => true,
562 - 'icon_url' => $urlAssets . 'images/payment-methods/stripe.svg',
563 - 'component_type' => 'GlobalSettingsComponent',
564 - 'route' => [
565 - 'name' => 'PaymentSettingsIndex',
566 - 'params' => [
567 - 'settings_key' => 'stripe'
568 - ]
569 - ]
570 - ],
571 - 'paypal' => [
572 - 'title' => __('PayPal', 'fluent-booking'),
573 - 'disable' => true,
574 - 'icon_url' => $urlAssets . 'images/payment-methods/paypal.svg',
575 - 'component_type' => 'GlobalSettingsComponent',
576 - 'route' => [
577 - 'name' => 'PaymentSettingsIndex',
578 - 'params' => [
579 - 'settings_key' => 'paypal'
580 - ]
581 - ]
582 - ],
583 735 'license' => [
584 736 'title' => __('License', 'fluent-booking'),
585 737 'disable' => true,
586 738 'el_icon' => 'Lock',
587 739 'component_type' => 'StandAloneComponent',
740 + 'class' => 'configure_license',
588 741 'route' => [
589 742 'name' => 'license'
590 743 ]
591 - ],
744 + ]
592 745 ]);
593 746 }
594 747
595 748 public static function getEventSettingsMenuItems($event)
@@ -606,9 +759,9 @@
606 759 'event_id' => $event->id
607 760 ]
608 761 ],
609 762 'label' => __('Event Details', 'fluent-booking'),
610 - '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>'
611 764 ],
612 765 'assignment' => [
613 766 'type' => 'route',
614 767 'visible' => false,
@@ -634,9 +787,9 @@
634 787 'event_id' => $event->id
635 788 ]
636 789 ],
637 790 'label' => __('Availability', 'fluent-booking'),
638 - '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>'
639 792 ],
640 793 'limit_settings' => [
641 794 'type' => 'route',
642 795 'visible' => true,
@@ -662,9 +815,9 @@
662 815 'event_id' => $event->id
663 816 ]
664 817 ],
665 818 'label' => __('Question Settings', 'fluent-booking'),
666 - '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>'
667 820 ],
668 821 'email_notification' => [
669 822 'type' => 'route',
670 823 'visible' => true,
@@ -692,8 +845,22 @@
692 845 ],
693 846 'label' => __('SMS Notification', 'fluent-booking'),
694 847 'elIcon' => 'Notification'
695 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 + ],
696 863 'advanced_settings' => [
697 864 'type' => 'route',
698 865 'visible' => true,
699 866 'disable' => true,
@@ -765,9 +932,22 @@
765 932 'calendar_id' => $calendar->id
766 933 ]
767 934 ],
768 935 'label' => __('Calendar Settings', 'fluent-booking'),
769 - '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>'
770 950 ],
771 951 'remote_calendars' => [
772 952 'type' => 'route',
773 953 'visible' => true,