Changeset 3468659
- Timestamp:
- 02/24/2026 01:12:12 PM (5 weeks ago)
- Location:
- creavi-booking-service
- Files:
-
- 53 added
- 9 edited
-
tags/1.2.0 (added)
-
tags/1.2.0/assets (added)
-
tags/1.2.0/assets/css (added)
-
tags/1.2.0/assets/css/admin.css (added)
-
tags/1.2.0/assets/css/creavibc-deactivation-feedback.css (added)
-
tags/1.2.0/assets/css/service-tour.css (added)
-
tags/1.2.0/assets/css/style.css (added)
-
tags/1.2.0/assets/images (added)
-
tags/1.2.0/assets/images/service_placeholder.png (added)
-
tags/1.2.0/assets/js (added)
-
tags/1.2.0/assets/js/admin.js (added)
-
tags/1.2.0/assets/js/booking.js (added)
-
tags/1.2.0/assets/js/cbs-gcal-busy-admin.js (added)
-
tags/1.2.0/assets/js/creavibc-deactivation-feedback.js (added)
-
tags/1.2.0/assets/js/service-tour.js (added)
-
tags/1.2.0/assets/vendor (added)
-
tags/1.2.0/assets/vendor/flatpickr (added)
-
tags/1.2.0/assets/vendor/flatpickr/flatpickr.min.css (added)
-
tags/1.2.0/assets/vendor/flatpickr/flatpickr.min.js (added)
-
tags/1.2.0/assets/vendor/flatpickr/l10n (added)
-
tags/1.2.0/assets/vendor/flatpickr/l10n/da.js (added)
-
tags/1.2.0/assets/vendor/flatpickr/l10n/fr.js (added)
-
tags/1.2.0/assets/vendor/luxon (added)
-
tags/1.2.0/assets/vendor/luxon/luxon.min.js (added)
-
tags/1.2.0/creavi-booking-service.php (added)
-
tags/1.2.0/includes (added)
-
tags/1.2.0/includes/activation-metrics.php (added)
-
tags/1.2.0/includes/activation-redirect.php (added)
-
tags/1.2.0/includes/admin.php (added)
-
tags/1.2.0/includes/ajax-handlers.php (added)
-
tags/1.2.0/includes/cbs-gcal-remote.php (added)
-
tags/1.2.0/includes/deactivation-feedback.php (added)
-
tags/1.2.0/includes/functions.php (added)
-
tags/1.2.0/includes/gcal-freebusy.php (added)
-
tags/1.2.0/includes/meta-boxes.php (added)
-
tags/1.2.0/includes/placeholders.php (added)
-
tags/1.2.0/includes/post-types.php (added)
-
tags/1.2.0/includes/reminders.php (added)
-
tags/1.2.0/includes/render-booking-inline.php (added)
-
tags/1.2.0/includes/save-service.php (added)
-
tags/1.2.0/languages (added)
-
tags/1.2.0/languages/creavi-booking-service-da_DK-creavibc-script.json (added)
-
tags/1.2.0/languages/creavi-booking-service-da_DK.mo (added)
-
tags/1.2.0/languages/creavi-booking-service-da_DK.po (added)
-
tags/1.2.0/languages/creavi-booking-service-fr_FR-creavibc-script.json (added)
-
tags/1.2.0/languages/creavi-booking-service-fr_FR.mo (added)
-
tags/1.2.0/languages/creavi-booking-service-fr_FR.po (added)
-
tags/1.2.0/languages/creavi-booking-service.pot (added)
-
tags/1.2.0/readme.txt (added)
-
trunk/assets/css/admin.css (modified) (2 diffs)
-
trunk/assets/css/service-tour.css (added)
-
trunk/assets/js/admin.js (modified) (1 diff)
-
trunk/assets/js/service-tour.js (added)
-
trunk/creavi-booking-service.php (modified) (4 diffs)
-
trunk/includes/activation-metrics.php (added)
-
trunk/includes/activation-redirect.php (added)
-
trunk/includes/admin.php (modified) (1 diff)
-
trunk/includes/ajax-handlers.php (modified) (2 diffs)
-
trunk/includes/meta-boxes.php (modified) (5 diffs)
-
trunk/includes/reminders.php (modified) (1 diff)
-
trunk/includes/save-service.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
creavi-booking-service/trunk/assets/css/admin.css
r3456986 r3468659 769 769 margin-bottom: 6px; /* space between label and control */ 770 770 font-weight: 600; 771 font-size: 1.1em !important; 771 772 } 772 773 … … 909 910 } 910 911 } 912 913 /* ========================================= 914 Service Basics boxes — match Creavi metabox UI 915 Uses the same gradient border + glass layers 916 ========================================= */ 917 918 #creavibc_service_title_box.postbox, 919 #creavibc_service_desc_box.postbox{ 920 position: relative; 921 border: 1px solid transparent !important; 922 border-radius: 18px !important; 923 background: transparent !important; 924 overflow: hidden; 925 box-shadow: var(--creavibc-shadow-soft) !important; 926 margin-bottom: 18px; 927 } 928 929 /* thin GRADIENT BORDER (1px) */ 930 #creavibc_service_title_box.postbox::before, 931 #creavibc_service_desc_box.postbox::before{ 932 content:""; 933 position:absolute; 934 inset:0; 935 padding: 1px; 936 border-radius: 18px; 937 background: linear-gradient(135deg, 938 rgba(120,2,159,.55), 939 rgba(221,129,249,.45), 940 rgba(17,24,39,.08) 941 ); 942 -webkit-mask: 943 linear-gradient(#000 0 0) content-box, 944 linear-gradient(#000 0 0); 945 -webkit-mask-composite: xor; 946 mask-composite: exclude; 947 pointer-events:none; 948 } 949 950 /* glass background layer inside */ 951 #creavibc_service_title_box.postbox::after, 952 #creavibc_service_desc_box.postbox::after{ 953 content:""; 954 position:absolute; 955 inset:1px; 956 border-radius: 17px; 957 background: 958 radial-gradient(1200px 220px at 20% 0%, 959 rgba(221,129,249,.16), 960 rgba(255,255,255,0) 60%), 961 radial-gradient(1000px 240px at 90% 20%, 962 rgba(120,2,159,.10), 963 rgba(255,255,255,0) 55%), 964 linear-gradient(180deg, 965 var(--creavibc-glass) 0%, 966 var(--creavibc-glass-2) 100%); 967 backdrop-filter: blur(10px); 968 -webkit-backdrop-filter: blur(10px); 969 pointer-events:none; 970 } 971 972 /* ensure header/content above layers */ 973 #creavibc_service_title_box.postbox > *, 974 #creavibc_service_desc_box.postbox > *{ 975 position: relative; 976 z-index: 1; 977 } 978 979 /* header = same as your other metaboxes */ 980 #creavibc_service_title_box .postbox-header, 981 #creavibc_service_desc_box .postbox-header{ 982 position: relative; 983 border-bottom: 1px solid rgba(17,24,39,.08) !important; 984 background: transparent !important; 985 padding: 14px 5px 12px !important; 986 } 987 988 /* accent hairline */ 989 #creavibc_service_title_box .postbox-header::before, 990 #creavibc_service_desc_box .postbox-header::before{ 991 content:""; 992 position:absolute; 993 left: 16px; 994 top: 10px; 995 width: 70px; 996 height: 3px; 997 border-radius: 999px; 998 background: linear-gradient(90deg, var(--creavibc-accent), var(--creavibc-accent-2)); 999 opacity: .85; 1000 } 1001 1002 #creavibc_service_title_box .postbox-header h2, 1003 #creavibc_service_desc_box .postbox-header h2{ 1004 font-weight: 800 !important; 1005 letter-spacing: -0.02em; 1006 color: var(--creavibc-text) !important; 1007 } 1008 1009 /* inside padding consistent */ 1010 #creavibc_service_title_box .inside, 1011 #creavibc_service_desc_box .inside{ 1012 padding: 16px !important; 1013 } 1014 1015 /* Title input: same Apple-ish fields */ 1016 .post-type-creavibc_service #title{ 1017 border-radius: 14px !important; 1018 border: 1px solid rgba(17,24,39,.10) !important; 1019 background: rgba(255,255,255,.78) !important; 1020 box-shadow: 1021 0 1px 0 rgba(255,255,255,.35) inset, 1022 0 10px 24px rgba(0,0,0,.05); 1023 padding: 12px 14px !important; 1024 font-size: 18px !important; 1025 } 1026 .post-type-creavibc_service #title:focus{ 1027 outline: none !important; 1028 border-color: rgba(120,2,159,.38) !important; 1029 box-shadow: 1030 0 0 0 3px rgba(255,255,255,.9), 1031 0 0 0 7px var(--creavibc-ring-2), 1032 0 12px 28px rgba(0,0,0,.08) !important; 1033 } 1034 1035 /* Editor: make it feel like it belongs inside the box */ 1036 .post-type-creavibc_service #postdivrich{ 1037 background: transparent !important; 1038 border: 0 !important; 1039 box-shadow: none !important; 1040 margin: 0 !important; 1041 } 1042 1043 /* Smaller editor (your request) */ 1044 .post-type-creavibc_service #content_ifr{ height: 140px !important; } 1045 .post-type-creavibc_service #content{ min-height: 140px !important; } 1046 1047 /* Remove extra top spacing WP adds around title section */ 1048 .post-type-creavibc_service #titlediv{ margin: 0 !important; } 1049 .post-type-creavibc_service #titlewrap{ margin: 0 !important; } 1050 1051 /* Creavi Booking Service — Shortcode metabox (admin) 1052 File: assets/css/admin-shortcode-metabox.css */ 1053 1054 #creavibc_shortcode_box .inside{ 1055 padding-top: 10px; 1056 } 1057 1058 #creavibc_shortcode_box .creavibc-sc-title{ 1059 margin: 0 0 6px; 1060 font-weight: 700; 1061 font-size: 13px; 1062 color: rgba(0,0,0,.90); 1063 } 1064 1065 #creavibc_shortcode_box .creavibc-sc-desc{ 1066 margin-top: 0; 1067 margin-bottom: 10px; 1068 } 1069 1070 #creavibc_shortcode_box .creavibc-sc-fieldwrap{ 1071 margin-bottom: 10px; 1072 } 1073 1074 #creavibc_shortcode_box .creavibc-sc-input{ 1075 width: 100%; 1076 height: 44px; 1077 padding: 10px 12px; 1078 1079 border-radius: 12px; 1080 border: 1px solid rgba(120,2,159,.22); 1081 1082 background: linear-gradient(180deg, rgba(221,129,249,.12), rgba(255,255,255,.92)); 1083 box-shadow: 0 10px 24px rgba(0,0,0,.06); 1084 1085 font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 1086 font-size: 13px; 1087 color: rgba(0,0,0,.90); 1088 1089 outline: none; 1090 } 1091 1092 #creavibc_shortcode_box .creavibc-sc-input:focus{ 1093 border-color: rgba(120,2,159,.38); 1094 box-shadow: 0 0 0 3px rgba(120,2,159,.14), 0 10px 24px rgba(0,0,0,.06); 1095 } 1096 1097 #creavibc_shortcode_box .creavibc-sc-actions{ 1098 display: flex; 1099 justify-content: flex-end; 1100 } 1101 1102 #creavibc_shortcode_box .creavibc-sc-copy{ 1103 border-radius: 12px; 1104 border: 1px solid rgba(120,2,159,.22); 1105 background: #fff; 1106 padding: 6px 12px; 1107 min-height: 36px; 1108 1109 display: inline-flex; 1110 align-items: center; 1111 gap: 8px; 1112 1113 transition: transform .3s ease, border-color .3s ease, box-shadow .3s ease; 1114 } 1115 1116 #creavibc_shortcode_box .creavibc-sc-copy:hover{ 1117 border-color: rgba(120,2,159,.45); 1118 box-shadow: 0 10px 24px rgba(120,2,159,.10); 1119 transform: translateY(-1px); 1120 } 1121 1122 #creavibc_shortcode_box .creavibc-sc-copy:active{ 1123 transform: translateY(0); 1124 } 1125 1126 #creavibc_shortcode_box .creavibc-sc-copy.is-done .creavibc-sc-copy-default{ display:none; } 1127 #creavibc_shortcode_box .creavibc-sc-copy.is-done .creavibc-sc-copy-done{ display:inline; } 1128 #creavibc_shortcode_box .creavibc-sc-copy-done{ display:none; } 1129 -
creavi-booking-service/trunk/assets/js/admin.js
r3454590 r3468659 673 673 }); 674 674 675 document.addEventListener('DOMContentLoaded', function () { 676 677 // Shortcode metabox id is "creavibc_shortcode_box" 678 const box = document.getElementById('creavibc_shortcode_box'); 679 if (!box) return; 680 681 const input = box.querySelector('.creavibc-sc-input'); 682 const copyBtn = box.querySelector('.creavibc-sc-copy'); 683 if (!input || !copyBtn) return; 684 685 // Click/focus selects the shortcode (nice UX) 686 function selectField() { 687 try { input.focus(); input.select(); } catch (e) {} 688 } 689 input.addEventListener('click', selectField); 690 input.addEventListener('focus', selectField); 691 692 // Copy (clipboard + fallback) 693 function copyText(text) { 694 if (navigator.clipboard && navigator.clipboard.writeText) { 695 return navigator.clipboard.writeText(text); 696 } 697 return new Promise(function (resolve, reject) { 698 try { 699 const ta = document.createElement('textarea'); 700 ta.value = text; 701 ta.setAttribute('readonly', ''); 702 ta.style.position = 'absolute'; 703 ta.style.left = '-9999px'; 704 document.body.appendChild(ta); 705 ta.select(); 706 const ok = document.execCommand('copy'); 707 document.body.removeChild(ta); 708 ok ? resolve() : reject(); 709 } catch (err) { 710 reject(err); 711 } 712 }); 713 } 714 715 copyBtn.addEventListener('click', function () { 716 const val = input.value || ''; 717 if (!val) return; 718 719 copyText(val).then(function () { 720 copyBtn.classList.add('is-done'); 721 window.setTimeout(function () { 722 copyBtn.classList.remove('is-done'); 723 }, 1200); 724 }).catch(function () { 725 // If copy fails, still select for manual copy 726 selectField(); 727 }); 728 }); 729 730 }); 731 -
creavi-booking-service/trunk/creavi-booking-service.php
r3460766 r3468659 5 5 * Text Domain: creavi-booking-service 6 6 * Domain Path: /languages 7 * Version: 1. 1.97 * Version: 1.2.0 8 8 * Author: Creavi 9 9 * License: GPL2 … … 16 16 define('CREAVIBC_PLUGIN_URL', plugin_dir_url(__FILE__)); 17 17 define('CREAVIBC_PLUGIN_PATH', plugin_dir_path(__FILE__)); 18 define('CREAVIBC_VERSION', '1. 1.9');18 define('CREAVIBC_VERSION', '1.2.0'); 19 19 20 20 … … 39 39 40 40 41 require_once CREAVIBC_PLUGIN_DIR . 'includes/activation-redirect.php'; 42 require_once CREAVIBC_PLUGIN_PATH . 'includes/activation-metrics.php'; 41 43 require_once CREAVIBC_PLUGIN_DIR . 'includes/deactivation-feedback.php'; 42 43 44 require_once CREAVIBC_PLUGIN_DIR . 'includes/cbs-gcal-remote.php'; 44 45 45 require_once CREAVIBC_PLUGIN_DIR . 'includes/post-types.php'; 46 46 require_once CREAVIBC_PLUGIN_DIR . 'includes/save-service.php'; … … 55 55 56 56 register_activation_hook( CREAVIBC_PLUGIN_FILE, 'creavibc_setup_placeholder_attachment' ); 57 register_activation_hook( CREAVIBC_PLUGIN_FILE, 'creavibc_metrics_mark_activated' ); 57 58 58 59 -
creavi-booking-service/trunk/includes/admin.php
r3439801 r3468659 2 2 if ( ! defined( 'ABSPATH' ) ) exit; 3 3 4 add_action('admin_enqueue_scripts', function ($hook) { 5 global $post; 6 7 if ($hook === 'post-new.php' || $hook === 'post.php') { 8 if ($post && $post->post_type === 'creavibc_service') { 9 10 // Load local Flatpickr CSS & JS from plugin assets 11 wp_enqueue_style( 12 'flatpickr', 13 CREAVIBC_PLUGIN_URL . 'assets/vendor/flatpickr/flatpickr.min.css', 14 [], 15 '4.6.13' // or whatever version you're using 16 ); 17 18 wp_enqueue_script( 19 'flatpickr', 20 CREAVIBC_PLUGIN_URL . 'assets/vendor/flatpickr/flatpickr.min.js', 21 [], 22 '4.6.13', 23 true 24 ); 25 26 // Local admin script 27 wp_enqueue_script( 28 'creavibc-admin-js', 29 CREAVIBC_PLUGIN_URL . 'assets/js/admin.js', 30 ['flatpickr'], 31 filemtime(CREAVIBC_PLUGIN_PATH . 'assets/js/admin.js'), 32 true 33 ); 34 35 wp_enqueue_style( 36 'creavibc-admin-style', 37 CREAVIBC_PLUGIN_URL . 'assets/css/admin.css', 38 [], 39 filemtime(CREAVIBC_PLUGIN_PATH . 'assets/css/admin.css') 40 ); 41 42 wp_enqueue_script( 43 'creavibc-gcal-busy-admin', 44 CREAVIBC_PLUGIN_URL . 'assets/js/cbs-gcal-busy-admin.js', 45 [ 'jquery' ], 46 filemtime( CREAVIBC_PLUGIN_PATH . 'assets/js/cbs-gcal-busy-admin.js' ), 47 true 48 ); 49 50 wp_localize_script( 51 'creavibc-gcal-busy-admin', 52 'creavibcGcalBusy', 53 [ 54 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 55 'nonce' => wp_create_nonce( 'creavibc_admin_nonce' ), 56 'serviceId' => $post->ID, // handy, optional 57 ] 58 ); 59 60 61 } 4 /** 5 * Title placeholder: "Service name" 6 */ 7 add_filter( 'enter_title_here', function( $title, $post ) { 8 if ( $post && $post->post_type === 'creavibc_service' ) { 9 return __( 'Service name', 'creavi-booking-service' ); 10 } 11 return $title; 12 }, 10, 2 ); 13 14 15 /** 16 * Wrap Title + Editor into metabox-like postboxes 17 * (We MOVE #titlediv and #postdivrich into hosts via JS) 18 */ 19 add_action( 'edit_form_after_title', function( $post ) { 20 if ( ! $post || $post->post_type !== 'creavibc_service' ) return; 21 ?> 22 <div id="creavibc-basics-wrap"> 23 24 <!-- Service Title (metabox style) --> 25 <div id="creavibc_service_title_box" class="postbox creavibc-basics-box"> 26 <div class="postbox-header"> 27 <h2 class="hndle ui-sortable-handle"> 28 <span><?php esc_html_e( 'Service title', 'creavi-booking-service' ); ?></span> 29 </h2> 30 </div> 31 <div class="inside"> 32 <p class="description" style="margin-top:0;"> 33 <?php esc_html_e( 'This is shown to customers as the service name.', 'creavi-booking-service' ); ?> 34 </p> 35 36 <!-- Move WP title field (#titlediv) here --> 37 <div id="creavibc-title-host"></div> 38 </div> 39 </div> 40 41 <!-- Service Description (metabox style) --> 42 <div id="creavibc_service_desc_box" class="postbox creavibc-basics-box"> 43 <div class="postbox-header"> 44 <h2 class="hndle ui-sortable-handle"> 45 <span><?php esc_html_e( 'Service description', 'creavi-booking-service' ); ?></span> 46 </h2> 47 </div> 48 <div class="inside"> 49 <p class="description" style="margin-top:0;"> 50 <?php esc_html_e( 'Shown on the left side of the booking popup / inline block.', 'creavi-booking-service' ); ?> 51 </p> 52 53 <!-- Move WP editor (#postdivrich) here --> 54 <div id="creavibc-editor-host"></div> 55 </div> 56 </div> 57 58 </div> 59 <?php 60 } ); 61 62 63 /** 64 * Make editor smaller + hide other notices only on Service edit screen 65 */ 66 add_action( 'admin_head', function() { 67 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; 68 if ( ! $screen || $screen->post_type !== 'creavibc_service' ) return; 69 70 // allow debugging: show notices if you add ?creavibc_show_notices=1 71 $show_notices = ( isset( $_GET['creavibc_show_notices'] ) && $_GET['creavibc_show_notices'] === '1' ); 72 73 echo '<style> 74 /* Smaller editor */ 75 .post-type-creavibc_service #content_ifr { height: 200px !important; } 76 .post-type-creavibc_service #content { min-height: 200px !important; } 77 .post-type-creavibc_service #postdivrich { margin: 0 !important; } 78 .post-type-creavibc_service #postdivrich .postbox-header { margin-bottom: 0; } 79 .post-type-creavibc_service .mce-top-part::before { box-shadow: none; } 80 81 /* Make moved title/editor blocks feel tighter */ 82 .post-type-creavibc_service #titlediv { margin: 0 !important; } 83 .post-type-creavibc_service #titlewrap { margin: 0 !important; } 84 85 ' . ( $show_notices ? '' : ' 86 /* Hide most admin notices on Creavi service editor */ 87 .post-type-creavibc_service .notice, 88 .post-type-creavibc_service div.error, 89 .post-type-creavibc_service div.updated, 90 .post-type-creavibc_service .update-nag, 91 .post-type-creavibc_service .settings-error, 92 .post-type-creavibc_service .fs-notice, 93 .post-type-creavibc_service .yoast-notice, 94 .post-type-creavibc_service .rank-math-notice, 95 .post-type-creavibc_service .woocommerce-message, 96 .post-type-creavibc_service .elementor-message { 97 display: none !important; 98 } 99 ' ) . ' 100 </style>'; 101 } ); 102 103 104 /** 105 * Enqueue admin assets on creavibc_service edit screens 106 * IMPORTANT: use get_current_screen() instead of relying on global $post 107 */ 108 add_action( 'admin_enqueue_scripts', function( $hook ) { 109 110 if ( $hook !== 'post-new.php' && $hook !== 'post.php' ) return; 111 112 $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; 113 if ( ! $screen || $screen->post_type !== 'creavibc_service' ) return; 114 115 // Best-effort post id (post-new.php may not have $post yet) 116 $post_id = 0; 117 if ( isset( $_GET['post'] ) ) { 118 $post_id = (int) $_GET['post']; 119 } else { 120 global $post; 121 if ( $post && ! empty( $post->ID ) ) { 122 $post_id = (int) $post->ID; 123 } 124 } 125 126 // Load local Flatpickr CSS & JS from plugin assets 127 wp_enqueue_style( 128 'flatpickr', 129 CREAVIBC_PLUGIN_URL . 'assets/vendor/flatpickr/flatpickr.min.css', 130 [], 131 '4.6.13' 132 ); 133 134 wp_enqueue_script( 135 'flatpickr', 136 CREAVIBC_PLUGIN_URL . 'assets/vendor/flatpickr/flatpickr.min.js', 137 [], 138 '4.6.13', 139 true 140 ); 141 142 // Local admin script 143 wp_enqueue_script( 144 'creavibc-admin-js', 145 CREAVIBC_PLUGIN_URL . 'assets/js/admin.js', 146 [ 'flatpickr' ], 147 filemtime( CREAVIBC_PLUGIN_PATH . 'assets/js/admin.js' ), 148 true 149 ); 150 151 wp_enqueue_style( 152 'creavibc-admin-style', 153 CREAVIBC_PLUGIN_URL . 'assets/css/admin.css', 154 [], 155 filemtime( CREAVIBC_PLUGIN_PATH . 'assets/css/admin.css' ) 156 ); 157 158 // Busy slots admin 159 wp_enqueue_script( 160 'creavibc-gcal-busy-admin', 161 CREAVIBC_PLUGIN_URL . 'assets/js/cbs-gcal-busy-admin.js', 162 [ 'jquery' ], 163 filemtime( CREAVIBC_PLUGIN_PATH . 'assets/js/cbs-gcal-busy-admin.js' ), 164 true 165 ); 166 167 wp_localize_script( 168 'creavibc-gcal-busy-admin', 169 'creavibcGcalBusy', 170 [ 171 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 172 'nonce' => wp_create_nonce( 'creavibc_admin_nonce' ), 173 'serviceId' => (int) $post_id, 174 ] 175 ); 176 177 // ───────────────────────────────────────────── 178 // Guided tour / top progress bar (service editor) 179 // ───────────────────────────────────────────── 180 wp_enqueue_style( 181 'creavibc-service-tour', 182 CREAVIBC_PLUGIN_URL . 'assets/css/service-tour.css', 183 [], 184 filemtime( CREAVIBC_PLUGIN_PATH . 'assets/css/service-tour.css' ) 185 ); 186 187 wp_enqueue_script( 188 'creavibc-service-tour', 189 CREAVIBC_PLUGIN_URL . 'assets/js/service-tour.js', 190 [ 'jquery' ], 191 filemtime( CREAVIBC_PLUGIN_PATH . 'assets/js/service-tour.js' ), 192 true 193 ); 194 195 // Only allow onboarding when parameter is present AND this is a NEW service 196 $is_onboarding = ( isset($_GET['creavibc_onboarding']) && $_GET['creavibc_onboarding'] === '1' ) ? 1 : 0; 197 198 // "new service" = post-new.php OR auto-draft 199 $is_new_service = 0; 200 201 if ( $hook === 'post-new.php' ) { 202 $is_new_service = 1; 203 } else { 204 // post.php editing 205 if ( $post_id ) { 206 $p = get_post( $post_id ); 207 if ( $p && $p->post_type === 'creavibc_service' && $p->post_status === 'auto-draft' ) { 208 $is_new_service = 1; 209 } 210 } 211 } 212 213 wp_localize_script( 214 'creavibc-service-tour', 215 'CREAVIBC_TOUR', 216 [ 217 'postId' => (int) $post_id, 218 'onboarding' => $is_onboarding, 219 'isNewService' => $is_new_service ? 1 : 0, // extra guard for JS 220 'steps' => [ 221 [ 222 'id' => 'creavibc_service_title_box', 223 'label' => __( 'Title', 'creavi-booking-service' ), 224 'text' => __( 'Set the name customers will see when booking.', 'creavi-booking-service' ), 225 ], 226 [ 227 'id' => 'creavibc_service_desc_box', 228 'label' => __( 'Description', 'creavi-booking-service' ), 229 'text' => __( 'Add a short summary shown in the booking block.', 'creavi-booking-service' ), 230 ], 231 [ 232 'id' => 'creavibc_available_days', 233 'label' => __( 'Available days', 'creavi-booking-service' ), 234 'text' => __( 'Choose which dates can be booked.', 'creavi-booking-service' ), 235 ], 236 [ 237 'id' => 'creavibc_time_slot_grid', 238 'label' => __( 'Available time', 'creavi-booking-service' ), 239 'text' => __( 'Select the time slots customers can pick.', 'creavi-booking-service' ), 240 ], 241 [ 242 'id' => 'creavibc_booking_form_fields', 243 'label' => __( 'Booking form', 'creavi-booking-service' ), 244 'text' => __( 'Choose what info you collect from customers.', 'creavi-booking-service' ), 245 ], 246 [ 247 'id' => 'creavibc_output_type', 248 'label' => __( 'Display type', 'creavi-booking-service' ), 249 'text' => __( 'Show booking as a popup or inline block.', 'creavi-booking-service' ), 250 ], 251 [ 252 'id' => 'creavibc_service_appearance', 253 'label' => __( 'Appearance', 'creavi-booking-service' ), 254 'text' => __( 'Customize colors, button text, and styling.', 'creavi-booking-service' ), 255 ], 256 [ 257 'id' => 'creavibc_service_notifications', 258 'label' => __( 'Notifications', 'creavi-booking-service' ), 259 'text' => __( 'Configure emails and optional reminders.', 'creavi-booking-service' ), 260 ], 261 [ 262 'id' => 'creavibc_google_calendar', 263 'label' => __( 'Google Calendar Integartion', 'creavi-booking-service' ), 264 'text' => __( 'Connect Google Calendar and event settings.', 'creavi-booking-service' ), 265 ], 266 [ 267 'id' => 'submitdiv', 268 'label' => __( 'Go to Publish', 'creavi-booking-service' ), 269 'text' => __( 'Publish the service to start accepting bookings.', 'creavi-booking-service' ), 270 ], 271 ], 272 ] 273 ); 274 275 276 } ); 277 278 279 /** 280 * Top progress bar container (always visible) 281 */ 282 add_action( 'edit_form_top', function( $post ) { 283 if ( ! $post || $post->post_type !== 'creavibc_service' ) return; 284 285 echo '<div id="creavibc-tour-bar" class="creavibc-tour-bar" aria-label="' . esc_attr__( 'Service setup steps', 'creavi-booking-service' ) . '"></div>'; 286 } ); 287 288 /** 289 * Prefill default description for new Service 290 */ 291 add_filter( 'default_content', function( $content, $post ) { 292 293 if ( ! $post || $post->post_type !== 'creavibc_service' ) { 294 return $content; 62 295 } 63 }); 64 65 296 297 // Only on brand new service (not editing existing) 298 if ( $post->post_status !== 'auto-draft' ) { 299 return $content; 300 } 301 302 // If something already exists, don't override 303 if ( ! empty( $content ) ) { 304 return $content; 305 } 306 307 $default = 308 '<p><strong>' . __( 'About this service', 'creavi-booking-service' ) . '</strong></p>' . 309 '<p>' . __( 'Describe what this service includes, who it is for, and what customers can expect during the appointment.', 'creavi-booking-service' ) . '</p>' . 310 '<ul>' . 311 '<li>' . __( 'Duration and format', 'creavi-booking-service' ) . '</li>' . 312 '<li>' . __( 'Preparation instructions (if any)', 'creavi-booking-service' ) . '</li>' . 313 '<li>' . __( 'What happens after booking', 'creavi-booking-service' ) . '</li>' . 314 '</ul>'; 315 316 return $default; 317 318 }, 10, 2 ); 319 320 add_action( 'post_submitbox_misc_actions', 'creavibc_metrics_optin_checkbox_in_publish_box' ); 321 function creavibc_metrics_optin_checkbox_in_publish_box() { 322 global $post; 323 if ( ! $post || $post->post_type !== 'creavibc_service' ) return; 324 325 $optin = get_option( 'creavibc_metrics_optin', '1' ); // default checked 326 wp_nonce_field( 'creavibc_metrics_optin_save', 'creavibc_metrics_optin_nonce' ); 327 328 ?> 329 <div class="misc-pub-section creavibc-metrics-optin" style="padding-top:10px;"> 330 <label style="display:block; line-height:1.35;"> 331 <input type="checkbox" name="creavibc_metrics_optin" value="1" <?php checked( $optin, '1' ); ?> /> 332 <strong><?php esc_html_e( 'Help improve Creavi Booking Service', 'creavi-booking-service' ); ?></strong><br> 333 <span style="color:#646970;"> 334 <?php esc_html_e( 'Send anonymous usage data.', 'creavi-booking-service' ); ?> 335 </span> 336 </label> 337 </div> 338 <?php 339 } -
creavi-booking-service/trunk/includes/ajax-handlers.php
r3460766 r3468659 355 355 '{admin_link}' => admin_url( "post.php?post=$service_id&action=edit" ), 356 356 '{google_calendar}' => $gcal_url, 357 '{name_url}' => rawurlencode( (string) $name ), 357 358 ]; 358 359 $replacements_admin = $replacements_user; … … 367 368 '{admin_link}' => admin_url( "post.php?post=$service_id&action=edit" ), 368 369 '{google_calendar}' => $gcal_url, 370 '{name_url}' => rawurlencode( (string) $name ), 369 371 ]; 370 372 $replacements_admin = $replacements_user; -
creavi-booking-service/trunk/includes/meta-boxes.php
r3460766 r3468659 2 2 if ( ! defined( 'ABSPATH' ) ) exit; 3 3 4 5 4 add_action('add_meta_boxes', function () { 6 7 add_meta_box('creavibc_output_type', __( 'Booking Display Type', 'creavi-booking-service' ), 'creavibc_render_output_type_box', 'creavibc_service', 'normal', 'high'); 8 9 add_meta_box('creavibc_available_days', __( 'Available Booking Days', 'creavi-booking-service' ), 'creavibc_render_available_days_box', 'creavibc_service', 'normal', 'high'); 10 11 add_meta_box('creavibc_time_slot_grid', __( 'Visual Time Slot Selector', 'creavi-booking-service' ), 'creavibc_render_weekday_slots_grid_box', 'creavibc_service', 'normal', 'high'); 12 13 add_meta_box('creavibc_booking_form_fields', __( 'Booking Form Fields', 'creavi-booking-service' ), 'creavibc_render_form_fields_box', 'creavibc_service', 'normal', 'default'); 14 15 add_meta_box('creavibc_service_appearance', __( 'Booking Appearance', 'creavi-booking-service' ), 'creavibc_render_service_appearance_box', 'creavibc_service', 'normal', 'default'); 16 17 add_meta_box('creavibc_service_notifications', __( 'Notifications', 'creavi-booking-service' ), 'creavibc_render_service_notifications_box', 'creavibc_service', 'normal', 'default'); 18 19 add_meta_box('creavibc_google_calendar', __( 'Google Calendar', 'creavi-booking-service' ), 'creavibc_render_google_calendar_box', 'creavibc_service', 'normal', 'low'); 20 21 add_meta_box('creavibc_booking_details', __( 'Booking Details', 'creavi-booking-service' ), 'creavibc_render_booking_meta', 'creavibc_booking', 'normal', 'default'); 22 5 6 // CREAVIBC SERVICE (main column) 7 8 add_meta_box( 9 'creavibc_available_days', 10 __( 'Available Booking Days', 'creavi-booking-service' ), 11 'creavibc_render_available_days_box', 12 'creavibc_service', 13 'normal', 14 'high' 15 ); 16 17 add_meta_box( 18 'creavibc_time_slot_grid', 19 __( 'Visual Time Slot Selector', 'creavi-booking-service' ), 20 'creavibc_render_weekday_slots_grid_box', 21 'creavibc_service', 22 'normal', 23 'high' 24 ); 25 26 add_meta_box( 27 'creavibc_output_type', 28 __( 'Booking Display Type', 'creavi-booking-service' ), 29 'creavibc_render_output_type_box', 30 'creavibc_service', 31 'normal', 32 'default' 33 ); 34 35 add_meta_box( 36 'creavibc_booking_form_fields', 37 __( 'Booking Form Fields', 'creavi-booking-service' ), 38 'creavibc_render_form_fields_box', 39 'creavibc_service', 40 'normal', 41 'default' 42 ); 43 44 add_meta_box( 45 'creavibc_service_appearance', 46 __( 'Booking Appearance', 'creavi-booking-service' ), 47 'creavibc_render_service_appearance_box', 48 'creavibc_service', 49 'normal', 50 'default' 51 ); 52 53 add_meta_box( 54 'creavibc_service_notifications', 55 __( 'Notifications', 'creavi-booking-service' ), 56 'creavibc_render_service_notifications_box', 57 'creavibc_service', 58 'normal', 59 'default' 60 ); 61 62 // Google Calendar should be LAST in main column 63 add_meta_box( 64 'creavibc_google_calendar', 65 __( 'Google Calendar', 'creavi-booking-service' ), 66 'creavibc_render_google_calendar_box', 67 'creavibc_service', 68 'normal', 69 'low' 70 ); 71 72 // CREAVIBC BOOKING (other CPT) 73 add_meta_box( 74 'creavibc_booking_details', 75 __( 'Booking Details', 'creavi-booking-service' ), 76 'creavibc_render_booking_meta', 77 'creavibc_booking', 78 'normal', 79 'default' 80 ); 81 82 $screen = 'creavibc_service'; 83 84 add_meta_box( 85 'creavibc_shortcode_box', 86 __( 'Shortcode', 'creavi-booking-service' ), 87 'creavibc_render_shortcode_metabox', 88 $screen, 89 'side', 90 'low' // low => usually appears AFTER Publish box 91 ); 92 93 }, 20); 94 95 /** 96 * Force metabox order on creavibc_service edit screen: 97 */ 98 99 add_filter('get_user_option_meta-box-order_creavibc_service', function($order) { 100 101 // Always enforce our default order (clean layout for services) 102 $normal = implode(',', [ 103 'creavibc_available_days', 104 'creavibc_time_slot_grid', 105 'creavibc_output_type', 106 'creavibc_booking_form_fields', 107 'creavibc_service_appearance', 108 'creavibc_service_notifications', 109 'creavibc_google_calendar', 110 ]); 111 112 // Right column: Featured Image first, then Publish (as you requested) 113 $side = implode(',', [ 114 'postimagediv', 115 'submitdiv', 116 ]); 117 118 return [ 119 'normal' => $normal, 120 'side' => $side, 121 'advanced' => '', 122 ]; 23 123 }); 124 24 125 25 126 … … 41 142 }); 42 143 144 function creavibc_render_shortcode_metabox( $post ) { 145 146 $post_id = isset( $post->ID ) ? (int) $post->ID : 0; 147 148 echo '<div class="creavibc-shortcode-box">'; 149 150 if ( $post_id <= 0 || 'auto-draft' === $post->post_status ) { 151 echo '<p class="description">' . 152 esc_html__( 'Save the service first to generate the shortcode.', 'creavi-booking-service' ) . 153 '</p>'; 154 echo '</div>'; 155 return; 156 } 157 158 $output_type = get_post_meta( $post_id, '_creavibc_output_type', true ); 159 $output_type = is_string( $output_type ) ? sanitize_key( $output_type ) : ''; 160 161 $shortcode_tag = ( 'inline' === $output_type ) ? 'creavibc_booking_inline' : 'creavibc_booking_button'; 162 $shortcode = '[' . $shortcode_tag . ' id="' . $post_id . '"]'; 163 164 $code_id = 'creavibc-shortcode-code-' . $post_id; 165 166 $title = ( 'inline' === $output_type ) 167 ? esc_html__( 'Inline booking shortcode', 'creavi-booking-service' ) 168 : esc_html__( 'Popup booking shortcode', 'creavi-booking-service' ); 169 170 $desc = esc_html__( 'Paste this into any page/post (Shortcode block / Elementor Shortcode widget):', 'creavi-booking-service' ); 171 172 echo '<p class="creavibc-sc-title">' . esc_html( $title ) . '</p>'; 173 echo '<p class="description creavibc-sc-desc">' . esc_html( $desc ) . '</p>'; 174 175 echo '<div class="creavibc-sc-fieldwrap">'; 176 echo ' <input type="text" class="creavibc-sc-input" id="' . esc_attr( $code_id ) . '" value="' . esc_attr( $shortcode ) . '" readonly spellcheck="false" />'; 177 echo '</div>'; 178 179 echo '<div class="creavibc-sc-actions">'; 180 echo ' <button type="button" class="button button-secondary creavibc-sc-copy" data-copy-target="' . esc_attr( $code_id ) . '">'; 181 echo ' <span class="creavibc-sc-copy-default">' . esc_html__( 'Copy shortcode', 'creavi-booking-service' ) . '</span>'; 182 echo ' <span class="creavibc-sc-copy-done" aria-hidden="true">' . esc_html__( 'Copied', 'creavi-booking-service' ) . '</span>'; 183 echo ' </button>'; 184 echo '</div>'; 185 186 echo '</div>'; 187 } 43 188 44 189 function creavibc_render_output_type_box($post) { … … 84 229 $mode = get_post_meta($post->ID, '_creavibc_availability_mode', true); 85 230 if ( ! in_array($mode, ['static', 'dynamic'], true) ) { 86 $mode = ' static';231 $mode = 'dynamic'; 87 232 } 88 233 89 234 $months_ahead = (int) get_post_meta($post->ID, '_creavibc_dynamic_months_ahead', true); 90 $months_ahead = max(1, min(12, $months_ahead ?: 1)); 235 $months_ahead = (int) $months_ahead_raw; 236 if ( $months_ahead <= 0 ) { 237 $months_ahead = 1; // default: 1 month ahead 238 } 239 $months_ahead = max( 1, min( 12, $months_ahead ) ); 91 240 92 241 // Canonical excluded field name + meta key (do not change!) … … 648 797 echo '<textarea name="creavibc_email_user_template" id="creavibc_email_user_template" rows="4" style="width: 100%;">' . esc_textarea($user_email_tpl) . '</textarea></p>'; 649 798 650 echo '<p class="description">' . esc_html__( 'Available tags:', 'creavi-booking-service' ) . ' {name}, { email}, {date}, {time}, {service}, {custom} <span style="color:#666;">' . esc_html__( '- submitted custom fields', 'creavi-booking-service' ) . '</span></p>';799 echo '<p class="description">' . esc_html__( 'Available tags:', 'creavi-booking-service' ) . ' {name}, {name_url}, {email}, {date}, {time}, {service}, {custom} <span style="color:#666;">' . esc_html__( '- submitted custom fields', 'creavi-booking-service' ) . '</span></p>'; 651 800 652 801 … … 715 864 716 865 echo '<p class="description">'; 717 echo esc_html__( 'Available tags:', 'creavi-booking-service' ) . ' {name}, { email}, {date}, {time}, {service}, {custom} ';866 echo esc_html__( 'Available tags:', 'creavi-booking-service' ) . ' {name}, {name_url}, {email}, {date}, {time}, {service}, {custom} '; 718 867 echo '<span style="color:#666;">' . esc_html__( '- submitted custom fields', 'creavi-booking-service' ) . '</span>'; 719 868 echo '</p>'; -
creavi-booking-service/trunk/includes/reminders.php
r3441012 r3468659 121 121 $replacements = [ 122 122 '{name}' => $name, 123 '{name_url}' => rawurlencode( (string) $name ), 123 124 '{email}' => $email, 124 125 '{date}' => $display_date, -
creavi-booking-service/trunk/includes/save-service.php
r3456986 r3468659 6 6 if (!current_user_can('edit_post', $post_id)) return; 7 7 8 // ───────────────────────────────────────────── 9 // Metrics opt-in (Publish box) + publish event 10 // ───────────────────────────────────────────── 11 $metrics_nonce = isset($_POST['creavibc_metrics_optin_nonce']) 12 ? sanitize_text_field(wp_unslash($_POST['creavibc_metrics_optin_nonce'])) 13 : ''; 14 15 if ( $metrics_nonce && wp_verify_nonce( $metrics_nonce, 'creavibc_metrics_optin_save' ) ) { 16 17 // Save opt-in (default checked in UI) 18 $optin = isset($_POST['creavibc_metrics_optin']) ? '1' : '0'; 19 update_option( 'creavibc_metrics_optin', $optin, false ); 20 21 // If opted in, fire publish events only once per service 22 if ( $optin === '1' ) { 23 24 // Check current status reliably 25 $post = get_post( $post_id ); 26 $is_publish = ( $post && $post->post_status === 'publish' ); 27 28 // Only send once per service 29 $already_sent = get_post_meta( $post_id, '_creavibc_metrics_published_sent', true ); 30 31 if ( $is_publish && $already_sent !== '1' ) { 32 33 // Backfill "plugin_activated" once (first legal moment to send) 34 $activated_at = (int) get_option( 'creavibc_activated_at', 0 ); 35 if ( $activated_at > 0 && function_exists( 'creavibc_metrics_send_event' ) ) { 36 creavibc_metrics_send_event( 'plugin_activated', [ 37 'activated_at' => $activated_at, 38 ] ); 39 delete_option( 'creavibc_activated_at' ); 40 } 41 42 if ( function_exists( 'creavibc_metrics_send_event' ) ) { 43 creavibc_metrics_send_event( 'service_published', [ 44 'service_id' => (int) $post_id, 45 ] ); 46 } 47 48 update_post_meta( $post_id, '_creavibc_metrics_published_sent', '1' ); 49 } 50 } 51 } 52 53 54 8 55 // Save available days 9 10 11 56 $days_nonce = isset($_POST['creavibc_days_nonce']) ? sanitize_text_field(wp_unslash($_POST['creavibc_days_nonce'])) : ''; 12 57 if ( $days_nonce && wp_verify_nonce( $days_nonce, 'creavibc_save_days' ) ) { -
creavi-booking-service/trunk/readme.txt
r3460772 r3468659 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1. 1.97 Stable tag: 1.2.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 99 99 == Changelog == 100 100 101 = 1.2.0 = 102 * Added `{name_url}` template tag for Booking emails, Reminder emails. 103 * Added Service setup onboarding navigation bar for a clearer configuration flow. 104 * Improved Service editor layout with structured top navigation 105 101 106 = 1.1.9 = 102 107 * Added per-service Google Calendar connections – each service can now connect to its own Google account.
Note: See TracChangeset
for help on using the changeset viewer.