Improves host details panel UI

* Hooks up the first two context menu buttons
* Makes the rename and details menu show up
    wherever the user's cursor's location
* Adds TopologyInventory and DeviceHost tables
* Adds design for host_id on the Device table
* Adds migrations for TopologyInventory
* Adds host_id to Device table
* Adds inventory_id and host_id tracking
* Auto-closes the right hand panel if focus is directed to the canvas.
* Retrieves the host details on inventory load.
* Adds back support for inventory and host_id tracking
* Adds host icon
* Changes rack icon to new icon
* Site icon replacement
* Fixes host icon "hitbox", and adding debug and construction
* Adds construction and debug lines for switch, router, rack, and site
* Adds some error handling for REST calls, as well as alert on
    host detail panel.
This commit is contained in:
Jared Tabor
2018-01-03 17:43:44 -08:00
committed by Ben Thomasson
parent 1c1844d889
commit 050f43e3bf
23 changed files with 1034 additions and 704 deletions

View File

@@ -34,9 +34,11 @@ from awx.network_ui.models import ToolboxItem
from awx.network_ui.models import FSMTrace from awx.network_ui.models import FSMTrace
from awx.network_ui.models import TopologyInventory
class DeviceAdmin(admin.ModelAdmin): class DeviceAdmin(admin.ModelAdmin):
fields = ('topology', 'name', 'x', 'y', 'id', 'type', 'interface_id_seq', 'process_id_seq',) fields = ('topology', 'name', 'x', 'y', 'id', 'type', 'interface_id_seq', 'process_id_seq', 'host_id',)
raw_id_fields = ('topology',) raw_id_fields = ('topology',)
@@ -169,3 +171,11 @@ class FSMTraceAdmin(admin.ModelAdmin):
admin.site.register(FSMTrace, FSMTraceAdmin) admin.site.register(FSMTrace, FSMTraceAdmin)
class TopologyInventoryAdmin(admin.ModelAdmin):
fields = ('topology', 'inventory_id',)
raw_id_fields = ('topology',)
admin.site.register(TopologyInventory, TopologyInventoryAdmin)

View File

@@ -9,13 +9,12 @@ from awx.network_ui.models import DataSheet, DataBinding, DataType
from awx.network_ui.models import Process, Stream from awx.network_ui.models import Process, Stream
from awx.network_ui.models import Toolbox, ToolboxItem from awx.network_ui.models import Toolbox, ToolboxItem
from awx.network_ui.models import FSMTrace from awx.network_ui.models import FSMTrace
from awx.network_ui.serializers import yaml_serialize_topology from awx.network_ui.models import TopologyInventory
from awx.network_ui.messages import MultipleMessage, InterfaceCreate, LinkCreate, to_dict from awx.network_ui.messages import MultipleMessage, InterfaceCreate, LinkCreate, to_dict
import urlparse import urlparse
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q from django.db.models import Q
from collections import defaultdict from collections import defaultdict
from django.conf import settings
import math import math
import random import random
import logging import logging
@@ -249,8 +248,19 @@ def parse_topology_id(data):
return topology_id return topology_id
def parse_inventory_id(data):
inventory_id = data.get('inventory_id', ['null'])
try:
inventory_id = int(inventory_id[0])
except ValueError:
inventory_id = None
if not inventory_id:
inventory_id = None
return inventory_id
# Persistence # Persistence
class _Persistence(object): class _Persistence(object):
def handle(self, message): def handle(self, message):
@@ -270,7 +280,7 @@ class _Persistence(object):
message_value = data[1] message_value = data[1]
try: try:
message_type_id = MessageType.objects.get(name=message_type).pk message_type_id = MessageType.objects.get(name=message_type).pk
except ObjectDoesNotExist, e: except ObjectDoesNotExist:
logger.warning("Unsupported message %s", message_type) logger.warning("Unsupported message %s", message_type)
return return
TopologyHistory(topology_id=topology_id, TopologyHistory(topology_id=topology_id,
@@ -292,11 +302,15 @@ class _Persistence(object):
y='y', y='y',
name='name', name='name',
type='type', type='type',
id='id'), device) id='id',
host_id='host_id'), device)
logger.info("Device %s", device)
print ("Device %s" % device)
d, _ = Device.objects.get_or_create(topology_id=topology_id, id=device['id'], defaults=device) d, _ = Device.objects.get_or_create(topology_id=topology_id, id=device['id'], defaults=device)
d.x = device['x'] d.x = device['x']
d.y = device['y'] d.y = device['y']
d.type = device['type'] d.type = device['type']
d.host_id = device['host_id']
d.save() d.save()
(Topology.objects (Topology.objects
.filter(topology_id=topology_id, device_id_seq__lt=device['id']) .filter(topology_id=topology_id, device_id_seq__lt=device['id'])
@@ -516,13 +530,13 @@ class _Persistence(object):
GroupDeviceMap.objects.bulk_create(new_entries) GroupDeviceMap.objects.bulk_create(new_entries)
def onFSMTrace(self, message_value, diagram_id, client_id): def onFSMTrace(self, message_value, diagram_id, client_id):
FSMTrace(trace_session_id=message_value['trace_id'], FSMTrace(trace_session_id=message_value['trace_id'],
fsm_name=message_value['fsm_name'], fsm_name=message_value['fsm_name'],
from_state=message_value['from_state'], from_state=message_value['from_state'],
to_state=message_value['to_state'], to_state=message_value['to_state'],
order=message_value['order'], order=message_value['order'],
client_id=client_id, client_id=client_id,
message_type=message_value['recv_message_type'] or "none").save() message_type=message_value['recv_message_type'] or "none").save()
persistence = _Persistence() persistence = _Persistence()
@@ -777,9 +791,19 @@ def ansible_disconnect(message):
def ws_connect(message): def ws_connect(message):
# Accept connection # Accept connection
data = urlparse.parse_qs(message.content['query_string']) data = urlparse.parse_qs(message.content['query_string'])
topology_id = parse_topology_id(data) inventory_id = parse_inventory_id(data)
topology, created = Topology.objects.get_or_create( topology_ids = list(TopologyInventory.objects.filter(inventory_id=inventory_id).values_list('topology_id', flat=True))
topology_id=topology_id, defaults=dict(name="topology", scale=1.0, panX=0, panY=0)) print ("topology_ids", topology_ids)
topology_id = 0
if len(topology_ids) > 0:
topology_id = topology_ids[0]
print ("topology_id", topology_id)
if topology_id:
topology = Topology.objects.get(topology_id=topology_id)
else:
topology = Topology(name="topology", scale=1.0, panX=0, panY=0)
topology.save()
TopologyInventory(inventory_id=inventory_id, topology_id=topology.topology_id).save()
topology_id = topology.topology_id topology_id = topology.topology_id
message.channel_session['topology_id'] = topology_id message.channel_session['topology_id'] = topology_id
Group("topology-%s" % topology_id).add(message.reply_channel) Group("topology-%s" % topology_id).add(message.reply_channel)
@@ -903,6 +927,7 @@ def console_printer(message):
# Tester channel events # Tester channel events
@channel_session @channel_session
def tester_connect(message): def tester_connect(message):
data = urlparse.parse_qs(message.content['query_string']) data = urlparse.parse_qs(message.content['query_string'])

View File

@@ -28,6 +28,9 @@ models:
- default: 0 - default: 0
name: process_id_seq name: process_id_seq
type: IntegerField type: IntegerField
- default: 0
name: host_id
type: IntegerField
name: Device name: Device
x: 348 x: 348
y: 124 y: 124
@@ -153,8 +156,8 @@ models:
- name: id - name: id
type: IntegerField type: IntegerField
name: Interface name: Interface
x: 600 x: 1157
y: 243 y: 337
- fields: - fields:
- name: group_id - name: group_id
pk: true pk: true
@@ -349,8 +352,21 @@ models:
name: FSMTrace name: FSMTrace
x: -872 x: -872
y: 507 y: 507
- fields:
- name: topology_inventory_id
pk: true
type: AutoField
- name: topology
ref: Topology
ref_field: topology_id
type: ForeignKey
- name: inventory_id
type: IntegerField
name: TopologyInventory
x: -226
y: -19
modules: [] modules: []
view: view:
panX: 213.72955551921206 panX: 213.729555519212
panY: 189.44695909464298 panY: 189.446959094643
scaleXY: 0.6900000000000002 scaleXY: 0.69

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('network_ui', '0024_auto_20171213_1949'),
]
operations = [
migrations.CreateModel(
name='DeviceHost',
fields=[
('device_host_id', models.AutoField(serialize=False, primary_key=True)),
('host_id', models.IntegerField()),
('device', models.ForeignKey(to='network_ui.Device')),
],
),
migrations.CreateModel(
name='TopologyInventory',
fields=[
('topology_inventory_id', models.AutoField(serialize=False, primary_key=True)),
('inventory_id', models.IntegerField()),
('topology', models.ForeignKey(to='network_ui.Topology')),
],
),
]

View File

@@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('network_ui', '0025_devicehost_topologyinventory'),
]
operations = [
migrations.RemoveField(
model_name='devicehost',
name='device',
),
migrations.AddField(
model_name='device',
name='host_id',
field=models.IntegerField(default=0),
),
migrations.DeleteModel(
name='DeviceHost',
),
]

View File

@@ -1,4 +1,3 @@
# Copyright (c) 2017 Red Hat, Inc
from django.db import models from django.db import models
@@ -13,6 +12,7 @@ class Device(models.Model):
type = models.CharField(max_length=200,) type = models.CharField(max_length=200,)
interface_id_seq = models.IntegerField(default=0) interface_id_seq = models.IntegerField(default=0)
process_id_seq = models.IntegerField(default=0) process_id_seq = models.IntegerField(default=0)
host_id = models.IntegerField(default=0)
def __unicode__(self): def __unicode__(self):
return self.name return self.name
@@ -168,3 +168,10 @@ class FSMTrace(models.Model):
client = models.ForeignKey('Client',) client = models.ForeignKey('Client',)
trace_session_id = models.IntegerField(default=0) trace_session_id = models.IntegerField(default=0)
order = models.IntegerField(default=0) order = models.IntegerField(default=0)
class TopologyInventory(models.Model):
topology_inventory_id = models.AutoField(primary_key=True,)
topology = models.ForeignKey('Topology',)
inventory_id = models.IntegerField()

View File

@@ -7,7 +7,7 @@ function NetworkingController (models, $state, $scope, strings) {
vm.strings = strings; vm.strings = strings;
vm.panelTitle = `${strings.get('state.BREADCRUMB_LABEL')} | ${inventory.name}`; vm.panelTitle = `${strings.get('state.BREADCRUMB_LABEL')} | ${inventory.name}`;
vm.hostDetail = {}; vm.hostDetail = false;
vm.panelIsExpanded = false; vm.panelIsExpanded = false;
@@ -19,11 +19,19 @@ function NetworkingController (models, $state, $scope, strings) {
$state.go('inventories'); $state.go('inventories');
}; };
$scope.$on('retrievedHostData', (e, hostData) => { $scope.$on('closeDetailsPanel', () => {
if (!vm.panelIsExpanded) { vm.panelIsExpanded = false;
});
$scope.$on('retrievedHostData', (e, hostData, expand) => {
if (expand) {
vm.panelIsExpanded = true; vm.panelIsExpanded = true;
} }
$scope.hostDetail = hostData; if (_.isEmpty(hostData)) {
$scope.hostDetail = false;
} else {
$scope.hostDetail = hostData;
}
}); });
} }

View File

@@ -26,73 +26,84 @@
</div> </div>
</div> </div>
</div> </div>
<div class="Networking-panels"> <div class="Networking-panels">
<div class="Networking-leftPanel"> <div class="Networking-leftPanel">
<awx-network-ui></awx-network-ui> <awx-network-ui></awx-network-ui>
</div> </div>
<div class="Networking-rightPanel" ng-show="vm.panelIsExpanded"> <div class="Networking-rightPanel" ng-show="vm.panelIsExpanded">
<!-- VIEW LAYERS -->
<!--beginning of header--> <div ng-if="hostDetail===false">
<div class="Networking-panelHeader"> NO HOST DETAIL
<div class="JobResults-panelHeaderText" translate="">DETAILS</div>
<!-- LEFT PANE HEADER ACTIONS -->
<!-- <div> -->
<!-- RELAUNCH ACTION -->
<!-- <button class="List-actionButton" data-placement="top" mode="all" ng-click="relaunchJob()" aw-tool-tip="Relaunch using the same parameters" data-original-title="" title="">
<i class="icon-launch"></i>
</button> -->
<!-- CANCEL ACTION -->
<!-- <button class="List-actionButton List-actionButton--delete ng-hide" data-placement="top" ng-click="cancelJob()" ng-show="job_status == 'running' ||
job_status=='pending' " aw-tool-tip="Cancel" data-original-title="" title="">
<i class="fa fa-minus-circle"></i>
</button> -->
<!-- DELETE ACTION -->
<!-- <button class="List-actionButton
List-actionButton--delete" data-placement="top" ng-click="deleteJob()" ng-hide="job_status == 'running' ||
job_status == 'pending' || !job.summary_fields.user_capabilities.delete" aw-tool-tip="Delete" data-original-title="" title="">
<i class="fa fa-trash-o"></i>
</button>
</div> -->
</div> </div>
<!--end of header-->
<!--beginning of name row -->
<div class="JobResults-resultRow"> <div ng-if="hostDetail!==false">
<label class="JobResults-resultRowLabel" translate="">Name</label> <!--beginning of header-->
<div class="JobResults-resultRowText"> <div class="Networking-panelHeader">
{{hostDetail.name}} <div class="JobResults-panelHeaderText" translate="">
DETAILS
</div>
</div>
<!--end of header-->
<!--beginning of name row -->
<div class="JobResults-resultRow">
<label class="JobResults-resultRowLabel" translate="">
Name
</label>
<div class="JobResults-resultRowText">
{{hostDetail.name}}
</div>
</div> </div>
<!--end of name row -->
<!-- beginning of extra variable row -->
<div class="JobResults-resultRow JobResults-resultRow--variables" ng-show="hostDetail.variables">
<label class="JobResults-resultRowLabel JobResults-resultRowLabel--fullWidth">
<span translate>
Extra Variables
</span>
<i class="JobResults-extraVarsHelp fa fa-question-circle"
aw-tool-tip="{{'Read only view of extra variables added to the job template.' | translate}}"
data-placement="top">
</i>
</label>
<textarea
rows="6"
ng-model="hostDetail.variables"
name="variables"
class="form-control Form-textArea Form-textAreaLabel Form-formGroup--fullWidth"
id="pre-formatted-variables"
disabled="disabled">
</textarea>
</div>
<!-- end of extra variable row -->
</div> </div>
<!--end of name row --> </div>
</div>
<!-- beginning of extra variable row --> <!--end of Networking-rightPanel -->
<div class="JobResults-resultRow
JobResults-resultRow--variables"
ng-show="hostDetail.variables">
<label class="JobResults-resultRowLabel <div id="alert-modal" class="modal fade">
JobResults-resultRowLabel--fullWidth"> <div class="modal-dialog">
<span translate> Extra Variables </span> <div class="modal-content">
<i class="JobResults-extraVarsHelp fa fa-question-circle" <div class="modal-header">
aw-tool-tip="{{'Read only view of extra variables added to the job template.' | translate}}" <button type="button" class="close" ng-hide="disableButtons" data-target="#alert-modal" data-dismiss="modal" class="modal" aria-hidden="true"><i class="fa fa-times-circle"></i></button>
data-placement="top"> <h3 id="alertHeader" ng-bind="alertHeader"></h3>
</i> </div>
</label> <div class="modal-body">
<textarea <div id="alert-modal-msg" class="alert" ng-bind-html="alertBody"></div>
rows="6" </div>
ng-model="hostDetail.variables" <div class="modal-footer">
name="variables" <a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-default" translate>OK</a>
class="form-control Form-textArea Form-textAreaLabel Form-formGroup--fullWidth" </div>
id="pre-formatted-variables" </div>
disabled="disabled"> <!-- modal-content -->
</textarea> </div>
</div> <!-- modal-dialog -->
<!-- end of extra variable row -->
</div><!--end of Networking-rightPanel -->
</div> </div>

View File

@@ -1,60 +1,87 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<g ng-if="item.moving"> <!-- vertical line -->
<line ng-attr-x1="{{-50 - 100}}" <line x1="0"
ng-attr-y1="0" y1="-150"
ng-attr-x2="{{50 + 100}}" x2="0"
ng-attr-y2="0" y2="150"
class="NetworkUI--construction"></line> class="NetworkUI--construction">
<line ng-attr-x1="0" </line>
ng-attr-y1="{{-15 - 100}}" <!-- end vertical line -->
ng-attr-x2="0" </g>
ng-attr-y2="{{15 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden"> <g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}" <!--horizontal line -->
ng-attr-y1="0" <line x1="-60"
ng-attr-x2="{{50 + 10}}" y1="0"
ng-attr-y2="0" x2="60"
class="NetworkUI--debug"></line> y2="0"
<line ng-attr-x1="0" class="NetworkUI--debug">
ng-attr-y1="{{-15 - 10}}" </line>
ng-attr-x2="0" <!-- end horizontal line -->
ng-attr-y2="{{15 + 10}}"
class="NetworkUI--debug"></line> <!-- vertical line -->
<rect ng-attr-x="{{-50}}" <line x1="0"
ng-attr-y="{{-15}}" y1="-40"
ng-attr-width="{{50 * 2}}" x2="0"
ng-attr-height="{{15 * 2}}" y2="40"
class="NetworkUI--debug"></rect> class="NetworkUI--debug">
</g> </line>
<g class="NetworkUI__host"> <!-- end vertical line -->
<rect
x="-52" <!-- debug rectangle -->
y="-17" <rect x="-50"
ng-attr-width="{{100 + 4}}" y="-30"
ng-attr-height="{{30 + 4}}" width="100"
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__host--selected-conflict' : item.selected ? 'NetworkUI__host--selected' : 'NetworkUI__host--remote-selected' : 'NetworkUI--hidden'}}" height="60"
rx=10> class="NetworkUI--debug">
</rect> </rect>
<rect <!-- end debug rectangle -->
x="-50" </g>
y="-15" <g transform="translate(-50,-30)">
ng-attr-width="{{100}}" <rect
ng-attr-height="{{30}}" ry=15
rx=10> rx=15
</rect> width=100
<circle cx="30" cy="0" r=7 /> height=60
</circle> ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__host--selected-conflict' : item.selected ? 'NetworkUI__host--selected' : 'NetworkUI__host--remote-selected' : 'NetworkUI__host--background'}}">
</g> </rect>
<g ng-show="item.icon || current_scale > 0.5"> <g transform="scale(2)">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__host-text--selected' : 'NetworkUI--hidden'}}" <path
filter="url(#selected)" class="NetworkUI__host"
text-anchor="middle" d="M17.8,14.7c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,14.7,17.8,14.7z"/>
x="0" <path
y="5"> {{item.name}} </text> class="NetworkUI__host"
<text class="NetworkUI__host-text" text-anchor="middle" x="0" y="5">{{item.name}}{{item.edit_label?'_':''}}</text> d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v11.5C0,25.8,4.2,30,9.2,30h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
</g> C50,4.2,45.8,0,40.8,0z M37.8,17.9c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8V13c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8
V17.9z"/>
<path
class="NetworkUI__host"
d="M36,12.5H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
C36.4,12.7,36.3,12.5,36,12.5z M17.8,17.2c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,17.2,17.8,17.2z
M28.2,17.1h-0.9c-0.3,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,16.8,28.6,17.1,28.2,17.1z M28.2,14.9
h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,14.7,28.6,14.9,28.2,14.9z M30.9,17.1H30
c-0.3,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,16.8,31.3,17.1,30.9,17.1z M30.9,14.9H30
c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6S31.3,14.9,30.9,14.9z M33.6,17.1h-0.9
c-0.4,0-0.6-0.2-0.6-0.6s0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,16.8,33.9,17.1,33.6,17.1z M33.6,14.9h-0.9
c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,14.7,33.9,14.9,33.6,14.9z"/>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__host-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
x="-25"
y="50"> {{item.name}}
</text>
<text class="NetworkUI__host-text" x="-25" y="50">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@@ -17,7 +17,7 @@ function DeviceMove(sender, id, x, y, previous_x, previous_y) {
} }
exports.DeviceMove = DeviceMove; exports.DeviceMove = DeviceMove;
function DeviceCreate(sender, id, x, y, name, type) { function DeviceCreate(sender, id, x, y, name, type, host_id) {
this.msg_type = "DeviceCreate"; this.msg_type = "DeviceCreate";
this.sender = sender; this.sender = sender;
this.id = id; this.id = id;
@@ -25,10 +25,11 @@ function DeviceCreate(sender, id, x, y, name, type) {
this.y = y; this.y = y;
this.name = name; this.name = name;
this.type = type; this.type = type;
this.host_id = host_id;
} }
exports.DeviceCreate = DeviceCreate; exports.DeviceCreate = DeviceCreate;
function DeviceDestroy(sender, id, previous_x, previous_y, previous_name, previous_type) { function DeviceDestroy(sender, id, previous_x, previous_y, previous_name, previous_type, previous_host_id) {
this.msg_type = "DeviceDestroy"; this.msg_type = "DeviceDestroy";
this.sender = sender; this.sender = sender;
this.id = id; this.id = id;
@@ -36,6 +37,7 @@ function DeviceDestroy(sender, id, previous_x, previous_y, previous_name, previo
this.previous_y = previous_y; this.previous_y = previous_y;
this.previous_name = previous_name; this.previous_name = previous_name;
this.previous_type = previous_type; this.previous_type = previous_type;
this.previous_host_id = previous_host_id;
} }
exports.DeviceDestroy = DeviceDestroy; exports.DeviceDestroy = DeviceDestroy;

View File

@@ -4,12 +4,13 @@ var button = require('./button.js');
var util = require('./util.js'); var util = require('./util.js');
var inherits = require('inherits'); var inherits = require('inherits');
function Device(id, name, x, y, type) { function Device(id, name, x, y, type, host_id) {
this.id = id; this.id = id;
this.host_id = host_id ? host_id: 0;
this.name = name; this.name = name;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.height = type === "host" ? 15 : 50; this.height = type === "host" ? 30 : 50;
this.width = 50; this.width = 50;
this.size = 50; this.size = 50;
this.type = type; this.type = type;
@@ -374,9 +375,9 @@ function ContextMenu(name, x, y, width, height, callback, enabled, buttons, trac
this.callback = callback; this.callback = callback;
this.is_pressed = false; this.is_pressed = false;
this.mouse_over = false; this.mouse_over = false;
this.enabled = enabled; this.enabled = false;
this.buttons = buttons; this.buttons = buttons;
this.fsm = new fsm.FSMController(this, "button_fsm", button.Start, tracer); this.fsm = new fsm.FSMController(this, "button_fsm", enabled ? button.Start : button.Disabled, tracer);
} }
exports.ContextMenu = ContextMenu; exports.ContextMenu = ContextMenu;

View File

@@ -76,6 +76,14 @@ var Placing = new _Placing();
exports.Placing = Placing; exports.Placing = Placing;
function _ContextMenu () {
this.name = 'ContextMenu';
}
inherits(_ContextMenu, _State);
var ContextMenu = new _ContextMenu();
exports.ContextMenu = ContextMenu;
_State.prototype.onUnselectAll = function (controller, msg_type, $event) { _State.prototype.onUnselectAll = function (controller, msg_type, $event) {
controller.changeState(Ready); controller.changeState(Ready);
@@ -135,7 +143,8 @@ _Ready.prototype.onNewDevice = function (controller, msg_type, message) {
device.x, device.x,
device.y, device.y,
device.name, device.name,
device.type)); device.type,
device.host_id));
scope.selected_devices.push(device); scope.selected_devices.push(device);
device.selected = true; device.selected = true;
controller.changeState(Placing); controller.changeState(Placing);
@@ -161,14 +170,16 @@ _Ready.prototype.onPasteDevice = function (controller, msg_type, message) {
message.device.name, message.device.name,
scope.scaledX, scope.scaledX,
scope.scaledY, scope.scaledY,
message.device.type); message.device.type,
message.device.host_id);
scope.devices.push(device); scope.devices.push(device);
c_messages.push(new messages.DeviceCreate(scope.client_id, c_messages.push(new messages.DeviceCreate(scope.client_id,
device.id, device.id,
device.x, device.x,
device.y, device.y,
device.name, device.name,
device.type)); device.type,
device.host_id));
for (i=0; i < message.device.interfaces.length; i++) { for (i=0; i < message.device.interfaces.length; i++) {
intf = new models.Interface(message.device.interfaces[i].id, message.device.interfaces[i].name); intf = new models.Interface(message.device.interfaces[i].id, message.device.interfaces[i].name);
device.interfaces.push(intf); device.interfaces.push(intf);
@@ -331,7 +342,8 @@ _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) {
devices[i].x, devices[i].x,
devices[i].y, devices[i].y,
devices[i].name, devices[i].name,
devices[i].type)); devices[i].type,
devices[i].host_id));
} }
for (j = 0; j < all_links.length; j++) { for (j = 0; j < all_links.length; j++) {
if (all_links[j].to_device === devices[i] || if (all_links[j].to_device === devices[i] ||
@@ -457,10 +469,20 @@ _Move.prototype.onMouseDown = function (controller) {
}; };
_Move.prototype.onMouseDown.transitions = ['Selected1']; _Move.prototype.onMouseDown.transitions = ['Selected1'];
_Selected3.prototype.onMouseUp = function (controller) { _Selected3.prototype.onMouseUp = function (controller, msg_type, $event) {
controller.changeState(EditLabel); let context_menu = controller.scope.context_menus[0];
context_menu.enabled = true;
context_menu.x = $event.x;
context_menu.y = $event.y;
context_menu.buttons.forEach(function(button, index){
button.x = $event.x;
let menuPaddingTop = 5;
button.y = $event.y + menuPaddingTop + (button.height * index);
});
controller.changeState(ContextMenu);
}; };
_Selected3.prototype.onMouseUp.transitions = ['EditLabel']; _Selected3.prototype.onMouseUp.transitions = ['ContextMenu'];
_Selected3.prototype.onTouchEnd = function (controller) { _Selected3.prototype.onTouchEnd = function (controller) {
controller.changeState(Selected2); controller.changeState(Selected2);
@@ -545,3 +567,21 @@ _Placing.prototype.onMouseMove = function (controller) {
_Placing.prototype.onMouseMove.transitions = ['Move']; _Placing.prototype.onMouseMove.transitions = ['Move'];
_ContextMenu.prototype.onLabelEdit = function (controller) {
controller.changeState(EditLabel);
};
_ContextMenu.prototype.onLabelEdit.transitions = ['EditLabel'];
_ContextMenu.prototype.onMouseDown = function (controller) {
var item = controller.scope.context_menus[0];
item.enabled = false;
controller.changeState(Ready);
};
_ContextMenu.prototype.onMouseDown.transitions = ['Ready'];

View File

@@ -21,7 +21,8 @@ var messages = require('./messages.js');
var svg_crowbar = require('./svg-crowbar.js'); var svg_crowbar = require('./svg-crowbar.js');
var ReconnectingWebSocket = require('reconnectingwebsocket'); var ReconnectingWebSocket = require('reconnectingwebsocket');
var NetworkUIController = function($scope, $document, $location, $window, $http, $q) { var NetworkUIController = function($scope, $document, $location, $window, $http,
$q, $state, ProcessErrors) {
window.scope = $scope; window.scope = $scope;
var i = 0; var i = 0;
@@ -31,16 +32,16 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.api_token = ''; $scope.api_token = '';
$scope.disconnected = false; $scope.disconnected = false;
$scope.topology_id = $location.search().topology_id || 0; $scope.topology_id = 0;
// Create a web socket to connect to the backend server // Create a web socket to connect to the backend server
//
$scope.inventory_id = $location.search().inventory_id || 1; $scope.inventory_id = $state.params.inventory_id;
$scope.initial_messages = []; $scope.initial_messages = [];
if (!$scope.disconnected) { if (!$scope.disconnected) {
$scope.control_socket = new ReconnectingWebSocket("wss://" + window.location.host + "/network_ui/topology?topology_id=" + $scope.topology_id, $scope.control_socket = new ReconnectingWebSocket("wss://" + window.location.host + "/network_ui/topology?inventory_id=" + $scope.inventory_id,
null, null,
{debug: false, reconnectInterval: 300}); {debug: false, reconnectInterval: 300});
} else { } else {
$scope.control_socket = { $scope.control_socket = {
on_message: util.noop on_message: util.noop
@@ -170,42 +171,27 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
} }
$scope.inventory_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope); $scope.inventory_toolbox_controller = new fsm.FSMController($scope, "toolbox_fsm", toolbox_fsm.Start, $scope);
function add_host (host) {
console.log(host);
var device = new models.Device(0, host.data.name, 0, 0, host.data.type);
device.icon = true;
$scope.inventory_toolbox.items.push(device);
}
//Inventory Toolbox Setup //Inventory Toolbox Setup
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, 40, 200, $scope.graph.height - 40); $scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, 40, 200, $scope.graph.height - 40);
if (!$scope.disconnected) { if (!$scope.disconnected) {
console.log($location.protocol() + "://" + $location.host() + ':' + $location.port()); console.log($location.protocol() + "://" + $location.host() + ':' + $location.port());
console.log($scope.my_location); console.log($scope.my_location);
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/?format=json') $http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/')
.then(function(inventory) { .then(function(response) {
console.log(inventory); let hosts = response.data.results;
console.log(inventory.headers()); for(var i = 0; i<hosts.length; i++){
let host = hosts[i];
var host = null; console.log(host);
var i = 0; host.data = jsyaml.safeLoad(host.variables);
var httpGets = []; var device = new models.Device(0, host.data.name, 0, 0, host.data.type, host.id, host.variables);
for (i=0; i < inventory.data.results.length;i++) { device.icon = true;
host = inventory.data.results[i]; $scope.inventory_toolbox.items.push(device);
console.log($location.protocol() + "://" + $location.host() + ':' + $location.port());
console.log($scope.my_location);
httpGets.push($http.get('/api/v2/hosts/'+ host.id + '/variable_data/?format=json'));
} }
return httpGets;
}) })
.then(function(httpGets) { .catch(({data, status}) => {
console.log(httpGets); ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
$q.all(httpGets).then(function (results) {
var i = 0;
for (i=0; i < results.length; i++) {
add_host(results[i]);
}
});
}); });
} }
$scope.inventory_toolbox.spacing = 150; $scope.inventory_toolbox.spacing = 150;
@@ -429,7 +415,7 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
// Do not select links if a device was selected // Do not select links if a device was selected
if (last_selected_device === null && last_selected_interface === null) { if (last_selected_device === null && last_selected_interface === null) {
for (i = $scope.links.length - 1; i >= 0; i--) { for (i = $scope.links.length - 1; i >= 0; i--) {
if($scope.links[i].is_selected($scope.scaledX, $scope.scaledY)) { if ($scope.links[i].is_selected($scope.scaledX, $scope.scaledY)) {
$scope.links[i].selected = true; $scope.links[i].selected = true;
$scope.send_control_message(new messages.LinkSelected($scope.client_id, $scope.links[i].id)); $scope.send_control_message(new messages.LinkSelected($scope.client_id, $scope.links[i].id));
last_selected_link = $scope.links[i]; last_selected_link = $scope.links[i];
@@ -638,27 +624,40 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$event.preventDefault(); $event.preventDefault();
}; };
// Conext Menu $scope.$watchCollection('selected_items', function(){
$scope.onDetailsContextButton = function (button) { $scope.onDetailsContextButton(false);
console.log(button.name); });
// Conext Menu Button Handlers
$scope.onDetailsContextButton = function (panelBoolean) {
if (!$scope.disconnected) { if (!$scope.disconnected) {
// this will end up being the id of the host the user clicked on if ($scope.selected_items.length === 1){
let host_id = 1; if ($scope.selected_items[0].host_id === 0){
let url = `/api/v2/hosts/${host_id}/?format=json`; $scope.$emit('retrievedHostData', {}, panelBoolean !== null ? panelBoolean: true);
$http.get(url) }
.then(function(host) { if ($scope.selected_items[0].host_id !== 0){
$scope.$emit('retrievedHostData', host.data); let host_id = $scope.selected_items[0].host_id;
}) let url = `/api/v2/hosts/${host_id}/`;
.catch(function(httpGets) { $http.get(url)
console.log(httpGets); .then(function(response) {
let host = response.data;
}); $scope.$emit('retrievedHostData', host, panelBoolean !== null ? panelBoolean: true);
$scope.context_menus[0].enabled = false;
})
.catch(({data, status}) => {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
});
}
}
} }
};
$scope.onRenameContextButton = function (button) {
$scope.context_menus[0].enabled = false;
$scope.first_channel.send("LabelEdit", {});
}; };
// Button Event Handlers // Button Event Handlers
//
$scope.onToggleToolboxButtonLeft = function (button) { $scope.onToggleToolboxButtonLeft = function (button) {
console.log(button.name); console.log(button.name);
$scope.first_channel.send("ToggleToolbox", {}); $scope.first_channel.send("ToggleToolbox", {});
@@ -771,13 +770,13 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
// Context Menu Buttons // Context Menu Buttons
$scope.context_menu_buttons = [ $scope.context_menu_buttons = [
new models.ContextMenuButton("Edit", 210, 200, 160, 26, $scope.onDetailsContextButton, $scope), new models.ContextMenuButton("Rename", 210, 200, 160, 26, $scope.onRenameContextButton, $scope),
new models.ContextMenuButton("Details", 236, 231, 160, 26, $scope.onDetailsContextButton, $scope) new models.ContextMenuButton("Details", 236, 231, 160, 26, $scope.onDetailsContextButton, $scope)
]; ];
// Context Menus // Context Menus
$scope.context_menus = [ $scope.context_menus = [
new models.ContextMenu('HOST', 210, 200, 160, 64, $scope.contextMenuCallback, true, $scope.context_menu_buttons, $scope) new models.ContextMenu('HOST', 210, 200, 160, 64, $scope.contextMenuCallback, false, $scope.context_menu_buttons, $scope)
]; ];
// Icons // Icons
@@ -976,7 +975,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
data.name, data.name,
data.x, data.x,
data.y, data.y,
data.type); data.type,
data.host_id);
$scope.device_id_seq = util.natural_numbers(data.id); $scope.device_id_seq = util.natural_numbers(data.id);
$scope.devices.push(device); $scope.devices.push(device);
}; };
@@ -1274,7 +1274,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
data.previous_x, data.previous_x,
data.previous_y, data.previous_y,
data.previous_name, data.previous_name,
data.previous_type); data.previous_type,
data.previous_host_id);
$scope.create_device(inverted_data); $scope.create_device(inverted_data);
} }
@@ -1306,7 +1307,6 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.link_id_seq = util.natural_numbers(data.link_id_seq); $scope.link_id_seq = util.natural_numbers(data.link_id_seq);
$scope.group_id_seq = util.natural_numbers(data.group_id_seq); $scope.group_id_seq = util.natural_numbers(data.group_id_seq);
$scope.device_id_seq = util.natural_numbers(data.device_id_seq); $scope.device_id_seq = util.natural_numbers(data.device_id_seq);
$location.search({topology_id: data.topology_id, inventory_id: $scope.inventory_id});
}; };
$scope.onDeviceSelected = function(data) { $scope.onDeviceSelected = function(data) {
@@ -1474,7 +1474,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
device.name, device.name,
device.x, device.x,
device.y, device.y,
device.type); device.type,
device.host_id);
new_device.interface_seq = util.natural_numbers(device.interface_id_seq); new_device.interface_seq = util.natural_numbers(device.interface_id_seq);
new_device.process_id_seq = util.natural_numbers(device.process_id_seq); new_device.process_id_seq = util.natural_numbers(device.process_id_seq);
$scope.devices.push(new_device); $scope.devices.push(new_device);

View File

@@ -135,7 +135,8 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
device.x, device.x,
device.y, device.y,
device.name, device.name,
device.type)); device.type,
device.host_id));
for (j=0; j < message.group.devices[i].interfaces.length; j++) { for (j=0; j < message.group.devices[i].interfaces.length; j++) {
intf = new models.Interface(message.group.devices[i].interfaces[j].id, message.group.devices[i].interfaces[j].name); intf = new models.Interface(message.group.devices[i].interfaces[j].id, message.group.devices[i].interfaces[j].name);
intf.device = device; intf.device = device;

View File

@@ -1,88 +1,118 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="current_scale >= 0.1 && current_scale <= 0.5 && item.type == 'rack'" ng-attr-transform="translate({{item.width()/2}}, {{item.height()/2}})"> <g ng-if="current_scale >= 0.1 && current_scale <= 0.5 && item.type == 'rack'" ng-attr-transform="translate({{item.width()/2}}, {{item.height()/2}})">
<g ng-attr-transform="scale({{1/0.5}})"> <g ng-attr-transform="scale({{1/0.5}})">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<g ng-if="item.moving"> <!-- vertical line -->
<line ng-attr-x1="{{-50 - 100}}" <line x1="0"
ng-attr-y1="0" y1="-150"
ng-attr-x2="{{50 + 100}}" x2="0"
ng-attr-y2="0" y2="150"
class="NetworkUI--construction"></line> class="NetworkUI--construction">
<line ng-attr-x1="0" </line>
ng-attr-y1="{{-15 - 100}}" <!-- end vertical line -->
ng-attr-x2="0" </g>
ng-attr-y2="{{15 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden"> <g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}" <!--horizontal line -->
ng-attr-y1="0" <line x1="-60"
ng-attr-x2="{{50 + 10}}" y1="0"
ng-attr-y2="0" x2="60"
class="NetworkUI--debug"></line> y2="0"
<line ng-attr-x1="0" class="NetworkUI--debug">
ng-attr-y1="{{-50 - 10}}" </line>
ng-attr-x2="0" <!-- end horizontal line -->
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line> <!-- vertical line -->
<rect ng-attr-x="{{-50}}" <line x1="0"
ng-attr-y="{{-50}}" y1="-60"
ng-attr-width="{{50 * 2}}" x2="0"
ng-attr-height="{{50 * 2}}" y2="60"
class="NetworkUI--debug"></rect> class="NetworkUI--debug">
</g> </line>
<rect <!-- end vertical line -->
x="-52"
y="-52" <!-- debug rectangle -->
ng-attr-width="{{100 + 4}}" <rect x="-50"
ng-attr-height="{{100 + 4}}" y="-50"
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__rack--selected-conflict' : item.selected ? 'NetworkUI__rack--selected' : 'NetworkUI__rack--remote-selected' : 'NetworkUI--hidden'}}" width="100"
rx=10> height="100"
</rect> class="NetworkUI--debug">
<g class="NetworkUI__rack"> </rect>
<rect <!-- end debug rectangle -->
x="-50" </g>
y="-50" <g transform="translate(-50,-50)">
ng-attr-width="{{100}}" <rect
ng-attr-height="{{100}}" ry=15
rx=10 rx=15
class="NetworkUI__rack-background"> width=100
</rect> height=100
<rect ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__rack--selected-conflict' : item.selected ? 'NetworkUI__rack--selected' : 'NetworkUI__rack--remote-selected' : 'NetworkUI__rack--background'}}">
x="-50" </rect>
y="-50" <g transform="scale(2)">
ng-attr-width="{{100}}" <path
ng-attr-height="{{30}}" class="NetworkUI__rack"
rx=10> d="M36,31.7H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
</rect> C36.4,31.9,36.3,31.7,36,31.7z M17.8,36.5c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,36.5,17.8,36.5z
<rect M28.2,36.3h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,36,28.6,36.3,28.2,36.3z
x="-50" M28.2,34.2h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,33.9,28.6,34.2,28.2,34.2z
y="-15" M30.9,36.3H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,36,31.3,36.3,30.9,36.3z M30.9,34.2
ng-attr-width="{{100}}" H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,33.9,31.3,34.2,30.9,34.2z M33.6,36.3h-0.9
ng-attr-height="{{30}}" c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,36,33.9,36.3,33.6,36.3z M33.6,34.2h-0.9
rx=10> c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,33.9,33.9,34.2,33.6,34.2z"/>
</rect> <path
<rect class="NetworkUI__rack"
x="-50" d="M17.8,34c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,34,17.8,34z"/>
y="20" <path
ng-attr-width="{{100}}" class="NetworkUI__rack"
ng-attr-height="{{30}}" d="M17.8,14.7c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,14.7,17.8,14.7z"/>
rx=10> <path
</rect> class="NetworkUI__rack"
<circle cx="30" cy="-35" r=7 /> d="M17.8,24.4c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,24.4,17.8,24.4z"/>
<circle cx="30" cy="0" r=7 /> <path
<circle cx="30" cy="35" r=7 /> class="NetworkUI__rack"
</circle> d="M36,22.1H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
</g> C36.4,22.3,36.3,22.1,36,22.1z M17.8,26.9c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9
</g> C19.7,26,18.9,26.9,17.8,26.9z M28.2,26.7h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
<g ng-attr-transform="scale({{1/current_scale}})"> C28.8,26.4,28.6,26.7,28.2,26.7z M28.2,24.5h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'selected' : 'NetworkUI--hidden'}}" C28.8,24.3,28.6,24.5,28.2,24.5z M30.9,26.7H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
filter="url(#selected)" C31.5,26.4,31.3,26.7,30.9,26.7z M30.9,24.5H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
text-anchor="middle" C31.5,24.3,31.3,24.5,30.9,24.5z M33.6,26.7h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
x="0" C34.2,26.4,33.9,26.7,33.6,26.7z M33.6,24.5h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
ng-attr-y="{{180*current_scale}}"> {{item.name}} </text> C34.2,24.3,33.9,24.5,33.6,24.5z"/>
<text class="NetworkUI__rack-text" text-anchor="middle" x="0" ng-attr-y="{{180*current_scale}}">{{item.name}}{{item.edit_label?'_':''}}</text> <path
</g> class="NetworkUI__rack"
d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
C50,4.2,45.8,0,40.8,0z M37.8,37.1c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8v-4.9c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8
V37.1z M37.8,27.5c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8v-4.9c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8V27.5z M37.8,17.9
c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8v-4.9c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8V17.9z"/>
<path
class="NetworkUI__rack"
d="M36,12.5H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
C36.4,12.7,36.3,12.5,36,12.5z M17.8,17.2c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,17.2,17.8,17.2z
M28.2,17.1h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,16.8,28.6,17.1,28.2,17.1z
M28.2,14.9h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,14.7,28.6,14.9,28.2,14.9z
M30.9,17.1H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,16.8,31.3,17.1,30.9,17.1z
M30.9,14.9H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,14.7,31.3,14.9,30.9,14.9z
M33.6,17.1h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,16.8,33.9,17.1,33.6,17.1z
M33.6,14.9h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,14.7,33.9,14.9,33.6,14.9z"/>
</g>
</g>
</g>
<g ng-attr-transform="scale({{1/current_scale}})">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__rack-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
x="-20"
ng-attr-y="{{180*current_scale}}"> {{item.name}}
</text>
<text class="NetworkUI__rack-text" x="-20" ng-attr-y="{{180*current_scale}}">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g> </g>

View File

@@ -1,71 +1,116 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}" <g ng-if="item.moving">
ng-attr-y1="0" <!--horizontal line -->
ng-attr-x2="{{50 + 10}}" <line x1="-150"
ng-attr-y2="0" y1="0"
class="NetworkUI--debug"></line> x2="150"
<line ng-attr-x1="0" y2="0"
ng-attr-y1="{{-50 - 10}}" class="NetworkUI--construction">
ng-attr-x2="0" </line>
ng-attr-y2="{{50 + 10}}" <!-- end horizontal line -->
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}" <!-- vertical line -->
ng-attr-y="{{-50}}" <line x1="0"
ng-attr-width="{{50 * 2}}" y1="-150"
ng-attr-height="{{50 * 2}}" x2="0"
class="NetworkUI--debug"></rect> y2="150"
</g> class="NetworkUI--construction">
<rect </line>
x="-52" <!-- end vertical line -->
y="-52" </g>
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}" <g ng-if="!debug.hidden">
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__rack--selected-conflict' : item.selected ? 'NetworkUI__rack--selected' : 'NetworkUI__rack--remote-selected' : 'NetworkUI--hidden'}}" <!--horizontal line -->
rx=10> <line x1="-60"
</rect> y1="0"
<g class="NetworkUI__rack"> x2="60"
<rect y2="0"
x="-50" class="NetworkUI--debug">
y="-50" </line>
ng-attr-width="{{100}}" <!-- end horizontal line -->
ng-attr-height="{{100}}"
rx=10 <!-- vertical line -->
class="NetworkUI__rack-background"> <line x1="0"
</rect> y1="-60"
<rect x2="0"
x="-50" y2="60"
y="-50" class="NetworkUI--debug">
ng-attr-width="{{100}}" </line>
ng-attr-height="{{30}}" <!-- end vertical line -->
rx=10>
</rect> <!-- debug rectangle -->
<rect <rect x="-50"
x="-50" y="-50"
y="-15" width="100"
ng-attr-width="{{100}}" height="100"
ng-attr-height="{{30}}" class="NetworkUI--debug">
rx=10> </rect>
</rect> <!-- end debug rectangle -->
<rect </g>
x="-50" <g transform="translate(-50,-50)">
y="20" <rect
ng-attr-width="{{100}}" ry=15
ng-attr-height="{{30}}" rx=15
rx=10> width=100
</rect> height=100
<circle cx="30" cy="-35" r=7 /> ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__rack--selected-conflict' : item.selected ? 'NetworkUI__rack--selected' : 'NetworkUI__rack--remote-selected' : 'NetworkUI__rack--background'}}">
<circle cx="30" cy="0" r=7 /> </rect>
<circle cx="30" cy="35" r=7 /> <g transform="scale(2)">
</circle> <path
</g> class="NetworkUI__rack"
<g ng-show="item.icon || current_scale > 0.5"> d="M36,31.7H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'selected' : 'NetworkUI--hidden'}}" C36.4,31.9,36.3,31.7,36,31.7z M17.8,36.5c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,36.5,17.8,36.5z
filter="url(#selected)" M28.2,36.3h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,36,28.6,36.3,28.2,36.3z
text-anchor="middle" M28.2,34.2h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,33.9,28.6,34.2,28.2,34.2z
x="0" M30.9,36.3H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,36,31.3,36.3,30.9,36.3z M30.9,34.2
y="6"> {{item.name}} </text> H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,33.9,31.3,34.2,30.9,34.2z M33.6,36.3h-0.9
<text class="NetworkUI__rack-text" text-anchor="middle" x="0" y="6">{{item.name}}{{item.edit_label?'_':''}}</text> c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,36,33.9,36.3,33.6,36.3z M33.6,34.2h-0.9
</g> c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,33.9,33.9,34.2,33.6,34.2z"/>
<path
class="NetworkUI__rack"
d="M17.8,34c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,34,17.8,34z"/>
<path
class="NetworkUI__rack"
d="M17.8,14.7c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,14.7,17.8,14.7z"/>
<path
class="NetworkUI__rack"
d="M17.8,24.4c-0.3,0-0.6,0.2-0.6,0.6c0,0.3,0.2,0.6,0.6,0.6c0.3,0,0.6-0.2,0.6-0.6S18.1,24.4,17.8,24.4z"/>
<path
class="NetworkUI__rack"
d="M36,22.1H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
C36.4,22.3,36.3,22.1,36,22.1z M17.8,26.9c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9
C19.7,26,18.9,26.9,17.8,26.9z M28.2,26.7h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
C28.8,26.4,28.6,26.7,28.2,26.7z M28.2,24.5h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
C28.8,24.3,28.6,24.5,28.2,24.5z M30.9,26.7H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
C31.5,26.4,31.3,26.7,30.9,26.7z M30.9,24.5H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
C31.5,24.3,31.3,24.5,30.9,24.5z M33.6,26.7h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
C34.2,26.4,33.9,26.7,33.6,26.7z M33.6,24.5h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6
C34.2,24.3,33.9,24.5,33.6,24.5z"/>
<path
class="NetworkUI__rack"
d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
C50,4.2,45.8,0,40.8,0z M37.8,37.1c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8v-4.9c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8
V37.1z M37.8,27.5c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8v-4.9c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8V27.5z M37.8,17.9
c0,1-0.8,1.8-1.8,1.8H14c-1,0-1.8-0.8-1.8-1.8v-4.9c0-1,0.8-1.8,1.8-1.8h22c1,0,1.8,0.8,1.8,1.8V17.9z"/>
<path
class="NetworkUI__rack"
d="M36,12.5H14c-0.3,0-0.4,0.2-0.4,0.4v4.9c0,0.3,0.2,0.4,0.4,0.4h22c0.3,0,0.4-0.2,0.4-0.4v-4.9
C36.4,12.7,36.3,12.5,36,12.5z M17.8,17.2c-1.1,0-1.9-0.9-1.9-1.9c0-1.1,0.9-1.9,1.9-1.9s1.9,0.9,1.9,1.9S18.9,17.2,17.8,17.2z
M28.2,17.1h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,16.8,28.6,17.1,28.2,17.1z
M28.2,14.9h-0.9c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C28.8,14.7,28.6,14.9,28.2,14.9z
M30.9,17.1H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,16.8,31.3,17.1,30.9,17.1z
M30.9,14.9H30c-0.3,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C31.5,14.7,31.3,14.9,30.9,14.9z
M33.6,17.1h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,16.8,33.9,17.1,33.6,17.1z
M33.6,14.9h-0.9c-0.4,0-0.6-0.2-0.6-0.6c0-0.4,0.2-0.6,0.6-0.6h0.9c0.4,0,0.6,0.2,0.6,0.6C34.2,14.7,33.9,14.9,33.6,14.9z"/>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__rack-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
x="-25"
y="70"> {{item.name}}
</text>
<text class="NetworkUI__rack-text" x="-25" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@@ -1,78 +1,79 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="item.moving"> <g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 100}}" <!--horizontal line -->
ng-attr-y1="0" <line x1="-60"
ng-attr-x2="{{50 + 100}}" y1="0"
ng-attr-y2="0" x2="60"
class="NetworkUI--construction"></line> y2="0"
<line ng-attr-x1="0" class="NetworkUI--debug">
ng-attr-y1="{{-50 - 100}}" </line>
ng-attr-x2="0" <!-- end horizontal line -->
ng-attr-y2="{{50 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden"> <!-- vertical line -->
<line ng-attr-x1="{{-50 - 10}}" <line x1="0"
ng-attr-y1="0" y1="-60"
ng-attr-x2="{{50 + 10}}" x2="0"
ng-attr-y2="0" y2="60"
class="NetworkUI--debug"></line> class="NetworkUI--debug">
<line ng-attr-x1="0" </line>
ng-attr-y1="{{-50 - 10}}" <!-- end vertical line -->
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}" <!-- debug rectangle -->
class="NetworkUI--debug"></line> <rect x="-50"
<rect ng-attr-x="{{-50}}" y="-50"
ng-attr-y="{{-50}}" width="100"
ng-attr-width="{{50 * 2}}" height="100"
ng-attr-height="{{50 * 2}}" class="NetworkUI--debug">
class="NetworkUI--debug"></rect> </rect>
</g> <!-- end debug rectangle -->
<g class="NetworkUI__router"> </g>
<circle <g transform="translate(-50,-50)">
cx="0" <circle
cy="0" cx="50"
ng-attr-r="{{50 + 2}}" cy="50"
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__router--selected-conflict' : item.selected ? 'NetworkUI__router--selected' : 'NetworkUI__router--remote-selected' : 'NetworkUI--hidden'}}"> r="50"
</circle> ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__router--selected-conflict' : item.selected ? 'NetworkUI__router--selected' : 'NetworkUI__router--remote-selected' : 'NetworkUI__router--background'}}">
<circle </circle>
cx="0" <g transform="scale(2)">
cy="0" <path
ng-attr-r="{{50}}"> class="NetworkUI__router"
</circle> d="M42.7,7.3c-9.8-9.8-25.6-9.8-35.4,0c-9.8,9.8-9.8,25.6,0,35.4c9.8,9.8,25.6,9.8,35.4,0
<g transform="rotate(45)"> C52.4,32.9,52.4,17.1,42.7,7.3z M20,12.3l4.2-4.2c0.2-0.2,0.5-0.3,0.8-0.3c0.3,0,0.6,0.1,0.8,0.3l4.2,4.2c0.4,0.4,0.4,1.2,0,1.6
<line ng-attr-x1="12" c-0.4,0.4-1.2,0.4-1.6,0l-2.3-2.3v10c0,0.6-0.5,1.1-1.1,1.1c-0.6,0-1.1-0.5-1.1-1.1l0-10L21.6,14c-0.4,0.4-1.2,0.4-1.6,0
ng-attr-y1="0" C19.5,13.5,19.5,12.8,20,12.3z M15.6,29.8c-0.4-0.4-0.4-1.2,0-1.6l0,0l2.1-2.1l-8.7,0c-0.6,0-1.1-0.5-1.1-1.1c0-0.3,0.1-0.6,0.3-0.8
ng-attr-x2="{{50-18}}" C8.4,24,8.7,23.8,9,23.8l8.7,0l-2.1-2.1c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4,4c0.2,0.2,0.3,0.5,0.3,0.8
ng-attr-y2="0"/> c0,0.3-0.1,0.6-0.3,0.8l0,0l-4,4C16.8,30.3,16.1,30.3,15.6,29.8z M30,37.7l-4.2,4.2c-0.2,0.2-0.5,0.3-0.8,0.3
<line ng-attr-x1="-12" c-0.3,0-0.6-0.1-0.8-0.3L20,37.7c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l2.3,2.3l0-10.2c0-0.3,0.1-0.6,0.3-0.8
ng-attr-y1="0" c0.2-0.2,0.5-0.3,0.8-0.3c0.6,0,1.1,0.5,1.1,1.1l0,10.2l2.3-2.3c0.4-0.4,1.2-0.4,1.6,0C30.5,36.5,30.5,37.2,30,37.7z M41,26.2
ng-attr-x2="{{-50+18}}" l-8.9,0l2.1,2.1c0.4,0.4,0.5,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0l-4-4c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.3,0.1-0.6,0.3-0.8l0,0l4-4
ng-attr-y2="0"/> c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l0,0l-2.1,2.1l8.8,0c0.6,0,1.1,0.5,1.1,1.1C42.1,25.6,41.6,26.2,41,26.2z"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(0) translate({{50-22}}, -20) scale(2.0)"/> </g>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(180) translate({{50-22}}, -20) scale(2.0)"/> </g>
<line ng-attr-x1="0" <g ng-show="item.icon || current_scale > 0.5">
ng-attr-y1="17" <text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__router-text--selected' : 'NetworkUI--hidden'}}"
ng-attr-x2="0" filter="url(#selected)"
ng-attr-y2="{{50-5}}"/> x="-30"
<line ng-attr-x1="0" y="70"> {{item.name}}</text>
ng-attr-y1="-17" <text class="NetworkUI__router-text" x="-30" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
ng-attr-x2="0" </g>
ng-attr-y2="{{-50+5}}"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(90) translate(-22, -20) scale(2.0)" />
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(270) translate(-22, -20) scale(2.0)"/>
</g>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__router-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="0"> {{item.name}}</text>
<text class="NetworkUI__router-text" text-anchor="middle" x="0" y="0">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@@ -138,7 +138,8 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
device.x, device.x,
device.y, device.y,
device.name, device.name,
device.type)); device.type,
device.host_id));
for (j=0; j < message.group.devices[i].interfaces.length; j++) { for (j=0; j < message.group.devices[i].interfaces.length; j++) {
intf = new models.Interface(message.group.devices[i].interfaces[j].id, message.group.devices[i].interfaces[j].name); intf = new models.Interface(message.group.devices[i].interfaces[j].id, message.group.devices[i].interfaces[j].name);
intf.device = device; intf.device = device;

View File

@@ -1,91 +1,103 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="current_scale <= 0.1 && item.type == 'site'" ng-attr-transform="translate({{item.width()/2}}, {{item.height()/2}})"> <g ng-if="current_scale <= 0.1 && item.type == 'site'" ng-attr-transform="translate({{item.width()/2}}, {{item.height()/2}})">
<g ng-attr-transform="scale({{1/(0.1)}})"> <g ng-attr-transform="scale({{1/(0.1)}})">
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<g ng-if="item.moving"> <!-- vertical line -->
<line ng-attr-x1="{{-50 - 100}}" <line x1="0"
ng-attr-y1="0" y1="-150"
ng-attr-x2="{{50 + 100}}" x2="0"
ng-attr-y2="0" y2="150"
class="NetworkUI--construction"></line> class="NetworkUI--construction">
<line ng-attr-x1="0" </line>
ng-attr-y1="{{-15 - 100}}" <!-- end vertical line -->
ng-attr-x2="0" </g>
ng-attr-y2="{{15 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden"> <g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}" <!--horizontal line -->
ng-attr-y1="0" <line x1="-60"
ng-attr-x2="{{50 + 10}}" y1="0"
ng-attr-y2="0" x2="60"
class="NetworkUI--debug"></line> y2="0"
<line ng-attr-x1="0" class="NetworkUI--debug">
ng-attr-y1="{{-50 - 10}}" </line>
ng-attr-x2="0" <!-- end horizontal line -->
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line> <!-- vertical line -->
<rect ng-attr-x="{{-50}}" <line x1="0"
ng-attr-y="{{-50}}" y1="-60"
ng-attr-width="{{50 * 2}}" x2="0"
ng-attr-height="{{50 * 2}}" y2="60"
class="NetworkUI--debug"></rect> class="NetworkUI--debug">
</g> </line>
<rect <!-- end vertical line -->
x="-52"
y="-52" <!-- debug rectangle -->
ng-attr-width="{{100 + 4}}" <rect x="-50"
ng-attr-height="{{100 + 4}}" y="-50"
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__site--selected-conflict' : item.selected ? 'NetworkUI__site--selected' : 'NetworkUI__site--remote-selected' : 'NetworkUI--hidden'}}" width="100"
rx=10> height="100"
</rect> class="NetworkUI--debug">
<g class="NetworkUI__site"> </rect>
<rect <!-- end debug rectangle -->
x="-50" </g>
y="-50" <g transform="translate(-50,-50)">
ng-attr-width="{{100}}" <rect
ng-attr-height="{{100}}" ry=15
rx=10 rx=15
class="NetworkUI__site-background"> width=100
</rect> height=100
<rect class="NetworkUI__site--network" x=-42 y=60 width="80" height="10" rx=5 /> ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__site--selected-conflict' : item.selected ? 'NetworkUI__site--selected' : 'NetworkUI__site--remote-selected' : 'NetworkUI__site--background'}}">
<rect class="NetworkUI__site--network" x=-42 y=30 width="10" height="40" rx=5 /> </rect>
<rect class="NetworkUI__site--network" x=-5 y=30 width="10" height="40" rx=5 /> <g transform="scale(2)">
<rect class="NetworkUI__site--network" x=32 y=30 width="10" height="40" rx=5 /> <path
<rect class="NetworkUI__site--fill0"
x="-50" d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
y="-40" C50,4.2,45.8,0,40.8,0z"/>
ng-attr-width="{{25}}" <path
ng-attr-height="{{80}}" class="NetworkUI__site--fill1"
rx=10> d="M38.5,30.5v5c0,2.8-2.2,5-5,5h-17c-2.8,0-5-2.2-5-5v-5"/>
</rect> <rect
<rect x="24"
x="-20" y="32.1"
y="-50" class="NetworkUI__site--fill2"
ng-attr-width="{{40}}" width="2"
ng-attr-height="{{100}}" height="8"/>
rx=10> <path
</rect> class="NetworkUI__site--fill2"
<rect d="M26,34.5h-2c-2.8,0-5-2.2-5-5v-17c0-2.8,2.2-5,5-5h2c2.8,0,5,2.2,5,5v17C31,32.2,28.7,34.5,26,34.5z"/>
x="25" <circle
y="-40" class="NetworkUI__site--fill0"
ng-attr-width="{{25}}" cx="25" cy="28.9" r="2.5"/>
ng-attr-height="{{80}}" <path
rx=10> class="NetworkUI__site--fill2"
</rect> d="M39.5,34.5h-2c-2.8,0-5-2.2-5-5v-12c0-2.8,2.2-5,5-5h2c2.8,0,5,2.2,5,5v12C44.5,32.2,42.2,34.5,39.5,34.5z"/>
<circle cy="20" cx="-37" r=7 /> <circle
<circle cy="25" cx="0" r=10 /> class="NetworkUI__site--fill0"
<circle cy="20" cx="37" r=7 /> cx="38.5" cy="28.9" r="2.5"/>
</g> <path
</g> class="NetworkUI__site--fill2"
<g ng-attr-transform="scale({{1/current_scale}})"> d="M12.5,34.5h-2c-2.8,0-5-2.2-5-5v-12c0-2.8,2.2-5,5-5h2c2.8,0,5,2.2,5,5v12C17.5,32.2,15.2,34.5,12.5,34.5z"/>
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__group-text--selected' : 'NetworkUI--hidden'}}" <circle
filter="url(#selected)" class="NetworkUI__site--fill0"
text-anchor="middle" cx="11.5" cy="28.9" r="2.5"/>
ng-attr-x="0" </g>
ng-attr-y="{{1200*current_scale}}"> {{item.name}} </text> </g>
<text class="NetworkUI__group-text" text-anchor="middle" x="0" ng-attr-y="{{1200*current_scale}}">{{item.name}}{{item.edit_label?'_':''}}</text> </g>
</g> <g ng-attr-transform="scale({{1/current_scale}})">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__site-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
ng-attr-x="0"
ng-attr-y="{{1200*current_scale}}"> {{item.name}} </text>
<text class="NetworkUI__site-text" text-anchor="middle" x="0" ng-attr-y="{{1200*current_scale}}">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
</g> </g>

View File

@@ -1,72 +1,100 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="!debug.hidden"> <g ng-if="item.moving">
<line ng-attr-x1="{{-50 - 10}}" <!--horizontal line -->
ng-attr-y1="0" <line x1="-150"
ng-attr-x2="{{50 + 10}}" y1="0"
ng-attr-y2="0" x2="150"
class="NetworkUI--debug"></line> y2="0"
<line ng-attr-x1="0" class="NetworkUI--construction">
ng-attr-y1="{{-50 - 10}}" </line>
ng-attr-x2="0" <!-- end horizontal line -->
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line> <!-- vertical line -->
<rect ng-attr-x="{{-50}}" <line x1="0"
ng-attr-y="{{-50}}" y1="-150"
ng-attr-width="{{50 * 2}}" x2="0"
ng-attr-height="{{50 * 2}}" y2="150"
class="NetworkUI--debug"></rect> class="NetworkUI--construction">
</g> </line>
<rect <!-- end vertical line -->
x="-52" </g>
y="-52"
ng-attr-width="{{100 + 4}}" <g ng-if="!debug.hidden">
ng-attr-height="{{100 + 4}}" <!--horizontal line -->
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__site--selected-conflict' : item.selected ? 'NetworkUI__site--selected' : 'NetworkUI__site--remote-selected' : 'NetworkUI--hidden'}}" <line x1="-60"
rx=10> y1="0"
</rect> x2="60"
<g class="NetworkUI__site"> y2="0"
<rect class="NetworkUI--debug">
x="-50" </line>
y="-50" <!-- end horizontal line -->
ng-attr-width="{{100}}"
ng-attr-height="{{100}}" <!-- vertical line -->
rx=10 <line x1="0"
class="NetworkUI__site-background"> y1="-60"
</rect> x2="0"
<rect class="NetworkUI__site--network" x=-42 y=60 width="80" height="10" rx=5 /> y2="60"
<rect class="NetworkUI__site--network" x=-42 y=30 width="10" height="40" rx=5 /> class="NetworkUI--debug">
<rect class="NetworkUI__site--network" x=-5 y=30 width="10" height="40" rx=5 /> </line>
<rect class="NetworkUI__site--network" x=32 y=30 width="10" height="40" rx=5 /> <!-- end vertical line -->
<rect
x="-50" <!-- debug rectangle -->
y="-40" <rect x="-50"
ng-attr-width="{{25}}" y="-50"
ng-attr-height="{{80}}" width="100"
rx=10> height="100"
</rect> class="NetworkUI--debug">
<rect </rect>
x="-20" <!-- end debug rectangle -->
y="-50" </g>
ng-attr-width="{{40}}" <g transform="translate(-50,-50)">
ng-attr-height="{{100}}" <rect
rx=10> ry=15
</rect> rx=15
<rect width=100
x="25" height=100
y="-40" ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__site--selected-conflict' : item.selected ? 'NetworkUI__site--selected' : 'NetworkUI__site--remote-selected' : 'NetworkUI__site--background'}}">
ng-attr-width="{{25}}" </rect>
ng-attr-height="{{80}}" <g transform="scale(2)">
rx=10> <path
</rect> class="NetworkUI__site--fill0"
<circle cy="20" cx="-37" r=7 /> d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2
<circle cy="25" cx="0" r=10 /> C50,4.2,45.8,0,40.8,0z"/>
<circle cy="20" cx="37" r=7 /> <path
</g> class="NetworkUI__site--fill1"
d="M38.5,30.5v5c0,2.8-2.2,5-5,5h-17c-2.8,0-5-2.2-5-5v-5"/>
<rect
x="24"
y="32.1"
class="NetworkUI__site--fill2"
width="2"
height="8"/>
<path
class="NetworkUI__site--fill2"
d="M26,34.5h-2c-2.8,0-5-2.2-5-5v-17c0-2.8,2.2-5,5-5h2c2.8,0,5,2.2,5,5v17C31,32.2,28.7,34.5,26,34.5z"/>
<circle
class="NetworkUI__site--fill0"
cx="25" cy="28.9" r="2.5"/>
<path
class="NetworkUI__site--fill2"
d="M39.5,34.5h-2c-2.8,0-5-2.2-5-5v-12c0-2.8,2.2-5,5-5h2c2.8,0,5,2.2,5,5v12C44.5,32.2,42.2,34.5,39.5,34.5z"/>
<circle
class="NetworkUI__site--fill0"
cx="38.5" cy="28.9" r="2.5"/>
<path
class="NetworkUI__site--fill2"
d="M12.5,34.5h-2c-2.8,0-5-2.2-5-5v-12c0-2.8,2.2-5,5-5h2c2.8,0,5,2.2,5,5v12C17.5,32.2,15.2,34.5,12.5,34.5z"/>
<circle
class="NetworkUI__site--fill0"
cx="11.5" cy="28.9" r="2.5"/>
</g>
</g>
<g ng-if="current_scale <= 0.1 && item.type == 'site'">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__site-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
x="-20"
y="70"> {{item.name}}
</text>
<text class="NetworkUI__site-text" x="-20" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g> </g>
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__group-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
ng-attr-x="0"
ng-attr-y="100"> {{item.name}} </text>
<text class="NetworkUI__group-text" text-anchor="middle" x="0" y="100">{{item.name}}{{item.edit_label?'_':''}}</text>

View File

@@ -31,9 +31,13 @@
@button-body-pressed: #848992; @button-body-pressed: #848992;
@button-text-pressed: #ffffff; @button-text-pressed: #ffffff;
@green: #5CB85C; @green: #5CB85C;
@host-green: #449D44;
@red: #D9534F; @red: #D9534F;
@blue: #337AB7;
@light-toolbox-background: #f6f6f6; @light-toolbox-background: #f6f6f6;
@icon-background-hover:#337AB7; @rack-orange: #F0AD4E;
@site-orange: #EC971F;
@icon-background-hover:@blue;
.NetworkUI { .NetworkUI {
background-color: @light-toolbox-background; background-color: @light-toolbox-background;
@@ -114,14 +118,17 @@
} }
.NetworkUI__router { .NetworkUI__router {
fill: @widget-body; fill: @green;
stroke: @dark-widget-detail; }
stroke-width: 2;
.NetworkUI__router--background{
fill: @light-background;
} }
.NetworkUI__router--selected { .NetworkUI__router--selected {
stroke: @selected-blue; stroke: @selected-blue;
stroke-width: 4; stroke-width: 4;
fill:@light-background;
} }
.NetworkUI__router--remote-selected { .NetworkUI__router--remote-selected {
@@ -134,16 +141,6 @@
stroke-width: 4; stroke-width: 4;
} }
.NetworkUI__router line {
stroke: @light-widget-detail;
stroke-width: 20;
}
.NetworkUI__router polygon {
fill: @light-widget-detail;
stroke: none;
}
.NetworkUI__router-text { .NetworkUI__router-text {
fill: @button-text; fill: @button-text;
font-family: 'Open Sans'; font-family: 'Open Sans';
@@ -156,14 +153,17 @@
.NetworkUI__switch { .NetworkUI__switch {
fill: @widget-body; fill: @blue;
stroke: @dark-widget-detail; }
stroke-width: 2;
.NetworkUI__switch--background{
fill: @light-background;
} }
.NetworkUI__switch--selected { .NetworkUI__switch--selected {
stroke: @selected-blue; stroke: @selected-blue;
stroke-width: 10; stroke-width: 10;
fill:@light-background;
} }
.NetworkUI__switch--remote-selected { .NetworkUI__switch--remote-selected {
@@ -197,19 +197,15 @@
} }
.NetworkUI__rack { .NetworkUI__rack {
fill: @widget-body; fill: @rack-orange;
stroke: @dark-widget-detail;
stroke-width: 2;
} }
.NetworkUI__rack-background { .NetworkUI__rack--background {
fill: @light-background; fill: @light-background;
stroke: @light-background;
stroke-width: 2;
} }
.NetworkUI__rack--selected { .NetworkUI__rack--selected {
fill: @selected-blue; fill: @light-background;
stroke: @selected-blue; stroke: @selected-blue;
stroke-width: 10; stroke-width: 10;
} }
@@ -252,20 +248,33 @@
stroke-width: 2; stroke-width: 2;
} }
.NetworkUI__site--fill0{
fill:@site-orange;
}
.NetworkUI__site--fill1{
fill:none;
stroke:@light-background;
stroke-width:2;
stroke-miterlimit:10;
}
.NetworkUI__site--fill2{
fill:@light-background;
}
.NetworkUI__site--network { .NetworkUI__site--network {
fill: @dark-widget-detail; fill: @dark-widget-detail;
stroke: @dark-widget-detail; stroke: @dark-widget-detail;
stroke-width: 2; stroke-width: 2;
} }
.NetworkUI__site-background { .NetworkUI__site--background {
fill: @light-background; fill: @light-background;
stroke: @light-background;
stroke-width: 2;
} }
.NetworkUI__site--selected { .NetworkUI__site--selected {
fill: @selected-blue; fill: @light-background;
stroke: @selected-blue; stroke: @selected-blue;
stroke-width: 10; stroke-width: 10;
} }
@@ -411,19 +420,15 @@
} }
.NetworkUI__host { .NetworkUI__host {
fill: @widget-body; fill: @host-green;
stroke: @dark-widget-detail;
stroke-width: 2;
} }
.NetworkUI__host-background { .NetworkUI__host--background {
fill: @light-background; fill: @light-background;
stroke: @light-background;
stroke-width: 2;
} }
.NetworkUI__host--selected { .NetworkUI__host--selected {
fill: @selected-blue; fill: @light-background;
stroke: @selected-blue; stroke: @selected-blue;
stroke-width: 10; stroke-width: 10;
} }
@@ -746,13 +751,13 @@
} }
.NetworkUI__contextMenuButtonText{ .NetworkUI__contextMenuButtonText{
fill: @button-text; fill: #333; //@button-text;
font-family: 'Open Sans'; font-family: 'Open Sans';
font-size: 14px; font-size: 14px;
} }
.NetworkUI__contextMenuButtonText-hover{ .NetworkUI__contextMenuButtonText-hover{
fill: @button-text; fill: #333; //@button-text;
font-family: 'Open Sans'; font-family: 'Open Sans';
font-size: 14px; font-size: 14px;
} }

View File

@@ -1,79 +1,81 @@
<!-- Copyright (c) 2017 Red Hat, Inc. --> <!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="item.moving">
<!--horizontal line -->
<line x1="-150"
y1="0"
x2="150"
y2="0"
class="NetworkUI--construction">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="item.moving"> <g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 100}}" <!--horizontal line -->
ng-attr-y1="0" <line x1="-60"
ng-attr-x2="{{50 + 100}}" y1="0"
ng-attr-y2="0" x2="60"
class="NetworkUI--construction"></line> y2="0"
<line ng-attr-x1="0" class="NetworkUI--debug">
ng-attr-y1="{{-50 - 100}}" </line>
ng-attr-x2="0" <!-- end horizontal line -->
ng-attr-y2="{{50 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden"> <!-- vertical line -->
<line ng-attr-x1="{{-50 - 10}}" <line x1="0"
ng-attr-y1="0" y1="-60"
ng-attr-x2="{{50 + 10}}" x2="0"
ng-attr-y2="0" y2="60"
class="NetworkUI--debug"></line> class="NetworkUI--debug">
<line ng-attr-x1="0" </line>
ng-attr-y1="{{-50 - 10}}" <!-- end vertical line -->
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}" <!-- debug rectangle -->
class="NetworkUI--debug"></line> <rect x="-50"
<rect ng-attr-x="{{-50}}" y="-50"
ng-attr-y="{{-50}}" width="100"
ng-attr-width="{{50 * 2}}" height="100"
ng-attr-height="{{50 * 2}}" class="NetworkUI--debug">
class="NetworkUI--debug"></rect> </rect>
</g> <!-- end debug rectangle -->
<rect </g>
x="-52"
y="-52" <g transform="translate(-50,-50)">
ng-attr-width="{{100 + 4}}" <rect
ng-attr-height="{{100 + 4}}" ry=15
ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__switch--selected-conflict' : item.selected ? 'NetworkUI__switch--selected' : 'NetworkUI__switch--remote-selected' : 'NetworkUI--hidden'}}" rx=15
rx=10> width=100
</rect> height=100
<g class="NetworkUI__switch"> ng-attr-class="{{item.selected || item.remote_selected ? item.selected && item.remote_selected ? 'NetworkUI__switch--selected-conflict' : item.selected ? 'NetworkUI__switch--selected' : 'NetworkUI__switch--remote-selected' : 'NetworkUI__switch--background'}}">
<rect </rect>
x="-50" <g transform="scale(2)">
y="-50" <path
ng-attr-width="{{100}}" class="NetworkUI__switch"
ng-attr-height="{{100}}" d="M40.8,0H9.2C4.2,0,0,4.2,0,9.2v31.5C0,45.8,4.2,50,9.2,50h31.5c5.1,0,9.2-4.2,9.2-9.2V9.2C50,4.2,45.8,0,40.8,0
rx=10> z M22.2,12.6l11.1,0l-2.3-2.3c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4.2,4.2c0.2,0.2,0.3,0.5,0.3,0.8c0,0.3-0.1,0.6-0.3,0.8
</rect> l-4.2,4.2c-0.4,0.4-1.2,0.4-1.6,0c-0.4-0.4-0.4-1.2,0-1.6l2.3-2.3H22.2c-0.6,0-1.1-0.5-1.1-1.1C21.1,13.1,21.6,12.6,22.2,12.6z
<line ng-attr-x1="2" M10,21.2c0-0.3,0.1-0.6,0.3-0.8l4.2-4.2c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l-2.3,2.3H25c0.6,0,1.1,0.5,1.1,1.1
ng-attr-y1="-28" c0,0.6-0.5,1.1-1.1,1.1l-11.1,0l2.3,2.3c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0L10.3,22C10.1,21.8,10,21.5,10,21.2z
ng-attr-x2="38" M27.8,37.4l-11.1,0l2.3,2.3c0.4,0.4,0.4,1.2,0,1.6c-0.4,0.4-1.2,0.4-1.6,0l-4.2-4.2c-0.2-0.2-0.3-0.5-0.3-0.8
ng-attr-y2="-28"/> c0-0.3,0.1-0.6,0.3-0.8l4.2-4.2c0.4-0.4,1.2-0.4,1.6,0c0.4,0.4,0.4,1.2,0,1.6l-2.3,2.3h11.1c0.6,0,1.1,0.5,1.1,1.1
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(0) translate(28, -48) scale(2.0)"/> C28.9,36.9,28.4,37.4,27.8,37.4z M39.7,29.6l-4.2,4.2c-0.4,0.4-1.2,0.4-1.6,0c-0.4-0.4-0.4-1.2,0-1.6l2.3-2.3H25
<line ng-attr-x1="2" c-0.6,0-1.1-0.5-1.1-1.1c0-0.6,0.5-1.1,1.1-1.1l11.1,0l-2.3-2.3c-0.4-0.4-0.4-1.2,0-1.6c0.4-0.4,1.2-0.4,1.6,0l4.2,4.2
ng-attr-y1="14" c0.2,0.2,0.3,0.5,0.3,0.8C40,29.1,39.9,29.4,39.7,29.6z"/>
ng-attr-x2="38" </g>
ng-attr-y2="14"/> </g>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(0) translate(28, -6) scale(2.0)"/> <g ng-show="item.icon || current_scale > 0.5">
<line ng-attr-x1="-2" <text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__switch-text--selected' : 'NetworkUI--hidden'}}"
ng-attr-y1="28" filter="url(#selected)"
ng-attr-x2="-38" x="-25"
ng-attr-y2="28"/> y="70"> {{item.name}}</text>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(180) translate(28, -48) scale(2.0)"/> <text class="NetworkUI__switch-text" x="-25" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
<line ng-attr-x1="-2" </g>
ng-attr-y1="-14"
ng-attr-x2="-38"
ng-attr-y2="-14"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(180) translate(28, -6) scale(2.0)"/>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'NetworkUI__switch-text--selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="0"> {{item.name}} </text>
<text class="NetworkUI__switch-text" text-anchor="middle" x="0" y="0">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@@ -50,6 +50,7 @@ _Ready.prototype.onMouseDown = function (controller) {
controller.scope.pressedY = controller.scope.mouseY; controller.scope.pressedY = controller.scope.mouseY;
controller.scope.lastPanX = controller.scope.panX; controller.scope.lastPanX = controller.scope.panX;
controller.scope.lastPanY = controller.scope.panY; controller.scope.lastPanY = controller.scope.panY;
controller.scope.$emit('closeDetailsPanel');
controller.changeState(Pressed); controller.changeState(Pressed);
}; };