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
No known key found for this signature in database
GPG Key ID: 5818EF4CC895D5F5
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 TopologyInventory
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',)
@ -169,3 +171,11 @@ class FSMTraceAdmin(admin.ModelAdmin):
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 Toolbox, ToolboxItem
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
import urlparse
from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Q
from collections import defaultdict
from django.conf import settings
import math
import random
import logging
@ -249,8 +248,19 @@ def parse_topology_id(data):
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
class _Persistence(object):
def handle(self, message):
@ -270,7 +280,7 @@ class _Persistence(object):
message_value = data[1]
try:
message_type_id = MessageType.objects.get(name=message_type).pk
except ObjectDoesNotExist, e:
except ObjectDoesNotExist:
logger.warning("Unsupported message %s", message_type)
return
TopologyHistory(topology_id=topology_id,
@ -292,11 +302,15 @@ class _Persistence(object):
y='y',
name='name',
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.x = device['x']
d.y = device['y']
d.type = device['type']
d.host_id = device['host_id']
d.save()
(Topology.objects
.filter(topology_id=topology_id, device_id_seq__lt=device['id'])
@ -516,13 +530,13 @@ class _Persistence(object):
GroupDeviceMap.objects.bulk_create(new_entries)
def onFSMTrace(self, message_value, diagram_id, client_id):
FSMTrace(trace_session_id=message_value['trace_id'],
fsm_name=message_value['fsm_name'],
from_state=message_value['from_state'],
to_state=message_value['to_state'],
order=message_value['order'],
client_id=client_id,
message_type=message_value['recv_message_type'] or "none").save()
FSMTrace(trace_session_id=message_value['trace_id'],
fsm_name=message_value['fsm_name'],
from_state=message_value['from_state'],
to_state=message_value['to_state'],
order=message_value['order'],
client_id=client_id,
message_type=message_value['recv_message_type'] or "none").save()
persistence = _Persistence()
@ -777,9 +791,19 @@ def ansible_disconnect(message):
def ws_connect(message):
# Accept connection
data = urlparse.parse_qs(message.content['query_string'])
topology_id = parse_topology_id(data)
topology, created = Topology.objects.get_or_create(
topology_id=topology_id, defaults=dict(name="topology", scale=1.0, panX=0, panY=0))
inventory_id = parse_inventory_id(data)
topology_ids = list(TopologyInventory.objects.filter(inventory_id=inventory_id).values_list('topology_id', flat=True))
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
message.channel_session['topology_id'] = topology_id
Group("topology-%s" % topology_id).add(message.reply_channel)
@ -903,6 +927,7 @@ def console_printer(message):
# Tester channel events
@channel_session
def tester_connect(message):
data = urlparse.parse_qs(message.content['query_string'])

View File

@ -28,6 +28,9 @@ models:
- default: 0
name: process_id_seq
type: IntegerField
- default: 0
name: host_id
type: IntegerField
name: Device
x: 348
y: 124
@ -153,8 +156,8 @@ models:
- name: id
type: IntegerField
name: Interface
x: 600
y: 243
x: 1157
y: 337
- fields:
- name: group_id
pk: true
@ -349,8 +352,21 @@ models:
name: FSMTrace
x: -872
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: []
view:
panX: 213.72955551921206
panY: 189.44695909464298
scaleXY: 0.6900000000000002
panX: 213.729555519212
panY: 189.446959094643
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
@ -13,6 +12,7 @@ class Device(models.Model):
type = models.CharField(max_length=200,)
interface_id_seq = models.IntegerField(default=0)
process_id_seq = models.IntegerField(default=0)
host_id = models.IntegerField(default=0)
def __unicode__(self):
return self.name
@ -168,3 +168,10 @@ class FSMTrace(models.Model):
client = models.ForeignKey('Client',)
trace_session_id = 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.panelTitle = `${strings.get('state.BREADCRUMB_LABEL')} | ${inventory.name}`;
vm.hostDetail = {};
vm.hostDetail = false;
vm.panelIsExpanded = false;
@ -19,11 +19,19 @@ function NetworkingController (models, $state, $scope, strings) {
$state.go('inventories');
};
$scope.$on('retrievedHostData', (e, hostData) => {
if (!vm.panelIsExpanded) {
$scope.$on('closeDetailsPanel', () => {
vm.panelIsExpanded = false;
});
$scope.$on('retrievedHostData', (e, hostData, expand) => {
if (expand) {
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 class="Networking-panels">
<div class="Networking-leftPanel">
<awx-network-ui></awx-network-ui>
</div>
<div class="Networking-rightPanel" ng-show="vm.panelIsExpanded">
<!-- VIEW LAYERS -->
<!--beginning of header-->
<div class="Networking-panelHeader">
<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 ng-if="hostDetail===false">
NO HOST DETAIL
</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 ng-if="hostDetail!==false">
<!--beginning of header-->
<div class="Networking-panelHeader">
<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>
<!--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>
<!--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><!--end of Networking-rightPanel -->
</div>
</div>
<!--end of Networking-rightPanel -->
<div id="alert-modal" class="modal fade">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<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>
<h3 id="alertHeader" ng-bind="alertHeader"></h3>
</div>
<div class="modal-body">
<div id="alert-modal-msg" class="alert" ng-bind-html="alertBody"></div>
</div>
<div class="modal-footer">
<a href="#" ng-hide="disableButtons" data-target="#form-modal" data-dismiss="modal" id="alert_ok_btn" class="btn btn-default" translate>OK</a>
</div>
</div>
<!-- modal-content -->
</div>
<!-- modal-dialog -->
</div>

View File

@ -1,60 +1,87 @@
<!-- 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">
<line ng-attr-x1="{{-50 - 100}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 100}}"
ng-attr-y2="0"
class="NetworkUI--construction"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-15 - 100}}"
ng-attr-x2="0"
ng-attr-y2="{{15 + 100}}"
class="NetworkUI--construction"></line>
</g>
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-15 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{15 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-15}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{15 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<g class="NetworkUI__host">
<rect
x="-52"
y="-17"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{30 + 4}}"
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'}}"
rx=10>
</rect>
<rect
x="-50"
y="-15"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<circle cx="30" cy="0" r=7 />
</circle>
</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)"
text-anchor="middle"
x="0"
y="5"> {{item.name}} </text>
<text class="NetworkUI__host-text" text-anchor="middle" x="0" y="5">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-40"
x2="0"
y2="40"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-30"
width="100"
height="60"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-30)">
<rect
ry=15
rx=15
width=100
height=60
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'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__host"
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__host"
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
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;
function DeviceCreate(sender, id, x, y, name, type) {
function DeviceCreate(sender, id, x, y, name, type, host_id) {
this.msg_type = "DeviceCreate";
this.sender = sender;
this.id = id;
@ -25,10 +25,11 @@ function DeviceCreate(sender, id, x, y, name, type) {
this.y = y;
this.name = name;
this.type = type;
this.host_id = host_id;
}
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.sender = sender;
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_name = previous_name;
this.previous_type = previous_type;
this.previous_host_id = previous_host_id;
}
exports.DeviceDestroy = DeviceDestroy;

View File

@ -4,12 +4,13 @@ var button = require('./button.js');
var util = require('./util.js');
var inherits = require('inherits');
function Device(id, name, x, y, type) {
function Device(id, name, x, y, type, host_id) {
this.id = id;
this.host_id = host_id ? host_id: 0;
this.name = name;
this.x = x;
this.y = y;
this.height = type === "host" ? 15 : 50;
this.height = type === "host" ? 30 : 50;
this.width = 50;
this.size = 50;
this.type = type;
@ -374,9 +375,9 @@ function ContextMenu(name, x, y, width, height, callback, enabled, buttons, trac
this.callback = callback;
this.is_pressed = false;
this.mouse_over = false;
this.enabled = enabled;
this.enabled = false;
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;

View File

@ -76,6 +76,14 @@ var Placing = new _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) {
controller.changeState(Ready);
@ -135,7 +143,8 @@ _Ready.prototype.onNewDevice = function (controller, msg_type, message) {
device.x,
device.y,
device.name,
device.type));
device.type,
device.host_id));
scope.selected_devices.push(device);
device.selected = true;
controller.changeState(Placing);
@ -161,14 +170,16 @@ _Ready.prototype.onPasteDevice = function (controller, msg_type, message) {
message.device.name,
scope.scaledX,
scope.scaledY,
message.device.type);
message.device.type,
message.device.host_id);
scope.devices.push(device);
c_messages.push(new messages.DeviceCreate(scope.client_id,
device.id,
device.x,
device.y,
device.name,
device.type));
device.type,
device.host_id));
for (i=0; i < message.device.interfaces.length; i++) {
intf = new models.Interface(message.device.interfaces[i].id, message.device.interfaces[i].name);
device.interfaces.push(intf);
@ -331,7 +342,8 @@ _Selected2.prototype.onKeyDown = function (controller, msg_type, $event) {
devices[i].x,
devices[i].y,
devices[i].name,
devices[i].type));
devices[i].type,
devices[i].host_id));
}
for (j = 0; j < all_links.length; j++) {
if (all_links[j].to_device === devices[i] ||
@ -457,10 +469,20 @@ _Move.prototype.onMouseDown = function (controller) {
};
_Move.prototype.onMouseDown.transitions = ['Selected1'];
_Selected3.prototype.onMouseUp = function (controller) {
controller.changeState(EditLabel);
_Selected3.prototype.onMouseUp = function (controller, msg_type, $event) {
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) {
controller.changeState(Selected2);
@ -545,3 +567,21 @@ _Placing.prototype.onMouseMove = function (controller) {
_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 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;
var i = 0;
@ -31,16 +32,16 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$scope.api_token = '';
$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
//
$scope.inventory_id = $location.search().inventory_id || 1;
$scope.inventory_id = $state.params.inventory_id;
$scope.initial_messages = [];
if (!$scope.disconnected) {
$scope.control_socket = new ReconnectingWebSocket("wss://" + window.location.host + "/network_ui/topology?topology_id=" + $scope.topology_id,
null,
{debug: false, reconnectInterval: 300});
$scope.control_socket = new ReconnectingWebSocket("wss://" + window.location.host + "/network_ui/topology?inventory_id=" + $scope.inventory_id,
null,
{debug: false, reconnectInterval: 300});
} else {
$scope.control_socket = {
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);
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
$scope.inventory_toolbox = new models.ToolBox(0, 'Inventory', 'device', 0, 40, 200, $scope.graph.height - 40);
if (!$scope.disconnected) {
console.log($location.protocol() + "://" + $location.host() + ':' + $location.port());
console.log($scope.my_location);
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/?format=json')
.then(function(inventory) {
console.log(inventory);
console.log(inventory.headers());
var host = null;
var i = 0;
var httpGets = [];
for (i=0; i < inventory.data.results.length;i++) {
host = inventory.data.results[i];
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'));
$http.get('/api/v2/inventories/' + $scope.inventory_id + '/hosts/')
.then(function(response) {
let hosts = response.data.results;
for(var i = 0; i<hosts.length; i++){
let host = hosts[i];
console.log(host);
host.data = jsyaml.safeLoad(host.variables);
var device = new models.Device(0, host.data.name, 0, 0, host.data.type, host.id, host.variables);
device.icon = true;
$scope.inventory_toolbox.items.push(device);
}
return httpGets;
})
.then(function(httpGets) {
console.log(httpGets);
$q.all(httpGets).then(function (results) {
var i = 0;
for (i=0; i < results.length; i++) {
add_host(results[i]);
}
});
.catch(({data, status}) => {
ProcessErrors($scope, data, status, null, { hdr: 'Error!', msg: 'Failed to get host data: ' + status });
});
}
$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
if (last_selected_device === null && last_selected_interface === null) {
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.send_control_message(new messages.LinkSelected($scope.client_id, $scope.links[i].id));
last_selected_link = $scope.links[i];
@ -638,27 +624,40 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
$event.preventDefault();
};
// Conext Menu
$scope.onDetailsContextButton = function (button) {
console.log(button.name);
$scope.$watchCollection('selected_items', function(){
$scope.onDetailsContextButton(false);
});
// Conext Menu Button Handlers
$scope.onDetailsContextButton = function (panelBoolean) {
if (!$scope.disconnected) {
// this will end up being the id of the host the user clicked on
let host_id = 1;
let url = `/api/v2/hosts/${host_id}/?format=json`;
$http.get(url)
.then(function(host) {
$scope.$emit('retrievedHostData', host.data);
})
.catch(function(httpGets) {
console.log(httpGets);
});
if ($scope.selected_items.length === 1){
if ($scope.selected_items[0].host_id === 0){
$scope.$emit('retrievedHostData', {}, panelBoolean !== null ? panelBoolean: true);
}
if ($scope.selected_items[0].host_id !== 0){
let host_id = $scope.selected_items[0].host_id;
let url = `/api/v2/hosts/${host_id}/`;
$http.get(url)
.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
//
$scope.onToggleToolboxButtonLeft = function (button) {
console.log(button.name);
$scope.first_channel.send("ToggleToolbox", {});
@ -771,13 +770,13 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
// 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)
];
// 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
@ -976,7 +975,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
data.name,
data.x,
data.y,
data.type);
data.type,
data.host_id);
$scope.device_id_seq = util.natural_numbers(data.id);
$scope.devices.push(device);
};
@ -1274,7 +1274,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
data.previous_x,
data.previous_y,
data.previous_name,
data.previous_type);
data.previous_type,
data.previous_host_id);
$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.group_id_seq = util.natural_numbers(data.group_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) {
@ -1474,7 +1474,8 @@ var NetworkUIController = function($scope, $document, $location, $window, $http,
device.name,
device.x,
device.y,
device.type);
device.type,
device.host_id);
new_device.interface_seq = util.natural_numbers(device.interface_id_seq);
new_device.process_id_seq = util.natural_numbers(device.process_id_seq);
$scope.devices.push(new_device);

View File

@ -135,7 +135,8 @@ _Ready.prototype.onPasteRack = function (controller, msg_type, message) {
device.x,
device.y,
device.name,
device.type));
device.type,
device.host_id));
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.device = device;

View File

@ -1,88 +1,118 @@
<!-- 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-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">
<line ng-attr-x1="{{-50 - 100}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 100}}"
ng-attr-y2="0"
class="NetworkUI--construction"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-15 - 100}}"
ng-attr-x2="0"
ng-attr-y2="{{15 + 100}}"
class="NetworkUI--construction"></line>
</g>
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<rect
x="-52"
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
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'}}"
rx=10>
</rect>
<g class="NetworkUI__rack">
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{100}}"
rx=10
class="NetworkUI__rack-background">
</rect>
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<rect
x="-50"
y="-15"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<rect
x="-50"
y="20"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<circle cx="30" cy="-35" r=7 />
<circle cx="30" cy="0" r=7 />
<circle cx="30" cy="35" r=7 />
</circle>
</g>
</g>
<g ng-attr-transform="scale({{1/current_scale}})">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
ng-attr-y="{{180*current_scale}}"> {{item.name}} </text>
<text class="NetworkUI__rack-text" text-anchor="middle" x="0" ng-attr-y="{{180*current_scale}}">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<rect
ry=15
rx=15
width=100
height=100
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'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__rack"
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
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
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
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
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
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
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
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>
<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>

View File

@ -1,71 +1,116 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<rect
x="-52"
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
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'}}"
rx=10>
</rect>
<g class="NetworkUI__rack">
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{100}}"
rx=10
class="NetworkUI__rack-background">
</rect>
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<rect
x="-50"
y="-15"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<rect
x="-50"
y="20"
ng-attr-width="{{100}}"
ng-attr-height="{{30}}"
rx=10>
</rect>
<circle cx="30" cy="-35" r=7 />
<circle cx="30" cy="0" r=7 />
<circle cx="30" cy="35" r=7 />
</circle>
</g>
<g ng-show="item.icon || current_scale > 0.5">
<text ng-attr-class="{{item.selected && ! item.edit_label ? 'selected' : 'NetworkUI--hidden'}}"
filter="url(#selected)"
text-anchor="middle"
x="0"
y="6"> {{item.name}} </text>
<text class="NetworkUI__rack-text" text-anchor="middle" x="0" y="6">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
<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="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<rect
ry=15
rx=15
width=100
height=100
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'}}">
</rect>
<g transform="scale(2)">
<path
class="NetworkUI__rack"
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
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
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
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
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
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
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
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. -->
<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">
<line ng-attr-x1="{{-50 - 100}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 100}}"
ng-attr-y2="0"
class="NetworkUI--construction"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 100}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<g class="NetworkUI__router">
<circle
cx="0"
cy="0"
ng-attr-r="{{50 + 2}}"
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'}}">
</circle>
<circle
cx="0"
cy="0"
ng-attr-r="{{50}}">
</circle>
<g transform="rotate(45)">
<line ng-attr-x1="12"
ng-attr-y1="0"
ng-attr-x2="{{50-18}}"
ng-attr-y2="0"/>
<line ng-attr-x1="-12"
ng-attr-y1="0"
ng-attr-x2="{{-50+18}}"
ng-attr-y2="0"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(0) translate({{50-22}}, -20) scale(2.0)"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(180) translate({{50-22}}, -20) scale(2.0)"/>
<line ng-attr-x1="0"
ng-attr-y1="17"
ng-attr-x2="0"
ng-attr-y2="{{50-5}}"/>
<line ng-attr-x1="0"
ng-attr-y1="-17"
ng-attr-x2="0"
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>
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<circle
cx="50"
cy="50"
r="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__router--background'}}">
</circle>
<g transform="scale(2)">
<path
class="NetworkUI__router"
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
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
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
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
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
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
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
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
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
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"/>
</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)"
x="-30"
y="70"> {{item.name}}</text>
<text class="NetworkUI__router-text" x="-30" y="70">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>

View File

@ -138,7 +138,8 @@ _Ready.prototype.onPasteSite = function (controller, msg_type, message) {
device.x,
device.y,
device.name,
device.type));
device.type,
device.host_id));
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.device = device;

View File

@ -1,91 +1,103 @@
<!-- 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-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">
<line ng-attr-x1="{{-50 - 100}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 100}}"
ng-attr-y2="0"
class="NetworkUI--construction"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-15 - 100}}"
ng-attr-x2="0"
ng-attr-y2="{{15 + 100}}"
class="NetworkUI--construction"></line>
</g>
<!-- vertical line -->
<line x1="0"
y1="-150"
x2="0"
y2="150"
class="NetworkUI--construction">
</line>
<!-- end vertical line -->
</g>
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<rect
x="-52"
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
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'}}"
rx=10>
</rect>
<g class="NetworkUI__site">
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{100}}"
rx=10
class="NetworkUI__site-background">
</rect>
<rect class="NetworkUI__site--network" x=-42 y=60 width="80" height="10" rx=5 />
<rect class="NetworkUI__site--network" x=-42 y=30 width="10" height="40" rx=5 />
<rect class="NetworkUI__site--network" x=-5 y=30 width="10" height="40" rx=5 />
<rect class="NetworkUI__site--network" x=32 y=30 width="10" height="40" rx=5 />
<rect
x="-50"
y="-40"
ng-attr-width="{{25}}"
ng-attr-height="{{80}}"
rx=10>
</rect>
<rect
x="-20"
y="-50"
ng-attr-width="{{40}}"
ng-attr-height="{{100}}"
rx=10>
</rect>
<rect
x="25"
y="-40"
ng-attr-width="{{25}}"
ng-attr-height="{{80}}"
rx=10>
</rect>
<circle cy="20" cx="-37" r=7 />
<circle cy="25" cx="0" r=10 />
<circle cy="20" cx="37" r=7 />
</g>
</g>
<g ng-attr-transform="scale({{1/current_scale}})">
<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="{{1200*current_scale}}"> {{item.name}} </text>
<text class="NetworkUI__group-text" text-anchor="middle" x="0" ng-attr-y="{{1200*current_scale}}">{{item.name}}{{item.edit_label?'_':''}}</text>
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<rect
ry=15
rx=15
width=100
height=100
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>
<g transform="scale(2)">
<path
class="NetworkUI__site--fill0"
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"/>
<path
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>
<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>

View File

@ -1,72 +1,100 @@
<!-- Copyright (c) 2017 Red Hat, Inc. -->
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<rect
x="-52"
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
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'}}"
rx=10>
</rect>
<g class="NetworkUI__site">
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{100}}"
rx=10
class="NetworkUI__site-background">
</rect>
<rect class="NetworkUI__site--network" x=-42 y=60 width="80" height="10" rx=5 />
<rect class="NetworkUI__site--network" x=-42 y=30 width="10" height="40" rx=5 />
<rect class="NetworkUI__site--network" x=-5 y=30 width="10" height="40" rx=5 />
<rect class="NetworkUI__site--network" x=32 y=30 width="10" height="40" rx=5 />
<rect
x="-50"
y="-40"
ng-attr-width="{{25}}"
ng-attr-height="{{80}}"
rx=10>
</rect>
<rect
x="-20"
y="-50"
ng-attr-width="{{40}}"
ng-attr-height="{{100}}"
rx=10>
</rect>
<rect
x="25"
y="-40"
ng-attr-width="{{25}}"
ng-attr-height="{{80}}"
rx=10>
</rect>
<circle cy="20" cx="-37" r=7 />
<circle cy="25" cx="0" r=10 />
<circle cy="20" cx="37" r=7 />
</g>
<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="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<rect
ry=15
rx=15
width=100
height=100
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>
<g transform="scale(2)">
<path
class="NetworkUI__site--fill0"
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"/>
<path
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>
<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-text-pressed: #ffffff;
@green: #5CB85C;
@host-green: #449D44;
@red: #D9534F;
@blue: #337AB7;
@light-toolbox-background: #f6f6f6;
@icon-background-hover:#337AB7;
@rack-orange: #F0AD4E;
@site-orange: #EC971F;
@icon-background-hover:@blue;
.NetworkUI {
background-color: @light-toolbox-background;
@ -114,14 +118,17 @@
}
.NetworkUI__router {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
fill: @green;
}
.NetworkUI__router--background{
fill: @light-background;
}
.NetworkUI__router--selected {
stroke: @selected-blue;
stroke-width: 4;
fill:@light-background;
}
.NetworkUI__router--remote-selected {
@ -134,16 +141,6 @@
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 {
fill: @button-text;
font-family: 'Open Sans';
@ -156,14 +153,17 @@
.NetworkUI__switch {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
fill: @blue;
}
.NetworkUI__switch--background{
fill: @light-background;
}
.NetworkUI__switch--selected {
stroke: @selected-blue;
stroke-width: 10;
fill:@light-background;
}
.NetworkUI__switch--remote-selected {
@ -197,19 +197,15 @@
}
.NetworkUI__rack {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
fill: @rack-orange;
}
.NetworkUI__rack-background {
.NetworkUI__rack--background {
fill: @light-background;
stroke: @light-background;
stroke-width: 2;
}
.NetworkUI__rack--selected {
fill: @selected-blue;
fill: @light-background;
stroke: @selected-blue;
stroke-width: 10;
}
@ -252,20 +248,33 @@
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 {
fill: @dark-widget-detail;
stroke: @dark-widget-detail;
stroke-width: 2;
}
.NetworkUI__site-background {
.NetworkUI__site--background {
fill: @light-background;
stroke: @light-background;
stroke-width: 2;
}
.NetworkUI__site--selected {
fill: @selected-blue;
fill: @light-background;
stroke: @selected-blue;
stroke-width: 10;
}
@ -411,19 +420,15 @@
}
.NetworkUI__host {
fill: @widget-body;
stroke: @dark-widget-detail;
stroke-width: 2;
fill: @host-green;
}
.NetworkUI__host-background {
.NetworkUI__host--background {
fill: @light-background;
stroke: @light-background;
stroke-width: 2;
}
.NetworkUI__host--selected {
fill: @selected-blue;
fill: @light-background;
stroke: @selected-blue;
stroke-width: 10;
}
@ -746,13 +751,13 @@
}
.NetworkUI__contextMenuButtonText{
fill: @button-text;
fill: #333; //@button-text;
font-family: 'Open Sans';
font-size: 14px;
}
.NetworkUI__contextMenuButtonText-hover{
fill: @button-text;
fill: #333; //@button-text;
font-family: 'Open Sans';
font-size: 14px;
}

View File

@ -1,79 +1,81 @@
<!-- 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">
<line ng-attr-x1="{{-50 - 100}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 100}}"
ng-attr-y2="0"
class="NetworkUI--construction"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 100}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 100}}"
class="NetworkUI--construction"></line>
</g>
<g ng-if="!debug.hidden">
<!--horizontal line -->
<line x1="-60"
y1="0"
x2="60"
y2="0"
class="NetworkUI--debug">
</line>
<!-- end horizontal line -->
<g ng-if="!debug.hidden">
<line ng-attr-x1="{{-50 - 10}}"
ng-attr-y1="0"
ng-attr-x2="{{50 + 10}}"
ng-attr-y2="0"
class="NetworkUI--debug"></line>
<line ng-attr-x1="0"
ng-attr-y1="{{-50 - 10}}"
ng-attr-x2="0"
ng-attr-y2="{{50 + 10}}"
class="NetworkUI--debug"></line>
<rect ng-attr-x="{{-50}}"
ng-attr-y="{{-50}}"
ng-attr-width="{{50 * 2}}"
ng-attr-height="{{50 * 2}}"
class="NetworkUI--debug"></rect>
</g>
<rect
x="-52"
y="-52"
ng-attr-width="{{100 + 4}}"
ng-attr-height="{{100 + 4}}"
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=10>
</rect>
<g class="NetworkUI__switch">
<rect
x="-50"
y="-50"
ng-attr-width="{{100}}"
ng-attr-height="{{100}}"
rx=10>
</rect>
<line ng-attr-x1="2"
ng-attr-y1="-28"
ng-attr-x2="38"
ng-attr-y2="-28"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(0) translate(28, -48) scale(2.0)"/>
<line ng-attr-x1="2"
ng-attr-y1="14"
ng-attr-x2="38"
ng-attr-y2="14"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(0) translate(28, -6) scale(2.0)"/>
<line ng-attr-x1="-2"
ng-attr-y1="28"
ng-attr-x2="-38"
ng-attr-y2="28"/>
<polygon points="0 0, 10 10, 0 20" ng-attr-transform="rotate(180) translate(28, -48) scale(2.0)"/>
<line ng-attr-x1="-2"
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>
<!-- vertical line -->
<line x1="0"
y1="-60"
x2="0"
y2="60"
class="NetworkUI--debug">
</line>
<!-- end vertical line -->
<!-- debug rectangle -->
<rect x="-50"
y="-50"
width="100"
height="100"
class="NetworkUI--debug">
</rect>
<!-- end debug rectangle -->
</g>
<g transform="translate(-50,-50)">
<rect
ry=15
rx=15
width=100
height=100
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>
<g transform="scale(2)">
<path
class="NetworkUI__switch"
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
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
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
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
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
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
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
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
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
c0.2,0.2,0.3,0.5,0.3,0.8C40,29.1,39.9,29.4,39.7,29.6z"/>
</g>
</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)"
x="-25"
y="70"> {{item.name}}</text>
<text class="NetworkUI__switch-text" x="-25" y="70">{{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.lastPanX = controller.scope.panX;
controller.scope.lastPanY = controller.scope.panY;
controller.scope.$emit('closeDetailsPanel');
controller.changeState(Pressed);
};