* UI: abbility to start container in exited state * Fix all Where() method usages * Container state is updated every list and get operation
		
			
				
	
	
		
			184 lines
		
	
	
	
		
			6.1 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			184 lines
		
	
	
	
		
			6.1 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').then(response => response.json())
 | 
						|
          .then(data => this.apps = data);
 | 
						|
        fetch('/v1/node').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').then(response => response.json())
 | 
						|
          .then(data => this.apps = data);
 | 
						|
          fetch('/v1/node').then(response => response.json())
 | 
						|
          .then(data => this.node = data);
 | 
						|
        },
 | 
						|
        start: (id) => {
 | 
						|
          app.api_response = "working"
 | 
						|
          fetch('/v1/apps/'+id+'/start', {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', {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', {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', {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, {method: 'DELETE'})
 | 
						|
            .then(response => {
 | 
						|
              response.json()
 | 
						|
              app.api_status_code = response.status
 | 
						|
            })
 | 
						|
            .then(data => app.api_response = data)
 | 
						|
        },
 | 
						|
      },
 | 
						|
    })
 | 
						|
  </script>
 | 
						|
 | 
						|
</body>
 | 
						|
 | 
						|
</html>
 |