2024-11-03 19:42:55 +00:00
|
|
|
<template>
|
2024-11-04 15:55:23 +00:00
|
|
|
<Loading class="content" :loading="loading" :message="error" type="danger">
|
|
|
|
<div class="block">
|
|
|
|
<h1>
|
|
|
|
<Icon name="cube">{{ container_name }}</Icon>
|
|
|
|
<router-link class="button ml-2" :to="`/update/${container_name}`">
|
|
|
|
<Icon name="edit">Update</Icon>
|
|
|
|
</router-link>
|
|
|
|
<button class="button ml-2" @click="refresh">
|
|
|
|
<Icon name="refresh">Refresh</Icon>
|
|
|
|
</button>
|
|
|
|
</h1>
|
|
|
|
</div>
|
|
|
|
<div class="box">
|
|
|
|
<div class="block is-flex is-align-items-baseline">
|
|
|
|
<Icon name="image">
|
|
|
|
<b>Image:</b>
|
|
|
|
<span class="m-2">{{ container?.image }}</span>
|
|
|
|
</Icon>
|
|
|
|
<button class="button ml-2" @click="pull">
|
|
|
|
<Icon name="cloud-download">Pull</Icon>
|
|
|
|
</button>
|
|
|
|
<button class="button ml-2" @click="remove">
|
|
|
|
<Icon name="trash">Remove</Icon>
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div class="block is-flex is-align-items-baseline">
|
|
|
|
<Icon name="support">
|
|
|
|
<b>Status:</b>
|
|
|
|
</Icon>
|
|
|
|
<Icon
|
|
|
|
:class="`has-text-${status_icon.type} m-2`"
|
|
|
|
:name="status_icon.name"
|
|
|
|
>
|
|
|
|
{{ container?.status }}
|
|
|
|
</Icon>
|
2024-11-05 22:45:23 +00:00
|
|
|
<button
|
|
|
|
v-if="container?.status == 'running'"
|
|
|
|
class="button ml-2"
|
|
|
|
@click="restart"
|
|
|
|
>
|
2024-11-04 15:55:23 +00:00
|
|
|
<Icon name="refresh">Restart</Icon>
|
|
|
|
</button>
|
2024-11-05 22:45:23 +00:00
|
|
|
<button
|
|
|
|
v-if="container?.status == 'running'"
|
|
|
|
class="button ml-2"
|
|
|
|
@click="stop"
|
|
|
|
>
|
|
|
|
<Icon name="stop">Stop</Icon>
|
|
|
|
</button>
|
|
|
|
<button
|
|
|
|
v-if="container?.status != 'running'"
|
|
|
|
class="button ml-2"
|
|
|
|
@click="start"
|
|
|
|
>
|
|
|
|
<Icon name="play">Start</Icon>
|
|
|
|
</button>
|
2024-11-04 15:55:23 +00:00
|
|
|
</div>
|
|
|
|
<div class="block is-flex is-align-items-baseline">
|
|
|
|
<Icon name="image"><b>Logs:</b></Icon>
|
|
|
|
<a
|
|
|
|
class="button ml-2"
|
|
|
|
:download="`${container_name}_logs.txt`"
|
|
|
|
:href="`/api/container/${container_name}/logs`"
|
|
|
|
>
|
|
|
|
<Icon name="download">Download</Icon>
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
<pre>{{ container?.logs?.trim().split('\n').reverse().join('\n') }}</pre>
|
|
|
|
</div>
|
|
|
|
</Loading>
|
2024-11-03 19:42:55 +00:00
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
2024-11-04 15:55:23 +00:00
|
|
|
import axios, { AxiosError } from 'axios'
|
|
|
|
import type { Container } from '../types'
|
|
|
|
import Icon from '../components/Icon.vue'
|
|
|
|
import Loading from '../components/Loading.vue'
|
2024-11-05 22:45:23 +00:00
|
|
|
import { get_status_icon } from '../utils'
|
2024-11-04 15:55:23 +00:00
|
|
|
|
2024-11-03 19:42:55 +00:00
|
|
|
export default {
|
|
|
|
name: 'Container',
|
2024-11-04 15:55:23 +00:00
|
|
|
components: {
|
|
|
|
Icon,
|
|
|
|
Loading,
|
|
|
|
},
|
|
|
|
data() {
|
|
|
|
return {
|
|
|
|
container: null as Container | null,
|
|
|
|
error: '',
|
|
|
|
loading: true,
|
|
|
|
}
|
|
|
|
},
|
|
|
|
computed: {
|
|
|
|
container_name(): string {
|
|
|
|
return this.$route.params.name as string
|
|
|
|
},
|
|
|
|
status_icon(): { name: string; type: string } {
|
2024-11-05 22:45:23 +00:00
|
|
|
return get_status_icon(this.container?.status ?? 'unknown')
|
2024-11-04 15:55:23 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
async mounted() {
|
|
|
|
await this.refresh()
|
|
|
|
},
|
|
|
|
methods: {
|
2024-11-04 23:12:25 +00:00
|
|
|
async request(method: 'get' | 'post' | 'delete', path: string) {
|
2024-11-04 15:55:23 +00:00
|
|
|
try {
|
|
|
|
this.loading = true
|
2024-11-04 23:12:25 +00:00
|
|
|
const response = await axios[method]<Container>(path)
|
2024-11-04 15:55:23 +00:00
|
|
|
this.container = response.data
|
|
|
|
} catch (error) {
|
|
|
|
console.error(error)
|
|
|
|
this.error =
|
|
|
|
error instanceof AxiosError
|
|
|
|
? error.message
|
2024-11-04 23:12:25 +00:00
|
|
|
: 'Error performing operation'
|
2024-11-04 15:55:23 +00:00
|
|
|
} finally {
|
|
|
|
this.loading = false
|
|
|
|
}
|
|
|
|
},
|
2024-11-04 23:12:25 +00:00
|
|
|
async pull() {
|
|
|
|
await this.request('post', `/api/container/${this.container_name}/pull`)
|
|
|
|
},
|
2024-11-04 15:55:23 +00:00
|
|
|
async refresh() {
|
2024-11-04 23:12:25 +00:00
|
|
|
await this.request('get', `/api/container/${this.container_name}`)
|
2024-11-04 15:55:23 +00:00
|
|
|
},
|
|
|
|
async remove() {
|
|
|
|
if (!confirm('Are you sure you want to remove this container?')) return
|
2024-11-04 23:12:25 +00:00
|
|
|
await this.request('delete', `/api/container/${this.container_name}`)
|
|
|
|
this.$router.push('/')
|
2024-11-04 15:55:23 +00:00
|
|
|
},
|
|
|
|
async restart() {
|
2024-11-04 23:12:25 +00:00
|
|
|
this.request('post', `/api/container/${this.container_name}/restart`)
|
2024-11-04 15:55:23 +00:00
|
|
|
},
|
2024-11-05 22:45:23 +00:00
|
|
|
async start() {
|
|
|
|
this.request('post', `/api/container/${this.container_name}/start`)
|
|
|
|
},
|
|
|
|
async stop() {
|
|
|
|
this.request('post', `/api/container/${this.container_name}/stop`)
|
|
|
|
},
|
2024-11-04 15:55:23 +00:00
|
|
|
},
|
2024-11-03 19:42:55 +00:00
|
|
|
}
|
|
|
|
</script>
|