instant has configurable options, custom too
This commit is contained in:
@@ -3378,6 +3378,7 @@ var wpcf7 = {
|
|||||||
let configIds = {};
|
let configIds = {};
|
||||||
let storageSelection = {}; // Track individual drive quantities
|
let storageSelection = {}; // Track individual drive quantities
|
||||||
let isInstantCustomized = false; // Track customization state for instant servers
|
let isInstantCustomized = false; // Track customization state for instant servers
|
||||||
|
let verifiedDefaults = {};
|
||||||
|
|
||||||
// --- Static Fallback Data (Generated from Live Site) ---
|
// --- Static Fallback Data (Generated from Live Site) ---
|
||||||
const FALLBACK_CONFIG_OPTIONS = [
|
const FALLBACK_CONFIG_OPTIONS = [
|
||||||
@@ -3763,10 +3764,37 @@ var wpcf7 = {
|
|||||||
|
|
||||||
return { id, label, type, values, formName };
|
return { id, label, type, values, formName };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkStock(configUrl) {
|
||||||
|
let lastError = null;
|
||||||
|
for (const proxy of this.proxies) {
|
||||||
|
try {
|
||||||
|
const controller = new AbortController();
|
||||||
|
const timeoutId = setTimeout(() => controller.abort(), 4000);
|
||||||
|
const response = await fetch(proxy + encodeURIComponent(configUrl), { signal: controller.signal });
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||||
|
const html = await response.text();
|
||||||
|
const doc = new DOMParser().parseFromString(html, 'text/html');
|
||||||
|
const bodyText = (doc.body?.innerText || '').toLowerCase();
|
||||||
|
const dangerBox = doc.querySelector('.alert-danger');
|
||||||
|
const dangerText = dangerBox ? dangerBox.innerText.toLowerCase() : '';
|
||||||
|
if (bodyText.includes('out of stock') || dangerText.includes('out of stock')) return true;
|
||||||
|
return false;
|
||||||
|
} catch (err) {
|
||||||
|
lastError = err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const scraper = new WHMCSScraper();
|
const scraper = new WHMCSScraper();
|
||||||
|
|
||||||
|
// Cache for OOS states to avoid repeated checks
|
||||||
|
const oosCache = new Map();
|
||||||
|
let oosCheckInProgress = new Set();
|
||||||
|
|
||||||
// Update Technical Specs Section (New Smart Card Layout)
|
// Update Technical Specs Section (New Smart Card Layout)
|
||||||
function updateSpecs(server) {
|
function updateSpecs(server) {
|
||||||
const set = (id, val) => {
|
const set = (id, val) => {
|
||||||
@@ -3793,8 +3821,10 @@ var wpcf7 = {
|
|||||||
set('spec-storage-config-hero', server.storage || 'Configurable');
|
set('spec-storage-config-hero', server.storage || 'Configurable');
|
||||||
|
|
||||||
// Network
|
// Network
|
||||||
const netSpeed = (server.network || '10Gbps').replace('Gbps', '');
|
const netSrc = verifiedDefaults.network || server.network || '';
|
||||||
set('spec-network-speed-hero', netSpeed);
|
const netSpeedMatch = netSrc ? netSrc.match(/(\d+)\s*Gbps/i) : null;
|
||||||
|
const netSpeed = netSpeedMatch ? netSpeedMatch[1] : (netSrc ? netSrc.replace('Gbps','') : '');
|
||||||
|
set('spec-network-speed-hero', netSpeed || '-');
|
||||||
set('spec-network-bandwidth-hero', server.bandwidth || 'Unmetered');
|
set('spec-network-bandwidth-hero', server.bandwidth || 'Unmetered');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3804,6 +3834,7 @@ var wpcf7 = {
|
|||||||
grid.innerHTML = instantServers.map(server => `
|
grid.innerHTML = instantServers.map(server => `
|
||||||
<div class="server-option instant ${selectedServer?.id === server.id ? 'active' : ''}" data-id="${server.id}" onclick="selectInstantServer('${server.id}')">
|
<div class="server-option instant ${selectedServer?.id === server.id ? 'active' : ''}" data-id="${server.id}" onclick="selectInstantServer('${server.id}')">
|
||||||
<div class="server-badge instant">⚡ INSTANT</div>
|
<div class="server-badge instant">⚡ INSTANT</div>
|
||||||
|
${server.oos ? '<div class="server-badge" style="background:#ef4444;color:#fff;margin-left:8px;">OOS</div>' : ''}
|
||||||
<div class="server-title">${server.cpu}</div>
|
<div class="server-title">${server.cpu}</div>
|
||||||
<div class="server-specs-row">
|
<div class="server-specs-row">
|
||||||
<span class="spec-pill">${server.cores} cores</span>
|
<span class="spec-pill">${server.cores} cores</span>
|
||||||
@@ -3817,6 +3848,80 @@ var wpcf7 = {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|
||||||
|
// Pre-fetch stock data in background for all instant servers
|
||||||
|
prefetchStockData();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pre-fetch stock data for all instant servers
|
||||||
|
async function prefetchStockData() {
|
||||||
|
const batchSize = 3; // Limit concurrent requests
|
||||||
|
const queue = [...instantServers];
|
||||||
|
|
||||||
|
async function processQueue() {
|
||||||
|
while (queue.length > 0) {
|
||||||
|
const batch = queue.splice(0, batchSize);
|
||||||
|
await Promise.all(batch.map(async (server) => {
|
||||||
|
const url = server.orderUrl;
|
||||||
|
|
||||||
|
// Skip if already cached or currently checking
|
||||||
|
if (oosCache.has(url) || oosCheckInProgress.has(url)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
oosCheckInProgress.add(url);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const isOutOfStock = await scraper.checkStock(url);
|
||||||
|
if (isOutOfStock !== server.oos) { // Only update if changed
|
||||||
|
server.oos = isOutOfStock;
|
||||||
|
oosCache.set(url, isOutOfStock);
|
||||||
|
updateServerCardOOS(server); // Update specific card
|
||||||
|
if (selectedServer?.id === server.id) {
|
||||||
|
updateSummary();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oosCache.set(url, isOutOfStock);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`Failed to check stock for ${server.id}:`, err);
|
||||||
|
oosCache.set(url, false); // Assume in stock on error
|
||||||
|
} finally {
|
||||||
|
oosCheckInProgress.delete(url);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
// Small delay between batches to be nice to proxies
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 500));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to update just the OOS badge on a specific card
|
||||||
|
function updateServerCardOOS(server) {
|
||||||
|
const card = document.querySelector(`.server-option.instant[data-id="${server.id}"]`);
|
||||||
|
if (!card) return;
|
||||||
|
|
||||||
|
const existingBadge = card.querySelector('.server-badge[style*="background:#ef4444"]');
|
||||||
|
|
||||||
|
if (server.oos) {
|
||||||
|
if (!existingBadge) {
|
||||||
|
// Insert badge after the INSTANT badge
|
||||||
|
const instantBadge = card.querySelector('.server-badge.instant');
|
||||||
|
if (instantBadge) {
|
||||||
|
const oosBadge = document.createElement('div');
|
||||||
|
oosBadge.className = 'server-badge';
|
||||||
|
oosBadge.style.cssText = 'background:#ef4444;color:#fff;margin-left:8px;';
|
||||||
|
oosBadge.textContent = 'OOS';
|
||||||
|
instantBadge.after(oosBadge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (existingBadge) {
|
||||||
|
existingBadge.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render Custom Servers
|
// Render Custom Servers
|
||||||
@@ -3849,6 +3954,8 @@ var wpcf7 = {
|
|||||||
// Reset Customization State
|
// Reset Customization State
|
||||||
isInstantCustomized = false;
|
isInstantCustomized = false;
|
||||||
document.getElementById('instantOptions').style.display = 'none';
|
document.getElementById('instantOptions').style.display = 'none';
|
||||||
|
const instantContainer = document.getElementById('instantDynamicConfigContainer');
|
||||||
|
if (instantContainer) instantContainer.innerHTML = '';
|
||||||
document.getElementById('instantServersGrid').style.display = 'grid'; // Ensure grid is visible
|
document.getElementById('instantServersGrid').style.display = 'grid'; // Ensure grid is visible
|
||||||
|
|
||||||
updateSummary();
|
updateSummary();
|
||||||
@@ -3877,59 +3984,43 @@ var wpcf7 = {
|
|||||||
serversGrid.style.display = 'none';
|
serversGrid.style.display = 'none';
|
||||||
instantOptions.style.display = 'block';
|
instantOptions.style.display = 'block';
|
||||||
|
|
||||||
// Fetch options if container is empty OR if we want to refresh ensures all options are loaded
|
loader.style.display = 'flex';
|
||||||
// Checking if container is empty is usually enough unless server changed.
|
container.innerHTML = '';
|
||||||
// However, to be safe and ensure "all customizable options" are shown as requested:
|
|
||||||
if (container.innerHTML.trim() === '') {
|
configState = {};
|
||||||
loader.style.display = 'flex';
|
storageSelection = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
let scrapeUrl = selectedServer.orderUrl;
|
||||||
|
if (scrapeUrl.includes('&configoption')) {
|
||||||
|
scrapeUrl = scrapeUrl.split('&configoption')[0];
|
||||||
|
}
|
||||||
|
|
||||||
// Reset selection state
|
const preselected = {};
|
||||||
configState = {};
|
const urlParams = new URLSearchParams(selectedServer.orderUrl);
|
||||||
storageSelection = {};
|
for (const [key, value] of urlParams.entries()) {
|
||||||
|
if (key.startsWith('configoption[')) {
|
||||||
try {
|
const idMatch = key.match(/\[(\d+)\]/);
|
||||||
// 1. CLEAN THE URL: Remove specific config options to get the full configuration page
|
if (idMatch) {
|
||||||
let scrapeUrl = selectedServer.orderUrl;
|
preselected[idMatch[1]] = value;
|
||||||
if (scrapeUrl.includes('&configoption')) {
|
|
||||||
scrapeUrl = scrapeUrl.split('&configoption')[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Parse Pre-selected Options from the Original URL
|
|
||||||
const preselected = {};
|
|
||||||
const urlParams = new URLSearchParams(selectedServer.orderUrl);
|
|
||||||
for (const [key, value] of urlParams.entries()) {
|
|
||||||
if (key.startsWith('configoption[')) {
|
|
||||||
// Extract ID: configoption[34] -> 34
|
|
||||||
const idMatch = key.match(/\[(\d+)\]/);
|
|
||||||
if (idMatch) {
|
|
||||||
preselected[idMatch[1]] = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("Pre-selected options for instant:", preselected);
|
|
||||||
|
|
||||||
// Use the scraper with the Clean URL
|
|
||||||
const optionsData = await scraper.getProductConfig(scrapeUrl, selectedServer);
|
|
||||||
|
|
||||||
if (optionsData && optionsData.options.length > 0) {
|
|
||||||
renderDynamicOptions(optionsData.options, true, preselected);
|
|
||||||
} else {
|
|
||||||
// Fallback if optionsData is null or empty
|
|
||||||
console.warn("No live options found, using fallback.");
|
|
||||||
renderFallbackOptions(container);
|
|
||||||
|
|
||||||
// Add a visual warning
|
|
||||||
const warning = document.createElement('div');
|
|
||||||
warning.style.cssText = "background: #fff3cd; color: #856404; padding: 10px; margin-bottom: 15px; border-radius: 4px; font-size: 0.9rem; text-align: center;";
|
|
||||||
warning.textContent = "Could not load live customization options. Standard configuration shown.";
|
|
||||||
container.insertBefore(warning, container.firstChild);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error in customize click:", err);
|
|
||||||
renderFallbackOptions(container);
|
|
||||||
} finally {
|
|
||||||
loader.style.display = 'none';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const optionsData = await scraper.getProductConfig(scrapeUrl, selectedServer);
|
||||||
|
if (optionsData && optionsData.options.length > 0) {
|
||||||
|
renderDynamicOptions(optionsData.options, true, preselected);
|
||||||
|
} else {
|
||||||
|
renderFallbackOptions(container);
|
||||||
|
const warning = document.createElement('div');
|
||||||
|
warning.style.cssText = "background: #fff3cd; color: #856404; padding: 10px; margin-bottom: 15px; border-radius: 4px; font-size: 0.9rem; text-align: center;";
|
||||||
|
warning.textContent = "Could not load live customization options. Standard configuration shown.";
|
||||||
|
container.insertBefore(warning, container.firstChild);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
renderFallbackOptions(container);
|
||||||
|
} finally {
|
||||||
|
loader.style.display = 'none';
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSummary();
|
updateSummary();
|
||||||
@@ -3939,7 +4030,6 @@ var wpcf7 = {
|
|||||||
async function selectCustomServer(id) {
|
async function selectCustomServer(id) {
|
||||||
selectedServer = customServers.find(s => s.id === id);
|
selectedServer = customServers.find(s => s.id === id);
|
||||||
renderCustomServers();
|
renderCustomServers();
|
||||||
updateSpecs(selectedServer);
|
|
||||||
|
|
||||||
document.getElementById('instantToggleContainer').style.display = 'none';
|
document.getElementById('instantToggleContainer').style.display = 'none';
|
||||||
|
|
||||||
@@ -3965,6 +4055,16 @@ var wpcf7 = {
|
|||||||
loader.style.display = 'none';
|
loader.style.display = 'none';
|
||||||
|
|
||||||
if (optionsData && optionsData.options.length > 0) {
|
if (optionsData && optionsData.options.length > 0) {
|
||||||
|
const netOpt = optionsData.options.find(o => o.type === 'network' || (o.label && o.label.toLowerCase().includes('network')) || (o.label && o.label.toLowerCase().includes('uplink')));
|
||||||
|
if (netOpt && netOpt.values && netOpt.values.length > 0) {
|
||||||
|
const defVal = netOpt.values[0];
|
||||||
|
verifiedDefaults.network = defVal.text;
|
||||||
|
configState[netOpt.label] = defVal.price || 0;
|
||||||
|
configIds[netOpt.id] = defVal.id;
|
||||||
|
} else {
|
||||||
|
verifiedDefaults.network = null;
|
||||||
|
}
|
||||||
|
updateSpecs(selectedServer);
|
||||||
renderDynamicOptions(optionsData.options);
|
renderDynamicOptions(optionsData.options);
|
||||||
} else {
|
} else {
|
||||||
// Fallback if scrape fails
|
// Fallback if scrape fails
|
||||||
@@ -4154,7 +4254,7 @@ var wpcf7 = {
|
|||||||
if(type === 'ram') {
|
if(type === 'ram') {
|
||||||
configState['RAM Configuration'] = price;
|
configState['RAM Configuration'] = price;
|
||||||
document.getElementById('summaryRam').textContent = name;
|
document.getElementById('summaryRam').textContent = name;
|
||||||
const specRam = document.getElementById('spec-ram-capacity');
|
const specRam = document.getElementById('spec-ram-capacity-hero');
|
||||||
if(specRam) specRam.innerText = name;
|
if(specRam) specRam.innerText = name;
|
||||||
} else if(type === 'location') {
|
} else if(type === 'location') {
|
||||||
configState['Location'] = price;
|
configState['Location'] = price;
|
||||||
@@ -4162,7 +4262,7 @@ var wpcf7 = {
|
|||||||
} else if(type === 'network') {
|
} else if(type === 'network') {
|
||||||
configState['Network'] = price;
|
configState['Network'] = price;
|
||||||
document.getElementById('summaryNetwork').textContent = name;
|
document.getElementById('summaryNetwork').textContent = name;
|
||||||
const specNetwork = document.getElementById('spec-network-speed');
|
const specNetwork = document.getElementById('spec-network-speed-hero');
|
||||||
if(specNetwork) specNetwork.innerText = name;
|
if(specNetwork) specNetwork.innerText = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4255,7 +4355,7 @@ var wpcf7 = {
|
|||||||
document.getElementById('summaryStorage').innerText = summaryText;
|
document.getElementById('summaryStorage').innerText = summaryText;
|
||||||
|
|
||||||
// Also update specs table if visible
|
// Also update specs table if visible
|
||||||
const specStorage = document.getElementById('spec-storage-config');
|
const specStorage = document.getElementById('spec-storage-config-hero');
|
||||||
if(specStorage) specStorage.innerText = summaryParts.length > 0 ? summaryParts.join(' + ') : 'Configurable';
|
if(specStorage) specStorage.innerText = summaryParts.length > 0 ? summaryParts.join(' + ') : 'Configurable';
|
||||||
|
|
||||||
updateSummary();
|
updateSummary();
|
||||||
@@ -4618,7 +4718,7 @@ var wpcf7 = {
|
|||||||
|
|
||||||
const storageText = storageNames.length > 0 ? storageNames.join(' + ') : 'None';
|
const storageText = storageNames.length > 0 ? storageNames.join(' + ') : 'None';
|
||||||
document.getElementById('summaryStorage').textContent = storageText;
|
document.getElementById('summaryStorage').textContent = storageText;
|
||||||
const specStorage = document.getElementById('spec-storage-config');
|
const specStorage = document.getElementById('spec-storage-config-hero');
|
||||||
if(specStorage) specStorage.innerText = storageText;
|
if(specStorage) specStorage.innerText = storageText;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -4645,13 +4745,13 @@ var wpcf7 = {
|
|||||||
if (opt.type === 'ram') {
|
if (opt.type === 'ram') {
|
||||||
const cleanName = val.text.replace(/\s?\(.*?\)/, '');
|
const cleanName = val.text.replace(/\s?\(.*?\)/, '');
|
||||||
document.getElementById('summaryRam').textContent = cleanName;
|
document.getElementById('summaryRam').textContent = cleanName;
|
||||||
const specRam = document.getElementById('spec-ram-capacity');
|
const specRam = document.getElementById('spec-ram-capacity-hero');
|
||||||
if(specRam) specRam.innerText = cleanName;
|
if(specRam) specRam.innerText = cleanName;
|
||||||
}
|
}
|
||||||
if (opt.type === 'location') document.getElementById('summaryLocation').textContent = val.text;
|
if (opt.type === 'location') document.getElementById('summaryLocation').textContent = val.text;
|
||||||
if (opt.type === 'network') {
|
if (opt.type === 'network') {
|
||||||
document.getElementById('summaryNetwork').textContent = val.text;
|
document.getElementById('summaryNetwork').textContent = val.text;
|
||||||
const specNet = document.getElementById('spec-network-speed');
|
const specNet = document.getElementById('spec-network-speed-hero');
|
||||||
if(specNet) specNet.innerText = val.text;
|
if(specNet) specNet.innerText = val.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4709,7 +4809,7 @@ var wpcf7 = {
|
|||||||
document.getElementById('summaryStorage').textContent = storageText;
|
document.getElementById('summaryStorage').textContent = storageText;
|
||||||
|
|
||||||
// Update Tech Specs
|
// Update Tech Specs
|
||||||
const specStorage = document.getElementById('spec-storage-config');
|
const specStorage = document.getElementById('spec-storage-config-hero');
|
||||||
if(specStorage) specStorage.innerText = storageText;
|
if(specStorage) specStorage.innerText = storageText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4764,6 +4864,22 @@ var wpcf7 = {
|
|||||||
if(countEl) countEl.textContent = `${filled}/${slots.length}`;
|
if(countEl) countEl.textContent = `${filled}/${slots.length}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildInstantOrderUrl() {
|
||||||
|
if (!selectedServer || !selectedServer.orderUrl) return null;
|
||||||
|
try {
|
||||||
|
const base = selectedServer.orderUrl.split('&configoption')[0];
|
||||||
|
const u = new URL(base);
|
||||||
|
const p = new URLSearchParams(u.search);
|
||||||
|
Object.entries(configIds).forEach(([id, val]) => {
|
||||||
|
if (id && val) p.set(`configoption[${id}]`, val);
|
||||||
|
});
|
||||||
|
p.set('billingcycle', 'monthly');
|
||||||
|
return u.origin + u.pathname + '?' + p.toString();
|
||||||
|
} catch (e) {
|
||||||
|
return selectedServer.orderUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update Summary
|
// Update Summary
|
||||||
function updateSummary() {
|
function updateSummary() {
|
||||||
const pill = document.getElementById('summaryHeaderPill');
|
const pill = document.getElementById('summaryHeaderPill');
|
||||||
@@ -4811,7 +4927,8 @@ var wpcf7 = {
|
|||||||
const totalPrice = selectedServer.price + addonPrice;
|
const totalPrice = selectedServer.price + addonPrice;
|
||||||
document.getElementById('totalPrice').textContent = selectedServer.currency + totalPrice.toFixed(2);
|
document.getElementById('totalPrice').textContent = selectedServer.currency + totalPrice.toFixed(2);
|
||||||
|
|
||||||
btnDeployInstant.href = selectedServer.orderUrl;
|
const customUrl = buildInstantOrderUrl();
|
||||||
|
btnDeployInstant.href = customUrl || selectedServer.orderUrl;
|
||||||
|
|
||||||
// Update Button Labels for Customized State
|
// Update Button Labels for Customized State
|
||||||
const mainLabel = btnDeployInstant.querySelector('.main-label');
|
const mainLabel = btnDeployInstant.querySelector('.main-label');
|
||||||
@@ -4825,9 +4942,9 @@ var wpcf7 = {
|
|||||||
pill.style.color = 'white';
|
pill.style.color = 'white';
|
||||||
subtext.textContent = 'Ready in 15 minutes';
|
subtext.textContent = 'Ready in 15 minutes';
|
||||||
document.getElementById('totalPrice').textContent = selectedServer.currency + selectedServer.price;
|
document.getElementById('totalPrice').textContent = selectedServer.currency + selectedServer.price;
|
||||||
|
|
||||||
btnDeployInstant.href = selectedServer.orderUrl;
|
btnDeployInstant.href = selectedServer.orderUrl;
|
||||||
|
|
||||||
// Update Button Labels for Default State
|
// Update Button Labels for Default State
|
||||||
const mainLabel = btnDeployInstant.querySelector('.main-label');
|
const mainLabel = btnDeployInstant.querySelector('.main-label');
|
||||||
const subLabel = btnDeployInstant.querySelector('.sub-label');
|
const subLabel = btnDeployInstant.querySelector('.sub-label');
|
||||||
@@ -4863,9 +4980,42 @@ var wpcf7 = {
|
|||||||
if (selectedServer.configUrl) {
|
if (selectedServer.configUrl) {
|
||||||
configureBtn.href = selectedServer.configUrl;
|
configureBtn.href = selectedServer.configUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const netEl = document.getElementById('summaryNetwork');
|
||||||
|
if (netEl && (netEl.textContent === '-' || netEl.textContent.trim() === '')) {
|
||||||
|
netEl.textContent = verifiedDefaults.network || netEl.textContent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.getElementById('btnDeployInstant').addEventListener('click', async (e) => {
|
||||||
|
if (!selectedServer) return;
|
||||||
|
e.preventDefault();
|
||||||
|
const url = isInstantCustomized ? (buildInstantOrderUrl() || selectedServer.orderUrl) : selectedServer.orderUrl;
|
||||||
|
|
||||||
|
// Check cache first for instant OOS response
|
||||||
|
let outOfStock = oosCache.get(url);
|
||||||
|
|
||||||
|
// If not cached, check stock (this should rarely happen now due to pre-fetch)
|
||||||
|
if (outOfStock === undefined) {
|
||||||
|
try {
|
||||||
|
outOfStock = await scraper.checkStock(url);
|
||||||
|
oosCache.set(url, outOfStock);
|
||||||
|
} catch (err) {
|
||||||
|
outOfStock = false;
|
||||||
|
oosCache.set(url, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outOfStock) {
|
||||||
|
selectedServer.oos = true;
|
||||||
|
renderInstantServers();
|
||||||
|
updateSummary();
|
||||||
|
} else {
|
||||||
|
window.location.href = url;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Tab switching
|
// Tab switching
|
||||||
document.querySelectorAll('.config-tab').forEach(tab => {
|
document.querySelectorAll('.config-tab').forEach(tab => {
|
||||||
tab.addEventListener('click', () => {
|
tab.addEventListener('click', () => {
|
||||||
@@ -4886,10 +5036,13 @@ var wpcf7 = {
|
|||||||
renderInstantServers();
|
renderInstantServers();
|
||||||
renderCustomServers();
|
renderCustomServers();
|
||||||
|
|
||||||
|
// Trigger initial OOS check for all instant servers on page load
|
||||||
|
prefetchStockData();
|
||||||
|
|
||||||
// Pre-select the first instant server so the UI is active immediately
|
// Pre-select the first instant server so the UI is active immediately
|
||||||
if(instantServers.length > 0) {
|
if(instantServers.length > 0) {
|
||||||
selectInstantServer(instantServers[0].id);
|
selectInstantServer(instantServers[0].id);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user