283 lines
6.8 KiB
Vue

<template>
<div>
<div v-if="server">
<div>
<header
class="sticky top-0 z-10 flex items-center justify-between border-b bg-white px-5 py-2.5"
>
<Breadcrumbs
:items="[
{ label: 'Servers', route: { name: 'Servers' } },
{
label: server?.title,
route: {
name: 'ServerOverview',
params: { serverName: server?.name }
}
}
]"
>
<template #actions>
<div>
<Button
v-if="server?.status === 'Active'"
icon-left="plus"
label="New Bench"
@click="
$router.push({
name: 'NewServerBench',
params: { server: server?.name }
})
"
/>
<Dropdown :options="serverActions">
<template v-slot="{ open }">
<Button
variant="ghost"
class="mr-2"
icon="more-horizontal"
/>
</template>
</Dropdown>
</div>
</template>
</Breadcrumbs>
</header>
<EditServerTitleDialog v-model="showEditTitleDialog" :server="server" />
<div
class="flex flex-col space-y-3 px-5 py-3 md:flex-row md:items-baseline md:justify-between md:space-y-0"
>
<div class="mt-2 flex items-center">
<h1 class="text-2xl font-bold">{{ server.title }}</h1>
<Badge class="ml-4" :label="server.status" />
<div
v-if="regionInfo"
class="ml-2 hidden cursor-default flex-row items-center self-end rounded-md bg-yellow-50 px-3 py-1 text-xs font-medium text-yellow-700 md:flex"
>
<img
v-if="regionInfo.image"
class="mr-2 h-4"
:src="regionInfo.image"
:alt="`Flag of ${regionInfo.title}`"
:title="regionInfo.image"
/>
<p>{{ regionInfo.title }}</p>
</div>
</div>
<div class="mb-10 flex flex-row justify-between md:hidden">
<div class="flex flex-row">
<div
v-if="regionInfo"
class="flex cursor-default flex-row items-center rounded-md bg-yellow-50 px-3 py-1 text-xs font-medium text-yellow-700"
>
<img
v-if="regionInfo.image"
class="mr-2 h-4"
:src="regionInfo.image"
:alt="`Flag of ${regionInfo.title}`"
:title="regionInfo.image"
/>
<p>{{ regionInfo.title }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="p-5 pt-1">
<Tabs :tabs="tabs">
<router-view v-slot="{ Component, route }">
<component v-if="server" :is="Component" :server="server"></component>
</router-view>
</Tabs>
</div>
</div>
</template>
<script>
import EditServerTitleDialog from './EditServerTitleDialog.vue';
import Tabs from '@/components/Tabs.vue';
import { notify } from '@/utils/toast';
export default {
name: 'Server',
pageMeta() {
return {
title: `Server - ${this.serverName} - 今果 Jingrow`
};
},
props: ['serverName'],
components: {
EditServerTitleDialog,
Tabs
},
data() {
return {
runningJob: false,
runningPlay: false,
showEditTitleDialog: false,
errorMessage: ''
};
},
resources: {
server() {
return {
url: 'jcloud.api.server.get',
params: {
name: this.serverName
},
auto: true,
onSuccess() {
this.routeToGeneral();
},
onError: this.$routeTo404PageIfNotFound
};
},
reboot() {
return {
url: 'jcloud.api.server.reboot',
params: {
name: this.serverName
},
onSuccess(data) {
notify({
title: 'Server Reboot Scheduled Successfully',
color: 'green',
icon: 'check'
});
this.$resources.server.reload();
},
onError() {
notify({
title: 'An error occurred',
color: 'red',
icon: 'x'
});
}
};
}
},
methods: {
routeToGeneral() {
if (this.$route.matched.length === 1) {
let path = this.$route.fullPath;
this.$router.replace(`${path}/overview`);
}
}
},
computed: {
server() {
return this.$resources.server.data;
},
regionInfo() {
if (!this.$resources.server.loading && this.$resources.server.data) {
return this.$resources.server.data.region_info;
}
return null;
},
serverActions() {
return [
{
label: 'Edit Title',
icon: 'edit',
onClick: () => (this.showEditTitleDialog = true)
},
{
label: 'Visit Server',
icon: 'external-link',
condition: () =>
['Active', 'Updating'].includes(this.server.status) &&
this.$account.user.user_type === 'System User',
onClick: () => {
window.open(`https://${this.server.name}`, '_blank');
}
},
{
label: 'View in Desk',
icon: 'external-link',
condition: () => this.$account.user.user_type == 'System User',
onClick: () => {
window.open(
`${window.location.protocol}//${window.location.host}/app/${this.server.type}/${this.server.name}`,
'_blank'
);
}
},
{
label: 'Reboot',
icon: 'tool',
condition: () =>
this.server.status === 'Active' &&
this.$account.hasPermission(
this.server.name,
'jcloud.api.server.reboot'
),
loading: this.$resources.reboot.loading,
onClick: () => {
return this.$resources.reboot.submit();
}
},
{
label: 'Impersonate Team',
icon: 'tool',
condition: () => this.$account.user.user_type == 'System User',
onClick: async () => {
await this.$account.switchTeam(this.server.team);
notify({
title: 'Switched Team',
message: `Switched to ${this.server.team}`,
icon: 'check',
color: 'green'
});
}
}
];
},
tabs() {
let tabRoute = subRoute => `/servers/${this.serverName}/${subRoute}`;
let tabs = [
{ label: 'Installing', route: 'install' },
{ label: 'Overview', route: 'overview' },
{ label: 'Analytics', route: 'analytics' },
{ label: 'Benches', route: 'benches' },
{ label: 'Jobs', route: 'jobs', showRedDot: this.runningJob },
{ label: 'Plays', route: 'plays', showRedDot: this.runningPlay },
{ label: 'Settings', route: 'settings' }
];
let tabsByStatus = {
Active: [
'Overview',
'Analytics',
'Benches',
'Jobs',
'Plays',
'Settings'
],
Pending: ['Installing'],
Installing: ['Installing', 'Plays']
};
if (this.server) {
let tabsToShow = tabsByStatus[this.server.status];
if (tabsToShow?.length) {
tabs = tabs.filter(tab => tabsToShow.includes(tab.label));
}
return tabs.map(tab => {
return {
...tab,
route: tabRoute(tab.route)
};
});
}
return [];
}
}
};
</script>