269 lines
11 KiB
JavaScript
269 lines
11 KiB
JavaScript
/**
|
|
* UI Manager - Handles UI updates and visual feedback
|
|
*/
|
|
class UIManager {
|
|
constructor() {
|
|
// Visual feedback states
|
|
this.isSlidersFaded = false;
|
|
}
|
|
|
|
// Update status message
|
|
updateStatusMessage(domManager, message, type) {
|
|
const planMatchStatus = domManager.get('planMatchStatus');
|
|
if (!planMatchStatus) return;
|
|
|
|
const iconClass = type === 'success' ? 'bi-check-circle' : 'bi-info-circle';
|
|
const textClass = type === 'success' ? 'text-success' : '';
|
|
const alertClass = type === 'success' ? 'alert-success' : 'alert-info';
|
|
|
|
planMatchStatus.innerHTML = `<i class="bi ${iconClass} me-2 ${textClass}"></i><span class="${textClass}">${message}</span>`;
|
|
planMatchStatus.className = `alert ${alertClass} mb-3`;
|
|
planMatchStatus.style.display = 'block';
|
|
}
|
|
|
|
// Show error message
|
|
showError(domManager, message) {
|
|
const planMatchStatus = domManager.get('planMatchStatus');
|
|
if (planMatchStatus) {
|
|
planMatchStatus.innerHTML = `<i class="bi bi-exclamation-triangle me-2 text-danger"></i><span class="text-danger">${message}</span>`;
|
|
planMatchStatus.className = 'alert alert-danger mb-3';
|
|
planMatchStatus.style.display = 'block';
|
|
}
|
|
}
|
|
|
|
// Show no matching plan found
|
|
showNoMatch(domManager) {
|
|
const planMatchStatus = domManager.get('planMatchStatus');
|
|
const selectedPlanDetails = domManager.get('selectedPlanDetails');
|
|
const noMatchFound = domManager.get('noMatchFound');
|
|
|
|
if (planMatchStatus) planMatchStatus.style.display = 'none';
|
|
if (selectedPlanDetails) selectedPlanDetails.style.display = 'none';
|
|
if (noMatchFound) noMatchFound.style.display = 'block';
|
|
}
|
|
|
|
// Show plan details in the UI
|
|
showPlanDetails(domManager, plan, storage, instances, serviceLevel, managedServicePrice, storagePriceValue, totalPriceValue) {
|
|
const selectedPlanDetails = domManager.get('selectedPlanDetails');
|
|
if (!selectedPlanDetails) return;
|
|
|
|
// Show plan details section
|
|
const planMatchStatus = domManager.get('planMatchStatus');
|
|
const noMatchFound = domManager.get('noMatchFound');
|
|
|
|
if (planMatchStatus) planMatchStatus.style.display = 'block';
|
|
selectedPlanDetails.style.display = 'block';
|
|
if (noMatchFound) noMatchFound.style.display = 'none';
|
|
|
|
// Update plan information
|
|
const planGroup = domManager.get('planGroup');
|
|
const planName = domManager.get('planName');
|
|
const planDescription = domManager.get('planDescription');
|
|
const planCpus = domManager.get('planCpus');
|
|
const planMemory = domManager.get('planMemory');
|
|
const planInstances = domManager.get('planInstances');
|
|
const planServiceLevel = domManager.get('planServiceLevel');
|
|
const managedServicePriceEl = domManager.get('managedServicePrice');
|
|
const storagePriceEl = domManager.get('storagePriceEl');
|
|
const storageAmount = domManager.get('storageAmount');
|
|
const totalPrice = domManager.get('totalPrice');
|
|
|
|
if (planGroup) planGroup.textContent = plan.groupName;
|
|
if (planName) planName.textContent = plan.compute_plan;
|
|
if (planDescription) planDescription.textContent = plan.compute_plan_group_description || '';
|
|
if (planCpus) planCpus.textContent = plan.vcpus;
|
|
if (planMemory) planMemory.textContent = plan.ram + ' GB';
|
|
if (planInstances) planInstances.textContent = instances;
|
|
if (planServiceLevel) planServiceLevel.textContent = serviceLevel;
|
|
|
|
// Update pricing display
|
|
if (managedServicePriceEl) managedServicePriceEl.textContent = managedServicePrice.toFixed(2);
|
|
if (storagePriceEl) storagePriceEl.textContent = storagePriceValue.toFixed(2);
|
|
if (storageAmount) storageAmount.textContent = storage;
|
|
if (totalPrice) totalPrice.textContent = totalPriceValue.toFixed(2);
|
|
}
|
|
|
|
// Update addon pricing display in the results panel
|
|
updateAddonPricingDisplay(domManager, mandatoryAddons, selectedOptionalAddons) {
|
|
// Update mandatory addons in the managed service includes container
|
|
const managedServiceIncludesContainer = domManager.get('managedServiceIncludesContainer');
|
|
if (managedServiceIncludesContainer) {
|
|
// Clear existing content
|
|
managedServiceIncludesContainer.innerHTML = '';
|
|
|
|
// Add mandatory addons to the managed service includes section
|
|
if (mandatoryAddons && mandatoryAddons.length > 0) {
|
|
mandatoryAddons.forEach(addon => {
|
|
const addonRow = document.createElement('div');
|
|
addonRow.className = 'd-flex justify-content-between small text-muted mb-1';
|
|
addonRow.innerHTML = `
|
|
<span><i class="bi bi-check-circle text-success me-1"></i>${addon.name}</span>
|
|
<span>CHF ${addon.price}</span>
|
|
`;
|
|
managedServiceIncludesContainer.appendChild(addonRow);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Update optional addons in the addon pricing container
|
|
const addonPricingContainer = domManager.get('addonPricingContainer');
|
|
if (!addonPricingContainer) return;
|
|
|
|
// Clear existing addon pricing display
|
|
addonPricingContainer.innerHTML = '';
|
|
|
|
// Add optional addons to pricing breakdown (these are added to total)
|
|
if (selectedOptionalAddons && selectedOptionalAddons.length > 0) {
|
|
selectedOptionalAddons.forEach(addon => {
|
|
const addonRow = document.createElement('div');
|
|
addonRow.className = 'd-flex justify-content-between mb-2';
|
|
addonRow.innerHTML = `
|
|
<span>Add-on: ${addon.name}</span>
|
|
<span class="fw-bold">CHF ${addon.price}</span>
|
|
`;
|
|
addonPricingContainer.appendChild(addonRow);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Fade out specified sliders when plan is manually selected
|
|
fadeOutSliders(domManager, sliderTypes) {
|
|
sliderTypes.forEach(type => {
|
|
const sliderContainer = domManager.getSliderContainer(type);
|
|
if (sliderContainer) {
|
|
sliderContainer.style.transition = 'opacity 0.3s ease-in-out';
|
|
sliderContainer.style.opacity = '0.3';
|
|
sliderContainer.style.pointerEvents = 'none';
|
|
|
|
// Add visual indicator that sliders are disabled
|
|
const slider = sliderContainer.querySelector('.form-range');
|
|
if (slider) {
|
|
slider.style.cursor = 'not-allowed';
|
|
}
|
|
}
|
|
});
|
|
this.isSlidersFaded = true;
|
|
}
|
|
|
|
// Fade in specified sliders when auto-select mode is chosen
|
|
fadeInSliders(domManager, sliderTypes) {
|
|
sliderTypes.forEach(type => {
|
|
const sliderContainer = domManager.getSliderContainer(type);
|
|
if (sliderContainer) {
|
|
sliderContainer.style.transition = 'opacity 0.3s ease-in-out';
|
|
sliderContainer.style.opacity = '1';
|
|
sliderContainer.style.pointerEvents = 'auto';
|
|
|
|
// Remove visual indicator
|
|
const slider = sliderContainer.querySelector('.form-range');
|
|
if (slider) {
|
|
slider.style.cursor = 'pointer';
|
|
}
|
|
}
|
|
});
|
|
this.isSlidersFaded = false;
|
|
}
|
|
|
|
// Setup service levels dynamically from pricing data
|
|
setupServiceLevels(domManager, pricingDataManager) {
|
|
const serviceLevelGroup = domManager.get('serviceLevelGroup');
|
|
if (!serviceLevelGroup) return;
|
|
|
|
// Get all available service levels from the pricing data
|
|
const availableServiceLevels = pricingDataManager.getAvailableServiceLevels();
|
|
|
|
// Clear existing service level buttons
|
|
serviceLevelGroup.innerHTML = '';
|
|
|
|
// Create buttons for each available service level
|
|
let isFirst = true;
|
|
availableServiceLevels.forEach(serviceLevel => {
|
|
const inputId = `serviceLevel${serviceLevel.replace(/\s+/g, '')}`;
|
|
|
|
// Create radio input
|
|
const input = document.createElement('input');
|
|
input.type = 'radio';
|
|
input.className = 'btn-check';
|
|
input.name = 'serviceLevel';
|
|
input.id = inputId;
|
|
input.value = serviceLevel;
|
|
if (isFirst) {
|
|
input.checked = true;
|
|
isFirst = false;
|
|
}
|
|
|
|
// Create label
|
|
const label = document.createElement('label');
|
|
label.className = 'btn btn-outline-primary';
|
|
label.setAttribute('for', inputId);
|
|
label.textContent = serviceLevel;
|
|
|
|
serviceLevelGroup.appendChild(input);
|
|
serviceLevelGroup.appendChild(label);
|
|
});
|
|
|
|
// Update the serviceLevelInputs reference
|
|
domManager.elements.serviceLevelInputs = document.querySelectorAll('input[name="serviceLevel"]');
|
|
}
|
|
|
|
// Update slider maximums based on pricing data
|
|
updateSliderMaximums(domManager, pricingDataManager) {
|
|
const cpuRange = domManager.get('cpuRange');
|
|
const memoryRange = domManager.get('memoryRange');
|
|
|
|
if (!cpuRange || !memoryRange) return;
|
|
|
|
const { maxCpus, maxMemory } = pricingDataManager.getSliderMaximums();
|
|
|
|
// Set slider maximums with some padding
|
|
if (maxCpus > 0) {
|
|
cpuRange.min = "0.25";
|
|
cpuRange.max = Math.ceil(maxCpus);
|
|
}
|
|
|
|
if (maxMemory > 0) {
|
|
memoryRange.min = "0.25";
|
|
memoryRange.max = Math.ceil(maxMemory);
|
|
}
|
|
|
|
// Update display values after changing min/max
|
|
domManager.updateSliderDisplayValues();
|
|
}
|
|
|
|
// Update instances slider based on service level and replica info
|
|
updateInstancesSlider(domManager, pricingDataManager) {
|
|
const instancesRange = domManager.get('instancesRange');
|
|
const instancesValue = domManager.get('instancesValue');
|
|
const replicaInfo = pricingDataManager.getReplicaInfo();
|
|
|
|
if (!instancesRange || !replicaInfo) return;
|
|
|
|
const serviceLevel = domManager.getSelectedServiceLevel();
|
|
|
|
if (serviceLevel === 'Guaranteed Availability') {
|
|
// For GA, min is ha_replica_min
|
|
instancesRange.min = replicaInfo.ha_replica_min;
|
|
instancesRange.value = Math.max(instancesRange.value, replicaInfo.ha_replica_min);
|
|
} else {
|
|
// For BE, min is 1
|
|
instancesRange.min = 1;
|
|
instancesRange.value = Math.max(instancesRange.value, 1);
|
|
}
|
|
|
|
// Set max to ha_replica_max
|
|
instancesRange.max = replicaInfo.ha_replica_max;
|
|
|
|
// Update display value
|
|
if (instancesValue) instancesValue.textContent = instancesRange.value;
|
|
|
|
// Update the min/max display under the slider
|
|
const instancesMinDisplay = document.getElementById('instancesMinDisplay');
|
|
const instancesMaxDisplay = document.getElementById('instancesMaxDisplay');
|
|
|
|
if (instancesMinDisplay) instancesMinDisplay.textContent = instancesRange.min;
|
|
if (instancesMaxDisplay) instancesMaxDisplay.textContent = instancesRange.max;
|
|
}
|
|
}
|
|
|
|
// Export for use in other modules
|
|
window.UIManager = UIManager;
|