--- a/product-sync-master-sheet/admin/admin-loader.php
+++ b/product-sync-master-sheet/admin/admin-loader.php
@@ -8,8 +8,15 @@
use PSSG_Sync_SheetAppHandleApi_Request_Handle as API_Handle;
use PSSG_Sync_SheetAppHttpSheet;
use PSSG_Sync_SheetAdminPage_Loader;
+use PSSG_Sync_SheetAppServiceRequest_Log;
+
class Admin_Loader extends Admin_Base
{
+ /**
+ * Option key for tracking if user has been notified about AppsScript update
+ */
+ const APPSCRIPT_UPDATE_NOTICE_KEY = 'pssg_appscript_update_notice_dismissed';
+
public function __construct()
{
@@ -17,6 +24,9 @@
public function init()
{
+ // Auto-generate Access Key if not exists
+ $this->maybe_generate_access_key();
+
$sheet = new Sheet();
$sheet->run();
@@ -35,6 +45,10 @@
//pssg_quick_table_update
add_action('wp_ajax_pssg_quick_table_update', [$this,'quick_table_update']);
add_action('wp_ajax_noprev_pssg_quick_table_update', [$this,'quick_table_update']);
+
+ // Show AppsScript update notice for existing users
+ add_action('admin_notices', [$this, 'show_appscript_update_notice']);
+ add_action('wp_ajax_pssg_dismiss_appscript_notice', [$this, 'dismiss_appscript_notice']);
}
public function plugin_action_links( $links )
@@ -73,4 +87,108 @@
echo wp_json_encode( $response );
wp_die();
}
+
+ /**
+ * Auto-generate Access Key if not exists
+ * This ensures Access Key is always available for AppsScript
+ *
+ * @return void
+ */
+ private function maybe_generate_access_key()
+ {
+ if (!Request_Log::has_access_key()) {
+ Request_Log::generate_access_key();
+ }
+ }
+
+ /**
+ * Show notice for existing users about AppsScript update
+ * This detects users who had the plugin before the security update
+ *
+ * Detection logic: If user has sheet configured but notice not dismissed,
+ * they are likely an existing user who needs to update AppsScript.
+ *
+ * @return void
+ */
+ public function show_appscript_update_notice()
+ {
+ // Only show on admin pages
+ if (!is_admin()) {
+ return;
+ }
+
+ // Check if notice was already dismissed
+ if (get_option(self::APPSCRIPT_UPDATE_NOTICE_KEY, false)) {
+ return;
+ }
+
+ // Check if this is an existing user (has saved data = has configured the plugin before)
+ $saved_data = get_option('pssg_saved_data', []);
+ $has_sheet_configured = !empty($saved_data['spreadsheet_id']) || !empty($saved_data['sheet_url']);
+
+ // Only show to users who have configured the plugin before
+ // New users won't have any saved data, so they won't see this notice
+ if (!$has_sheet_configured) {
+ return;
+ }
+
+ // Only show to users who appear to be existing users
+ $current_screen = get_current_screen();
+ if (!$current_screen) {
+ return;
+ }
+
+ ?>
+ <div class="notice notice-warning is-dismissible pssg-appscript-update-notice" data-nonce="<?php echo esc_attr(wp_create_nonce('pssg_dismiss_notice')); ?>">
+ <h3 style="margin-top: 10px;">
+ <span class="dashicons dashicons-warning" style="color: #dba617;"></span>
+ <?php echo esc_html__('Sync Master Sheet - Important Security Update', 'product-sync-master-sheet'); ?>
+ </h3>
+ <p>
+ <?php echo esc_html__('The AppsScript has been updated with a new security feature. You need to update your Google Sheet with the new AppsScript code for continued functionality.', 'product-sync-master-sheet'); ?>
+ </p>
+ <p><strong><?php echo esc_html__('Please follow these steps:', 'product-sync-master-sheet'); ?></strong></p>
+ <ol style="margin-left: 20px;">
+ <li><?php echo esc_html__('Go to Settings > Security Settings', 'product-sync-master-sheet'); ?></li>
+ <li><?php echo esc_html__('Your Access Token has been automatically generated', 'product-sync-master-sheet'); ?></li>
+ <li><?php echo esc_html__('Click "Copy AppsScript" button', 'product-sync-master-sheet'); ?></li>
+ <li><?php echo esc_html__('Open your Google Sheet > Extensions > Apps Script', 'product-sync-master-sheet'); ?></li>
+ <li><?php echo esc_html__('Replace the old script with the new one and save', 'product-sync-master-sheet'); ?></li>
+ </ol>
+ <p>
+ <a href="<?php echo esc_url(admin_url('admin.php?page=pssg-setup-wizard#pssg-security-settings')); ?>" class="button button-primary">
+ <?php echo esc_html__('Go to Security Settings', 'product-sync-master-sheet'); ?>
+ </a>
+ <button type="button" class="button pssg-dismiss-notice" style="margin-left: 10px;">
+ <?php echo esc_html__('Dismiss', 'product-sync-master-sheet'); ?>
+ </button>
+ </p>
+ </div>
+ <script>
+ jQuery(document).ready(function($) {
+ $('.pssg-appscript-update-notice').on('click', '.pssg-dismiss-notice, .notice-dismiss', function(e) {
+ var $notice = $(this).closest('.pssg-appscript-update-notice');
+ var nonce = $notice.data('nonce');
+ $.post(ajaxurl, {
+ action: 'pssg_dismiss_appscript_notice',
+ nonce: nonce
+ });
+ $notice.fadeOut();
+ });
+ });
+ </script>
+ <?php
+ }
+
+ /**
+ * AJAX handler to dismiss the AppsScript update notice
+ *
+ * @return void
+ */
+ public function dismiss_appscript_notice()
+ {
+ check_ajax_referer('pssg_dismiss_notice', 'nonce');
+ update_option(self::APPSCRIPT_UPDATE_NOTICE_KEY, true);
+ wp_send_json_success();
+ }
}
No newline at end of file
--- a/product-sync-master-sheet/admin/page-loader.php
+++ b/product-sync-master-sheet/admin/page-loader.php
@@ -12,6 +12,7 @@
use PSSG_Sync_SheetAppHandleSetup_Wizard;
use PSSG_Sync_SheetAppHandleInactive_Element;
use PSSG_Sync_SheetAppServiceStandalone;
+use PSSG_Sync_SheetAppServiceRequest_Log;
class Page_Loader extends Admin_Base
{
@@ -56,6 +57,10 @@
add_action('wp_ajax_pssg_setting_wizard_submit', [$this, 'form_submit']);
add_action('wp_ajax_pssg_configure_form_submit', [$this, 'form_submit']);
add_action('wp_ajax_handle_json_file_upload', [$this, 'handle_json_file_upload']);
+
+ // Access Key AJAX handlers
+ add_action('wp_ajax_pssg_generate_access_key', [$this, 'ajax_generate_access_key']);
+ add_action('wp_ajax_pssg_regenerate_access_key', [$this, 'ajax_regenerate_access_key']);
add_action('admin_body_class', [$this, 'admin_body_class']);
if (!$this->is_premium) {
@@ -83,6 +88,9 @@
$qt_page_title = __('Product Quick Edit', 'product-sync-master-sheet');
$qt_menu_title = __('Product Quick Edit', 'product-sync-master-sheet');
+ $log_page_title = __('API Logs', 'product-sync-master-sheet');
+ $log_menu_title = __('API Logs', 'product-sync-master-sheet');
+
$multiple_site_title = __('Multiple Site Connect', 'product-sync-master-sheet');
$multiple_site_menu_title = __('Multiple Site Connect', 'product-sync-master-sheet');
@@ -91,21 +99,27 @@
$page_title .= __(' Premium', 'product-sync-master-sheet');
$qt_page_title .= __(' Premium', 'product-sync-master-sheet');
$sw_page_title .= __(' Premium', 'product-sync-master-sheet');
+ $log_page_title .= __(' Premium', 'product-sync-master-sheet');
$multiple_site_title .= __(' Premium', 'product-sync-master-sheet');
}
add_menu_page($page_title, $menu_title, $capability, $menu_slug, $callback, $icon_url, $position);
add_submenu_page($menu_slug, $sw_page_title, $sw_menu_title, $capability, 'pssg-setup-wizard', [$this, 'config_settings_page']);
add_submenu_page($menu_slug, $qt_page_title, $qt_menu_title, $capability, 'pssg-quick-edit', [$this, 'quick_edit_page']);
+ add_submenu_page($menu_slug, $log_page_title, $log_menu_title, $capability, 'pssg-api-logs', [$this, 'request_log_page']);
- if (! $this->is_premium) {
+ if ( ! $this->is_premium) {
add_submenu_page($menu_slug, $multiple_site_title, $multiple_site_menu_title, $capability, 'pssg-multisite-connection', [$this, 'multiple_site_menu_page_render']);
- $get_pro_title = __('Get Premium 🛒', 'product-sync-master-sheet');
- add_submenu_page($menu_slug, $get_pro_title, $get_pro_title, $capability, 'pssg-pricing', [$this, 'pricing_page_render']);
}
}
- public function admin_body_class($classes)
+ /**
+ * To set class on admin body tag
+ *
+ * @param string $classes
+ * @return void
+ */
+ public function admin_body_class( $classes )
{
if ( $this->is_premium) {
$classes .= ' pssg-body-premium ';
@@ -123,13 +137,7 @@
if (! is_file($main_page_file)) return;
include $main_page_file;
}
- public function pricing_page_render()
- {
- $this->topbar_sub_title = __("Pricing", 'product-sync-master-sheet');
- $pricing_page_file = $this->page_folder_dir . 'pricing/table.php';
- if (! is_file($pricing_page_file)) return;
- include $pricing_page_file;
- }
+
public function multiple_site_menu_page_render()
{
$this->topbar_sub_title = __("Sync Stock with Multiple Sites", 'product-sync-master-sheet');
@@ -157,6 +165,70 @@
include $quick_edit;
}
+ public function request_log_page()
+ {
+ $this->topbar_sub_title = __("API Logs", 'product-sync-master-sheet');
+ $request_log = $this->page_folder_dir . 'request-log.php';
+ if (! is_file($request_log)) return;
+ include $request_log;
+ }
+
+ /**
+ * AJAX handler for generating access key
+ */
+ public function ajax_generate_access_key()
+ {
+ // Verify nonce
+ if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'pssg_access_key_action')) {
+ wp_send_json_error(['message' => __('Security check failed.', 'product-sync-master-sheet')]);
+ }
+
+ // Check capability
+ if (!current_user_can('manage_woocommerce')) {
+ wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'product-sync-master-sheet')]);
+ }
+
+ // Generate new access key
+ $new_key = Request_Log::generate_access_key();
+
+ if ($new_key) {
+ wp_send_json_success([
+ 'message' => __('Access Key generated successfully!', 'product-sync-master-sheet'),
+ 'access_key' => $new_key,
+ ]);
+ } else {
+ wp_send_json_error(['message' => __('Failed to generate Access Key.', 'product-sync-master-sheet')]);
+ }
+ }
+
+ /**
+ * AJAX handler for regenerating access key
+ */
+ public function ajax_regenerate_access_key()
+ {
+ // Verify nonce
+ if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'pssg_access_key_action')) {
+ wp_send_json_error(['message' => __('Security check failed.', 'product-sync-master-sheet')]);
+ }
+
+ // Check capability
+ if (!current_user_can('manage_woocommerce')) {
+ wp_send_json_error(['message' => __('You do not have permission to perform this action.', 'product-sync-master-sheet')]);
+ }
+
+ // Regenerate access key
+ $new_key = Request_Log::generate_access_key();
+
+ if ($new_key) {
+ wp_send_json_success([
+ 'message' => __('Access Key regenerated successfully! Remember to update the AppsScript in your Google Sheet.', 'product-sync-master-sheet'),
+ 'access_key' => $new_key,
+ ]);
+ } else {
+ wp_send_json_error(['message' => __('Failed to regenerate Access Key.', 'product-sync-master-sheet')]);
+ }
+ }
+
public function premium_version_update_notice()
{
@@ -244,6 +316,9 @@
'script_copied_msg' => __('Script Copied! - Now add to your Sheet.', 'product-sync-master-sheet'),
'error_in_copy' => __('Unable to copy to clipboard', 'product-sync-master-sheet'),
'show_all' => __('Show All', 'product-sync-master-sheet'),
+ 'access_key_not_generated' => __('Access Key is not generated. Please generate an Access Key from the Security Settings before copying the AppsScript.', 'product-sync-master-sheet'),
+ 'regenerate_key_confirm' => __('Are you sure you want to regenerate the Access Key? The current key will be invalidated and you will need to update the AppsScript in your Google Sheet.', 'product-sync-master-sheet'),
+ 'access_key_copied' => __('Access Key copied to clipboard!', 'product-sync-master-sheet'),
],
'nonce' => wp_create_nonce(plugin_basename(PSSG_BASE_FILE)),
'dev_version' => $this->dev_version,
--- a/product-sync-master-sheet/admin/pages/incs/security.php
+++ b/product-sync-master-sheet/admin/pages/incs/security.php
@@ -0,0 +1,326 @@
+<?php
+/**
+ * Security Settings Section
+ * Access Token Generation and Management
+ *
+ * @package PSSG_Sync_Sheet
+ * @since 1.1.4
+ */
+
+if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
+
+use PSSG_Sync_SheetAppServiceRequest_Log;
+
+// Get current access key
+$current_access_key = Request_Log::get_access_key();
+$has_access_key = !empty($current_access_key);
+
+// Get AppsScript code for copy button
+$APPSCRIPT_VERSION = '1.0.1';
+
+?>
+<table class="pssg-table security-settings" id="pssg-security-settings-table">
+ <thead>
+ <tr>
+ <th class="pssg-inside">
+ <div class="pssg-table-header-inside">
+ <h3>
+ <i class="pssg_icon-lock"></i>
+ <?php echo esc_html__( 'Security Settings', 'product-sync-master-sheet' ); ?>
+ </h3>
+ </div>
+ </th>
+ <th>
+ <div class="pssg-table-header-right-side"></div>
+ </th>
+ </tr>
+ </thead>
+
+ <tbody>
+ <tr>
+ <td colspan="2">
+ <div class="pssg-form-control pssg-access-key-section">
+ <div class="form-label col-lg-4">
+ <label for="pssg_access_key">
+ <i class="pssg_icon-key"></i>
+ <?php echo esc_html__( 'Access Token', 'product-sync-master-sheet' ); ?>
+ </label>
+ <p class="description">
+ <?php echo esc_html__( 'This key is required for Google Sheet to communicate with your WooCommerce store securely.', 'product-sync-master-sheet' ); ?>
+ </p>
+ </div>
+ <div class="form-field col-lg-8">
+ <div class="pssg-access-key-wrapper">
+ <?php if ( $has_access_key ) : ?>
+ <div class="pssg-access-key-display">
+ <input type="text"
+ id="pssg_access_key_display"
+ class="pssg-access-key-input"
+ value="<?php echo esc_attr( $current_access_key ); ?>"
+ readonly
+ onclick="this.select();">
+ <button type="button"
+ id="pssg-copy-access-key"
+ class="pssg-btn pssg-btn-small pssg-has-icon"
+ title="<?php echo esc_attr__( 'Copy Access Token', 'product-sync-master-sheet' ); ?>">
+ <span><i class="pssg_icon-floppy"></i></span>
+ <strong><?php echo esc_html__( 'Copy', 'product-sync-master-sheet' ); ?></strong>
+ </button>
+ </div>
+
+ <!-- AppsScript Copy Button -->
+ <div class="pssg-appscript-copy-section">
+ <a id="pssg-appscript-copy-button-security" class="pssg-btn pssg-has-icon primary" data-has-access-key="yes">
+ <span><i class="pssg_icon-note"></i></span>
+ <strong class="sync-btn-txt"><?php echo esc_html__( 'Copy AppsScript', 'product-sync-master-sheet' ); ?> <i>V<?php echo esc_html( $APPSCRIPT_VERSION ); ?></i></strong>
+ </a>
+ <p class="script-copy-msg-security"></p>
+ <p class="pssg-appscript-help">
+ <i class="pssg_icon-info-circled"></i>
+ <?php echo esc_html__( 'Copy this AppsScript and paste it in your Google Sheet Extensions > Apps Script.', 'product-sync-master-sheet' ); ?>
+ </p>
+ </div>
+
+ <div class="pssg-access-key-actions">
+ <button type="button"
+ id="pssg-regenerate-access-key"
+ class="pssg-btn pssg-btn-small pssg-has-icon warning"
+ data-nonce="<?php echo esc_attr( wp_create_nonce( 'pssg_access_key_action' ) ); ?>">
+ <span><i class="pssg_icon-arrows-cw"></i></span>
+ <strong><?php echo esc_html__( 'Regenerate Token', 'product-sync-master-sheet' ); ?></strong>
+ </button>
+ <p class="pssg-key-warning">
+ <i class="pssg_icon-attention"></i>
+ <?php echo esc_html__( 'Warning: Regenerating the token will invalidate the current one. You will need to update the AppsScript in your Google Sheet.', 'product-sync-master-sheet' ); ?>
+ </p>
+ </div>
+ <?php else : ?>
+ <div class="pssg-no-access-key">
+ <p class="pssg-generate-key-message">
+ <i class="pssg_icon-attention" style="color: #d63031;"></i>
+ <?php echo esc_html__( 'No Access Token generated yet. Generate one to secure your API endpoints.', 'product-sync-master-sheet' ); ?>
+ </p>
+ <button type="button"
+ id="pssg-generate-access-key"
+ class="pssg-btn pssg-has-icon primary"
+ data-nonce="<?php echo esc_attr( wp_create_nonce( 'pssg_access_key_action' ) ); ?>">
+ <span><i class="pssg_icon-key"></i></span>
+ <strong><?php echo esc_html__( 'Generate Access Token', 'product-sync-master-sheet' ); ?></strong>
+ </button>
+ </div>
+ <?php endif; ?>
+ </div>
+ <div class="pssg-access-key-status" id="pssg-access-key-status"></div>
+ </div>
+ </div>
+ </td>
+ </tr>
+
+ <tr>
+ <td colspan="2">
+ <div class="pssg-security-info-box">
+ <h4><i class="pssg_icon-info-circled"></i> <?php echo esc_html__( 'How Access Token Works', 'product-sync-master-sheet' ); ?></h4>
+ <ul>
+ <li><?php echo esc_html__( '1. Generate an Access Token from this settings page.', 'product-sync-master-sheet' ); ?></li>
+ <li><?php echo esc_html__( '2. The Access Token will be automatically included when you copy the AppsScript code.', 'product-sync-master-sheet' ); ?></li>
+ <li><?php echo esc_html__( '3. Every request from Google Sheet to your website will include this token for authentication.', 'product-sync-master-sheet' ); ?></li>
+ <li><?php echo esc_html__( '4. Requests without a valid Access Token will be rejected.', 'product-sync-master-sheet' ); ?></li>
+ </ul>
+ <p class="pssg-important-note">
+ <strong><?php echo esc_html__( 'Important:', 'product-sync-master-sheet' ); ?></strong>
+ <?php echo esc_html__( 'After generating or regenerating the Access Token, you must copy the new AppsScript code and update it in your Google Sheet.', 'product-sync-master-sheet' ); ?>
+ </p>
+ </div>
+ </td>
+ </tr>
+
+ </tbody>
+</table>
+
+<?php
+// Include AppsScript code for copy button
+$sheet_name = get_option('pssg_saved_data', [])['sheet_name'] ?? '';
+?>
+<textarea id="appscript-code-area-security" style="display: none;visibility:hidden;height:0;width:0;">
+<?php
+$website_routespace = 'pssg_gsheet_sync/v1/product';
+$website_routespace_multiple = 'pssg_gsheet_sync/v1/multiples';
+$replacements = [
+ 'pssg_namespace_route' => $website_routespace,
+ 'multiple_product_route' => $website_routespace_multiple,
+ 'pssg_json_website' => trailingslashit( get_rest_url() )
+];
+$script_file = PSSG_BASE_DIR . 'assets/js/script.js';
+if( is_file( $script_file ) ){
+ $code = pssg_file_get_content( $script_file );
+ $code = preg_replace('///(.+?)n/', '', $code);
+ $code = preg_replace('//*.*?*//s', '', $code);
+ $code = preg_replace('/^s*[rn]/m', '', $code);
+ $code = str_replace( array_keys($replacements), array_values($replacements), $code );
+ $appsV = 'var AppsScriptVersion = "' . $APPSCRIPT_VERSION . '";';
+ $appsAccessKey = 'var AppsScriptAccessKey = "' . esc_js( $current_access_key ) . '";';
+ $extraCode = $appsV . $appsAccessKey;
+ $code = $extraCode . $code;
+ $code = 'var YourSheetTabName = "' . sanitize_text_field( $sheet_name ) . '";' . $code;
+ echo esc_js( $code );
+}
+?>
+</textarea>
+
+<script>
+jQuery(document).ready(function($) {
+ // AppsScript copy button in security settings
+ $(document.body).on('click', '#pssg-appscript-copy-button-security', function(e) {
+ e.preventDefault();
+ var msgBox = $('.script-copy-msg-security');
+ var contentToCopy = document.getElementById('appscript-code-area-security');
+
+ if (navigator.clipboard && navigator.clipboard.writeText) {
+ navigator.clipboard.writeText(contentToCopy.textContent)
+ .then(function () {
+ msgBox.text('AppsScript copied! Now paste it in your Google Sheet.').addClass('success');
+ setTimeout(function(){
+ msgBox.text("");
+ }, 3000);
+ })
+ .catch(function (err) {
+ msgBox.text('Unable to copy. Please try again.').addClass('error');
+ console.log(err);
+ });
+ } else {
+ // Fallback for older browsers
+ var textArea = document.createElement("textarea");
+ textArea.value = contentToCopy.textContent;
+ document.body.appendChild(textArea);
+ textArea.select();
+ document.execCommand('copy');
+ document.body.removeChild(textArea);
+ msgBox.text('AppsScript copied! Now paste it in your Google Sheet.').addClass('success');
+ setTimeout(function(){
+ msgBox.text("");
+ }, 3000);
+ }
+ });
+});
+</script>
+
+<style>
+.pssg-access-key-section {
+ padding: 20px;
+ background: #f9f9f9;
+ border-radius: 8px;
+}
+.pssg-access-key-wrapper {
+ margin-bottom: 15px;
+}
+.pssg-access-key-display {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ margin-bottom: 15px;
+}
+.pssg-access-key-input {
+ flex: 1;
+ padding: 10px 15px;
+ font-family: monospace;
+ font-size: 14px;
+ background: #fff;
+ border: 2px solid #ddd;
+ border-radius: 5px;
+ cursor: pointer;
+}
+.pssg-access-key-input:focus {
+ border-color: #0073aa;
+ outline: none;
+}
+.pssg-appscript-copy-section {
+ margin: 20px 0;
+ padding: 15px;
+ background: #f0f8ff;
+ border-radius: 8px;
+ border: 1px solid #b8daff;
+}
+.pssg-appscript-copy-section .pssg-btn {
+ margin-bottom: 10px;
+}
+.pssg-appscript-help {
+ margin: 0;
+ color: #666;
+ font-size: 13px;
+}
+.script-copy-msg-security {
+ margin: 5px 0;
+ color: #28a745;
+ font-weight: 500;
+}
+.pssg-access-key-actions {
+ margin-top: 15px;
+}
+.pssg-key-warning {
+ margin-top: 10px;
+ color: #856404;
+ background: #fff3cd;
+ padding: 10px 15px;
+ border-radius: 5px;
+ border-left: 4px solid #ffc107;
+}
+.pssg-no-access-key {
+ text-align: center;
+ padding: 30px;
+ background: #fff;
+ border: 2px dashed #ddd;
+ border-radius: 8px;
+}
+.pssg-generate-key-message {
+ font-size: 16px;
+ margin-bottom: 20px;
+}
+.pssg-security-info-box {
+ background: #e8f4fd;
+ padding: 20px;
+ border-radius: 8px;
+ border-left: 4px solid #0073aa;
+}
+.pssg-security-info-box h4 {
+ margin: 0 0 15px 0;
+ color: #0073aa;
+}
+.pssg-security-info-box ul {
+ margin: 0 0 15px 20px;
+ padding: 0;
+}
+.pssg-security-info-box li {
+ margin-bottom: 8px;
+}
+.pssg-important-note {
+ margin: 0;
+ padding: 10px 15px;
+ background: #fff;
+ border-radius: 5px;
+}
+.pssg-btn.warning {
+ background: #f0ad4e;
+ border-color: #eea236;
+ color: #fff;
+}
+.pssg-btn.warning:hover {
+ background: #ec971f;
+}
+.pssg-btn.primary {
+ background: #0073aa;
+ border-color: #006799;
+ color: #fff;
+}
+.pssg-btn.primary:hover {
+ background: #005a87;
+}
+.pssg-access-key-status {
+ margin-top: 10px;
+}
+.pssg-access-key-status.success {
+ color: #28a745;
+}
+.pssg-access-key-status.error {
+ color: #dc3545;
+}
+</style>
--- a/product-sync-master-sheet/admin/pages/multsite_con_demo.php
+++ b/product-sync-master-sheet/admin/pages/multsite_con_demo.php
@@ -6,246 +6,499 @@
?>
-
-
-
-
<div class="wrap pssg_wrap pssg-content">
- <h1 class="wp-heading "></h1>
+ <h1 class="wp-heading"></h1>
<div class="fieldwrap">
-
-
+ <div class="pssg-section-panel quick-edit-section multiple-site-connection-demo pssg-multisite-modern" id="quick-edit-section" data-icon="pssg_icon-home">
+
+ <!-- Modern Header Card -->
+ <div class="pssg-multisite-header-card">
+ <div class="pssg-multisite-header-icon">
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <circle cx="12" cy="12" r="10"></circle>
+ <line x1="2" y1="12" x2="22" y2="12"></line>
+ <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
+ </svg>
+ </div>
+ <div class="pssg-multisite-header-content">
+ <h2><?php esc_html_e('Multiple Site Connection', 'product-sync-master-sheet'); ?></h2>
+ <p><?php esc_html_e('Sync your WooCommerce stock across multiple WordPress sites seamlessly. Connect your stores and keep inventory synchronized automatically.', 'product-sync-master-sheet'); ?></p>
+ </div>
+ </div>
- <div class="pssg-section-panel quick-edit-section multiple-site-connection-demo" id="quick-edit-section" data-icon="pssg_icon-home">
+ <form action="#" method="post" id="pssg-multisite-form" class="pssg-multisite-form-parent">
+ <!-- Connection Type Section -->
+ <div class="pssg-multisite-section">
+ <div class="pssg-section-header">
+ <div class="pssg-section-icon">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M12 20h9"></path>
+ <path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"></path>
+ </svg>
+ </div>
+ <h3><?php esc_html_e('API Connection Type', 'product-sync-master-sheet'); ?></h3>
+ </div>
+ <div class="pssg-section-body">
+ <div class="pssg-form-group">
+ <label for="connection-type"><?php esc_html_e('Select Connection Mode', 'product-sync-master-sheet'); ?></label>
+ <select name="pssg-connection-setting[type]" id="connection-type" class="site-type-changer-dropdown pssg-modern-select">
+ <option value=""><?php esc_html_e('Disable API Connection', 'product-sync-master-sheet'); ?></option>
+ <option value="child"><?php esc_html_e('Enable as Child (Share permission to Parent)', 'product-sync-master-sheet'); ?></option>
+ <option value="parent" selected="selected"><?php esc_html_e('Enable as Parent (Able to add Child Sites)', 'product-sync-master-sheet'); ?></option>
+ </select>
+ <p class="pssg-field-description"><?php esc_html_e('Choose how this site will participate in the multi-site sync network.', 'product-sync-master-sheet'); ?></p>
+ </div>
+
+ <div class="pssg-info-box">
+ <div class="pssg-info-icon">
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <circle cx="12" cy="12" r="10"></circle>
+ <line x1="12" y1="16" x2="12" y2="12"></line>
+ <line x1="12" y1="8" x2="12.01" y2="8"></line>
+ </svg>
+ </div>
+ <div class="pssg-info-content">
+ <strong><?php esc_html_e('How it works:', 'product-sync-master-sheet'); ?></strong>
+ <ul>
+ <li><strong><?php esc_html_e('Parent Site:', 'product-sync-master-sheet'); ?></strong> <?php esc_html_e('The main site connected to Google Sheet. It manages and distributes stock updates to all child sites.', 'product-sync-master-sheet'); ?></li>
+ <li><strong><?php esc_html_e('Child Site:', 'product-sync-master-sheet'); ?></strong> <?php esc_html_e('Receives stock updates from the parent site. Stock changes sync automatically with the parent.', 'product-sync-master-sheet'); ?></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
- <!-- <h1>Multisite hhhh</h1> -->
- <form action="#" method="post" id="pssg-multisite-form" class="pssg-multisite-form-parent">
- <div class="site-type-changer-wrapper">
- <table class="form-table" role="presentation">
- <tbody>
- <tr>
- <th scope="row">API Connection</th>
- <td>
- <p class="site-type-changer-dropdown-p">
- <select name="pssg-connection-setting[type]" class="site-type-changer-dropdown">
- <option value="">Disable API Connection</option>
- <option value="child">Enable as Child (Share permission to Parent)</option>
- <option value="parent" selected="selected">Enable as Parent (Able to add Some Child Site)</option>
- </select>
- </p>
- <p>
- Please select site type to connect your sheet with Multiple sites </p>
- </td>
- </tr>
- </tbody>
- </table>
- <p class="site-type-changer-message">
- This feature to connect your sheet with Multiple sites. If you connect your sheet with this single site, you have to choose this site as a <strong>Parent</strong> site.<br>
- And if you want, this site Stock will be sync with other site with a Parent site, you have to choose this site as a <strong>Child</strong> site.<br>
- If you connect your sheet with this multiple sites, you have to choose this site as a child site.
- </p>
- <div class="access-token-area">
-
- <table class="form-table" role="presentation">
- <tbody>
- <tr>
- <th scope="row">Site URL</th>
- <td>
- <div class="pssg-access-token-area">
- <input type="text" class="pssg-this-access-token pssg-site-url" value="<?php echo esc_attr( site_url() ); ?>" readonly="">
- </div>
- </td>
- </tr>
- <tr>
- <th scope="row">Access Token</th>
- <td>
- <div class="pssg-access-token-area">
- <input type="text" class="pssg-this-access-token" value="97C65B09CCF5814FBDD8B418AD22C*******************************************" readonly="">
- </div>
- </td>
- </tr>
- </tbody>
- </table>
-
- </div>
- </div>
- <div class="connect-parent-site-area pssg-multisite-setting-panel">
-
- <h2>Add your Parent Site</h2>
- <div class="add-child-site-section-desc" style="font-size: 19px;">
- <p>Carefully insert valid and full URL(target webstie's main url) and 68 character long Token.
- eg: <i>https://www.example.com/</i>
- <b>Important:</b> No wp-admin, wp-content, wp-includes, wp-json in URL
- </p>
- </div>
- <table class="form-table" role="presentation">
- <tbody>
- <tr>
- <th scope="row">Connect to Parent Site</th>
- <td>
- <div class="pssg-connected-sites-wrapper" data-my_nonce="cbf6408344">
- <div class="pssg-connected-site-single pssg-connected-site-single-1">
- <input type="url" id="parent_site_access" name="pssg-connection-setting[parent_site_access][url]" class="site-url-input input-text regular-input" placeholder="Parent Site URL" value="">
- <input type="text" id="parent_site_access" name="pssg-connection-setting[parent_site_access][token]" placeholder="Parent Site Access Token" class="site-url-input input-text regular-input" value="">
- </div>
- <button id="pssg-connect-site-check-connection-btn" class="button button-primary">Check Connection</button>
- <div class="connection-response-wrapper"></div>
- </div>
- </td>
- </tr>
- </tbody>
- </table>
- </div>
- <div class="connect-other-site-area pssg-multisite-setting-panel">
- <!-- <h1>Multisite Connection</h1> -->
-
- <input type="hidden" name="option_page" value="my_plugin_settings_group"><input type="hidden" name="action" value="update"><input type="hidden" id="_wpnonce" name="_wpnonce" value="2c0ad801cb"><input type="hidden" name="_wp_http_referer" value="/wp-admin/admin.php?page=pssg-multisite-connection">
- <h2>Add your Child Sites</h2>
- <div class="add-child-site-section-desc" style="font-size: 19px;">
- <p>Carefully insert valid and full URL(target webstie's main url) and 68 character long Token.
- eg: <i>https://www.example.com/</i>
- <b>Important:</b> No wp-admin, wp-content, wp-includes, wp-json in URL
- </p>
- </div>
- <table class="form-table" role="presentation">
- <tbody>
- <tr>
- <th scope="row">Connected Sites</th>
- <td>
- <div class="pssg-connected-sites-wrapper" data-my_nonce="cbf6408344" data-max_connected_site="5">
- <div class="pssg-connected-site-single pssg-connected-site-single-1">
- <input type="url" id="connected_sites" name="pssg-connection-setting[connected_sites][1][url]" placeholder="Site URL" class="site-url-input input-text regular-input" value="">
- <input type="text" id="connected_sites" name="pssg-connection-setting[connected_sites][1][token]" placeholder="Access Token" class="site-access-token-input input-text regular-input" value="">
- <a class="pssg-remove-connected-site-btn">x</a>
- </div>
- <button id="pssg-connect-site-add-new-btn" class="button button-warning">Add New</button>
- <button id="pssg-connect-site-check-connection-btn" class="button button-primary">Check Connection</button>
- <div class="connection-response-wrapper"></div>
- </div>
-
- </td>
- </tr>
- </tbody>
- </table>
+ <!-- Site Credentials Section -->
+ <div class="pssg-multisite-section">
+ <div class="pssg-section-header">
+ <div class="pssg-section-icon">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>
+ <path d="M7 11V7a5 5 0 0 1 10 0v4"></path>
+ </svg>
+ </div>
+ <h3><?php esc_html_e('Your Site Credentials', 'product-sync-master-sheet'); ?></h3>
+ </div>
+ <div class="pssg-section-body">
+ <p class="pssg-section-description"><?php esc_html_e('Share these credentials with other sites that need to connect to this site.', 'product-sync-master-sheet'); ?></p>
+
+ <div class="pssg-credential-row">
+ <div class="pssg-form-group">
+ <label><?php esc_html_e('Site URL', 'product-sync-master-sheet'); ?></label>
+ <div class="pssg-input-with-copy">
+ <input type="text" class="pssg-modern-input" value="<?php echo esc_attr( site_url() ); ?>" readonly>
+ <button type="button" class="pssg-copy-btn" title="<?php esc_attr_e('Copy to clipboard', 'product-sync-master-sheet'); ?>">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
+ </svg>
+ </button>
+ </div>
+ </div>
+ <div class="pssg-form-group">
+ <label><?php esc_html_e('Access Token', 'product-sync-master-sheet'); ?></label>
+ <div class="pssg-input-with-copy">
+ <input type="text" class="pssg-modern-input pssg-token-masked" value="97C65B09CCF5814FBDD8B418AD22C*******************************************" readonly>
+ <button type="button" class="pssg-copy-btn" title="<?php esc_attr_e('Copy to clipboard', 'product-sync-master-sheet'); ?>">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
+ <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
+ </svg>
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Parent Site Connection (for Child mode) -->
+ <div class="pssg-multisite-section connect-parent-site-area pssg-multisite-setting-panel">
+ <div class="pssg-section-header">
+ <div class="pssg-section-icon pssg-icon-parent">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path>
+ <polyline points="9 22 9 12 15 12 15 22"></polyline>
+ </svg>
+ </div>
+ <h3><?php esc_html_e('Connect to Parent Site', 'product-sync-master-sheet'); ?></h3>
+ </div>
+ <div class="pssg-section-body">
+ <div class="pssg-alert pssg-alert-info">
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <circle cx="12" cy="12" r="10"></circle>
+ <line x1="12" y1="16" x2="12" y2="12"></line>
+ <line x1="12" y1="8" x2="12.01" y2="8"></line>
+ </svg>
+ <span><?php esc_html_e('Enter the full URL and 68-character Access Token from your parent site apply. Do not include wp-admin or wp-json in the URL.', 'product-sync-master-sheet'); ?></span>
+ </div>
+
+ <div class="pssg-connected-sites-wrapper" data-my_nonce="demo">
+ <div class="pssg-site-connection-card">
+ <div class="pssg-form-group">
+ <label><?php esc_html_e('Parent Site URL', 'product-sync-master-sheet'); ?></label>
+ <input type="url" name="pssg-connection-setting[parent_site_access][url]" class="pssg-modern-input site-url-input" placeholder="https://parent-site.com/">
+ </div>
+ <div class="pssg-form-group">
+ <label><?php esc_html_e('Parent Site Access Token', 'product-sync-master-sheet'); ?></label>
+ <input type="text" name="pssg-connection-setting[parent_site_access][token]" class="pssg-modern-input" placeholder="<?php esc_attr_e('68-character Access Token', 'product-sync-master-sheet'); ?>">
+ </div>
+ </div>
+ <div class="pssg-connection-actions">
+ <button type="button" id="pssg-connect-site-check-connection-btn" class="pssg-btn pssg-btn-primary">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
+ <polyline points="22 4 12 14.01 9 11.01"></polyline>
+ </svg>
+ <?php esc_html_e('Check Connection', 'product-sync-master-sheet'); ?>
+ </button>
+ </div>
+ <div class="connection-response-wrapper"></div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Child Sites Connection (for Parent mode) -->
+ <div class="pssg-multisite-section connect-other-site-area pssg-multisite-setting-panel">
+ <div class="pssg-section-header">
+ <div class="pssg-section-icon pssg-icon-child">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path>
+ <circle cx="9" cy="7" r="4"></circle>
+ <path d="M23 21v-2a4 4 0 0 0-3-3.87"></path>
+ <path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
+ </svg>
+ </div>
+ <h3><?php esc_html_e('Connected Child Sites', 'product-sync-master-sheet'); ?></h3>
+ </div>
+ <div class="pssg-section-body">
+ <div class="pssg-alert pssg-alert-info">
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <circle cx="12" cy="12" r="10"></circle>
+ <line x1="12" y1="16" x2="12" y2="12"></line>
+ <line x1="12" y1="8" x2="12.01" y2="8"></line>
+ </svg>
+ <span><?php esc_html_e('Add your child sites below. Each site needs its full URL and 68-character Access Token apply. You can add up to 5 child sites.', 'product-sync-master-sheet'); ?></span>
+ </div>
+
+ <div class="pssg-connected-sites-wrapper" data-my_nonce="demo" data-max_connected_site="5">
+ <div class="pssg-site-connection-card pssg-connected-site-single pssg-connected-site-single-1">
+ <div class="pssg-form-group">
+ <label><?php esc_html_e('Site URL', 'product-sync-master-sheet'); ?></label>
+ <input type="url" name="pssg-connection-setting[connected_sites][1][url]" class="pssg-modern-input site-url-input" placeholder="https://child-site.com/">
+ </div>
+ <div class="pssg-form-group">
+ <label><?php esc_html_e('Access Token', 'product-sync-master-sheet'); ?></label>
+ <input type="text" name="pssg-connection-setting[connected_sites][1][token]" class="pssg-modern-input site-access-token-input" placeholder="<?php esc_attr_e('68-character Access Token', 'product-sync-master-sheet'); ?>">
+ </div>
+ <button type="button" class="pssg-remove-site-btn pssg-remove-connected-site-btn" title="<?php esc_attr_e('Remove this site', 'product-sync-master-sheet'); ?>">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <line x1="18" y1="6" x2="6" y2="18"></line>
+ <line x1="6" y1="6" x2="18" y2="18"></line>
+ </svg>
+ </button>
+ </div>
+
+ <div class="pssg-connection-actions">
+ <button type="button" id="pssg-connect-site-add-new-btn" class="pssg-btn pssg-btn-secondary">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <line x1="12" y1="5" x2="12" y2="19"></line>
+ <line x1="5" y1="12" x2="19" y2="12"></line>
+ </svg>
+ <?php esc_html_e('Add New Site', 'product-sync-master-sheet'); ?>
+ </button>
+ <button type="button" id="pssg-connect-site-check-connection-btn" class="pssg-btn pssg-btn-primary">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
+ <polyline points="22 4 12 14.01 9 11.01"></polyline>
+ </svg>
+ <?php esc_html_e('Check Connection', 'product-sync-master-sheet'); ?>
+ </button>
+ </div>
+ <div class="connection-response-wrapper"></div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Premium CTA -->
+ <div class="pssg-multisite-section pssg-premium-cta">
+ <div class="pssg-premium-cta-content">
+ <div class="pssg-premium-badge">
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
+ </svg>
+ <span><?php esc_html_e('Premium Feature', 'product-sync-master-sheet'); ?></span>
+ </div>
+ <h3><?php esc_html_e('Unlock Multiple Site Connection', 'product-sync-master-sheet'); ?></h3>
+ <p><?php esc_html_e('Upgrade to Premium to sync your WooCommerce inventory across multiple WordPress sites automatically.', 'product-sync-master-sheet'); ?></p>
+ <a href="https://codeastrology.com/sync-master-sheet/pricing/" target="_blank" class="pssg-btn pssg-btn-premium">
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
+ <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path>
+ <line x1="3" y1="6" x2="21" y2="6"></line>
+ <path d="M16 10a4 4 0 0 1-8 0"></path>
+ </svg>
+ <?php esc_html_e('Get Premium Now', 'product-sync-master-sheet'); ?>
+ </a>
+ </div>
</div>
- <p class="submit"><a type="submit" name="submit" id="submit" href="https://codeastrology.com/downloads/product-sync-master-sheet-premium/" target="_blank" class="button button-primary">Save Changes</a></p>
- </form>
+ </form>
</div>
</div>
-</div>
+</div>
+
<style>
-p.attr-alert.attr-alert-success {
- color: #4caf50;
-}
-.site-type-changer-message {
- display: none;
- color: #9E9E9E;
- font-size: 22px;
- font-weight: normal;
-}
-.site-type-changer-message b, .site-type-changer-message i, .site-type-changer-message u, .site-type-changer-message strong, .site-type-changer-message span {
- color: black;
- background: #ddd;
- padding: 2px 5px;
- border-radius: 7px;
-}
-.pssg-multisite-setting-panel{
- margin-top: 18px;
- display: none;
-}
-form.pssg-multisite-form- .access-token-area{
- display: none;
-}
-form.pssg-multisite-form- .site-type-changer-message,
-form.pssg-multisite-form-parent .connect-other-site-area.pssg-multisite-setting-panel,
-form.pssg-multisite-form-child .connect-parent-site-area.pssg-multisite-setting-panel{
- display: block;
-}
-.pssg-this-access-token{width: 100%;color: blue;min-width: 500px;max-width: 800px;}
-.pssg-connected-site-single{
- margin: 5px 0;
-}
-.pssg-connected-site-single input[type="text"]{
- width: 100%;
- max-width: 500px;
- min-width: 200px;
-}
-a.pssg-remove-connected-site-btn{
- background-color: red;
- color: white;
- padding: 5px 10px;
- border-radius: 5px;
- display: inline-block;
- cursor: pointer;
-}
-.add-child-site-section-desc p {
- font-size: 17px;
- color: #b1b1b1;
+/* Modern Multiple Site Connection Styles */
+.pssg-multisite-modern {
+ padding: 0 !important;
+ background: transparent !important;
+ box-shadow: none !important;
}
-.add-child-site-section-desc p i {
- color: #2271b1;
+.pssg-multisite-header-card {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+ padding: 32px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 16px;
+ margin-bottom: 24px;
+ color: white;
}
-.add-child-site-section-desc p strong, .add-child-site-section-desc p b, .add-child-site-section-desc p span {
- color: black;
-}
-.connection-response-wrapper {
- padding: 23px;
- background: aliceblue;
- margin: 20px 0;
- display: none;
-}
-.connection-response-wrapper>span {
- color: black;
- font-size: 30px;
+.pssg-multisite-header-icon {
+ width: 80px;
+ height: 80px;
+ background: rgba(255, 255, 255, 0.2);
+ border-radius: 16px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+}
+
+.pssg-multisite-header-icon svg { color: white; }
+
+.pssg-multisite-header-content h2 {
+ margin: 0 0 8px 0;
+ font-size: 28px;
+ font-weight: 700;
+ color: white;
}
-.connection-response-wrapper>span.error{color: #c00;}
-.connection-response-wrapper h2 {
- color: #023046;
- font-weight: bold;
+.pssg-multisite-header-content p {
margin: 0;
- font-size: 22px;
- line-height: 12px;
+ font-size: 16px;
+ opacity: 0.9;
+ line-height: 1.6;
+}
+
+.pssg-multisite-section {
+ background: white;
+ border-radius: 12px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+ margin-bottom: 20px;
+ overflow: hidden;
+ border: 1px solid #e5e7eb;
+}
+
+.pssg-section-header {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ padding: 20px 24px;
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
+ border-bottom: 1px solid #e5e7eb;
+}
+
+.pssg-section-icon {
+ width: 40px;
+ height: 40px;
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+ border-radius: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: white;
+ flex-shrink: 0;
}
-.connection-response-wrapper > div {
- border: 1px solid #ffffff87;
- margin: 15px 0;
- padding: 20px;
- min-width: 400px;
- max-width: 100%;
- border-radius: 9px;
- display: block;
-}
+.pssg-section-icon.pssg-icon-parent { background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); }
+.pssg-section-icon.pssg-icon-child { background: linear-gradient(135deg, #10b981 0%, #059669 100%); }
-.connection-response-wrapper > div.pssg-con-stat-success-box {
- border-color: #ffffff;
- background: #ffffffed;
-}
+.pssg-section-header h3 { margin: 0; font-size: 18px; font-weight: 600; color: #1e293b; }
+.pssg-section-body { padding: 24px; }
+.pssg-section-description { margin: 0 0 20px 0; color: #64