Adam Štrauch
9348504f9e
* Possibility to pass token in query param * More appropriate names for gathering and resource updating functions * Shorter measuring delay * Container status available immediatelly when needed
185 lines
6.3 KiB
HTML
185 lines
6.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
|
<meta name="description" content="">
|
|
<meta name="author" content="">
|
|
|
|
<title>Node manager</title>
|
|
|
|
<!-- Bootstrap core CSS -->
|
|
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet">
|
|
|
|
<style>
|
|
body {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.success {
|
|
color: green;
|
|
}
|
|
|
|
.error {
|
|
color: red;
|
|
}
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<!-- Page Content -->
|
|
<div class="container" id="app">
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<h1 class="mt-5">Node</h1>
|
|
|
|
<p>
|
|
Overall index: <em>{( node.index.toFixed(2) )}</em><br>
|
|
Load 1 index: <em>{( node.load1_index.toFixed(2) )}</em><br>
|
|
Load 5 index: <em>{( node.load5_index.toFixed(2) )}</em><br>
|
|
Load 15 index: <em>{( node.load15_index.toFixed(2) )}</em><br>
|
|
Memory index: <em>{( node.memory_index.toFixed(2) )}</em><br>
|
|
Disk space index: <em>{( node.disk_space_index.toFixed(2) )}</em>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="col-lg-12">
|
|
<h1 class="mt-5">Applications</h1>
|
|
|
|
<div v-if="api_response">
|
|
<strong>Response:</strong> <span v-bind:class="{ success: isSuccess, error: hasError }">{( api_response )}</span>
|
|
</div>
|
|
|
|
<table class="table table-striped">
|
|
<thead>
|
|
<tr>
|
|
<th>Name</th>
|
|
<th>Status</th>
|
|
<th>Image</th>
|
|
<th>CPU</th>
|
|
<th>Memory</th>
|
|
<th>Disk space</th>
|
|
<th>Inodes</th>
|
|
<th>Tags</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr v-for="app in apps">
|
|
<td><strong>{( app.name )}</strong></td>
|
|
<td>{( app.state )}</td>
|
|
<td>{( app.image.replace("docker.io/", "") )}</td>
|
|
<td>{( (app.cpu_usage).toFixed(2) )} % / {( app.cpu )} %</td>
|
|
<td>{( (app.memory_usage/1000/1000).toFixed(2) )} MB / {( app.memory )} MB</td>
|
|
<td>{( (app.disk_usage_bytes / 1000 / 1000 / 1000).toFixed(2) )} GB</td>
|
|
<td>{( app.disk_usage_inodes )}</td>
|
|
<td>
|
|
<span v-for="label in app.labels" class="label label-info">{( label.value )}</span>
|
|
</td>
|
|
<td>
|
|
<button class="btn btn-success btn-sm" v-on:click="start(app.name)" v-if="['stopped', 'created', 'exited'].includes(app.state)">Start</button>
|
|
<button class="btn btn-warning btn-sm" v-on:click="stop(app.name)" v-if="['running'].includes(app.state)">Stop</button>
|
|
<button class="btn btn-warning btn-sm" v-on:click="restart(app.name)" v-if="['running'].includes(app.state)">Restart</button>
|
|
<button class="btn btn-warning btn-sm" v-on:click="rebuild(app.name)">Rebuild</button>
|
|
<button class="btn btn-danger btn-sm" v-on:click="remove(app.name)">Delete</button>
|
|
</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bootstrap core JavaScript -->
|
|
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
|
|
<script>
|
|
var app = new Vue({
|
|
el: '#app',
|
|
delimiters: ['{(', ')}'],
|
|
data: {
|
|
apps: [],
|
|
api_status_code: 0,
|
|
api_response: "",
|
|
node: {},
|
|
},
|
|
created() {
|
|
fetch('/v1/apps?token={{ .Token }}').then(response => response.json())
|
|
.then(data => this.apps = data);
|
|
fetch('/v1/node?token={{ .Token }}').then(response => response.json())
|
|
.then(data => this.node = data);
|
|
},
|
|
methods: {
|
|
isSuccess: () => {
|
|
return this.api_status_code >= 200 && this.api_status_code <= 299
|
|
},
|
|
hasError: () => {
|
|
return this.api_status_code >= 400 && this.api_status_code < 505
|
|
},
|
|
refresh: () => {
|
|
fetch('/v1/apps?token={{ .Token }}').then(response => response.json())
|
|
.then(data => this.apps = data);
|
|
fetch('/v1/node?token={{ .Token }}').then(response => response.json())
|
|
.then(data => this.node = data);
|
|
},
|
|
start: (id) => {
|
|
app.api_response = "working"
|
|
fetch('/v1/apps/'+id+'/start?token={{ .Token }}', {method: 'PUT'})
|
|
.then(response => {
|
|
app.api_status_code = response.status
|
|
return response.json()
|
|
})
|
|
.then(data => app.api_response = data)
|
|
},
|
|
stop: (id) => {
|
|
app.api_response = "working"
|
|
fetch('/v1/apps/'+id+'/stop?token={{ .Token }}', {method: 'PUT'})
|
|
.then(response => {
|
|
app.api_status_code = response.status
|
|
return response.json()
|
|
})
|
|
.then(data => app.api_response = data)
|
|
},
|
|
restart: (id) => {
|
|
app.api_response = "working"
|
|
fetch('/v1/apps/'+id+'/restart?token={{ .Token }}', {method: 'PUT'})
|
|
.then(response => {
|
|
app.api_status_code = response.status
|
|
return response.json()
|
|
})
|
|
.then(data => app.api_response = data)
|
|
},
|
|
rebuild: (id) => {
|
|
app.api_response = "working"
|
|
fetch('/v1/apps/'+id+'/rebuild?token={{ .Token }}', {method: 'PUT'})
|
|
.then(response => {
|
|
app.api_status_code = response.status
|
|
return response.json()
|
|
})
|
|
.then(data => {
|
|
app.api_response = data
|
|
})
|
|
},
|
|
remove: (id) => {
|
|
app.api_response = "working"
|
|
fetch('/v1/apps/'+id+"?token={{ .Token }}", {method: 'DELETE'})
|
|
.then(response => {
|
|
response.json()
|
|
app.api_status_code = response.status
|
|
})
|
|
.then(data => app.api_response = data)
|
|
},
|
|
},
|
|
})
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|