Polished UI for tracer

* added logo and favicon
* upgraded Bootstrap to v4
* use FontAwesome as icon font
* applied weave colors
* auto-select first container
* mock backend in server.js to serve *.json files for API requests
This commit is contained in:
David Kaltschmidt
2015-09-17 23:00:38 +02:00
committed by Tom Wilkie
parent 3e4b3ad0eb
commit 7dff1bd85e
7 changed files with 189 additions and 13 deletions

4
experimental/tracer/ui/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
container.json
traces.json
node_modules

View File

@@ -0,0 +1,10 @@
Develop UI
##########
* npm install
* npm start
`server.js` serves a fake backend. You can add `container.json` and
`traces.json` to this directory to serve them as /traces and /container
respectively.

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

View File

@@ -3,14 +3,12 @@
<head>
<title>Weave Tracer</title>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="https://cask.scotch.io/bootstrap-4.0-flex.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
<!-- Latest compiled and minified JavaScript -->
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.3/handlebars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
<script src="sprintf.min.js"></script>
@@ -24,6 +22,12 @@
var containers = [];
var traces = [];
Handlebars.registerHelper('isSelected', function(input) {
if (currentContainer && input === currentContainer.Id) {
return 'class=selected';
}
});
Handlebars.registerHelper('spaces', function(input) {
return new Array(input + 1).join("> ");
});
@@ -75,6 +79,10 @@
$.each(data, function(i, container) {
containersByID[container.Id] = container
});
// auto-select first container
if (containers.length) {
currentContainer = containersByID[containers[0].Id];
}
render();
window.setTimeout(updateContainers, 5 * 1000);
});
@@ -113,13 +121,70 @@
})
</script>
<style>
body {
height: 100%;
width: 100%;
color: #46466a;
font-family: "Roboto", sans-serif;
}
.logo {
margin-bottom: 30px;
}
.container-fluid {
background: linear-gradient(30deg, #e2e2ec 0%, #fafafc 100%);
padding: 30px 45px;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow-y: scroll;
}
ul.containers li {
cursor: pointer;
list-style: none;
font-size: 85%;
margin-bottom: 0.5rem;
opacity: 0.7;
}
ul.containers li.selected {
opacity: 1;
}
.heading {
margin: 10px 40px;
opacity: 0.4;
text-transform: uppercase;
}
.btn-default {
text-transform: uppercase;
margin-top: 3px;
opacity: 0.8;
}
h2 {
font-weight: normal;
margin-left: 1.5rem;
margin-right: 2rem;
margin-bottom: 1rem;
}
table {
width: 100%;
}
th {
text-transform: uppercase;
opacity: 0.4;
font-weight: normal;
}
.mainview {
margin-top: 2rem;
}
.table td {
font-size: 80%;
font-family: monospace;
padding-left: 0.5rem;
}
.table-striped tbody tr:nth-of-type(odd) {
background-color: #e2e2ec;
}
</style>
<script type="text/x-handlebars-template" id="traces">
{{#.}}
@@ -144,26 +209,28 @@
<script type="text/x-handlebars-template" id="process-template">
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h1>Weave Tracer</h1>
<div class="logo"><img src="logo.svg" width="300"/></div>
<div class="heading">Containers</div>
<ul class="containers">
{{#containers}}
<li id={{Id}}>{{Name}}</li>
<li {{isSelected Id}} id={{Id}}>{{Name}}</li>
{{/containers}}
</ul>
</div>
<div class="col-md-8 mainview">
{{#if container}}
<h2>{{container.Name}}</h2>
<div class="btn-group" role="group" data-container-id="{{container.Id}}">
<h2 class="pull-left">{{container.Name}}</h2>
<div class="btn-group btn-group-sm" role="group" data-container-id="{{container.Id}}">
<button type="button" class="btn btn-default start">
<span class="glyphicon glyphicon-play" aria-hidden="true"></span> Start</button>
<span class="fa fa-play" aria-hidden="true"></span> Start</button>
<button type="button" class="btn btn-default stop">
<span class="glyphicon glyphicon-stop" aria-hidden="true"></span> Stop</button>
<span class="fa fa-stop" aria-hidden="true"></span> Stop</button>
</div>
<table padding="2">
<table class="table table-striped table-sm">
<thead><tr><th>Start time</th><th>Duration</th><th>PID<th>From</th><th>To</th><th>Sub-traces</th></tr></thead>
<tbody>
{{>traces traces}}
@@ -172,6 +239,7 @@
{{/if}}
</div>
</div>
</div>
</script>
</head>

View File

@@ -0,0 +1,54 @@
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="960px" height="173px" viewBox="0 0 960 173" enable-background="new 0 0 960 173" xml:space="preserve">
<path fill="#32324B" d="M51.937,95.165l75.419-67.366c-5.989-4.707-12.71-8.52-19.981-11.211l-55.438,49.52V95.165z"/>
<path fill="#32324B" d="M30.265,85.465l-20.431,18.25c1.86,7.57,4.88,14.683,8.87,21.135l11.561-10.326V85.465z"/>
<path fill="#00D2FF" d="M92.276,30.074V12.768C88.815,12.27,85.282,12,81.685,12c-3.766,0-7.465,0.286-11.079,0.828v36.604
L92.276,30.074z"/>
<path fill="#00D2FF" d="M92.276,131.874V59.133L70.605,78.49v80.682c3.614,0.543,7.313,0.828,11.079,0.828
c4.41,0,8.723-0.407,12.921-1.147l58.033-51.838c1.971-6.664,3.046-13.712,3.046-21.015c0-3.439-0.254-6.817-0.708-10.132
L92.276,131.874z"/>
<path fill="#FF4B19" d="M92.276,110.518l58.14-51.933c-2.77-6.938-6.551-13.358-11.175-19.076L92.276,81.46V110.518z"/>
<path fill="#FF4B19" d="M70.605,100.817l-18.668,16.676V18.242c-8.086,3.555-15.409,8.513-21.672,14.567V139.19
c4.885,4.724,10.409,8.787,16.444,12.03l23.896-21.345V100.817z"/>
<polygon fill="#32324B" points="262.563,101.099 276.389,49.22 294.955,49.22 274.414,121.377 252.556,121.377 240.311,72.79
228.065,121.377 206.207,121.377 185.666,49.22 204.232,49.22 218.058,101.099 231.752,49.22 248.869,49.22 "/>
<path fill="#32324B" d="M363.429,97.676c-2.106,14.352-13.167,24.623-32.128,24.623c-20.146,0-35.025-12.114-35.025-36.605
c0-24.622,15.406-37.395,35.025-37.395c21.726,0,33.182,15.933,33.182,37.263v3.819h-49.772c0,8.031,3.291,18.17,16.327,18.17
c7.242,0,12.904-3.555,14.353-10.27L363.429,97.676z M345.654,76.608c-0.659-10.008-7.11-13.694-14.484-13.694
c-8.427,0-14.879,5.135-15.801,13.694H345.654z"/>
<path fill="#32324B" d="M417.628,74.634v-2.502c0-5.662-2.37-9.351-13.036-9.351c-13.298,0-13.694,7.375-13.694,9.877h-17.117
c0-10.666,4.477-24.359,31.338-24.359c25.676,0,30.285,12.771,30.285,23.174v39.766c0,2.897,0.131,5.267,0.395,7.11l0.527,3.028
h-18.172v-7.241c-5.134,5.134-12.245,8.163-22.384,8.163c-14.221,0-25.018-8.296-25.018-22.648c0-16.59,15.67-20.146,21.99-21.199
L417.628,74.634z M417.628,88.195l-6.979,1.054c-3.819,0.658-8.427,1.315-11.192,1.843c-3.029,0.527-5.662,1.186-7.637,2.765
c-1.844,1.449-2.765,3.425-2.765,5.926c0,2.107,0.79,8.69,10.666,8.69c5.793,0,10.928-2.105,13.693-4.872
c3.556-3.555,4.214-8.032,4.214-11.587V88.195z"/>
<polygon fill="#32324B" points="486.495,121.377 462.399,121.377 438.698,49.221 458.186,49.221 474.775,104.392 491.499,49.221
510.459,49.221 "/>
<path fill="#32324B" d="M578.273,97.676c-2.106,14.352-13.167,24.623-32.128,24.623c-20.146,0-35.025-12.114-35.025-36.605
c0-24.622,15.406-37.395,35.025-37.395c21.726,0,33.182,15.933,33.182,37.263v3.819h-49.772c0,8.031,3.291,18.17,16.327,18.17
c7.242,0,12.904-3.555,14.354-10.27L578.273,97.676z M560.498,76.608c-0.659-10.008-7.109-13.694-14.483-13.694
c-8.428,0-14.88,5.135-15.802,13.694H560.498z"/>
<g>
<path fill="#32324B" d="M615.355,120.575c-11.88,0-15.841-5.017-15.841-16.765V58.797h-11.616v-9.108h11.616V27.776h10.825v21.912
h18.216v9.108H610.34v42.241c0,8.977,1.979,10.164,9.107,10.164c1.98,0,7.524-0.396,8.185-0.396v8.976
C627.632,119.782,622.22,120.575,615.355,120.575z"/>
<path fill="#32324B" d="M674.095,60.777c-12.672,0-21.517,4.355-21.517,20.988v38.413h-10.824v-70.49h10.692v12.145
c4.62-8.977,13.992-12.145,21.385-12.145h5.016v11.089H674.095z"/>
<path fill="#32324B" d="M732.703,75.957v-3.828c0-9.768-4.224-14.388-16.633-14.388c-13.332,0-17.028,6.072-17.556,13.2H687.69
c0-9.108,5.147-22.177,28.116-22.177c24.157,0,27.721,12.54,27.721,23.761v36.301c0,3.301,0.132,8.58,0.924,11.353h-10.956
c0,0-0.264-3.828-0.264-9.504c-3.433,4.487-10.297,10.428-24.685,10.428c-13.597,0-23.761-7.92-23.761-21.12
c0-14.652,11.748-18.613,18.876-20.064C710.395,78.598,732.703,75.957,732.703,75.957z M732.703,84.67
c0,0-15.312,1.979-23.101,3.168c-7.524,1.056-13.597,3.564-13.597,11.88c0,6.996,4.753,12.276,14.389,12.276
c13.332,0,22.309-7.656,22.309-19.272V84.67z"/>
<path fill="#32324B" d="M790.649,111.994c10.429,0,17.953-5.939,19.009-16.632h10.957c-1.98,17.028-13.597,25.74-29.966,25.74
c-18.744,0-32.076-12.012-32.076-35.905c0-23.76,13.464-36.433,32.209-36.433c16.104,0,27.721,8.712,29.568,25.213h-10.956
c-1.452-11.353-9.24-16.104-18.877-16.104c-12.012,0-20.856,8.448-20.856,27.324C769.661,104.471,778.901,111.994,790.649,111.994z
"/>
<path fill="#32324B" d="M895.062,96.022c-1.452,12.408-10.032,25.08-30.229,25.08c-18.745,0-32.341-12.804-32.341-36.037
c0-21.912,13.464-36.301,32.209-36.301c19.8,0,30.757,14.784,30.757,38.018h-51.878c0.265,13.332,5.809,25.212,21.385,25.212
c11.484,0,18.217-7.128,19.141-16.104L895.062,96.022z M883.71,78.201c-1.056-14.916-9.636-20.328-19.272-20.328
c-10.824,0-19.141,7.26-20.46,20.328H883.71z"/>
<path fill="#32324B" d="M942.976,60.777c-12.672,0-21.517,4.355-21.517,20.988v38.413h-10.824v-70.49h10.692v12.145
c4.62-8.977,13.992-12.145,21.385-12.145h5.016v11.089H942.976z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@@ -0,0 +1,15 @@
{
"name": "scope-tracer",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "node server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "David Kaltschmidt <david.kaltschmidt@gmail.com>",
"license": "UNLICENSED",
"devDependencies": {
"express": "^4.13.3"
}
}

View File

@@ -0,0 +1,25 @@
var express = require('express')
var app = express();
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/container', function(req, res) {
res.sendFile(__dirname + '/container.json');
});
app.get('/traces', function(req, res) {
res.sendFile(__dirname + '/traces.json');
});
app.use(express.static('./'));
var port = process.env.PORT || 4050;
var server = app.listen(port, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Scope Tracer UI listening at http://%s:%s', host, port);
});