* 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
		
			
				
	
	
		
			184 lines
		
	
	
	
		
			6.3 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			184 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>
 |