1/** 2 * tyga.run Panel â ready-made SaaS APIs (bookings, logins, payments, CRM...) 3 * Viber-proof: ONE click to enable. No credentials, no code, no config shown. 4 * Power users can expand "Advanced" to paste their own key. 5 * States: onboarding (not enabled), connected, unavailable 6 */ 7 8import { api } from '../common/api.js'; 9 10// Friendly names for the modules Vibers actually ask for 11const FRIENDLY_MODULES = [ 12 { key: 'scheduling', label: 'Bookings', icon: 'fa-calendar-check' }, 13 { key: 'auth', label: 'Logins & Accounts', icon: 'fa-user-shield' }, 14 { key: 'crm', label: 'Contacts', icon: 'fa-address-book' }, 15 { key: 'ecommerce', label: 'Online Store', icon: 'fa-shopping-cart' }, 16 { key: 'billing', label: 'Payments', icon: 'fa-credit-card' }, 17 { key: 'email', label: 'Email', icon: 'fa-envelope' }, 18 { key: 'support', label: 'Support Tickets', icon: 'fa-headset' }, 19 { key: 'surveys', label: 'Surveys & Forms', icon: 'fa-poll' }, 20 { key: 'event-ticketing', label: 'Event Tickets', icon: 'fa-ticket-alt' }, 21 { key: 'elearning', label: 'Courses', icon: 'fa-graduation-cap' }, 22 { key: 'notifications', label: 'Notifications', icon: 'fa-bell' }, 23 { key: 'file-management', label: 'File Uploads', icon: 'fa-cloud-upload-alt' }, 24]; 25 26class TygarunPanel { 27 constructor() { 28 this.projectId = null; 29 this.status = null; // { configured, enabled, sandbox, modules } 30 this.$container = null; 31 } 32 33 async initialize(projectId, status, $container) { 34 this.projectId = projectId; 35 this.status = status; 36 this.$container = $container || $('#database-tab'); 37 38 if (status.enabled) { 39 this.showConnected(); 40 } else { 41 this.showOnboarding(); 42 } 43 } 44 45 // âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 46 // State A: Onboarding â ONE button. Like assembling Lego. 47 // âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 48 49 showOnboarding() { 50 this.$container.html(` 51 <div class="anydb-onboarding"> 52 <div class="anydb-onboarding-card"> 53 <div class="anydb-icon"><i class="fas fa-bolt"></i></div> 54 <h3>Ready-made APIs</h3> 55 <p class="text-muted"> 56 Add real bookings, logins, payments, contacts and more to your site â 57 powered by <strong>tyga.run</strong>. Nothing to set up, nothing to code. 58 </p> 59 60 <div class="anydb-hint-chips mb-3"> 61 ${FRIENDLY_MODULES.slice(0, 6).map(m => 62 `<span class="anydb-hint-chip"><i class="fas ${m.icon}"></i> ${m.label}</span>`).join('')} 63 </div> 64 65 <button class="btn btn-primary btn-lg w-100" id="tygarun-enable-btn"> 66 <i class="fas fa-bolt"></i> Enable Ready-made APIs 67 </button> 68 <div class="form-text text-muted mt-2"> 69 Starts in safe test mode â no real charges or emails until you go live. 70 </div> 71 72 <div class="mt-3"> 73 <a class="text-muted small" data-bs-toggle="collapse" href="#tygarun-advanced" role="button" style="cursor:pointer;"> 74 <i class="fas fa-cog"></i> Advanced (optional) 75 </a> 76 <div class="collapse mt-2" id="tygarun-advanced"> 77 <input type="password" class="form-control form-control-sm bg-dark text-light border-secondary" 78 id="tygarun-input-apikey" placeholder="Your own tyga.run API key (optional)"> 79 <div class="form-text text-muted">Leave empty to use the built-in connection.</div> 80 </div> 81 </div> 82 </div> 83 </div> 84 `); 85 86 $('#tygarun-enable-btn').on('click', () => this.enable()); 87 } 88 89 async enable() { 90 const userKey = ($('#tygarun-input-apikey').val() || '').trim(); 91 const $btn = $('#tygarun-enable-btn'); 92 $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Enabling...'); 93 94 try { 95 const body = { sandbox: true }; 96 if (userKey) body.apiKey = userKey; 97 const result = await api.post(`/api/tygarun/${this.projectId}/connect`, body); 98 if (result?.status === 'ok') { 99 this.status.enabled = true;
100 this.status.sandbox = result.tygarun?.sandbox ?? true; 101 this._toast('Ready-made APIs enabled!', 'success'); 102 this.showConnected(); 103 } else { 104 throw new Error(result?.message || 'Could not enable'); 105 } 106 } catch (err) { 107 $btn.prop('disabled', false).html('<i class="fas fa-bolt"></i> Enable Ready-made APIs'); 108 this._toast(`Could not enable: ${err.message}`, 'error'); 109 } 110 } 111 112 // âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 113 // State B: Connected â friendly module grid + AI hints. No code shown. 114 // âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ 115 116 showConnected() { 117 const sandbox = this.status.sandbox !== false; 118 this.$container.html(` 119 <div class="anydb-onboarding"> 120 <div class="anydb-onboarding-card" style="max-width: 640px;"> 121 <div class="d-flex align-items-center justify-content-between mb-3"> 122 <h4 class="mb-0"><i class="fas fa-bolt text-warning"></i> Ready-made APIs</h4> 123 <span class="anydb-status-badge connected"><i class="fas fa-circle"></i> Enabled</span> 124 </div> 125 126 <div class="anydb-info-row mb-3"> 127 <span class="anydb-info-label">Mode</span> 128 <span class="anydb-info-value">${sandbox 129 ? '<span class="badge bg-info">Test mode</span> <span class="text-muted small">safe to experiment</span>' 130 : '<span class="badge bg-success">Live</span>'}</span> 131 </div> 132 133 <div class="mb-3"> 134 ${sandbox ? ` 135 <button class="btn btn-success w-100" id="tygarun-golive-btn"> 136 <i class="fas fa-rocket"></i> Go live 137 </button> 138 <div class="form-text text-muted mt-1">${this._goLiveHint()}</div> 139 ` : ` 140 <button class="btn btn-outline-secondary btn-sm" id="tygarun-testmode-btn"> 141 <i class="fas fa-flask"></i> Back to test mode 142 </button> 143 `} 144 </div> 145 146 <p class="text-muted small mb-2">Your site can now use:</p> 147 <div class="anydb-hint-chips mb-4"> 148 ${FRIENDLY_MODULES.map(m => 149 `<span class="anydb-hint-chip"><i class="fas ${m.icon}"></i> ${m.label}</span>`).join('')} 150 </div> 151 152 <div class="anydb-ai-hints"> 153 <p class="text-muted small mb-1">Just ask the AI:</p> 154 <div class="anydb-hint-chips"> 155 <span class="anydb-hint-chip">"Add a booking form"</span> 156 <span class="anydb-hint-chip">"Let visitors create an account"</span> 157 <span class="anydb-hint-chip">"Add a contact form that saves leads"</span> 158 </div> 159 </div> 160 161 <div class="mt-4 text-end"> 162 <button class="btn btn-sm btn-outline-danger" id="tygarun-disable-btn"> 163 <i class="fas fa-unlink"></i> Turn off 164 </button> 165 </div> 166 </div> 167 </div> 168 `); 169 170 $('#tygarun-disable-btn').on('click', () => this.disable()); 171 $('#tygarun-golive-btn').on('click', () => this.setLive(true)); 172 $('#tygarun-testmode-btn').on('click', () => this.setLive(false)); 173 } 174 175 // Plain-language description of what going live turns on, from enabled modules 176 _goLiveHint() { 177 const modules = this.status.modules || []; 178 const labels = FRIENDLY_MODULES.filter(m => modules.includes(m.key)).map(m => m.label.toLowerCase()); 179 const what = labels.length ? labels.join(', ') : 'your site\u2019s features'; 180 const payments = modules.includes('billing') ? ' Payments will charge real cards.' : ''; 181 return `Turns on real ${what} for visitors.${payments}`; 182 } 183 184 async setLive(live) { 185 const msg = live 186 ? `Go live? ${this._goLiveHint()}` 187 : 'Switch back to test mode? Visitors will see demo data again.'; 188 if (!confirm(msg)) return; 189 const $btn = $(live ? '#tygarun-golive-btn' : '#tygarun-testmode-btn'); 190 $btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i>'); 191 try { 192 const result = await api.post(`/api/tygarun/${this.projectId}/live`, { live }); 193 if (result?.status !== 'ok') throw new Error(result?.message || 'Could not switch mode'); 194 this.status.sandbox = result.sandbox; 195 this._toast(result.message, 'success'); 196 this.showConnected(); 197 } catch (err) { 198 this._toast(`Error: ${err.message}`, 'error'); 199 this.showConnected(); 200 } 201 } 202 203 async disable() { 204 if (!confirm('Turn off ready-made APIs? Booking forms, logins etc. will stop working.')) return; 205 try { 206 await api.post(`/api/tygarun/${this.projectId}/disconnect`); 207 this.status.enabled = false;
208 this._toast('Ready-made APIs turned off', 'success'); 209 this.showOnboarding(); 210 } catch (err) { 211 this._toast(`Error: ${err.message}`, 'error'); 212 } 213 } 214 215 _toast(message, type = 'info') { 216 if (window.showToast) window.showToast(message, type); 217 else console.log(`[tygarun] ${type}: ${message}`); 218 } 219 220 destroy() { 221 this.projectId = null; 222 this.status = null; 223 } 224} 225 226const tygarunPanel = new TygarunPanel(); 227export default tygarunPanel;
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.