Software: Apache. PHP/8.1.30 uname -a: Linux server1.tuhinhossain.com 5.15.0-163-generic #173-Ubuntu SMP Tue Oct 14 17:51:00 UTC uid=1002(picotech) gid=1003(picotech) groups=1003(picotech),0(root) Safe-mode: OFF (not secure) /home/picotech/domains/test.sms.picotech.app/public_html/public/js/ drwxr-xr-x | |
| Viewing file: Select action/file-type: /**
* PicoSMS Admin Panel Tour Guide
* Professional onboarding tour for new administrators with page navigation
* Maintains tour progress across page redirects using sessionStorage
*/
(function () {
'use strict';
// Check if Shepherd is loaded
if (typeof Shepherd === 'undefined') {
console.error('Shepherd.js is not loaded. Please include it before this script.');
return;
}
// Storage keys
const TOUR_ACTIVE_KEY = 'picosms_admin_tour_active';
const TOUR_STEP_KEY = 'picosms_admin_tour_step';
// Helper function to navigate to a page
function navigateToPage(url, nextStepId) {
return new Promise((resolve) => {
if (window.location.pathname === url || window.location.href.includes(url)) {
// Already on the page
resolve();
} else {
// Save that we're in the middle of a tour
sessionStorage.setItem(TOUR_ACTIVE_KEY, 'true');
sessionStorage.setItem(TOUR_STEP_KEY, nextStepId);
// Navigate to the page
window.location.href = url;
// Don't resolve - page will reload
}
});
}
// Tour configuration
const tourConfig = {
useModalOverlay: true,
defaultStepOptions: {
classes: 'shepherd-theme-custom',
scrollTo: { behavior: 'smooth', block: 'center' },
cancelIcon: {
enabled: true
}
}
};
// Initialize tour
const adminTour = new Shepherd.Tour(tourConfig);
// Save current step whenever it changes
adminTour.on('show', function () {
const currentStep = adminTour.getCurrentStep();
if (currentStep) {
sessionStorage.setItem(TOUR_STEP_KEY, currentStep.id);
}
});
// Clear storage when tour completes or is cancelled
adminTour.on('complete', function () {
sessionStorage.removeItem(TOUR_ACTIVE_KEY);
sessionStorage.removeItem(TOUR_STEP_KEY);
});
adminTour.on('cancel', function () {
sessionStorage.removeItem(TOUR_ACTIVE_KEY);
sessionStorage.removeItem(TOUR_STEP_KEY);
});
// Helper function to create buttons
function createButtons(showBack = true, showNext = true, isLast = false) {
const buttons = [];
if (showBack) {
buttons.push({
text: 'Back',
classes: 'shepherd-button-secondary',
action: adminTour.back
});
}
if (showNext && !isLast) {
buttons.push({
text: 'Next',
classes: 'shepherd-button-primary',
action: adminTour.next
});
}
if (isLast) {
buttons.push({
text: 'Finish Tour',
classes: 'shepherd-button-primary',
action: function () {
completeTour();
adminTour.complete();
}
});
}
return buttons;
}
// Step 1: Welcome (Dashboard)
adminTour.addStep({
id: 'welcome',
title: `Welcome to ${window.appName || 'PicoSMS'}!`,
text: `
<div class="shepherd-welcome-modal">
<p>Welcome to your ${window.appName || 'PicoSMS'} administration panel! This quick tour will guide you through the essential settings you need to configure to get your SMS platform up and running.</p>
<p>You can skip this tour at any time and restart it later from the help menu.</p>
</div>
`,
classes: 'shepherd-welcome-modal',
buttons: [
{
text: 'Skip Tour',
classes: 'shepherd-button-skip',
action: function () {
completeTour();
adminTour.cancel();
}
},
{
text: "Let's Start",
classes: 'shepherd-button-primary',
action: adminTour.next
}
]
});
// Step 2: General Settings
adminTour.addStep({
id: 'general-settings',
title: 'Configure General Settings',
text: `
<div class="shepherd-step-counter">Step 1 of 11</div>
<p>Set up your business information and basic settings:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Your Brand:</strong> Add your company name and upload your logo</li>
<li><strong>Contact Details:</strong> Enter your business address, phone number, and email</li>
<li><strong>Website Features:</strong> Turn on/off customer registration, landing page, and maintenance mode</li>
<li><strong>Live Chat:</strong> Add Crisp chat widget to help customers reach you instantly</li>
</ul>
`,
beforeShowPromise: function () {
return navigateToPage('/admin/settings', 'general-settings');
},
attachTo: {
element: 'a[href="#general_settings_tab"]',
on: 'right'
},
buttons: createButtons(true, true)
});
// Step 3: User & Access Management
adminTour.addStep({
id: 'user-access-settings',
title: 'Manage Users & Permissions',
text: `
<div class="shepherd-step-counter">Step 2 of 11</div>
<p>Control who can access what in your system:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Your Profile:</strong> Update your name, email, and password</li>
<li><strong>User Roles:</strong> Create different access levels (like Manager, Staff, etc.) and decide what each role can do - send messages, view reports, manage billing, etc.</li>
</ul>
<p><strong>Click the "User & Access" tab.</strong></p>
`,
attachTo: {
element: 'a[href="#user_access_tab"]',
on: 'right'
},
buttons: createButtons(true, true)
});
// Step 4: Communication Settings
adminTour.addStep({
id: 'communication-settings',
title: 'Setup Communication Channels',
text: `
<div class="shepherd-step-counter">Step 3 of 11</div>
<p>Set up how your platform sends emails and security codes:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Email Setup:</strong> Connect your email account (like Gmail or Outlook) to send automated emails to customers</li>
<li><strong>Email Messages:</strong> Customize the emails customers receive for things like password resets and invoices</li>
<li><strong>Security Codes:</strong> Turn on one-time passwords (OTP) for extra login security</li>
</ul>
`,
attachTo: {
element: 'a[href="#communication_tab"]',
on: 'right'
},
buttons: createButtons(true, true)
});
// Step 5: Localization Settings
adminTour.addStep({
id: 'localization-settings',
title: 'Configure Regional Settings',
text: `
<div class="shepherd-step-counter">Step 4 of 11</div>
<p>Set up your location and language preferences:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Language:</strong> Choose your preferred language for the dashboard</li>
<li><strong>Time Zone:</strong> Select your local time zone so times display correctly</li>
<li><strong>Date Format:</strong> Pick how you want dates to appear (like MM/DD/YYYY or DD/MM/YYYY)</li>
</ul>
`,
attachTo: {
element: 'a[href="#localization_tab"]',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 6: Payment & Billing Settings
adminTour.addStep({
id: 'payment-billing-settings',
title: 'Setup Payment Processing',
text: `
<div class="shepherd-step-counter">Step 5 of 11</div>
<p>Connect payment methods to accept money from customers:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Payment Options:</strong> Set up PayPal, Stripe, credit cards, and other payment methods</li>
<li><strong>Account Details:</strong> Enter your payment account information to receive payments</li>
<li><strong>Test First:</strong> Use test mode to make sure everything works before accepting real payments</li>
</ul>
`,
attachTo: {
element: '#payment_gateway_nav',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 7: System & Maintenance
adminTour.addStep({
id: 'system-maintenance-settings',
title: 'Manage System Settings',
text: `
<div class="shepherd-step-counter">Step 6 of 11</div>
<p>Keep your platform secure and running smoothly:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Spam Protection:</strong> Add Google reCAPTCHA to stop bots and fake registrations</li>
<li><strong>Clean Up Data:</strong> Delete old message logs to free up space and keep your database tidy</li>
<li><strong>Languages:</strong> Customize text and translations for different languages</li>
</ul>
`,
attachTo: {
element: 'a[href="#system_maintenance_tab"]',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 8: SMS Gateway
adminTour.addStep({
id: 'gateway-config',
title: 'Connect Your SMS Gateway',
text: `
<div class="shepherd-step-counter">Step 7 of 11</div>
<p>Connect to SMS providers so you can send text messages:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>SMS Providers:</strong> Choose from Twilio, Nexmo, Plivo, or other SMS services</li>
<li><strong>Account Info:</strong> Enter your account details from your SMS provider</li>
<li><strong>Manage Providers:</strong> Turn providers on/off, choose your default, and test if they're working</li>
</ul>
<p><strong>Click the "SMS Gateway" Menu.</strong></p>
`,
beforeShowPromise: function () {
return navigateToPage('/admin/gateway', 'gateway-config');
},
attachTo: {
element: '#gateway-sidebar',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 9: Coverage Management
adminTour.addStep({
id: 'coverage-setup',
title: 'Define Service Coverage',
text: `
<div class="shepherd-step-counter">Step 8 of 11</div>
<p>Choose which countries you'll send SMS to and set your prices:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Add Countries:</strong> Select the countries where you want to offer SMS services</li>
<li><strong>Set Prices:</strong> Decide how much to charge per SMS for each country</li>
<li><strong>Turn On/Off:</strong> Enable or disable service for specific countries anytime</li>
<li><strong>Extra Features:</strong> Choose what features are available (like delivery confirmations)</li>
</ul>
`,
beforeShowPromise: function () {
return navigateToPage('/admin/coverage', 'coverage-setup');
},
attachTo: {
element: '#coverage-sidebar',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 10: Phone Numbers
adminTour.addStep({
id: 'phone-numbers',
title: 'Manage Virtual Phone Numbers',
text: `
<div class="shepherd-step-counter">Step 9 of 11</div>
<p>Manage phone numbers for sending and receiving text messages:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Get Numbers:</strong> Buy or add phone numbers from your SMS provider</li>
<li><strong>Assign to Customers:</strong> Give specific numbers to customers or share them among everyone</li>
<li><strong>Set Rental Fees:</strong> Charge customers monthly fees for using dedicated numbers</li>
<li><strong>Number Type:</strong> Choose if numbers can send SMS, receive SMS, or both</li>
</ul>
`,
beforeShowPromise: function () {
return navigateToPage('/admin/numbers', 'phone-numbers');
},
attachTo: {
element: '#numbers-sidebar',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 11: Subscription Plans
adminTour.addStep({
id: 'subscription-plans',
title: 'Create Subscription Plans',
text: `
<div class="shepherd-step-counter">Step 10 of 11</div>
<p>Create different pricing packages for your customers:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Plan Levels:</strong> Create packages like Free, Starter, Professional, or Business</li>
<li><strong>Set Limits:</strong> Decide how many SMS and contacts each plan gets</li>
<li><strong>Monthly Pricing:</strong> Set how much customers pay each month or year</li>
<li><strong>Special Features:</strong> Give premium plans extra features like advanced reports or priority support</li>
</ul>
`,
beforeShowPromise: function () {
return navigateToPage('/admin/plans', 'subscription-plans');
},
attachTo: {
element: '#plan-sidebar',
on: 'left'
},
buttons: createButtons(true, true)
});
// Step 12: Dashboard Overview
adminTour.addStep({
id: 'dashboard-overview',
title: 'Monitor Your Platform',
text: `
<div class="shepherd-step-counter">Step 11 of 11</div>
<p>See everything happening in your business at a glance:</p>
<ul style="margin-left: 20px; margin-top: 10px;">
<li><strong>Key Numbers:</strong> Total customers, active plans, messages sent, and money earned</li>
<li><strong>Visual Charts:</strong> Graphs showing your growth over time</li>
<li><strong>Recent Activity:</strong> Latest customer sign-ups, campaigns sent, and payments received</li>
<li><strong>Quick Links:</strong> Jump to your most-used features with one click</li>
</ul>
`,
beforeShowPromise: function () {
return navigateToPage('/admin/dashboard', 'dashboard-overview');
},
attachTo: {
element: '.counters',
on: 'bottom'
},
buttons: createButtons(true, true)
});
// Step 13: Completion
adminTour.addStep({
id: 'completion',
title: "You're All Set!",
text: `
<div class="shepherd-completion-modal">
<p>Congratulations! You've completed the setup tour. You now know where to find all the essential configuration options.</p>
<p>Remember, you can restart this tour anytime from the help menu. If you need assistance, check our documentation or contact support.</p>
</div>
`,
classes: 'shepherd-completion-modal',
buttons: createButtons(false, false, true)
});
// Function to mark tour as completed
function completeTour() {
// Get CSRF token from meta tag or hidden input
let csrfToken = null;
const metaTag = document.querySelector('meta[name="csrf-token"]');
if (metaTag) {
csrfToken = metaTag.getAttribute('content');
} else {
// Fallback: try to get from hidden input
const hiddenInput = document.querySelector('input[name="_token"]');
if (hiddenInput) {
csrfToken = hiddenInput.value;
}
}
if (!csrfToken) {
console.error('CSRF token not found');
return;
}
fetch('/admin/tour/complete', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
}
}).then(response => response.json())
.then(data => {
console.log('Tour completed:', data);
})
.catch(error => {
console.error('Error marking tour as completed:', error);
});
}
// Function to start the tour
window.startAdminTour = function () {
sessionStorage.setItem(TOUR_ACTIVE_KEY, 'true');
adminTour.start();
};
// Function to reset the tour
window.resetAdminTour = function () {
// Get CSRF token from meta tag or hidden input
let csrfToken = null;
const metaTag = document.querySelector('meta[name="csrf-token"]');
if (metaTag) {
csrfToken = metaTag.getAttribute('content');
} else {
const hiddenInput = document.querySelector('input[name="_token"]');
if (hiddenInput) {
csrfToken = hiddenInput.value;
}
}
if (!csrfToken) {
console.error('CSRF token not found');
return;
}
fetch('/admin/tour/reset', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken
}
}).then(response => response.json())
.then(data => {
console.log('Tour reset:', data);
sessionStorage.removeItem(TOUR_ACTIVE_KEY);
sessionStorage.removeItem(TOUR_STEP_KEY);
window.startAdminTour();
})
.catch(error => {
console.error('Error resetting tour:', error);
});
};
// Check if we should resume the tour
const isTourActive = sessionStorage.getItem(TOUR_ACTIVE_KEY) === 'true';
const savedStepId = sessionStorage.getItem(TOUR_STEP_KEY);
if (isTourActive && savedStepId) {
// Resume tour from saved step
setTimeout(function () {
adminTour.show(savedStepId);
}, 500);
} else if (window.tourEnabled && typeof window.adminTourCompleted !== 'undefined' && !window.adminTourCompleted) {
// Auto-start tour for new users only if tour is enabled
setTimeout(function () {
adminTour.start();
}, 1000);
}
})();
|
:: Command execute :: | |
--[ c99shell v. 2.5 [PHP 8 Update] [24.05.2025] | Generation time: 0.0051 ]-- |