Simon Hunt
Committed by Gerrit Code Review

ONOS-4359: continued work on theming UI

- topo view: map and instance panel re-theming.

Change-Id: I8e5b0eda61b78b7d54593d84efccb16c54c1611e
Showing 27 changed files with 291 additions and 125 deletions
......@@ -127,6 +127,11 @@
glyphDataSet = {
_viewbox: '0 0 110 110',
uiAttached: 'M91.9,16.7H18.1A5.3,5.3,0,0,0,12.8,22V68' +
'a5.3,5.3,0,0,0,5.3,5.3H91.9A5.3,5.3,0,0,0,97.2,68V22' +
'A5.3,5.3,0,0,0,91.9,16.7ZM91.6,65.2H18.4V22.3H91.6V65.2Z' +
'M71.5,87.5h3.8v5.9h-40.6v-5.9h3.8v-1.7h5.4v-9.7h22.3v9.7h5.3v1.7z',
// Small dot
unknown: 'M35,40a5,5,0,0,1,5-5h30a5,5,0,0,1,5,5v30a5,5,0,0,1-5,5' +
'h-30a5,5,0,0,1-5-5z',
......@@ -525,11 +530,6 @@
badgeDataSet = {
_viewbox: '0 0 10 10',
uiAttached: 'M2,2.5a.5,.5,0,0,1,.5-.5h5a.5,.5,0,0,1,.5,.5v3' +
'a.5,.5,0,0,1-.5,.5h-5a.5,.5,0,0,1-.5-.5zM2.5,2.8a.3,.3,0,0,1,' +
'.3-.3h4.4a.3,.3,0,0,1,.3,.3v2.4a.3,.3,0,0,1-.3,.3h-4.4' +
'a.3,.3,0,0,1-.3-.3zM2,6.55h6l1,1.45h-8z',
checkMark: 'M8.6,3.4L4.4,7.7L1.4,4.7L2.5,3.6L4.4,5.5L7.5,2.3L8.6,3.4Z',
xMark: 'M7.8,6.7L6.7,7.8,5,6.1,3.3,7.8,2.2,6.7,3.9,5,2.2,3.3,3.3,' +
......
......@@ -159,12 +159,13 @@
// --- Ordinal scales for 7 values.
// blue brown brick red sea green purple dark teal lime
var lightNorm = ['#3E5780', '#78533B', '#CB4D28', '#018D61', '#8A2979', '#006D73', '#56AF00'],
lightMute = ['#A8B8CC', '#CCB3A8', '#FFC2BD', '#96D6BF', '#D19FCE', '#8FCCCA', '#CAEAA4'],
darkNorm = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'],
darkMute = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'];
// Colors per Mojo-Design's color palette..
// blue lt blue red lt red dk grey lt grey steel
var lightNorm = ['#5b99d2', '#66cef6', '#d05a55', '#db7773', '#716b6b', '#aeada8', '#7e9aa8'],
lightMute = ['#a8cceb', '#a8e9fd', '#f1a7a7', '#f8c9c9', '#b9b5b5', '#d7d6d4', '#bdcdd5'],
// TODO: dark theme
darkNorm = ['#5b99d2', '#66cef6', '#d05a55', '#db7773', '#716b6b', '#aeada8', '#7e9aa8'],
darkMute = ['#a8cceb', '#a8e9fd', '#f1a7a7', '#f8c9c9', '#b9b5b5', '#d7d6d4', '#bdcdd5'];
var colors= {
light: {
......@@ -215,7 +216,7 @@
dom.forEach(function (id, i) {
var x = i * 20,
y = k * 20,
f = get(id, muted, theme);
f = getColor(id, muted, theme);
g.append('circle').attr({
cx: x,
cy: y,
......
......@@ -110,7 +110,8 @@
}
function adjustWidth(btnWidth) {
if (fs.noPxStyle(currentRow, 'width') >= maxWidth) {
// 0.1 fudge for rounding error
if (fs.noPxStyle(currentRow, 'width') + 0.1 >= maxWidth) {
tbWidth += btnWidth;
maxWidth = tbWidth;
}
......
......@@ -127,7 +127,8 @@ html[data-platform='iPad'] #topo-p-detail {
/* --- Topo Instance Panel --- */
#topo-p-instance {
height: 100px;
height: 85px;
padding: 10px;
}
#topo-p-instance div.onosInst {
......@@ -140,15 +141,20 @@ html[data-platform='iPad'] #topo-p-detail {
#topo-p-instance svg text.instTitle {
font-size: 11pt;
font-weight: bold;
font-variant: small-caps;
text-transform: uppercase;
}
#topo-p-instance svg text.instLabel {
font-size: 9pt;
font-style: italic;
font-size: 10pt;
}
/* --- Toolbar --- */
#toolbar-topo-tbar {
padding: 6px;
}
#toolbar-topo-tbar .tbar-row.right {
width: 100%;
}
......@@ -228,10 +234,6 @@ html[data-platform='iPad'] #topo-p-detail {
/* -- MISC -- */
.notReady .readyBadge {
visibility: hidden;
}
.map-list {
padding: 10px;
}
......
......@@ -67,6 +67,9 @@
E: [equalizeMasters, 'Equalize mastership roles'],
//-- instance color palette debug
// 9: function () { sus.cat7().testCard(svg); },
// topology overlay selections
F1: function () { ttbs.fnkey(0); },
F2: function () { ttbs.fnkey(1); },
......
......@@ -32,20 +32,7 @@
*/
// configuration
var instCfg = {
rectPad: 8,
nodeOx: 9,
nodeOy: 9,
nodeDim: 40,
birdOx: 19,
birdOy: 21,
birdDim: 21,
uiDy: 45,
titleDy: 30,
textYOff: 20,
textYSpc: 15
},
showLogicErrors = true,
var showLogicErrors = true,
idIns = 'topo-p-instance',
instOpts = {
edge: 'left',
......@@ -102,14 +89,6 @@
// ==========================
function computeDim(self) {
var css = window.getComputedStyle(self);
return {
w: sus.stripPx(css.width),
h: sus.stripPx(css.height)
};
}
function clickInst(d) {
var el = d3.select(this),
aff = el.classed('affinity');
......@@ -139,28 +118,13 @@
oiShowMaster = false;
}
function instRectAttr(dim) {
var pad = instCfg.rectPad;
return {
x: pad,
y: pad,
width: dim.w - pad*2,
height: dim.h - pad*2,
rx: 6
};
}
function viewBox(dim) {
return '0 0 ' + dim.w + ' ' + dim.h;
}
function attachUiBadge(svg) {
gs.addGlyph(svg, 'uiAttached', 24, true, [28, instCfg.uiDy])
gs.addGlyph(svg, 'uiAttached', 24, true, [14, 54])
.classed('badgeIcon uiBadge', true);
}
function attachReadyBadge(svg) {
gs.addGlyph(svg, 'checkMark', 16, true, [12, instCfg.uiDy + 4])
gs.addGlyph(svg, 'checkMark', 16, true, [18, 40])
.classed('badgeIcon readyBadge', true);
}
......@@ -171,24 +135,50 @@
// ==============================
function updateInstances() {
var rox = 5,
roy = 5,
rw = 160,
rhh = 30,
rbh = 45,
tx = 48,
instSvg = {
width: 170,
height: 85,
viewBox: '0 0 170 85'
},
headRect = {
x: rox,
y: roy,
width: rw,
height: rhh
},
bodyRect = {
x: rox,
y: roy + rhh,
width: rw,
height: rbh
},
titleAttr = {
class: 'instTitle',
x: tx,
y: 27
};
var onoses = oiBox.el().selectAll('.onosInst')
.data(onosOrder, function (d) { return d.id; }),
instDim = {w:0,h:0},
c = instCfg;
.data(onosOrder, function (d) { return d.id; });
function nSw(n) {
return '# Switches: ' + n;
return 'Switches: ' + n;
}
// operate on existing onos instances if necessary
onoses.each(function (d) {
var el = d3.select(this),
svg = el.select('svg');
instDim = computeDim(this);
// update online state
el.classed('online', d.online);
el.classed('notReady', !d.ready);
el.classed('ready', d.ready);
// update ui-attached state
svg.select('use.uiBadge').remove();
......@@ -196,8 +186,6 @@
attachUiBadge(svg);
}
attachReadyBadge(svg, d.ready);
function updAttr(id, value) {
svg.select('text.instLabel.'+id).text(value);
}
......@@ -210,59 +198,39 @@
// operate on new onos instances
var entering = onoses.enter()
.append('div')
.attr('class', 'onosInst')
.classed('onosInst', true)
.classed('online', function (d) { return d.online; })
.classed('notReady', function (d) { return !d.ready; })
.classed('ready', function (d) { return d.ready; })
.on('click', clickInst);
entering.each(function (d) {
var el = d3.select(this),
rectAttr,
svg;
instDim = computeDim(this);
rectAttr = instRectAttr(instDim);
svg = el.append('svg').attr(instSvg);
svg = el.append('svg').attr({
width: instDim.w,
height: instDim.h,
viewBox: viewBox(instDim)
});
svg.append('rect').attr(headRect);
svg.append('rect').attr(bodyRect);
svg.append('rect').attr(rectAttr);
gs.addGlyph(svg, 'bird', 20, false, [15, 10])
.classed('badgeIcon bird', true);
gs.addGlyph(svg, 'bird', 28, true, [14, 14])
.classed('badgeIcon', true);
attachReadyBadge(svg);
if (d.uiAttached) {
attachUiBadge(svg);
}
attachReadyBadge(svg);
var left = c.nodeOx + c.nodeDim,
len = rectAttr.width - left,
hlen = len / 2,
midline = hlen + left;
// title
svg.append('text')
.attr({
class: 'instTitle',
x: midline,
y: c.titleDy
})
.attr(titleAttr)
.text(d.id);
// a couple of attributes
var ty = c.titleDy + c.textYOff;
var ty = 55;
function addAttr(id, label) {
svg.append('text').attr({
class: 'instLabel ' + id,
x: midline,
x: tx,
y: ty
}).text(label);
ty += c.textYSpc;
ty += 18;
}
addAttr('ip', d.ip);
......@@ -279,8 +247,8 @@
});
// adjust the panel size appropriately...
oiBox.width(instDim.w * onosOrder.length);
oiBox.height(instDim.h);
oiBox.width(instSvg.width * onosOrder.length);
oiBox.height(instSvg.height);
// remove any outgoing instances
onoses.exit().remove();
......
......@@ -89,7 +89,8 @@ describe('factory: fw/svg/glyph.js', function() {
diamond: 'M.2,.5'
},
glyphIds = [
'unknown', 'node', 'switch', 'roadm', 'endstation', 'router',
'unknown', 'uiAttached',
'node', 'switch', 'roadm', 'endstation', 'router',
'bgpSpeaker', 'chain', 'crown', 'lock', 'topo', 'refresh',
'garbage',
'flowTable', 'portTable', 'groupTable',
......@@ -98,7 +99,7 @@ describe('factory: fw/svg/glyph.js', function() {
'prevIntent', 'intentTraffic', 'allTraffic', 'flows', 'eqMaster'
],
badgeIds = [
'uiAttached', 'checkMark', 'xMark', 'triangleUp', 'triangleDown',
'checkMark', 'xMark', 'triangleUp', 'triangleDown',
'plus', 'minus', 'play', 'stop'
],
spriteIds = [
......
......@@ -153,39 +153,40 @@ describe('factory: fw/svg/svgUtil.js', function() {
])).toBeTruthy();
});
it('should provide a certain shade of blue', function () {
expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#3E5780');
it('should provide blue', function () {
expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#5b99d2');
});
it('should not matter what the ID really is for shade of blue', function () {
expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#78533B');
it('should provide light blue', function () {
expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#66cef6');
});
it('should provide different shade of blue for muted', function () {
expect(sus.cat7().getColor('foo', true, 'light')).toEqual('#A8B8CC');
it('should provide paler shade of blue for muted', function () {
expect(sus.cat7().getColor('foo', true, 'light')).toEqual('#a8cceb');
});
it('should provide an alternate (dark) shade of blue', function () {
expect(sus.cat7().getColor('foo', false, 'dark')).toEqual('#304860');
// TODO: dark theme required
xit('should provide an alternate (dark) shade of blue', function () {
expect(sus.cat7().getColor('foo', false, 'dark')).toEqual('#5b99d2');
});
it('should provide an alternate (dark) shade of blue for muted', function () {
expect(sus.cat7().getColor('foo', true, 'dark')).toEqual('#304860');
// TODO: dark theme required
xit('should provide an alternate (dark) shade of blue for muted', function () {
expect(sus.cat7().getColor('foo', true, 'dark')).toEqual('#a8cceb');
});
it('should iterate across the colors', function () {
expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#3E5780');
expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#78533B');
expect(sus.cat7().getColor('baz', false, 'light')).toEqual('#CB4D28');
expect(sus.cat7().getColor('goo', false, 'light')).toEqual('#018D61');
expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#8A2979');
expect(sus.cat7().getColor('pip', false, 'light')).toEqual('#006D73');
expect(sus.cat7().getColor('sdh', false, 'light')).toEqual('#56AF00');
expect(sus.cat7().getColor('foo', false, 'light')).toEqual('#5b99d2');
expect(sus.cat7().getColor('bar', false, 'light')).toEqual('#66cef6');
expect(sus.cat7().getColor('baz', false, 'light')).toEqual('#d05a55');
expect(sus.cat7().getColor('goo', false, 'light')).toEqual('#db7773');
expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#716b6b');
expect(sus.cat7().getColor('pip', false, 'light')).toEqual('#aeada8');
expect(sus.cat7().getColor('sdh', false, 'light')).toEqual('#7e9aa8');
// and cycle back to the first color for item #8
expect(sus.cat7().getColor('bri', false, 'light')).toEqual('#3E5780');
expect(sus.cat7().getColor('bri', false, 'light')).toEqual('#5b99d2');
// and return the same color for the same ID
expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#8A2979');
expect(sus.cat7().getColor('zoo', false, 'light')).toEqual('#716b6b');
});
// === translate(), scale(), skewX(), rotate()
......
......@@ -7,7 +7,7 @@
"lastAuto": 29
},
"description": [
"Press '=' to load initial events.",
"Press '-' to fire further events."
"Press 'a' to load initial events.",
"Press 'n' to fire further events."
]
}
......
{
"event": "updateInstance",
"payload": {
"id": "222.222.222.222",
"ip": "222.222.222.222",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-6",
"ip": "192.168.224.126",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-5",
"ip": "192.168.56.105",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-4",
"ip": "192.168.56.104",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-3",
"ip": "192.168.56.103",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-2",
"ip": "192.168.56.102",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "updateInstance",
"payload": {
"id": "192.168.56.101",
"ip": "192.168.56.101",
"online": false,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "addInstance",
"payload": {
"id": "192.168.56.101",
"ip": "192.168.56.101",
"online": true,
"ready": true,
"uiAttached": true,
"switches": 4
}
}
{
"event": "addInstance",
"payload": {
"id": "ONOS-2",
"ip": "192.168.56.102",
"online": true,
"ready": true,
"uiAttached": false,
"switches": 3
}
}
{
"event": "addInstance",
"payload": {
"id": "ONOS-3",
"ip": "192.168.56.103",
"online": true,
"ready": false,
"uiAttached": false,
"switches": 3
}
}
{
"event": "addInstance",
"payload": {
"id": "ONOS-4",
"ip": "192.168.56.104",
"online": true,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "addInstance",
"payload": {
"id": "ONOS-5",
"ip": "192.168.56.105",
"online": true,
"ready": false,
"uiAttached": false,
"switches": 17
}
}
{
"event": "addInstance",
"payload": {
"id": "ONOS-6",
"ip": "192.168.224.126",
"online": true,
"ready": false,
"uiAttached": false,
"switches": 0
}
}
{
"event": "addInstance",
"payload": {
"id": "222.222.222.222",
"ip": "222.222.222.222",
"online": true,
"ready": false,
"uiAttached": false,
"switches": 6
}
}
{
"event": "updateInstance",
"payload": {
"id": "192.168.56.101",
"ip": "192.168.56.101",
"online": true,
"ready": true,
"uiAttached": false,
"switches": 3
}
}
{
"event": "updateInstance",
"payload": {
"id": "ONOS-3",
"ip": "192.168.56.103",
"online": true,
"ready": true,
"uiAttached": true,
"switches": 3
}
}
{
"comments": [
"Tweaking Mojo Colors"
],
"title": "Color-Tweaking Scenario for Mojo Palette",
"params": {
"lastAuto": 7
},
"description": [
"Press 'a' to load initial events.",
"Press 'n' to fire further events."
]
}