mirror of
https://github.com/hanzo-io/cloud.git
synced 2026-10-30 18:57:42 +00:00
294 lines
7.6 KiB
Vue
294 lines
7.6 KiB
Vue
<template>
|
|
<div class="flex items-center justify-between gap-1">
|
|
<div>
|
|
<h3 class="text-base font-medium">{{ props.actionLabel }}</h3>
|
|
<p class="mt-1 text-p-base text-gray-600">{{ props.description }}</p>
|
|
</div>
|
|
<Button
|
|
v-if="site?.doc"
|
|
class="whitespace-nowrap"
|
|
@click="getSiteActionHandler(props.actionLabel)"
|
|
>
|
|
<p
|
|
:class="
|
|
group === 'Dangerous Actions' ? 'text-red-600' : 'text-gray-800'
|
|
"
|
|
>
|
|
{{ props.buttonLabel }}
|
|
</p>
|
|
</Button>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { getCachedDocumentResource } from 'frappe-ui';
|
|
import { defineAsyncComponent, h } from 'vue';
|
|
import { toast } from 'vue-sonner';
|
|
import { confirmDialog, renderDialog } from '../utils/components';
|
|
import { getToastErrorMessage } from '../utils/toast';
|
|
import router from '../router';
|
|
import { isLastSite } from '../data/team';
|
|
|
|
const props = defineProps({
|
|
siteName: { type: String, required: true },
|
|
actionLabel: { type: String, required: true },
|
|
method: { type: String, required: true },
|
|
description: { type: String, required: true },
|
|
buttonLabel: { type: String, required: true },
|
|
group: { type: String, required: false },
|
|
});
|
|
|
|
const site = getCachedDocumentResource('Site', props.siteName);
|
|
|
|
function getSiteActionHandler(action) {
|
|
const actionDialogs = {
|
|
'Restore with files': defineAsyncComponent(
|
|
() => import('./SiteDatabaseRestoreDialog.vue'),
|
|
),
|
|
'Restore from an existing site': defineAsyncComponent(
|
|
() => import('./site/SiteDatabaseRestoreFromURLDialog.vue'),
|
|
),
|
|
'Manage database users': defineAsyncComponent(
|
|
() => import('./SiteDatabaseAccessDialog.vue'),
|
|
),
|
|
'Version upgrade': defineAsyncComponent(
|
|
() => import('./site/SiteVersionUpgradeDialog.vue'),
|
|
),
|
|
'Change bench group': defineAsyncComponent(
|
|
() => import('./site/SiteChangeGroupDialog.vue'),
|
|
),
|
|
'Change region': defineAsyncComponent(
|
|
() => import('./site/SiteChangeRegionDialog.vue'),
|
|
),
|
|
'Change server': defineAsyncComponent(
|
|
() => import('./site/SiteChangeServerDialog.vue'),
|
|
),
|
|
'Schedule backup': defineAsyncComponent(
|
|
() => import('./site/SiteScheduleBackup.vue'),
|
|
),
|
|
};
|
|
if (actionDialogs[action]) {
|
|
const dialog = h(actionDialogs[action], { site: site.doc.name });
|
|
renderDialog(dialog);
|
|
return;
|
|
}
|
|
|
|
const actionHandlers = {
|
|
'Activate site': onActivateSite,
|
|
'Deactivate site': onDeactivateSite,
|
|
'Drop site': onDropSite,
|
|
'Migrate site': onMigrateSite,
|
|
'Transfer site': onTransferSite,
|
|
'Reset site': onSiteReset,
|
|
'Clear cache': onClearCache,
|
|
};
|
|
if (actionHandlers[action]) {
|
|
actionHandlers[action].call(this);
|
|
}
|
|
}
|
|
|
|
function onDeactivateSite() {
|
|
return confirmDialog({
|
|
title: 'Deactivate Site',
|
|
message: `
|
|
Are you sure you want to deactivate this site?<br><br>
|
|
<div class="text-bg-base bg-gray-100 p-2 rounded-md">
|
|
The site will go in an <strong>inactive</strong> state.It won't be accessible and background jobs won't run.
|
|
<br><br>
|
|
<div class="text-red-600">You will still be charged for it.</div>
|
|
</div>
|
|
`,
|
|
primaryAction: {
|
|
label: 'Deactivate',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick({ hide }) {
|
|
return site.deactivate.submit().then(hide);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function onActivateSite() {
|
|
return confirmDialog({
|
|
title: 'Activate Site',
|
|
message: `
|
|
Are you sure you want to activate this site?
|
|
<br><br>
|
|
<strong>Note: Use this as last resort if site is broken and inaccessible</strong>
|
|
`,
|
|
primaryAction: {
|
|
label: 'Activate',
|
|
variant: 'solid',
|
|
onClick({ hide }) {
|
|
return site.activate.submit().then(hide);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function onDropSite() {
|
|
return confirmDialog({
|
|
title: 'Drop Site',
|
|
message: `
|
|
Are you sure you want to drop your site? The site will be archived and
|
|
all of its files and Offsite Backups will be deleted. This action cannot
|
|
be undone.
|
|
`,
|
|
fields: [
|
|
{
|
|
label: 'Please type the site name to confirm.',
|
|
fieldname: 'confirmSiteName',
|
|
},
|
|
{
|
|
label: 'Force drop site',
|
|
fieldname: 'force',
|
|
type: 'checkbox',
|
|
},
|
|
],
|
|
primaryAction: {
|
|
label: 'Drop Site',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick: async ({ hide, values }) => {
|
|
if (
|
|
![site.doc.name, site.doc.host_name].includes(values.confirmSiteName)
|
|
) {
|
|
throw new Error('Site name does not match.');
|
|
}
|
|
|
|
const val = await isLastSite(site.doc.team);
|
|
const FeedbackDialog = defineAsyncComponent(
|
|
() => import('./ChurnFeedbackDialog.vue'),
|
|
);
|
|
|
|
return site.archive.submit({ force: values.force }).then(() => {
|
|
hide();
|
|
if (val) {
|
|
renderDialog(
|
|
h(FeedbackDialog, {
|
|
team: site.doc.team,
|
|
onUpdated() {
|
|
router.replace({ name: 'Site List' });
|
|
toast.success('Site dropped successfully');
|
|
},
|
|
}),
|
|
);
|
|
} else {
|
|
router.replace({ name: 'Site List' });
|
|
}
|
|
});
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function onMigrateSite() {
|
|
return confirmDialog({
|
|
title: 'Migrate Site',
|
|
message: `
|
|
<span class="rounded-sm bg-gray-100 p-0.5 font-mono text-sm font-semibold">bench migrate</span>
|
|
command will be executed on your site. Are you sure you want to run this
|
|
command? We recommend that you take a database backup before continuing.
|
|
`,
|
|
fields: [
|
|
{
|
|
label: 'Skip patches if they fail during migration (Not recommended)',
|
|
fieldname: 'skipFailingPatches',
|
|
type: 'checkbox',
|
|
},
|
|
{
|
|
label: 'Please type the site name to confirm.',
|
|
fieldname: 'confirmSiteName',
|
|
},
|
|
],
|
|
primaryAction: {
|
|
label: 'Migrate',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick: ({ hide, values }) => {
|
|
if (values.confirmSiteName !== site.doc.name) {
|
|
throw new Error('Site name does not match');
|
|
}
|
|
return site.migrate
|
|
.submit({ skip_failing_patches: values.skipFailingPatches })
|
|
.then(hide);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function onSiteReset() {
|
|
return confirmDialog({
|
|
title: 'Reset Site',
|
|
message: `
|
|
All the data from your site will be lost. Are you sure you want to reset your database?
|
|
`,
|
|
fields: [
|
|
{
|
|
label: 'Please type the site name to confirm.',
|
|
fieldname: 'confirmSiteName',
|
|
},
|
|
],
|
|
primaryAction: {
|
|
label: 'Reset',
|
|
variant: 'solid',
|
|
theme: 'red',
|
|
onClick: ({ hide, values }) => {
|
|
if (values.confirmSiteName !== site.doc.name) {
|
|
throw new Error('Site name does not match.');
|
|
}
|
|
return site.reinstall.submit().then(hide);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function onTransferSite() {
|
|
return confirmDialog({
|
|
title: 'Transfer Site Ownership',
|
|
fields: [
|
|
{
|
|
label: 'Enter email address of the team for transfer of site ownership',
|
|
fieldname: 'email',
|
|
},
|
|
{
|
|
label: 'Reason for transfer',
|
|
fieldname: 'reason',
|
|
type: 'textarea',
|
|
},
|
|
],
|
|
primaryAction: {
|
|
label: 'Transfer',
|
|
variant: 'solid',
|
|
onClick: ({ hide, values }) => {
|
|
return site.sendTransferRequest
|
|
.submit({ team_mail_id: values.email, reason: values.reason || '' })
|
|
.then(() => {
|
|
hide();
|
|
toast.success(
|
|
`Transfer request sent to ${values.email} successfully.`,
|
|
);
|
|
});
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function onClearCache() {
|
|
return confirmDialog({
|
|
title: 'Clear Cache',
|
|
message: `<span class="rounded-sm bg-gray-100 p-0.5 font-mono text-sm font-semibold">bench clear-cache</span> and
|
|
<span class="rounded-sm bg-gray-100 p-0.5 font-mono text-sm font-semibold">bench clear-website-cache</span> commands
|
|
will be executed on your site. Are you sure you want to run these commands?`,
|
|
primaryAction: {
|
|
label: 'Clear Cache',
|
|
variant: 'solid',
|
|
onClick: ({ hide }) => {
|
|
return site.clearSiteCache.submit().then(hide);
|
|
},
|
|
},
|
|
});
|
|
}
|
|
</script>
|