fix(vps): drop Windows License toggle from estimator
Windows BYOL is free and doesn't change the price, so the toggle was UI clutter. The Included With All Plans card already communicates the BYOL requirement (line updated to read "Linux included; Windows supported (bring your own license)" for clarity), and OS template selection at checkout still lets users pick a Windows image when they're ready to deploy. - AddOnsPanel.vue: removed the Windows License switch - EstimatorSection.vue: removed onWindowsChange handler - stores/estimator.ts: removed windowsLicense state, dropped from share/checkout URL params and hydration - ConfigOptionSeeder.php: dropped the legacy 'Windows License' option from the VPS Add-ons group (deletes existing row) - CheckoutController.php: removed ?windows=1 query-param handling from buildPrefilledSelections - VpsHosting.vue: tightened the BYOL line in the Included card Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -98,7 +98,6 @@ class CheckoutController extends Controller
|
|||||||
*
|
*
|
||||||
* Recognized params:
|
* Recognized params:
|
||||||
* ?ipv4=N — total IPv4 count (1-8). N>1 sets the IPv4 quantity option to (N - 1) extras.
|
* ?ipv4=N — total IPv4 count (1-8). N>1 sets the IPv4 quantity option to (N - 1) extras.
|
||||||
* ?windows=1 — toggles the Windows License checkbox.
|
|
||||||
* ?managed=X — value slug for the VPS Managed Support radio (self|basic|pro|pilot).
|
* ?managed=X — value slug for the VPS Managed Support radio (self|basic|pro|pilot).
|
||||||
* ?backup=X — value slug for the Off-site Backup radio (none|lite|standard|extended|vault).
|
* ?backup=X — value slug for the Off-site Backup radio (none|lite|standard|extended|vault).
|
||||||
*
|
*
|
||||||
@@ -141,22 +140,6 @@ class CheckoutController extends Controller
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows License — single-value checkbox
|
|
||||||
if ($request->boolean('windows')) {
|
|
||||||
$option = $findOption('VPS Add-ons', 'Windows License');
|
|
||||||
if ($option && $option->values->isNotEmpty()) {
|
|
||||||
$value = $option->values->first();
|
|
||||||
$selections[] = [
|
|
||||||
'option_id' => $option->id,
|
|
||||||
'value_id' => $value->id,
|
|
||||||
'quantity' => null,
|
|
||||||
'text_value' => null,
|
|
||||||
'locked_price' => (float) ($value->monthly_price ?? 0),
|
|
||||||
'locked_hourly_price' => $value->hourly_price !== null ? (float) $value->hourly_price : null,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Managed Support — radio
|
// Managed Support — radio
|
||||||
$managed = $request->query('managed');
|
$managed = $request->query('managed');
|
||||||
if ($managed && $managed !== 'self') {
|
if ($managed && $managed !== 'self') {
|
||||||
|
|||||||
@@ -165,11 +165,12 @@ class ConfigOptionSeeder extends Seeder
|
|||||||
// IPv4 Addresses (quantity)
|
// IPv4 Addresses (quantity)
|
||||||
$ipv4Option = $this->seedQuantityOption($vpsAddons, 'IPv4 Addresses', 1, 8, 'addresses', 8.00, 1);
|
$ipv4Option = $this->seedQuantityOption($vpsAddons, 'IPv4 Addresses', 1, 8, 'addresses', 8.00, 1);
|
||||||
|
|
||||||
// Windows License (checkbox)
|
// Drop the legacy Windows License option if it exists (BYOL is now communicated
|
||||||
$winOption = $this->seedCheckboxOption($vpsAddons, 'Windows License', 2);
|
// via marketing copy + OS template selection at checkout).
|
||||||
$this->seedValues($winOption, [
|
PlanConfigOption::query()
|
||||||
['label' => 'Yes (Free BYOL)', 'value' => 'yes', 'monthly' => 0, 'is_default' => false],
|
->where('group_id', $vpsAddons->id)
|
||||||
]);
|
->where('name', 'Windows License')
|
||||||
|
->delete();
|
||||||
|
|
||||||
// Attach to all active VPS plans
|
// Attach to all active VPS plans
|
||||||
$vpsSlugs = ['vps-1', 'vps-2', 'vps-3-custom', 'vps-4', 'vps-8', 'vps-16', 'vps-32', 'stor-500', 'stor-1tb'];
|
$vpsSlugs = ['vps-1', 'vps-2', 'vps-3-custom', 'vps-4', 'vps-8', 'vps-16', 'vps-32', 'stor-500', 'stor-1tb'];
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import BackupTierSelector from './BackupTierSelector.vue'
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
ipv4Count: number
|
ipv4Count: number
|
||||||
windowsLicense: boolean
|
|
||||||
managedTier: ManagedTier
|
managedTier: ManagedTier
|
||||||
backupTier: BackupTier
|
backupTier: BackupTier
|
||||||
pilotAvailable: boolean
|
pilotAvailable: boolean
|
||||||
@@ -19,7 +18,6 @@ defineProps<Props>()
|
|||||||
|
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
'update:ipv4Count': [value: number]
|
'update:ipv4Count': [value: number]
|
||||||
'update:windowsLicense': [value: boolean]
|
|
||||||
'update:managedTier': [value: ManagedTier]
|
'update:managedTier': [value: ManagedTier]
|
||||||
'update:backupTier': [value: BackupTier]
|
'update:backupTier': [value: BackupTier]
|
||||||
'request-upgrade': []
|
'request-upgrade': []
|
||||||
@@ -44,7 +42,7 @@ const expanded = ref<boolean>(false)
|
|||||||
<span class="text-subtitle-1 font-weight-bold">Customize add-ons</span>
|
<span class="text-subtitle-1 font-weight-bold">Customize add-ons</span>
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
<span class="text-caption text-medium-emphasis me-3 d-none d-sm-inline">
|
<span class="text-caption text-medium-emphasis me-3 d-none d-sm-inline">
|
||||||
IPv4, Windows BYOL, Managed support, Backup
|
IPv4, Managed support, Backup
|
||||||
</span>
|
</span>
|
||||||
<VIcon :icon="expanded ? 'tabler-chevron-up' : 'tabler-chevron-down'" />
|
<VIcon :icon="expanded ? 'tabler-chevron-up' : 'tabler-chevron-down'" />
|
||||||
</button>
|
</button>
|
||||||
@@ -61,25 +59,6 @@ const expanded = ref<boolean>(false)
|
|||||||
|
|
||||||
<VDivider class="my-5" />
|
<VDivider class="my-5" />
|
||||||
|
|
||||||
<div class="d-flex align-center justify-space-between flex-wrap ga-3">
|
|
||||||
<div>
|
|
||||||
<div class="text-subtitle-2 font-weight-bold">Windows License</div>
|
|
||||||
<div class="text-caption text-medium-emphasis">
|
|
||||||
Bring your own license. Free.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<VSwitch
|
|
||||||
:model-value="windowsLicense"
|
|
||||||
color="primary"
|
|
||||||
density="compact"
|
|
||||||
hide-details
|
|
||||||
inset
|
|
||||||
@update:model-value="(v: boolean | null) => emit('update:windowsLicense', !!v)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<VDivider class="my-5" />
|
|
||||||
|
|
||||||
<ManagedSupportSelector
|
<ManagedSupportSelector
|
||||||
:model-value="managedTier"
|
:model-value="managedTier"
|
||||||
:pilot-available="pilotAvailable"
|
:pilot-available="pilotAvailable"
|
||||||
|
|||||||
@@ -118,11 +118,6 @@ function onIpv4Change(value: number): void {
|
|||||||
debouncePushUrl()
|
debouncePushUrl()
|
||||||
}
|
}
|
||||||
|
|
||||||
function onWindowsChange(value: boolean): void {
|
|
||||||
store.windowsLicense = value
|
|
||||||
debouncePushUrl()
|
|
||||||
}
|
|
||||||
|
|
||||||
function onManagedChange(value: 'self' | 'basic' | 'pro' | 'pilot'): void {
|
function onManagedChange(value: 'self' | 'basic' | 'pro' | 'pilot'): void {
|
||||||
store.setManagedTier(value)
|
store.setManagedTier(value)
|
||||||
debouncePushUrl()
|
debouncePushUrl()
|
||||||
@@ -200,14 +195,12 @@ watch(
|
|||||||
<div class="mt-5">
|
<div class="mt-5">
|
||||||
<AddOnsPanel
|
<AddOnsPanel
|
||||||
:ipv4-count="store.ipv4Count"
|
:ipv4-count="store.ipv4Count"
|
||||||
:windows-license="store.windowsLicense"
|
|
||||||
:managed-tier="store.managedTier"
|
:managed-tier="store.managedTier"
|
||||||
:backup-tier="store.backupTier"
|
:backup-tier="store.backupTier"
|
||||||
:pilot-available="store.pilotAvailable"
|
:pilot-available="store.pilotAvailable"
|
||||||
:cycle-suffix="cycleSuffix"
|
:cycle-suffix="cycleSuffix"
|
||||||
:monthly-multiplier="monthlyMultiplier"
|
:monthly-multiplier="monthlyMultiplier"
|
||||||
@update:ipv4-count="onIpv4Change"
|
@update:ipv4-count="onIpv4Change"
|
||||||
@update:windows-license="onWindowsChange"
|
|
||||||
@update:managed-tier="onManagedChange"
|
@update:managed-tier="onManagedChange"
|
||||||
@update:backup-tier="onBackupChange"
|
@update:backup-tier="onBackupChange"
|
||||||
@request-upgrade="onRequestUpgrade"
|
@request-upgrade="onRequestUpgrade"
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ const includedFeatures: IncludedItem[] = [
|
|||||||
{ text: 'ZFS storage snapshots (free)' },
|
{ text: 'ZFS storage snapshots (free)' },
|
||||||
{ text: 'KVM virtualization' },
|
{ text: 'KVM virtualization' },
|
||||||
{ text: 'Full root access' },
|
{ text: 'Full root access' },
|
||||||
{ text: 'Linux & Windows (BYOL) support' },
|
{ text: 'Linux included; Windows supported (bring your own license)' },
|
||||||
{ text: 'VirtFusion control panel' },
|
{ text: 'VirtFusion control panel' },
|
||||||
{ text: 'Out-of-band console / VNC access' },
|
{ text: 'Out-of-band console / VNC access' },
|
||||||
{ text: 'Near-instant provisioning' },
|
{ text: 'Near-instant provisioning' },
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ export const useEstimatorStore = defineStore('estimator', () => {
|
|||||||
const workload = ref<string | null>(null)
|
const workload = ref<string | null>(null)
|
||||||
const planId = ref<number | null>(null)
|
const planId = ref<number | null>(null)
|
||||||
const ipv4Count = ref<number>(1)
|
const ipv4Count = ref<number>(1)
|
||||||
const windowsLicense = ref<boolean>(false)
|
|
||||||
const managedTier = ref<ManagedTier>('self')
|
const managedTier = ref<ManagedTier>('self')
|
||||||
const backupTier = ref<BackupTier>('none')
|
const backupTier = ref<BackupTier>('none')
|
||||||
const cycle = ref<EstimatorCycle>('monthly')
|
const cycle = ref<EstimatorCycle>('monthly')
|
||||||
@@ -212,7 +211,6 @@ export const useEstimatorStore = defineStore('estimator', () => {
|
|||||||
if (workload.value) params.set('w', workload.value)
|
if (workload.value) params.set('w', workload.value)
|
||||||
if (planId.value !== null) params.set('plan', String(planId.value))
|
if (planId.value !== null) params.set('plan', String(planId.value))
|
||||||
if (ipv4Count.value > 1) params.set('ipv4', String(ipv4Count.value))
|
if (ipv4Count.value > 1) params.set('ipv4', String(ipv4Count.value))
|
||||||
if (windowsLicense.value) params.set('windows', '1')
|
|
||||||
if (managedTier.value !== 'self') params.set('managed', managedTier.value)
|
if (managedTier.value !== 'self') params.set('managed', managedTier.value)
|
||||||
if (backupTier.value !== 'none') params.set('backup', backupTier.value)
|
if (backupTier.value !== 'none') params.set('backup', backupTier.value)
|
||||||
if (cycle.value !== 'monthly') params.set('cycle', cycle.value)
|
if (cycle.value !== 'monthly') params.set('cycle', cycle.value)
|
||||||
@@ -225,7 +223,6 @@ export const useEstimatorStore = defineStore('estimator', () => {
|
|||||||
if (planId.value === null) return null
|
if (planId.value === null) return null
|
||||||
const params = new URLSearchParams()
|
const params = new URLSearchParams()
|
||||||
if (ipv4Count.value > 1) params.set('ipv4', String(ipv4Count.value))
|
if (ipv4Count.value > 1) params.set('ipv4', String(ipv4Count.value))
|
||||||
if (windowsLicense.value) params.set('windows', '1')
|
|
||||||
if (managedTier.value !== 'self') params.set('managed', managedTier.value)
|
if (managedTier.value !== 'self') params.set('managed', managedTier.value)
|
||||||
if (backupTier.value !== 'none') params.set('backup', backupTier.value)
|
if (backupTier.value !== 'none') params.set('backup', backupTier.value)
|
||||||
if (cycle.value !== 'monthly') params.set('cycle', cycle.value)
|
if (cycle.value !== 'monthly') params.set('cycle', cycle.value)
|
||||||
@@ -252,8 +249,6 @@ export const useEstimatorStore = defineStore('estimator', () => {
|
|||||||
if (!Number.isNaN(n) && n >= 1 && n <= 8) ipv4Count.value = n
|
if (!Number.isNaN(n) && n >= 1 && n <= 8) ipv4Count.value = n
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p.get('windows') === '1' || p.get('windows') === 'true') windowsLicense.value = true
|
|
||||||
|
|
||||||
const m = p.get('managed')
|
const m = p.get('managed')
|
||||||
if (m && ['self', 'basic', 'pro', 'pilot'].includes(m)) managedTier.value = m as ManagedTier
|
if (m && ['self', 'basic', 'pro', 'pilot'].includes(m)) managedTier.value = m as ManagedTier
|
||||||
|
|
||||||
@@ -277,7 +272,6 @@ export const useEstimatorStore = defineStore('estimator', () => {
|
|||||||
workload,
|
workload,
|
||||||
planId,
|
planId,
|
||||||
ipv4Count,
|
ipv4Count,
|
||||||
windowsLicense,
|
|
||||||
managedTier,
|
managedTier,
|
||||||
backupTier,
|
backupTier,
|
||||||
cycle,
|
cycle,
|
||||||
|
|||||||
Reference in New Issue
Block a user