jcloud/dashboard/src2/views/server/ServerOverviewPlan.vue

199 lines
4.5 KiB
Vue

<template>
<Card
title="Plan"
:subtitle="'Upgrade or downgrade your plan based on your usage'"
>
<template #actions>
<Button
@click="
() => {
showChangePlanDialog = true;
!plans.length && $resources.plans.fetch();
}
"
>
Change
</Button>
</template>
<div v-if="plan" class="flex items-center rounded-lg bg-gray-50 p-5">
<PlanIcon />
<div class="ml-4">
<h4 class="text-4xl font-semibold text-gray-900">
{{ $planTitle(plan) }}
<span v-if="plan.price_usd > 0" class="text-lg"> /mo </span>
</h4>
<p class="text-base text-gray-700">
{{ plan.vcpu }} {{ $plural(plan.vcpu, 'vCPU', 'vCPUs') }} +
{{ formatBytes(plan.memory, 0, 2) }} Memory +
{{ formatBytes(plan.disk, 0, 3) }} Storage
</p>
</div>
</div>
<div v-if="plan && used?.memory" class="mt-4 grid grid-cols-3 gap-12">
<div v-for="d in usage" :key="d.label">
<ProgressArc :percentage="d.percentage" />
<div class="mt-2 text-base font-medium text-gray-900">
{{ d.label }}
{{
isNaN(d.percentage) ? '' : `(${Number(d.percentage).toFixed(1)}%)`
}}
</div>
<div class="mt-1 text-xs text-gray-600">{{ d.value }}</div>
</div>
</div>
<Dialog
:options="{
title: 'Change Plan',
actions: [
{
label: 'Submit',
variant: 'solid',
loading: $resources.changePlan.loading,
onClick: () => $resources.changePlan.submit()
}
]
}"
v-model="showChangePlanDialog"
>
<template v-slot:body-content>
<ServerPlansTable
class="mt-6"
:plans="plans"
v-model:selectedPlan="selectedPlan"
/>
<ErrorMessage class="mt-4" :message="$resources.changePlan.error" />
</template>
</Dialog>
</Card>
</template>
<script>
import ServerPlansTable from '@/components/ServerPlansTable.vue';
import ProgressArc from '@/components/ProgressArc.vue';
import PlanIcon from '@/components/PlanIcon.vue';
import { notify } from '@/utils/toast';
export default {
name: 'ServerOverviewPlan',
props: ['server', 'plan'],
components: {
ServerPlansTable,
ProgressArc,
PlanIcon
},
data() {
return {
showChangePlanDialog: false,
selectedPlan: null
};
},
resources: {
usageResource() {
return {
url: 'jcloud.api.server.usage',
params: {
name: this.server?.name
},
initialData: {},
auto: true
};
},
plans() {
return {
url: 'jcloud.api.server.plans',
params: {
name: 'Server',
cluster: this.server.region_info.name
},
initialData: []
};
},
changePlan() {
return {
url: 'jcloud.api.server.change_plan',
params: {
name: this.server?.name,
plan: this.selectedPlan?.name
},
onSuccess() {
notify({
title: `Plan changed to ${this.selectedPlan.plan_title}`,
icon: 'check',
color: 'green'
});
this.showChangePlanDialog = false;
this.selectedPlan = null;
this.$emit('plan-change');
this.$resources.plans.reset();
},
onError(error) {
this.showChangePlanDialog = false;
notify({
title: error,
icon: 'x',
color: 'red'
});
}
};
}
},
methods: {
plan_title(plan) {
let china = this.$account.team.country == 'china';
let currency = china ? '¥' : '$';
let price_field = china ? 'price_cny' : 'price_usd';
let price = plan[price_field];
return price > 0 ? `${currency}${price}` : plan.plan_title;
}
},
computed: {
plans() {
let processedPlans = this.$resources.plans.data.map(plan => {
if (this.plan.name === plan.name) {
plan.disabled = true;
}
return plan;
});
return processedPlans;
},
used() {
return this.$resources.usageResource.data;
},
usage() {
return [
{
label: 'CPU',
value: `${this.used.vcpu} / ${this.plan.vcpu} ${this.$plural(
this.plan.vcpu,
'vCPU',
'vCPUs'
)}`,
percentage: (this.used.vcpu / this.plan.vcpu) * 100
},
{
label: 'Memory',
value: `${this.formatBytes(
this.used.memory,
0,
2
)} / ${this.formatBytes(this.plan.memory, 0, 2)}`,
percentage: (this.used.memory / this.plan.memory) * 100
},
{
label: 'Storage',
value: `${this.formatBytes(
this.used.disk,
0,
3
)} / ${this.formatBytes(this.plan.disk, 0, 3)}`,
percentage: (this.used.disk / this.plan.disk) * 100
}
];
}
}
};
</script>