Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions dashboard/src/components/ConfigureComputeAllocationDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<script setup lang="ts">
import { getCachedDocumentResource, Switch } from 'frappe-ui';
import { computed, getCurrentInstance, ref, watch } from 'vue';

const { appContext } = getCurrentInstance()!;
const $toast = appContext.config.globalProperties.$toast;
const props = defineProps<{ site: string }>();
const site = getCachedDocumentResource('Site', props.site);

const open = ref(true);
const switchValue = ref(false);

const isHighPerformanceEnabled = computed(() => {
const sitePlanName = site.doc.current_plan.name?.toLowerCase();
return !sitePlanName?.includes('low');
});

watch(
isHighPerformanceEnabled,
(val) => {
switchValue.value = val;
},
{ immediate: true },
);

const LOW_PERFORMANCE_PLAN_PREFIX = 'Unlimited - Low';
const HIGH_PERFORMANCE_PLAN_PREFIX = 'Unlimited';

const nextSitePlanName = computed(() => {
if (isHighPerformanceEnabled.value) {
return site.doc.current_plan.name?.replace(
HIGH_PERFORMANCE_PLAN_PREFIX,
LOW_PERFORMANCE_PLAN_PREFIX,
);
} else {
return site.doc.current_plan.name?.replace(
LOW_PERFORMANCE_PLAN_PREFIX,
HIGH_PERFORMANCE_PLAN_PREFIX,
);
}
});

function onClickSave() {
$toast.promise(site.setPlan.submit({ plan: nextSitePlanName }), {
loading: 'Reconfiguring bench workers...',
success: 'Performance has been reconfigured',
error: 'Failed to configure performance',
});
}
</script>

<template>
<Dialog
:options="{
title: 'Configure compute allocation',
size: 'xl',
}"
v-model="open"
>
<template #body-content>
<div class="flex flex-col gap-7 text-base">
<div class="flex w-full space-x-4">
<div class="flex flex-col flex-grow space-y-3">
<p class="font-semibold">Enable higher compute allocation</p>
<p class="text-ink-gray-6 leading-normal">
Maximize computing power for this site, or share resources equally
with sites on this server.
</p>
</div>
<Switch v-model="switchValue" size="md" class="px-4" />
</div>

<div class="flex w-full">
<div class="flex-grow">
<Button variant="ghost">
<template #prefix>
<LucideHelpCircle class="size-4" />
</template>
Learn More
</Button>
</div>

<div class="flex gap-3">
<Button @click="open = false">Cancel</Button>
<Button
:loading="site.setPlan.loading"
:disabled="switchValue === isHighPerformanceEnabled"
variant="solid"
@click="onClickSave"
>Save changes</Button
>
</div>
</div>
</div>
</template>
</Dialog>
</template>
148 changes: 148 additions & 0 deletions dashboard/src/components/ManageProductWarrantyDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<script setup lang="ts">
import dayjs from '../utils/dayjs';
import { getCachedDocumentResource, Switch } from 'frappe-ui';
import { computed, getCurrentInstance, ref, watch } from 'vue';

const { appContext } = getCurrentInstance()!;
const $toast = appContext.config.globalProperties.$toast;
const props = defineProps<{ site: string }>();
const site = getCachedDocumentResource('Site', props.site);

const open = ref(true);
const switchValue = ref(false);

const isSupportEnabled = computed(() => {
const sitePlan = site.doc?.current_plan;
return (
!!sitePlan?.support_included && sitePlan?.name?.includes(' - Supported')
);
});

watch(
isSupportEnabled,
(val) => {
switchValue.value = val;
},
{ immediate: true },
);

const LOW_PERFORMANCE_PLAN_PREFIX = 'Unlimited - Low';
const HIGH_PERFORMANCE_PLAN_PREFIX = 'Unlimited';
const SUPPORTED_PLAN_CLAUSE = ' - Supported';
const UNSUPPORTED_PLAN_CLAUSE = '';

const nextSitePlanName = computed(() => {
const planName = site.doc?.current_plan?.name as string;

if (planName.includes(' - Supported') && isSupportEnabled.value) {
return site.doc.current_plan.name?.replace(
SUPPORTED_PLAN_CLAUSE,
UNSUPPORTED_PLAN_CLAUSE,
);
} else {
// assuming format for supported plan is: {PERFORMANCE_PLAN_PREFIX} - {SUPPORT_CLAUSE} - {CLOUD_PROVIDER (optional)}
if (planName.includes(LOW_PERFORMANCE_PLAN_PREFIX)) {
return planName.replace(
LOW_PERFORMANCE_PLAN_PREFIX,
`${LOW_PERFORMANCE_PLAN_PREFIX}${SUPPORTED_PLAN_CLAUSE}`,
);
} else if (planName.includes(HIGH_PERFORMANCE_PLAN_PREFIX)) {
return planName.replace(
HIGH_PERFORMANCE_PLAN_PREFIX,
`${HIGH_PERFORMANCE_PLAN_PREFIX}${SUPPORTED_PLAN_CLAUSE}`,
);
}
}
});

const nextChangeAvailableOn = computed(() => {
const nextDate = dayjs(
site.doc?.next_allowed_dedicated_product_warranty_change_date,
);
if (dayjs().isAfter(nextDate)) {
return 'Available Now';
} else {
return nextDate.format('D MMM YYYY, hh:mm a');
}
});

function onClickSave() {
$toast.promise(site.setPlan.submit({ plan: nextSitePlanName }), {
loading: 'Changing product warranty...',
success: 'Product warranty changed successfully',
error: 'Failed to change product warranty',
});
}
</script>

<template>
<Dialog
:options="{
title: 'Configure compute allocation',
size: 'xl',
}"
v-model="open"
>
<template #body-content>
<div class="flex flex-col gap-4 text-base">
<div class="flex w-full space-x-4">
<div class="flex flex-col flex-grow space-y-3">
<p class="font-semibold">Enable higher compute allocation</p>
<p class="text-ink-gray-6 leading-normal">
Get support for issues with Frappe apps, not functional queries
</p>
</div>
<Switch v-model="switchValue" size="md" class="px-4" />
</div>

<hr />

<div class="flex flex-col gap-2 w-full">
<div class="flex">
<p class="flex-grow text-ink-gray-6">
Warranty limit for this server
</p>
<p>
{{ site.doc?.dedicated_server_warranty_limit?.consumed }} /
{{ site.doc?.dedicated_server_warranty_limit?.total }} sites
</p>
</div>
<div class="flex">
<p class="flex-grow text-ink-gray-6">Next change available on</p>
<p
:class="
nextChangeAvailableOn === 'Available Now'
? 'text-ink-green-3 font-medium'
: ''
"
>
{{ nextChangeAvailableOn }}
</p>
</div>
</div>

<div class="flex w-full">
<div class="flex-grow">
<Button variant="ghost">
<template #prefix>
<LucideHelpCircle class="size-4" />
</template>
Learn More
</Button>
</div>

<div class="flex gap-3">
<Button @click="open = false">Cancel</Button>
<Button
:loading="site.setPlan.loading"
:disabled="switchValue === isSupportEnabled"
variant="solid"
@click="onClickSave"
>Save changes</Button
>
</div>
</div>
</div>
</template>
</Dialog>
</template>
6 changes: 6 additions & 0 deletions dashboard/src/components/SiteActionCell.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@ onMounted(() => {

function getSiteActionHandler(action) {
const actionDialogs = {
'Manage Product Warranty': defineAsyncComponent(
() => import('./ManageProductWarrantyDialog.vue'),
),
'Configure compute allocation': defineAsyncComponent(
() => import('./ConfigureComputeAllocationDialog.vue'),
),
'Restore with files': defineAsyncComponent(
() => import('./SiteDatabaseRestoreDialog.vue'),
),
Expand Down
40 changes: 32 additions & 8 deletions dashboard/src/components/SiteOverview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
</DismissableBanner>

<div class="col-span-1 rounded-md border lg:col-span-2">
<div class="grid grid-cols-2 lg:grid-cols-4">
<div class="grid grid-cols-2 lg:flex lg:*:flex-grow">
<div class="border-b border-r p-5 lg:border-b-0">
<div class="flex h-full items-center justify-between">
<div>
Expand All @@ -139,7 +139,10 @@
<div>
<div class="leading-4">
<span class="flex items-center text-base text-gray-900">
<template v-if="$site.doc.trial_end_date">
<template v-if="$site.doc.is_dedicated_server">
Dedicated Server Site
</template>
<template v-else-if="$site.doc.trial_end_date">
{{ trialDays($site.doc.trial_end_date) }}
</template>
<template v-else-if="currentPlan">
Expand Down Expand Up @@ -169,12 +172,24 @@
</div>
</div>
</div>
<Button @click="showPlanChangeDialog">
{{ currentPlan?.is_trial_plan ? 'Upgrade' : 'Change' }}
</Button>
<template v-if="!$site.doc.is_dedicated_server">
<Button @click="showPlanChangeDialog">
{{ currentPlan?.is_trial_plan ? 'Upgrade' : 'Change' }}
</Button>
</template>
<template v-else>
<Tooltip
text="No individual plans needed for sites on dedicated servers"
>
<LucideHelpCircle class="size-4" />
</Tooltip>
</template>
</div>
</div>
<div class="border-b p-5 lg:border-b-0 lg:border-r">
<div
v-if="$site.doc.is_dedicated_server"
class="border-b p-5 lg:border-b-0 lg:border-r"
>
<div
class="flex items-center justify-between text-base text-gray-700"
>
Expand Down Expand Up @@ -209,8 +224,17 @@
<div
class="flex items-center justify-between text-base text-gray-700"
>
<span>Storage</span>
<div class="h-7"></div>
<div class="flex w-full">
<div class="flex-grow">Object Storage</div>

<Tooltip
text="Includes private and public file uploads and backups"
>
<LucideHelpCircle class="inline size-4 ml-2" />
</Tooltip>

<div class="h-7"></div>
</div>
</div>
<div class="mt-2">
<Progress
Expand Down
36 changes: 36 additions & 0 deletions dashboard/src/components/SitePlansCards.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export default {
'isPrivateBenchSite',
'isDedicatedServerSite',
'serverPlanPrice',
'serverSupportQuotaAvailable',
'selectedCluster',
'selectedApps',
'selectedVersion',
Expand Down Expand Up @@ -154,5 +155,40 @@ export default {
});
},
},
watch: {
plans: {
immediate: true,
handler: function (plans) {
if (!this.isDedicatedServerSite) return;

if (!plans.length) return;

const bestPlan = this.getBestDedicatedSitePlan();

if (bestPlan) {
this.currentPlan = bestPlan;
}
},
},
},
methods: {
// Currently best plan is determined based on warranty and CPU time only (may change later)
getBestDedicatedSitePlan() {
let filteredPlans = this.plans;

if (this.serverSupportQuotaAvailable) {
filteredPlans = filteredPlans.filter((plan) => plan.support_included);
}

const bestPlan = filteredPlans.reduce((best, curr) => {
return parseFloat(curr.cpu_time_per_day) >
parseFloat(best.cpu_time_per_day)
? curr
: best;
});

return bestPlan;
},
},
};
</script>
Loading
Loading